diff --git a/catalogue/nhcx/README.md b/catalogue/nhcx/README.md index aa68b31ac..5e776e0dd 100644 --- a/catalogue/nhcx/README.md +++ b/catalogue/nhcx/README.md @@ -13,6 +13,10 @@ MCP index and compile into agent skills; they are not site pages. | `flows/` | One atom per end-to-end journey, stitching endpoints and callbacks in call order. | | `decisions/` | One atom per integration decision: the options, the trade-off, the recommendation. | | `tests/` | One atom per test case: what it proves functionally, and its exact pass and fail conditions. | +| `troubleshooting/` | One atom per symptom a developer reports, not per error code: the checks that rule out the common causes, in order. | +| `fhir/` | One atom per FHIR bundle an exchange carries: its resources, profiles and the fields a payer reads. | +| `glossary/` | One atom per NHCX term, where the term is the exchange's own rather than shared across gateways. Shared terms live in `catalogue/shared/glossary/`. | +| `sandbox/` | One atom per fact about the NHCX sandbox: hosts, test participants, the dummy payer, callback rules, exit and going live. | Scaffold a new atom with the `atom-new` skill so the frontmatter and the five mandatory sections come out right. READMEs like this one are contributor diff --git a/catalogue/nhcx/callbacks/claim-on-submit.md b/catalogue/nhcx/callbacks/claim-on-submit.md new file mode 100644 index 000000000..4c16d4025 --- /dev/null +++ b/catalogue/nhcx/callbacks/claim-on-submit.md @@ -0,0 +1,303 @@ +--- +id: nhcx.callback.claim-on-submit +type: callback +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Receiving POST /v1/claim/on_submit +summary: >- + What your hospital system receives when the payer answers a claim through the + claims exchange, and how to acknowledge and read it. +sources: +- url: https://hcxsbx.abdm.gov.in/claimhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/claimhcxservice.json + hash: sha256:488eea449c6ee45dc324f4f7c095a862c7d50d0e238075846122b51b2bab4878 + fetched: '2026-09-14' + note: 'API specification: claimhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/claim/on_submit.' +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Message Structure, Status Description. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 4.2 Payer-Side Response Codes. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Q14 and Q21 (Not getting call back). +- url: https://hcxsbx.abdm.gov.in/images/064cf2e059987011e53a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Claim.pdf + hash: sha256:66290de20d57d69e681946a0101518092ca43b3775bb38997c43beb17fb38076 + fetched: '2026-09-14' + note: Claim, listed on https://hcxsbx.abdm.gov.in/#/documents, not named in the NHCX document sheet. pages 1-2, Claim Submit Response. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item 8. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.claim-on-submit + - nhcx.endpoint.claim-submit + - nhcx.endpoint.status + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.participant-update + callbacks: + - nhcx.callback.claim-submit + - nhcx.callback.on-status + - nhcx.callback.error + flows: + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + - nhcx.flow.status-check + - nhcx.flow.receive-a-sealed-callback + fhir: + - nhcx.fhir.claim-response + - nhcx.fhir.query-update + tests: + - nhcx.test.provider-uc-09 + errors: + - nhcx.error.nhcx-1001 + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1015 + - nhcx.error.payr-1001 + - nhcx.error.payr-1002 + concepts: + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.retries-and-expiry + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.participant-registry + - nhcx.concept.encryption-certificate + - nhcx.concept.four-message-legs + - nhcx.concept.claim-cycle + - nhcx.concept.workflow-codes + - nhcx.concept.status-lifecycle + troubleshooting: + - nhcx.troubleshooting.callback-url-rejected + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.accepted-then-no-callback + sandbox: + - nhcx.sandbox.callback-url-requirements + decisions: + - nhcx.decision.key-encryption-algorithm + - nhcx.decision.status-poll-or-wait + glossary: + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - nhcx.glossary.api-call-id + - nhcx.glossary.protected-header + - nhcx.glossary.participant-code + - nhcx.glossary.payer + - nhcx.glossary.provider + - nhcx.glossary.claim + - shared.glossary.fhir + - shared.glossary.abha +--- + +# Receiving POST /v1/claim/on_submit + +## In plain words + +After you submit a claim, the [payer](../glossary/payer.md) answers through [NHCX](../../shared/glossary/nhcx.md). NHCX delivers the answer to your system as `POST /v1/claim/on_submit`. You receive it as the [provider](../glossary/provider.md) that sent the claim. One claim can bring several deliveries: an interim answer first, such as received or in process, then the final decision. Acknowledge each delivery within 30 seconds, then update the case. + +## Before you start + +**Who receives it:** the provider that sent `/v1/claim/submit`. **Who sends it:** the payer, through NHCX. + +- Your participant record in the [participant registry](../concepts/participant-registry.md) holds an `endpoint_url`. [NHCX](../../shared/glossary/nhcx.md) posts to that address with `/v1/claim/on_submit` appended. +- You set `endpoint_url` when you register, in [sandbox onboarding](../flows/sandbox-onboarding.md). You change it with [`/participant/update`](../endpoints/participant-update.md). +- The URL uses a domain name over HTTPS. It has no IP address and no port number. +- The server behind it is in India. Your firewall accepts calls from the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). +- Your handler can open a [JWE](../glossary/jwe.md) with your private key. That key pairs with the certificate in your registry record. See [your encryption certificate](../concepts/encryption-certificate.md). +- Your handler answers within 30 seconds and does slow work afterwards. See [the 202 acknowledgement](../concepts/synchronous-acknowledgement.md). +- You sent the request with [`/v1/claim/submit`](../endpoints/claim-submit.md). You stored its `x-hcx-api_call_id` and `x-hcx-correlation_id` before sending it. +- You also host [`/v1/error`](error.md), so a request that dies is never silent. + +## What happens + +```mermaid +sequenceDiagram + participant Y as Your provider system + participant N as NHCX gateway + participant O as Payer system + Y->>N: POST /v1/claim/submit + N-->>Y: 202 Accepted + N->>O: POST /v1/claim/submit + O->>N: POST /v1/claim/on_submit (sealed answer) + N->>Y: POST /v1/claim/on_submit + Y-->>N: 202 Accepted with receipt, within 30 seconds +``` + +### What arrives + +[NHCX](../../shared/glossary/nhcx.md) sends `POST /v1/claim/on_submit`. The body takes one of two forms. Branch on its `type` field. + +- `ProtocolResponse`: the payer could not process your request. The body is plain JSON with the error details, and nothing is sealed. +- Any other body carries the payer's answer sealed in `payload`, with `type` set to `JWEPayload`. + +```json +{ + "type": "JWEPayload", + "payload": "" +} +``` + +The payload is a JWE in compact form: five base64url parts joined by dots. Decode the first part to read the protected header. You do not need your private key for that step. + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-correlation_id": "", + "x-hcx-workflow_id": "26", + "x-hcx-timestamp": "", + "x-hcx-status": "response.complete", + "x-hcx-ben-abha-id": "" +} +``` + +| Protected header | What it tells you | +|---|---| +| `x-hcx-sender_code` | The payer that answered. | +| `x-hcx-recipient_code` | Your participant code. | +| `x-hcx-api_call_id` | This one message. Each answer has its own value. A repeat delivery carries the same value. | +| `x-hcx-correlation_id` | The exchange you started. Match it to the request you stored. | +| `x-hcx-workflow_id` | The step the answer reports. Read it when present. See [workflow codes](../concepts/workflow-codes.md). | +| `x-hcx-status` | Where the exchange stands. See the status list below. | +| `x-hcx-error_details` | An object with `code`, `message` and `trace` when something failed. | +| `x-hcx-ben-abha-id` | The beneficiary's [ABHA](../../shared/glossary/abha.md) number. Accept it with or without hyphens. | + +Look up `x-hcx-correlation_id` against the correlation ids you sent. If nothing matches, look it up against the `x-hcx-api_call_id` values you sent. + +`x-hcx-status` takes these values: + +- `response.partial`: an interim answer, such as received or in process. More follows on the same correlation id. +- `response.complete`: the final answer. The case is closed on this exchange. +- `response.error`: the request failed on protocol grounds. Treat `response.fail` the same way. + +The payer's workflow code says which step the answer reports: + +| `x-hcx-workflow_id` | Meaning | +|---|---| +| `25` | Claim received by the payer | +| `26` | Claim approved | +| `27` | Claim queried: the payer needs more documents | +| `28` | Claim in process | +| `29` | Claim forwarded to another processing entity | + +Answer a query with a claim query response on [`/v1/claim/submit`](../endpoints/claim-submit.md). See [answer a payer query on a claim](../flows/claim-query-response.md). + +Decrypt the payload with your private key. Use the algorithm the header names in `alg`. [RSA-OAEP or RSA-OAEP-256](../decisions/key-encryption-algorithm.md) covers both values. The plaintext is a [FHIR](../../shared/glossary/fhir.md) collection bundle: see [the claim response bundle](../fhir/claim-response.md). The ClaimResponse carries the decision, the approved amounts and any reason. + +#### When `type` is `ProtocolResponse` + +The body is plain JSON. Read `x-hcx-error_details` for the reason. + +```json +{ + "type": "ProtocolResponse", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-correlation_id": "", + "x-hcx-workflow_id": "", + "x-hcx-timestamp": "", + "x-hcx-debug_flag": "Error", + "x-hcx-status": "response.error", + "x-hcx-redirect_to": "", + "x-hcx-error_details": { + "code": "", + "message": "", + "trace": "" + }, + "x-hcx-debug_details": { + "code": "", + "message": "", + "trace": "" + }, + "x-hcx-domain-header": { + "use_case_name": "", + "amt_processed": "" + }, + "x-hcx-entity-type": "claim", + "x-hcx-ben-abha-id": "" +} +``` + +### What you send back + +Answer the delivery first, before you decrypt or act on it. Return HTTP status `202 Accepted` with this receipt: + +```json +{ + "timestamp": "", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "claim", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `api_call_id` and `correlation_id` repeat the values in this delivery. +- `result.sender_code` is the sender's code. `result.recipient_code` is yours. +- `result.entity_type` is `claim` for this exchange. +- `result.protocol_status` is one of `request.queued`, `request.dispatched` or `request.error`. +- `error.code` and `error.message` stay empty when you accept the message. +- `timestamp` takes the form `DD/MM/YYYY hh:mm:ss:sss`. + +### Retries and repeat deliveries + +- NHCX waits 30 seconds for your 202 and receipt. +- A late answer, another status code or a receipt in another shape counts as a failed delivery. NHCX sends the same message again. +- After 5 attempts NHCX stops. It deletes the request and retires its correlation id. The original sender learns of it on its own `/v1/error`. +- A repeat delivery is the same sealed message, so it carries the same `x-hcx-api_call_id`. Record every `x-hcx-api_call_id` you accept. +- On a repeat, return 202 with the same receipt and do not process the message again. +- Never deduplicate on `x-hcx-correlation_id`. Every message in one exchange shares it. +- An interim answer and a final answer share `x-hcx-correlation_id`. They differ in `x-hcx-api_call_id`. + +## How you know it worked + +- NHCX receives your HTTP 202 and receipt within 30 seconds of the delivery. +- Your log shows one delivery per `x-hcx-api_call_id`. A second delivery with the same value means NHCX did not accept your receipt. +- The `x-hcx-correlation_id` matches a request you sent. +- The case holds the payer's latest answer. It is final when `x-hcx-status` is `response.complete`. + +## When it goes wrong + +- **It never arrives.** Check these in order. + 1. Your `/v1/claim/submit` call got a 202 from NHCX. Without it, NHCX never forwarded the request. + 2. Your `/v1/error` endpoint holds no report for this correlation id. A report means the payer never received your request. + 3. The `endpoint_url` in your registry record is right. It uses a domain name, with no IP address and no port number. + 4. Your server is in India, and your firewall accepts the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). + 5. Your application routes the path to the handler: load balancer rules, service routes and endpoint versions. + 6. Ask NHCX with [`/v1/status`](../endpoints/status.md). `request.dispatched` means the payer has your request, so wait. `request.stopped` means it is dead. + If the payer cannot seal its answer to your certificate, it reports [PAYR-1002](../errors/payr-1002.md). Update the certificate in your registry record. See [accepted with 202 and no callback arrives](../troubleshooting/accepted-then-no-callback.md). +- **It arrives as a `ProtocolResponse`.** The payer could not open or validate your request. Read `x-hcx-error_details.code` and open its error atom. [PAYR-1001](../errors/payr-1001.md) means your payload could not be decrypted: fetch the recipient's certificate again with [`/fetch/certs`](../endpoints/fetch-certs.md). The correlation id of a failed request is inactive. Send a fresh request with a new correlation id; reusing the old one is refused as [NHCX-1006](../errors/nhcx-1006.md). +- **The same message arrives again and again.** NHCX did not accept your receipt. It was later than 30 seconds, used another status code, or had another shape. Fix the receipt, and keep processing each `x-hcx-api_call_id` once. An invalid answer from a receiver is reported as [NHCX-1015](../errors/nhcx-1015.md), "Invalid response received from receiver." +- **The correlation id matches nothing you sent.** You stored the ids after sending instead of before, or you looked in one field only. Look up `x-hcx-correlation_id` against the correlation ids you sent. If nothing matches, look it up against the `x-hcx-api_call_id` values you sent. See [responses arrive against the wrong request](../troubleshooting/duplicate-or-mismatched-correlation.md). +- **The answer is a rejection.** A rejection is not a protocol error. It arrives sealed, like an approval. The reason sits inside the decrypted resource, not in `x-hcx-error_details`. diff --git a/catalogue/nhcx/callbacks/claim-submit.md b/catalogue/nhcx/callbacks/claim-submit.md new file mode 100644 index 000000000..4226da62d --- /dev/null +++ b/catalogue/nhcx/callbacks/claim-submit.md @@ -0,0 +1,267 @@ +--- +id: nhcx.callback.claim-submit +type: callback +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Receiving POST /v1/claim/submit +summary: >- + What your payer system receives when a hospital submits a claim through the claims + exchange, and how to acknowledge it before you adjudicate. +sources: +- url: https://hcxsbx.abdm.gov.in/claimhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/claimhcxservice.json + hash: sha256:488eea449c6ee45dc324f4f7c095a862c7d50d0e238075846122b51b2bab4878 + fetched: '2026-09-14' + note: 'API specification: claimhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/claim/submit.' +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Message Structure, Status Description. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 4.1 Provider-Side Workflow Codes; 9.1. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Value sets, Use case codes. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Q14 and Q21 (Not getting call back). +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use case 11 Respond to the Claim Submitted. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. items 4, 7 and 8. +- url: https://hcxsbx.abdm.gov.in/images/064cf2e059987011e53a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Claim.pdf + hash: sha256:66290de20d57d69e681946a0101518092ca43b3775bb38997c43beb17fb38076 + fetched: '2026-09-14' + note: Claim, listed on https://hcxsbx.abdm.gov.in/#/documents, not named in the NHCX document sheet. page 2, items 4-6. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.claim-submit + - nhcx.endpoint.claim-on-submit + - nhcx.endpoint.participant-update + callbacks: + - nhcx.callback.claim-on-submit + - nhcx.callback.error + flows: + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + - nhcx.flow.payer-process-a-request + - nhcx.flow.receive-a-sealed-callback + fhir: + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + - nhcx.fhir.claim-response + - nhcx.fhir.validation + tests: + - nhcx.test.payer-uc-11 + errors: + - nhcx.error.nhcx-1001 + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1015 + - nhcx.error.nhcx-1016 + - nhcx.error.payr-1001 + concepts: + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.retries-and-expiry + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.participant-registry + - nhcx.concept.encryption-certificate + - nhcx.concept.four-message-legs + - nhcx.concept.claim-cycle + - nhcx.concept.workflow-codes + troubleshooting: + - nhcx.troubleshooting.callback-url-rejected + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.recipient-cannot-decrypt + sandbox: + - nhcx.sandbox.callback-url-requirements + decisions: + - nhcx.decision.key-encryption-algorithm + glossary: + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - nhcx.glossary.api-call-id + - nhcx.glossary.protected-header + - nhcx.glossary.participant-code + - nhcx.glossary.payer + - nhcx.glossary.provider + - nhcx.glossary.claim + - shared.glossary.fhir + - shared.glossary.abha + - shared.glossary.nrces +--- + +# Receiving POST /v1/claim/submit + +## In plain words + +When a [provider](../glossary/provider.md) submits a claim, [NHCX](../../shared/glossary/nhcx.md) delivers `POST /v1/claim/submit` to your system. You receive it as the [payer](../glossary/payer.md), or as the entity that processes claims for the policy. The message is the final claim after discharge. The same path also carries the provider's answer to your query on a claim, and a resubmitted claim. Acknowledge each delivery within 30 seconds. Then adjudicate and answer on [`/v1/claim/on_submit`](../endpoints/claim-on-submit.md). + +## Before you start + +**Who receives it:** the payer, as the system that processes the request for the policy. **Who sends it:** a provider, through NHCX. + +- Your participant record in the [participant registry](../concepts/participant-registry.md) holds an `endpoint_url`. [NHCX](../../shared/glossary/nhcx.md) posts to that address with `/v1/claim/submit` appended. +- You set `endpoint_url` when you register, in [sandbox onboarding](../flows/sandbox-onboarding.md). You change it with [`/participant/update`](../endpoints/participant-update.md). +- The URL uses a domain name over HTTPS. It has no IP address and no port number. +- The server behind it is in India. Your firewall accepts calls from the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). +- Your handler can open a [JWE](../glossary/jwe.md) with your private key. That key pairs with the certificate in your registry record. See [your encryption certificate](../concepts/encryption-certificate.md). +- Your handler answers within 30 seconds and does slow work afterwards. See [the 202 acknowledgement](../concepts/synchronous-acknowledgement.md). +- Your system can call [`/v1/claim/on_submit`](../endpoints/claim-on-submit.md) to answer. +- You also host [`/v1/error`](error.md), so a request that dies is never silent. + +## What happens + +```mermaid +sequenceDiagram + participant S as Provider system + participant N as NHCX gateway + participant Y as Your payer system + S->>N: POST /v1/claim/submit (sealed) + N-->>S: 202 Accepted + N->>Y: POST /v1/claim/submit (same sealed message) + Y-->>N: 202 Accepted with receipt, within 30 seconds + Note over Y: Decrypt, validate, process + Y->>N: POST /v1/claim/on_submit (your answer) + N->>S: POST /v1/claim/on_submit +``` + +### What arrives + +[NHCX](../../shared/glossary/nhcx.md) sends `POST /v1/claim/submit`. The JSON body carries one field, `payload`: + +```json +{ + "payload": "" +} +``` + +The payload is a JWE in compact form: five base64url parts joined by dots. Decode the first part to read the protected header. You do not need your private key for that step. + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-request_id": "", + "x-hcx-correlation_id": "", + "x-hcx-workflow_id": "15", + "x-hcx-timestamp": "", + "x-hcx-status": "request.initiated", + "x-hcx-ben-abha-id": "", + "x-hcx-use_case": "New" +} +``` + +| Protected header | What it tells you | +|---|---| +| `x-hcx-sender_code` | The provider that sent it. Your answer goes back to this code. | +| `x-hcx-recipient_code` | Your participant code. | +| `x-hcx-api_call_id` | This one message. A repeat delivery carries the same value. | +| `x-hcx-request_id` | The originating request. Read it when present. | +| `x-hcx-correlation_id` | The whole exchange. Copy it into your answer. | +| `x-hcx-workflow_id` | The business step. Read it when present. See [workflow codes](../concepts/workflow-codes.md). | +| `x-hcx-timestamp` | When the sender sealed the message. | +| `x-hcx-status` | `request.initiated` for a new request. Accept `request.initiate` as the same value. | +| `x-hcx-ben-abha-id` | The beneficiary's [ABHA](../../shared/glossary/abha.md) number. Accept it with or without hyphens. | +| `x-hcx-use_case` | `New` or `Resubmit`. Optional. | + +Decrypt the payload with your private key. Use the algorithm the header names in `alg`. [RSA-OAEP or RSA-OAEP-256](../decisions/key-encryption-algorithm.md) covers both values. The plaintext is a [FHIR](../../shared/glossary/fhir.md) collection bundle: see [the claim request bundle](../fhir/claim-request.md). `Claim.use` is `claim`. Validate it against the [NRCeS](../../shared/glossary/nrces.md) profiles before you adjudicate; see [validating a bundle](../fhir/validation.md). `x-hcx-workflow_id` `15` marks a new claim. `151` marks the provider's answer to your claim query; see [query update bundles](../fhir/query-update.md). + +### What you send back + +Answer the delivery first, before you decrypt or act on it. Return HTTP status `202 Accepted` with this receipt: + +```json +{ + "timestamp": "", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "claim", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `api_call_id` and `correlation_id` repeat the values in this delivery. +- `result.sender_code` is the sender's code. `result.recipient_code` is yours. +- `result.entity_type` is `claim` for this exchange. +- `result.protocol_status` is one of `request.queued`, `request.dispatched` or `request.error`. +- `error.code` and `error.message` stay empty when you accept the message. +- `timestamp` takes the form `DD/MM/YYYY hh:mm:ss:sss`. + +### Retries and repeat deliveries + +- NHCX waits 30 seconds for your 202 and receipt. +- A late answer, another status code or a receipt in another shape counts as a failed delivery. NHCX sends the same message again. +- After 5 attempts NHCX stops. It deletes the request and retires its correlation id. The original sender learns of it on its own `/v1/error`. +- A repeat delivery is the same sealed message, so it carries the same `x-hcx-api_call_id`. Record every `x-hcx-api_call_id` you accept. +- On a repeat, return 202 with the same receipt and do not process the message again. +- Never deduplicate on `x-hcx-correlation_id`. Every message in one exchange shares it. + +### What you do next + +Process the message, then answer on [`/v1/claim/on_submit`](../endpoints/claim-on-submit.md): + +- Copy `x-hcx-correlation_id` from this message. +- Give your answer its own fresh `x-hcx-api_call_id`. +- Send it to the sender: its `x-hcx-sender_code` becomes your `x-hcx-recipient_code`. +- Set `x-hcx-status` to `response.partial` for an interim answer, such as received or in process. Use `response.complete` for the decision. +- Seal a ClaimResponse bundle to the provider's certificate. See [the claim response bundle](../fhir/claim-response.md). +- If you cannot decrypt or validate this message, answer with a protocol response instead. Set `type` to `ProtocolResponse`, `x-hcx-status` to `response.error`, and fill `x-hcx-error_details`. + +## How you know it worked + +- NHCX receives your HTTP 202 and receipt within 30 seconds of the delivery. +- Your log shows one delivery per `x-hcx-api_call_id`. A second delivery with the same value means NHCX did not accept your receipt. +- You decrypted the payload and hold a Claim bundle with `Claim.use` `claim`, stored against its `x-hcx-correlation_id`. +- Your answer on `/v1/claim/on_submit` gets its own 202 from NHCX. No NHCX error names its correlation id. + +## When it goes wrong + +- **It never arrives.** Check these in order. + 1. The `endpoint_url` in your registry record is the address you expect. + 2. It uses a domain name, with no IP address and no port number. + 3. Your server is in India, and your firewall accepts the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). + 4. Your application routes the path to the handler: load balancer rules, service routes and endpoint versions. + 5. The provider addressed the message to your participant code. Providers address the processor code from their policy lookup, so check that code is yours. + When NHCX cannot reach you, the sender is told [NHCX-1001](../errors/nhcx-1001.md), "Receiver system is not reachable." See [your callback URL is rejected or never called](../troubleshooting/callback-url-rejected.md). +- **The same message arrives again and again.** NHCX did not accept your receipt. It was later than 30 seconds, used another status code, or had another shape. Fix the receipt, and keep processing each `x-hcx-api_call_id` once. An invalid answer from a receiver is reported as [NHCX-1015](../errors/nhcx-1015.md), "Invalid response received from receiver." +- **You cannot decrypt it.** The sender sealed it to an old certificate, or your registry certificate does not match your private key. Still return 202 with the receipt. Then answer on `/v1/claim/on_submit` with a protocol response. [PAYR-1001](../errors/payr-1001.md) names a decryption failure. See [the recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). +- **Your answer is refused.** [NHCX-1010](../errors/nhcx-1010.md) means NHCX holds no exchange with that correlation id. [NHCX-1016](../errors/nhcx-1016.md) means the action does not fit that correlation id. [NHCX-1011](../errors/nhcx-1011.md) means the `x-hcx-status` value is invalid. Copy the correlation id from this message, answer on the paired path, and use a documented status. See [responses arrive against the wrong request](../troubleshooting/duplicate-or-mismatched-correlation.md). +- **The request fails your business rules.** That is not a protocol error. Answer with a sealed ClaimResponse that carries the decision and the reason. Keep protocol responses for messages you cannot open or validate. diff --git a/catalogue/nhcx/callbacks/communication-on-request.md b/catalogue/nhcx/callbacks/communication-on-request.md new file mode 100644 index 000000000..63cfba880 --- /dev/null +++ b/catalogue/nhcx/callbacks/communication-on-request.md @@ -0,0 +1,286 @@ +--- +id: nhcx.callback.communication-on-request +type: callback +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Receiving POST /v1/communication/on_request +summary: >- + What your payer system receives when a hospital answers your request for documents + or information, and how to acknowledge it. +sources: +- url: https://hcxsbx.abdm.gov.in/communicationhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/communicationhcxservice.json + hash: sha256:0ad58a98851158057d38d42a8327349548644c1b2f1a33b4f94acb4c1840a8a4 + fetched: '2026-09-14' + note: 'API specification: communicationhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/communication/on_request.' +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Communication (additional docs), on_request. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 12.1 API and workflow codes. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Message Structure, Status Description. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Q14 and Q21 (Not getting call back). +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item 8. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.communication-on-request + - nhcx.endpoint.communication-request + - nhcx.endpoint.status + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.participant-update + callbacks: + - nhcx.callback.communication-request + - nhcx.callback.on-status + - nhcx.callback.error + flows: + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-query-response + - nhcx.flow.payer-process-a-request + - nhcx.flow.receive-a-sealed-callback + fhir: + - nhcx.fhir.task + - nhcx.fhir.collection-bundle + tests: + - nhcx.test.payer-uc-10 + - nhcx.test.provider-uc-08 + errors: + - nhcx.error.nhcx-1001 + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1015 + - nhcx.error.payr-1001 + - nhcx.error.payr-1002 + concepts: + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.retries-and-expiry + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.participant-registry + - nhcx.concept.encryption-certificate + - nhcx.concept.four-message-legs + - nhcx.concept.queries-and-communication + troubleshooting: + - nhcx.troubleshooting.callback-url-rejected + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.accepted-then-no-callback + sandbox: + - nhcx.sandbox.callback-url-requirements + decisions: + - nhcx.decision.key-encryption-algorithm + glossary: + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - nhcx.glossary.api-call-id + - nhcx.glossary.protected-header + - nhcx.glossary.participant-code + - nhcx.glossary.payer + - nhcx.glossary.provider + - nhcx.glossary.communication-request + - shared.glossary.fhir + - shared.glossary.abha +--- + +# Receiving POST /v1/communication/on_request + +## In plain words + +After you send a communication request, the [provider](../glossary/provider.md) answers through [NHCX](../../shared/glossary/nhcx.md). NHCX delivers the answer to your system as `POST /v1/communication/on_request`. You receive it as the [payer](../glossary/payer.md) that asked. It carries the documents or information you requested. Acknowledge the delivery within 30 seconds, then resume the case it belongs to. + +## Before you start + +**Who receives it:** the payer that sent `/v1/communication/request`. **Who sends it:** the provider, through NHCX. + +- Your participant record in the [participant registry](../concepts/participant-registry.md) holds an `endpoint_url`. [NHCX](../../shared/glossary/nhcx.md) posts to that address with `/v1/communication/on_request` appended. +- You set `endpoint_url` when you register, in [sandbox onboarding](../flows/sandbox-onboarding.md). You change it with [`/participant/update`](../endpoints/participant-update.md). +- The URL uses a domain name over HTTPS. It has no IP address and no port number. +- The server behind it is in India. Your firewall accepts calls from the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). +- Your handler can open a [JWE](../glossary/jwe.md) with your private key. That key pairs with the certificate in your registry record. See [your encryption certificate](../concepts/encryption-certificate.md). +- Your handler answers within 30 seconds and does slow work afterwards. See [the 202 acknowledgement](../concepts/synchronous-acknowledgement.md). +- You sent the request with [`/v1/communication/request`](../endpoints/communication-request.md). You stored its `x-hcx-api_call_id` and `x-hcx-correlation_id` before sending it. +- You also host [`/v1/error`](error.md), so a request that dies is never silent. + +## What happens + +```mermaid +sequenceDiagram + participant Y as Your payer system + participant N as NHCX gateway + participant O as Provider system + Y->>N: POST /v1/communication/request + N-->>Y: 202 Accepted + N->>O: POST /v1/communication/request + O->>N: POST /v1/communication/on_request (sealed answer) + N->>Y: POST /v1/communication/on_request + Y-->>N: 202 Accepted with receipt, within 30 seconds +``` + +### What arrives + +[NHCX](../../shared/glossary/nhcx.md) sends `POST /v1/communication/on_request`. The body takes one of two forms. Branch on its `type` field. + +- `ProtocolResponse`: the provider could not process your request. The body is plain JSON with the error details, and nothing is sealed. +- Any other body carries the provider's answer sealed in `payload`, with `type` set to `JWEPayload`. + +```json +{ + "type": "JWEPayload", + "payload": "" +} +``` + +The payload is a JWE in compact form: five base64url parts joined by dots. Decode the first part to read the protected header. You do not need your private key for that step. + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-correlation_id": "", + "x-hcx-timestamp": "", + "x-hcx-status": "response.complete", + "x-hcx-ben-abha-id": "" +} +``` + +| Protected header | What it tells you | +|---|---| +| `x-hcx-sender_code` | The provider that answered. | +| `x-hcx-recipient_code` | Your participant code. | +| `x-hcx-api_call_id` | This one message. Each answer has its own value. A repeat delivery carries the same value. | +| `x-hcx-correlation_id` | The exchange you started. Match it to the request you stored. | +| `x-hcx-workflow_id` | The step the answer reports. Read it when present. See [workflow codes](../concepts/workflow-codes.md). | +| `x-hcx-status` | Where the exchange stands. See the status list below. | +| `x-hcx-error_details` | An object with `code`, `message` and `trace` when something failed. | +| `x-hcx-ben-abha-id` | The beneficiary's [ABHA](../../shared/glossary/abha.md) number. Accept it with or without hyphens. | + +Look up `x-hcx-correlation_id` against the correlation ids you sent. If nothing matches, look it up against the `x-hcx-api_call_id` values you sent. + +`x-hcx-status` takes these values: + +- `response.complete`: the provider's answer. Accept `response.completed` as the same value. +- `response.error`: the request failed on protocol grounds. Treat `response.fail` the same way. + +Decrypt the payload with your private key. Use the algorithm the header names in `alg`. [RSA-OAEP or RSA-OAEP-256](../decisions/key-encryption-algorithm.md) covers both values. The plaintext is a [FHIR](../../shared/glossary/fhir.md) collection bundle built around a Task: see [the Task bundle](../fhir/task.md). The Task has `status` `completed`. Its input is a Communication, and the documents sit in `payload.contentAttachment`. The `x-hcx-workflow_id` matches the one on your request. + +#### When `type` is `ProtocolResponse` + +The body is plain JSON. Read `x-hcx-error_details` for the reason. + +```json +{ + "type": "ProtocolResponse", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-correlation_id": "", + "x-hcx-workflow_id": "", + "x-hcx-timestamp": "", + "x-hcx-debug_flag": "Error", + "x-hcx-status": "response.error", + "x-hcx-redirect_to": "", + "x-hcx-error_details": { + "code": "", + "message": "", + "trace": "" + }, + "x-hcx-debug_details": { + "code": "", + "message": "", + "trace": "" + }, + "x-hcx-domain-header": { + "use_case_name": "", + "amt_processed": "" + }, + "x-hcx-entity-type": "", + "x-hcx-ben-abha-id": "" +} +``` + +### What you send back + +Answer the delivery first, before you decrypt or act on it. Return HTTP status `202 Accepted` with this receipt: + +```json +{ + "timestamp": "", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `api_call_id` and `correlation_id` repeat the values in this delivery. +- `result.sender_code` is the sender's code. `result.recipient_code` is yours. +- An `entity_type` value for this exchange is not yet published. The published values are `coverageeligibility`, `preauth`, `claim`, `task`, `payment` and `insuranceplan`. +- `result.protocol_status` is one of `request.queued`, `request.dispatched` or `request.error`. +- `error.code` and `error.message` stay empty when you accept the message. +- `timestamp` takes the form `DD/MM/YYYY hh:mm:ss:sss`. + +### Retries and repeat deliveries + +- NHCX waits 30 seconds for your 202 and receipt. +- A late answer, another status code or a receipt in another shape counts as a failed delivery. NHCX sends the same message again. +- After 5 attempts NHCX stops. It deletes the request and retires its correlation id. The original sender learns of it on its own `/v1/error`. +- A repeat delivery is the same sealed message, so it carries the same `x-hcx-api_call_id`. Record every `x-hcx-api_call_id` you accept. +- On a repeat, return 202 with the same receipt and do not process the message again. +- Never deduplicate on `x-hcx-correlation_id`. Every message in one exchange shares it. + +## How you know it worked + +- NHCX receives your HTTP 202 and receipt within 30 seconds of the delivery. +- Your log shows one delivery per `x-hcx-api_call_id`. A second delivery with the same value means NHCX did not accept your receipt. +- The `x-hcx-correlation_id` matches a request you sent. +- You decrypted the payload and hold the Communication with its attachments, matched to your request. + +## When it goes wrong + +- **It never arrives.** Check these in order. + 1. Your `/v1/communication/request` call got a 202 from NHCX. Without it, NHCX never forwarded the request. + 2. Your `/v1/error` endpoint holds no report for this correlation id. A report means the provider never received your request. + 3. The `endpoint_url` in your registry record is right. It uses a domain name, with no IP address and no port number. + 4. Your server is in India, and your firewall accepts the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). + 5. Your application routes the path to the handler: load balancer rules, service routes and endpoint versions. + 6. Ask NHCX with [`/v1/status`](../endpoints/status.md). `request.dispatched` means the provider has your request, so wait. `request.stopped` means it is dead. + If the provider cannot seal its answer to your certificate, it reports [PAYR-1002](../errors/payr-1002.md). Update the certificate in your registry record. See [accepted with 202 and no callback arrives](../troubleshooting/accepted-then-no-callback.md). +- **It arrives as a `ProtocolResponse`.** The provider could not open or validate your request. Read `x-hcx-error_details.code` and open its error atom. [PAYR-1001](../errors/payr-1001.md) means your payload could not be decrypted: fetch the recipient's certificate again with [`/fetch/certs`](../endpoints/fetch-certs.md). The correlation id of a failed request is inactive. Send a fresh request with a new correlation id; reusing the old one is refused as [NHCX-1006](../errors/nhcx-1006.md). +- **The same message arrives again and again.** NHCX did not accept your receipt. It was later than 30 seconds, used another status code, or had another shape. Fix the receipt, and keep processing each `x-hcx-api_call_id` once. An invalid answer from a receiver is reported as [NHCX-1015](../errors/nhcx-1015.md), "Invalid response received from receiver." +- **The correlation id matches nothing you sent.** You stored the ids after sending instead of before, or you looked in one field only. Look up `x-hcx-correlation_id` against the correlation ids you sent. If nothing matches, look it up against the `x-hcx-api_call_id` values you sent. See [responses arrive against the wrong request](../troubleshooting/duplicate-or-mismatched-correlation.md). +- **The attachments are missing.** Answer the provider with a new communication request that names what is still needed. diff --git a/catalogue/nhcx/callbacks/communication-request.md b/catalogue/nhcx/callbacks/communication-request.md new file mode 100644 index 000000000..19c23f99a --- /dev/null +++ b/catalogue/nhcx/callbacks/communication-request.md @@ -0,0 +1,256 @@ +--- +id: nhcx.callback.communication-request +type: callback +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Receiving POST /v1/communication/request +summary: >- + What your hospital system receives when a payer asks for more documents or information + in the middle of a case, and how to acknowledge it. +sources: +- url: https://hcxsbx.abdm.gov.in/communicationhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/communicationhcxservice.json + hash: sha256:0ad58a98851158057d38d42a8327349548644c1b2f1a33b4f94acb4c1840a8a4 + fetched: '2026-09-14' + note: 'API specification: communicationhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/communication/request.' +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 12.1 Business context; API and workflow codes; 12.2. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Communication (additional docs). +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use case 8. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Message Structure, Status Description. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Q14 and Q21 (Not getting call back). +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. items 4, 7 and 8. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.communication-request + - nhcx.endpoint.communication-on-request + - nhcx.endpoint.participant-update + callbacks: + - nhcx.callback.communication-on-request + - nhcx.callback.error + flows: + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-query-response + - nhcx.flow.receive-a-sealed-callback + fhir: + - nhcx.fhir.task + - nhcx.fhir.collection-bundle + tests: + - nhcx.test.provider-uc-08 + - nhcx.test.payer-uc-10 + errors: + - nhcx.error.nhcx-1001 + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1015 + - nhcx.error.nhcx-1016 + - nhcx.error.payr-1001 + concepts: + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.retries-and-expiry + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.participant-registry + - nhcx.concept.encryption-certificate + - nhcx.concept.four-message-legs + - nhcx.concept.queries-and-communication + - nhcx.concept.workflow-codes + troubleshooting: + - nhcx.troubleshooting.callback-url-rejected + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.recipient-cannot-decrypt + sandbox: + - nhcx.sandbox.callback-url-requirements + decisions: + - nhcx.decision.key-encryption-algorithm + glossary: + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - nhcx.glossary.api-call-id + - nhcx.glossary.protected-header + - nhcx.glossary.participant-code + - nhcx.glossary.payer + - nhcx.glossary.provider + - nhcx.glossary.communication-request + - shared.glossary.fhir + - shared.glossary.abha +--- + +# Receiving POST /v1/communication/request + +## In plain words + +A [payer](../glossary/payer.md) that needs more from you in the middle of a case sends a communication request. [NHCX](../../shared/glossary/nhcx.md) delivers it to your system as `POST /v1/communication/request`. You receive it as the [provider](../glossary/provider.md). The payer can ask for additional documents, raise a turnaround-time query, or tell you about a grievance, a wallet change or a policy change. Acknowledge the delivery within 30 seconds. Then answer on [`/v1/communication/on_request`](../endpoints/communication-on-request.md). + +## Before you start + +**Who receives it:** the provider. **Who sends it:** a payer, through NHCX. + +- Your participant record in the [participant registry](../concepts/participant-registry.md) holds an `endpoint_url`. [NHCX](../../shared/glossary/nhcx.md) posts to that address with `/v1/communication/request` appended. +- You set `endpoint_url` when you register, in [sandbox onboarding](../flows/sandbox-onboarding.md). You change it with [`/participant/update`](../endpoints/participant-update.md). +- The URL uses a domain name over HTTPS. It has no IP address and no port number. +- The server behind it is in India. Your firewall accepts calls from the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). +- Your handler can open a [JWE](../glossary/jwe.md) with your private key. That key pairs with the certificate in your registry record. See [your encryption certificate](../concepts/encryption-certificate.md). +- Your handler answers within 30 seconds and does slow work afterwards. See [the 202 acknowledgement](../concepts/synchronous-acknowledgement.md). +- Your system can call [`/v1/communication/on_request`](../endpoints/communication-on-request.md) to answer. +- You also host [`/v1/error`](error.md), so a request that dies is never silent. + +## What happens + +```mermaid +sequenceDiagram + participant S as Payer system + participant N as NHCX gateway + participant Y as Your provider system + S->>N: POST /v1/communication/request (sealed) + N-->>S: 202 Accepted + N->>Y: POST /v1/communication/request (same sealed message) + Y-->>N: 202 Accepted with receipt, within 30 seconds + Note over Y: Decrypt, validate, process + Y->>N: POST /v1/communication/on_request (your answer) + N->>S: POST /v1/communication/on_request +``` + +### What arrives + +[NHCX](../../shared/glossary/nhcx.md) sends `POST /v1/communication/request`. The JSON body carries one field, `payload`: + +```json +{ + "payload": "" +} +``` + +The payload is a JWE in compact form: five base64url parts joined by dots. Decode the first part to read the protected header. You do not need your private key for that step. + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-request_id": "", + "x-hcx-correlation_id": "", + "x-hcx-timestamp": "", + "x-hcx-status": "request.initiated", + "x-hcx-ben-abha-id": "" +} +``` + +| Protected header | What it tells you | +|---|---| +| `x-hcx-sender_code` | The payer that sent it. Your answer goes back to this code. | +| `x-hcx-recipient_code` | Your participant code. | +| `x-hcx-api_call_id` | This one message. A repeat delivery carries the same value. | +| `x-hcx-request_id` | The originating request. Read it when present. | +| `x-hcx-correlation_id` | The whole exchange. Copy it into your answer. | +| `x-hcx-workflow_id` | The business step. Read it when present. See [workflow codes](../concepts/workflow-codes.md). | +| `x-hcx-timestamp` | When the sender sealed the message. | +| `x-hcx-status` | `request.initiated` for a new request. Accept `request.initiate` as the same value. | +| `x-hcx-ben-abha-id` | The beneficiary's [ABHA](../../shared/glossary/abha.md) number. Accept it with or without hyphens. | + +Decrypt the payload with your private key. Use the algorithm the header names in `alg`. [RSA-OAEP or RSA-OAEP-256](../decisions/key-encryption-algorithm.md) covers both values. The plaintext is a [FHIR](../../shared/glossary/fhir.md) collection bundle built around a Task: see [the Task bundle](../fhir/task.md). The Task `code` is `poll`. Follow the Task's `input` reference to the resource it names in the bundle. That resource carries the payer's message. `Task.reasonCode` says why the payer wrote. Codes in use include `tatquery`, `grievance`, `walletupdate`, `policychange`, `additionalinfo` and `claimArbitration`. + +### What you send back + +Answer the delivery first, before you decrypt or act on it. Return HTTP status `202 Accepted` with this receipt: + +```json +{ + "timestamp": "", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `api_call_id` and `correlation_id` repeat the values in this delivery. +- `result.sender_code` is the sender's code. `result.recipient_code` is yours. +- An `entity_type` value for this exchange is not yet published. The published values are `coverageeligibility`, `preauth`, `claim`, `task`, `payment` and `insuranceplan`. +- `result.protocol_status` is one of `request.queued`, `request.dispatched` or `request.error`. +- `error.code` and `error.message` stay empty when you accept the message. +- `timestamp` takes the form `DD/MM/YYYY hh:mm:ss:sss`. + +### Retries and repeat deliveries + +- NHCX waits 30 seconds for your 202 and receipt. +- A late answer, another status code or a receipt in another shape counts as a failed delivery. NHCX sends the same message again. +- After 5 attempts NHCX stops. It deletes the request and retires its correlation id. The original sender learns of it on its own `/v1/error`. +- A repeat delivery is the same sealed message, so it carries the same `x-hcx-api_call_id`. Record every `x-hcx-api_call_id` you accept. +- On a repeat, return 202 with the same receipt and do not process the message again. +- Never deduplicate on `x-hcx-correlation_id`. Every message in one exchange shares it. + +### What you do next + +Process the message, then answer on [`/v1/communication/on_request`](../endpoints/communication-on-request.md): + +- Copy `x-hcx-correlation_id` from this message. +- Give your answer its own fresh `x-hcx-api_call_id`. +- Send it to the sender: its `x-hcx-sender_code` becomes your `x-hcx-recipient_code`. +- Keep `x-hcx-workflow_id` the same as the request's. NHCX validates the workflow id on both messages. Set `x-hcx-status` to `response.complete`. +- Seal a Task bundle whose Task has `status` `completed` and carries a Communication with the documents as attachments. +- If you cannot decrypt or validate this message, answer with a protocol response instead. Set `type` to `ProtocolResponse`, `x-hcx-status` to `response.error`, and fill `x-hcx-error_details`. + +## How you know it worked + +- NHCX receives your HTTP 202 and receipt within 30 seconds of the delivery. +- Your log shows one delivery per `x-hcx-api_call_id`. A second delivery with the same value means NHCX did not accept your receipt. +- You decrypted the payload, followed the Task input and stored the payer's message against its `x-hcx-correlation_id`. +- Your answer on `/v1/communication/on_request` gets its own 202 from NHCX. It carries the same correlation id and workflow id. + +## When it goes wrong + +- **It never arrives.** Check these in order. + 1. The `endpoint_url` in your registry record is the address you expect. + 2. It uses a domain name, with no IP address and no port number. + 3. Your server is in India, and your firewall accepts the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). + 4. Your application routes the path to the handler: load balancer rules, service routes and endpoint versions. + 5. The payer addressed the message to your participant code. + When NHCX cannot reach you, the sender is told [NHCX-1001](../errors/nhcx-1001.md), "Receiver system is not reachable." See [your callback URL is rejected or never called](../troubleshooting/callback-url-rejected.md). +- **The same message arrives again and again.** NHCX did not accept your receipt. It was later than 30 seconds, used another status code, or had another shape. Fix the receipt, and keep processing each `x-hcx-api_call_id` once. An invalid answer from a receiver is reported as [NHCX-1015](../errors/nhcx-1015.md), "Invalid response received from receiver." +- **You cannot decrypt it.** The sender sealed it to an old certificate, or your registry certificate does not match your private key. Still return 202 with the receipt. Then answer on `/v1/communication/on_request` with a protocol response. [PAYR-1001](../errors/payr-1001.md) names a decryption failure. See [the recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). +- **Your answer is refused.** [NHCX-1010](../errors/nhcx-1010.md) means NHCX holds no exchange with that correlation id. [NHCX-1016](../errors/nhcx-1016.md) means the action does not fit that correlation id. [NHCX-1011](../errors/nhcx-1011.md) means the `x-hcx-status` value is invalid. Copy the correlation id from this message, answer on the paired path, and use a documented status. See [responses arrive against the wrong request](../troubleshooting/duplicate-or-mismatched-correlation.md). +- **The payer receives no documents.** The Communication in your answer needs its attachment in `payload.contentAttachment`. Check the bundle before you seal it. diff --git a/catalogue/nhcx/callbacks/coverageeligibility-check.md b/catalogue/nhcx/callbacks/coverageeligibility-check.md new file mode 100644 index 000000000..47e260fc0 --- /dev/null +++ b/catalogue/nhcx/callbacks/coverageeligibility-check.md @@ -0,0 +1,253 @@ +--- +id: nhcx.callback.coverageeligibility-check +type: callback +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Receiving POST /v1/coverageeligibility/check +summary: >- + What your payer system receives when a hospital asks whether a patient's policy + is in force and what it covers, and how to acknowledge it. +sources: +- url: https://hcxsbx.abdm.gov.in/coverageeligibilityhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/coverageeligibilityhcxservice.json + hash: sha256:1723a4020b1b33d0bc1d7175609f0d05e6a6a78e8b4c52041222396639ceb52c + fetched: '2026-09-14' + note: 'API specification: coverageeligibilityhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/coverageeligibility/check.' +- url: https://hcxsbx.abdm.gov.in/images/cfcbe62e8378d4f48ee6.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Coverage Eligibility.pdf + hash: sha256:69dd680ddac44231a97276a1d735e45777d8e43b5563b7248fd367a838d9744f + fetched: '2026-09-14' + note: Coverage Eligibility, listed on https://hcxsbx.abdm.gov.in/#/documents, not named in the NHCX document sheet. pages 1-2. +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use case 7 Response to the coverageeligibility request. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Message Structure, Status Description. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Q14 and Q21 (Not getting call back). +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. items 4, 7 and 8. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.coverageeligibility-on-check + - nhcx.endpoint.participant-update + callbacks: + - nhcx.callback.coverageeligibility-on-check + - nhcx.callback.error + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.payer-process-a-request + - nhcx.flow.receive-a-sealed-callback + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.coverage-eligibility-response + - nhcx.fhir.validation + tests: + - nhcx.test.payer-uc-07 + errors: + - nhcx.error.nhcx-1001 + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1015 + - nhcx.error.nhcx-1016 + - nhcx.error.payr-1001 + - nhcx.error.payr-1004 + concepts: + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.retries-and-expiry + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.participant-registry + - nhcx.concept.encryption-certificate + - nhcx.concept.four-message-legs + - nhcx.concept.coverage-eligibility-purposes + troubleshooting: + - nhcx.troubleshooting.callback-url-rejected + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.recipient-cannot-decrypt + sandbox: + - nhcx.sandbox.callback-url-requirements + decisions: + - nhcx.decision.key-encryption-algorithm + - nhcx.decision.eligibility-purpose + glossary: + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - nhcx.glossary.api-call-id + - nhcx.glossary.protected-header + - nhcx.glossary.participant-code + - nhcx.glossary.payer + - nhcx.glossary.provider + - nhcx.glossary.coverage-eligibility + - shared.glossary.fhir + - shared.glossary.abha + - shared.glossary.nrces +--- + +# Receiving POST /v1/coverageeligibility/check + +## In plain words + +Before treatment, a [provider](../glossary/provider.md) asks whether a patient's policy is in force and what it covers. [NHCX](../../shared/glossary/nhcx.md) delivers that question to your system as `POST /v1/coverageeligibility/check`. You receive it as the [payer](../glossary/payer.md). The request can also ask for the plan's benefits, or for what a preauthorisation will need. Acknowledge the delivery within 30 seconds. Then answer on [`/v1/coverageeligibility/on_check`](../endpoints/coverageeligibility-on-check.md). + +## Before you start + +**Who receives it:** the payer, as the system that processes the request for the policy. **Who sends it:** a provider, through NHCX. + +- Your participant record in the [participant registry](../concepts/participant-registry.md) holds an `endpoint_url`. [NHCX](../../shared/glossary/nhcx.md) posts to that address with `/v1/coverageeligibility/check` appended. +- You set `endpoint_url` when you register, in [sandbox onboarding](../flows/sandbox-onboarding.md). You change it with [`/participant/update`](../endpoints/participant-update.md). +- The URL uses a domain name over HTTPS. It has no IP address and no port number. +- The server behind it is in India. Your firewall accepts calls from the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). +- Your handler can open a [JWE](../glossary/jwe.md) with your private key. That key pairs with the certificate in your registry record. See [your encryption certificate](../concepts/encryption-certificate.md). +- Your handler answers within 30 seconds and does slow work afterwards. See [the 202 acknowledgement](../concepts/synchronous-acknowledgement.md). +- Your system can call [`/v1/coverageeligibility/on_check`](../endpoints/coverageeligibility-on-check.md) to answer. +- You also host [`/v1/error`](error.md), so a request that dies is never silent. + +## What happens + +```mermaid +sequenceDiagram + participant S as Provider system + participant N as NHCX gateway + participant Y as Your payer system + S->>N: POST /v1/coverageeligibility/check (sealed) + N-->>S: 202 Accepted + N->>Y: POST /v1/coverageeligibility/check (same sealed message) + Y-->>N: 202 Accepted with receipt, within 30 seconds + Note over Y: Decrypt, validate, process + Y->>N: POST /v1/coverageeligibility/on_check (your answer) + N->>S: POST /v1/coverageeligibility/on_check +``` + +### What arrives + +[NHCX](../../shared/glossary/nhcx.md) sends `POST /v1/coverageeligibility/check`. The JSON body carries one field, `payload`: + +```json +{ + "payload": "" +} +``` + +The payload is a JWE in compact form: five base64url parts joined by dots. Decode the first part to read the protected header. You do not need your private key for that step. + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-request_id": "", + "x-hcx-correlation_id": "", + "x-hcx-timestamp": "", + "x-hcx-status": "request.initiated", + "x-hcx-ben-abha-id": "" +} +``` + +| Protected header | What it tells you | +|---|---| +| `x-hcx-sender_code` | The provider that sent it. Your answer goes back to this code. | +| `x-hcx-recipient_code` | Your participant code. | +| `x-hcx-api_call_id` | This one message. A repeat delivery carries the same value. | +| `x-hcx-request_id` | The originating request. Read it when present. | +| `x-hcx-correlation_id` | The whole exchange. Copy it into your answer. | +| `x-hcx-workflow_id` | The business step. Read it when present. See [workflow codes](../concepts/workflow-codes.md). | +| `x-hcx-timestamp` | When the sender sealed the message. | +| `x-hcx-status` | `request.initiated` for a new request. Accept `request.initiate` as the same value. | +| `x-hcx-ben-abha-id` | The beneficiary's [ABHA](../../shared/glossary/abha.md) number. Accept it with or without hyphens. | + +Decrypt the payload with your private key. Use the algorithm the header names in `alg`. [RSA-OAEP or RSA-OAEP-256](../decisions/key-encryption-algorithm.md) covers both values. The plaintext is a [FHIR](../../shared/glossary/fhir.md) collection bundle: see [the coverage eligibility request bundle](../fhir/coverage-eligibility-request.md). Its purpose tells you what the provider asks; see [the three coverage eligibility purposes](../concepts/coverage-eligibility-purposes.md). Check the benefit, payer and provider identifiers in the request against your records. + +### What you send back + +Answer the delivery first, before you decrypt or act on it. Return HTTP status `202 Accepted` with this receipt: + +```json +{ + "timestamp": "", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "coverageeligibility", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `api_call_id` and `correlation_id` repeat the values in this delivery. +- `result.sender_code` is the sender's code. `result.recipient_code` is yours. +- `result.entity_type` is `coverageeligibility` for this exchange. +- `result.protocol_status` is one of `request.queued`, `request.dispatched` or `request.error`. +- `error.code` and `error.message` stay empty when you accept the message. +- `timestamp` takes the form `DD/MM/YYYY hh:mm:ss:sss`. + +### Retries and repeat deliveries + +- NHCX waits 30 seconds for your 202 and receipt. +- A late answer, another status code or a receipt in another shape counts as a failed delivery. NHCX sends the same message again. +- After 5 attempts NHCX stops. It deletes the request and retires its correlation id. The original sender learns of it on its own `/v1/error`. +- A repeat delivery is the same sealed message, so it carries the same `x-hcx-api_call_id`. Record every `x-hcx-api_call_id` you accept. +- On a repeat, return 202 with the same receipt and do not process the message again. +- Never deduplicate on `x-hcx-correlation_id`. Every message in one exchange shares it. + +### What you do next + +Process the message, then answer on [`/v1/coverageeligibility/on_check`](../endpoints/coverageeligibility-on-check.md): + +- Copy `x-hcx-correlation_id` from this message. +- Give your answer its own fresh `x-hcx-api_call_id`. +- Send it to the sender: its `x-hcx-sender_code` becomes your `x-hcx-recipient_code`. +- Set `x-hcx-status` to `response.complete` for your answer. +- Seal a CoverageEligibilityResponse bundle to the provider's certificate. Business failures, such as a provider not registered with you for the policy, go inside it. See [the coverage eligibility response bundle](../fhir/coverage-eligibility-response.md). +- If you cannot decrypt or validate this message, answer with a protocol response instead. Set `type` to `ProtocolResponse`, `x-hcx-status` to `response.error`, and fill `x-hcx-error_details`. + +## How you know it worked + +- NHCX receives your HTTP 202 and receipt within 30 seconds of the delivery. +- Your log shows one delivery per `x-hcx-api_call_id`. A second delivery with the same value means NHCX did not accept your receipt. +- You decrypted the payload and hold a CoverageEligibilityRequest bundle, stored against its `x-hcx-correlation_id`. +- Your answer on `/v1/coverageeligibility/on_check` gets its own 202 from NHCX. No NHCX error names its correlation id. + +## When it goes wrong + +- **It never arrives.** Check these in order. + 1. The `endpoint_url` in your registry record is the address you expect. + 2. It uses a domain name, with no IP address and no port number. + 3. Your server is in India, and your firewall accepts the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). + 4. Your application routes the path to the handler: load balancer rules, service routes and endpoint versions. + 5. The provider addressed the message to your participant code. Providers address the processor code from their policy lookup, so check that code is yours. + When NHCX cannot reach you, the sender is told [NHCX-1001](../errors/nhcx-1001.md), "Receiver system is not reachable." See [your callback URL is rejected or never called](../troubleshooting/callback-url-rejected.md). +- **The same message arrives again and again.** NHCX did not accept your receipt. It was later than 30 seconds, used another status code, or had another shape. Fix the receipt, and keep processing each `x-hcx-api_call_id` once. An invalid answer from a receiver is reported as [NHCX-1015](../errors/nhcx-1015.md), "Invalid response received from receiver." +- **You cannot decrypt it.** The sender sealed it to an old certificate, or your registry certificate does not match your private key. Still return 202 with the receipt. Then answer on `/v1/coverageeligibility/on_check` with a protocol response. [PAYR-1001](../errors/payr-1001.md) names a decryption failure. See [the recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). +- **Your answer is refused.** [NHCX-1010](../errors/nhcx-1010.md) means NHCX holds no exchange with that correlation id. [NHCX-1016](../errors/nhcx-1016.md) means the action does not fit that correlation id. [NHCX-1011](../errors/nhcx-1011.md) means the `x-hcx-status` value is invalid. Copy the correlation id from this message, answer on the paired path, and use a documented status. See [responses arrive against the wrong request](../troubleshooting/duplicate-or-mismatched-correlation.md). +- **The request fails your business rules.** That is not a protocol error. Answer with a sealed CoverageEligibilityResponse that carries the decision and the reason. Keep protocol responses for messages you cannot open or validate. [PAYR-1004](../errors/payr-1004.md) names a provider not registered with you for the requested policy. diff --git a/catalogue/nhcx/callbacks/coverageeligibility-on-check.md b/catalogue/nhcx/callbacks/coverageeligibility-on-check.md new file mode 100644 index 000000000..ce65f7957 --- /dev/null +++ b/catalogue/nhcx/callbacks/coverageeligibility-on-check.md @@ -0,0 +1,292 @@ +--- +id: nhcx.callback.coverageeligibility-on-check +type: callback +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Receiving POST /v1/coverageeligibility/on_check +summary: >- + What your hospital system receives when the payer answers a coverage check through + the claims exchange, and how to acknowledge and read it. +sources: +- url: https://hcxsbx.abdm.gov.in/coverageeligibilityhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/coverageeligibilityhcxservice.json + hash: sha256:1723a4020b1b33d0bc1d7175609f0d05e6a6a78e8b4c52041222396639ceb52c + fetched: '2026-09-14' + note: 'API specification: coverageeligibilityhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/coverageeligibility/on_check.' +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use case 5 Callback API logic. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet CoverageEligibility, on_check. +- url: https://hcxsbx.abdm.gov.in/images/cfcbe62e8378d4f48ee6.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Coverage Eligibility.pdf + hash: sha256:69dd680ddac44231a97276a1d735e45777d8e43b5563b7248fd367a838d9744f + fetched: '2026-09-14' + note: Coverage Eligibility, listed on https://hcxsbx.abdm.gov.in/#/documents, not named in the NHCX document sheet. pages 1-2. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Message Structure, Status Description. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Q14 and Q21 (Not getting call back). +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item 8. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.coverageeligibility-on-check + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.status + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.participant-update + callbacks: + - nhcx.callback.coverageeligibility-check + - nhcx.callback.on-status + - nhcx.callback.error + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.status-check + - nhcx.flow.receive-a-sealed-callback + fhir: + - nhcx.fhir.coverage-eligibility-response + tests: + - nhcx.test.provider-uc-05 + errors: + - nhcx.error.nhcx-1001 + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1015 + - nhcx.error.payr-1001 + - nhcx.error.payr-1002 + - nhcx.error.payr-1004 + concepts: + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.retries-and-expiry + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.participant-registry + - nhcx.concept.encryption-certificate + - nhcx.concept.four-message-legs + - nhcx.concept.coverage-eligibility-purposes + - nhcx.concept.status-lifecycle + troubleshooting: + - nhcx.troubleshooting.callback-url-rejected + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.accepted-then-no-callback + sandbox: + - nhcx.sandbox.callback-url-requirements + decisions: + - nhcx.decision.key-encryption-algorithm + - nhcx.decision.status-poll-or-wait + glossary: + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - nhcx.glossary.api-call-id + - nhcx.glossary.protected-header + - nhcx.glossary.participant-code + - nhcx.glossary.payer + - nhcx.glossary.provider + - nhcx.glossary.coverage-eligibility + - shared.glossary.fhir + - shared.glossary.abha +--- + +# Receiving POST /v1/coverageeligibility/on_check + +## In plain words + +After you check a patient's coverage, the [payer](../glossary/payer.md) answers through [NHCX](../../shared/glossary/nhcx.md). NHCX delivers the answer to your system as `POST /v1/coverageeligibility/on_check`. You receive it as the [provider](../glossary/provider.md) that asked. It says whether the policy is in force. Depending on what you asked, it also gives the benefits or what a preauthorisation will need. Acknowledge it within 30 seconds, then update the case. + +## Before you start + +**Who receives it:** the provider that sent `/v1/coverageeligibility/check`. **Who sends it:** the payer, through NHCX. + +- Your participant record in the [participant registry](../concepts/participant-registry.md) holds an `endpoint_url`. [NHCX](../../shared/glossary/nhcx.md) posts to that address with `/v1/coverageeligibility/on_check` appended. +- You set `endpoint_url` when you register, in [sandbox onboarding](../flows/sandbox-onboarding.md). You change it with [`/participant/update`](../endpoints/participant-update.md). +- The URL uses a domain name over HTTPS. It has no IP address and no port number. +- The server behind it is in India. Your firewall accepts calls from the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). +- Your handler can open a [JWE](../glossary/jwe.md) with your private key. That key pairs with the certificate in your registry record. See [your encryption certificate](../concepts/encryption-certificate.md). +- Your handler answers within 30 seconds and does slow work afterwards. See [the 202 acknowledgement](../concepts/synchronous-acknowledgement.md). +- You sent the request with [`/v1/coverageeligibility/check`](../endpoints/coverageeligibility-check.md). You stored its `x-hcx-api_call_id` and `x-hcx-correlation_id` before sending it. +- You also host [`/v1/error`](error.md), so a request that dies is never silent. + +## What happens + +```mermaid +sequenceDiagram + participant Y as Your provider system + participant N as NHCX gateway + participant O as Payer system + Y->>N: POST /v1/coverageeligibility/check + N-->>Y: 202 Accepted + N->>O: POST /v1/coverageeligibility/check + O->>N: POST /v1/coverageeligibility/on_check (sealed answer) + N->>Y: POST /v1/coverageeligibility/on_check + Y-->>N: 202 Accepted with receipt, within 30 seconds +``` + +### What arrives + +[NHCX](../../shared/glossary/nhcx.md) sends `POST /v1/coverageeligibility/on_check`. The body takes one of two forms. Branch on its `type` field. + +- `ProtocolResponse`: the payer could not process your request. The body is plain JSON with the error details, and nothing is sealed. +- Any other body carries the payer's answer sealed in `payload`, with `type` set to `JWEPayload`. + +```json +{ + "type": "JWEPayload", + "payload": "" +} +``` + +The payload is a JWE in compact form: five base64url parts joined by dots. Decode the first part to read the protected header. You do not need your private key for that step. + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-correlation_id": "", + "x-hcx-timestamp": "", + "x-hcx-status": "response.complete", + "x-hcx-ben-abha-id": "" +} +``` + +| Protected header | What it tells you | +|---|---| +| `x-hcx-sender_code` | The payer that answered. | +| `x-hcx-recipient_code` | Your participant code. | +| `x-hcx-api_call_id` | This one message. Each answer has its own value. A repeat delivery carries the same value. | +| `x-hcx-correlation_id` | The exchange you started. Match it to the request you stored. | +| `x-hcx-workflow_id` | The step the answer reports. Read it when present. See [workflow codes](../concepts/workflow-codes.md). | +| `x-hcx-status` | Where the exchange stands. See the status list below. | +| `x-hcx-error_details` | An object with `code`, `message` and `trace` when something failed. | +| `x-hcx-ben-abha-id` | The beneficiary's [ABHA](../../shared/glossary/abha.md) number. Accept it with or without hyphens. | + +Look up `x-hcx-correlation_id` against the correlation ids you sent. If nothing matches, look it up against the `x-hcx-api_call_id` values you sent. + +`x-hcx-status` takes these values: + +- `response.complete`: the payer's answer. Accept `response.completed` as the same value. +- `response.error`: the request failed on protocol grounds. Treat `response.fail` the same way. + +Decrypt the payload with your private key. Use the algorithm the header names in `alg`. [RSA-OAEP or RSA-OAEP-256](../decisions/key-encryption-algorithm.md) covers both values. The plaintext is a [FHIR](../../shared/glossary/fhir.md) collection bundle: see [the coverage eligibility response bundle](../fhir/coverage-eligibility-response.md). Business failures sit inside the CoverageEligibilityResponse, sealed like any answer. + +#### When `type` is `ProtocolResponse` + +The body is plain JSON. Read `x-hcx-error_details` for the reason. + +```json +{ + "type": "ProtocolResponse", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-correlation_id": "", + "x-hcx-workflow_id": "", + "x-hcx-timestamp": "", + "x-hcx-debug_flag": "Error", + "x-hcx-status": "response.error", + "x-hcx-redirect_to": "", + "x-hcx-error_details": { + "code": "", + "message": "", + "trace": "" + }, + "x-hcx-debug_details": { + "code": "", + "message": "", + "trace": "" + }, + "x-hcx-domain-header": { + "use_case_name": "", + "amt_processed": "" + }, + "x-hcx-entity-type": "coverageeligibility", + "x-hcx-ben-abha-id": "" +} +``` + +### What you send back + +Answer the delivery first, before you decrypt or act on it. Return HTTP status `202 Accepted` with this receipt: + +```json +{ + "timestamp": "", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "coverageeligibility", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `api_call_id` and `correlation_id` repeat the values in this delivery. +- `result.sender_code` is the sender's code. `result.recipient_code` is yours. +- `result.entity_type` is `coverageeligibility` for this exchange. +- `result.protocol_status` is one of `request.queued`, `request.dispatched` or `request.error`. +- `error.code` and `error.message` stay empty when you accept the message. +- `timestamp` takes the form `DD/MM/YYYY hh:mm:ss:sss`. + +### Retries and repeat deliveries + +- NHCX waits 30 seconds for your 202 and receipt. +- A late answer, another status code or a receipt in another shape counts as a failed delivery. NHCX sends the same message again. +- After 5 attempts NHCX stops. It deletes the request and retires its correlation id. The original sender learns of it on its own `/v1/error`. +- A repeat delivery is the same sealed message, so it carries the same `x-hcx-api_call_id`. Record every `x-hcx-api_call_id` you accept. +- On a repeat, return 202 with the same receipt and do not process the message again. +- Never deduplicate on `x-hcx-correlation_id`. Every message in one exchange shares it. +- An interim answer and a final answer share `x-hcx-correlation_id`. They differ in `x-hcx-api_call_id`. + +## How you know it worked + +- NHCX receives your HTTP 202 and receipt within 30 seconds of the delivery. +- Your log shows one delivery per `x-hcx-api_call_id`. A second delivery with the same value means NHCX did not accept your receipt. +- The `x-hcx-correlation_id` matches a request you sent. +- The case shows whether the policy is in force, with the benefits or requirements you asked for. + +## When it goes wrong + +- **It never arrives.** Check these in order. + 1. Your `/v1/coverageeligibility/check` call got a 202 from NHCX. Without it, NHCX never forwarded the request. + 2. Your `/v1/error` endpoint holds no report for this correlation id. A report means the payer never received your request. + 3. The `endpoint_url` in your registry record is right. It uses a domain name, with no IP address and no port number. + 4. Your server is in India, and your firewall accepts the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). + 5. Your application routes the path to the handler: load balancer rules, service routes and endpoint versions. + 6. Ask NHCX with [`/v1/status`](../endpoints/status.md). `request.dispatched` means the payer has your request, so wait. `request.stopped` means it is dead. + If the payer cannot seal its answer to your certificate, it reports [PAYR-1002](../errors/payr-1002.md). Update the certificate in your registry record. See [accepted with 202 and no callback arrives](../troubleshooting/accepted-then-no-callback.md). +- **It arrives as a `ProtocolResponse`.** The payer could not open or validate your request. Read `x-hcx-error_details.code` and open its error atom. [PAYR-1001](../errors/payr-1001.md) means your payload could not be decrypted: fetch the recipient's certificate again with [`/fetch/certs`](../endpoints/fetch-certs.md). The correlation id of a failed request is inactive. Send a fresh request with a new correlation id; reusing the old one is refused as [NHCX-1006](../errors/nhcx-1006.md). +- **The same message arrives again and again.** NHCX did not accept your receipt. It was later than 30 seconds, used another status code, or had another shape. Fix the receipt, and keep processing each `x-hcx-api_call_id` once. An invalid answer from a receiver is reported as [NHCX-1015](../errors/nhcx-1015.md), "Invalid response received from receiver." +- **The correlation id matches nothing you sent.** You stored the ids after sending instead of before, or you looked in one field only. Look up `x-hcx-correlation_id` against the correlation ids you sent. If nothing matches, look it up against the `x-hcx-api_call_id` values you sent. See [responses arrive against the wrong request](../troubleshooting/duplicate-or-mismatched-correlation.md). +- **The answer is a rejection.** A rejection is not a protocol error. It arrives sealed, like an approval. The reason sits inside the decrypted resource, not in `x-hcx-error_details`. [PAYR-1004](../errors/payr-1004.md) names a provider not registered with the payer for the requested policy. diff --git a/catalogue/nhcx/callbacks/error.md b/catalogue/nhcx/callbacks/error.md new file mode 100644 index 000000000..3661426b5 --- /dev/null +++ b/catalogue/nhcx/callbacks/error.md @@ -0,0 +1,217 @@ +--- +id: nhcx.callback.error +type: callback +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Receiving POST /v1/error +summary: >- + What your system receives when the claims exchange gives up delivering a request + you sent, and what to do with the report. +sources: +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. items 2 and 8. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Error Handling. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Q14 and Q21 (Not getting call back). +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.status + - nhcx.endpoint.participant-update + callbacks: + - nhcx.callback.on-status + flows: + - nhcx.flow.report-a-processing-error + - nhcx.flow.send-a-sealed-request + - nhcx.flow.status-check + - nhcx.flow.receive-a-sealed-callback + errors: + - nhcx.error.nhcx-1001 + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1014 + - nhcx.error.nhcx-1015 + concepts: + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.retries-and-expiry + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.participant-registry + - nhcx.concept.encryption-certificate + - nhcx.concept.four-message-legs + - nhcx.concept.error-code-spaces + - nhcx.concept.status-lifecycle + troubleshooting: + - nhcx.troubleshooting.callback-url-rejected + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.accepted-then-no-callback + sandbox: + - nhcx.sandbox.callback-url-requirements + - nhcx.sandbox.support-contacts + decisions: + - nhcx.decision.key-encryption-algorithm + glossary: + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - nhcx.glossary.api-call-id + - nhcx.glossary.protected-header + - nhcx.glossary.participant-code + - nhcx.glossary.payer + - nhcx.glossary.provider + - shared.glossary.abha +--- + +# Receiving POST /v1/error + +## In plain words + +When [NHCX](../../shared/glossary/nhcx.md) cannot deliver a request you sent, it tells you on `POST /v1/error`. Every participant receives it: [providers](../glossary/provider.md) and [payers](../glossary/payer.md) alike. It arrives after NHCX has tried 5 times and given up. Without it, a dead request looks the same as a case still under review. Acknowledge the report within 30 seconds, then mark the case undelivered. + +## Before you start + +**Who receives it:** every participant, as the sender of the failed request. **Who sends it:** NHCX. + +- Your participant record in the [participant registry](../concepts/participant-registry.md) holds an `endpoint_url`. [NHCX](../../shared/glossary/nhcx.md) posts to that address with `/v1/error` appended. +- You set `endpoint_url` when you register, in [sandbox onboarding](../flows/sandbox-onboarding.md). You change it with [`/participant/update`](../endpoints/participant-update.md). +- The URL uses a domain name over HTTPS. It has no IP address and no port number. +- The server behind it is in India. Your firewall accepts calls from the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). +- Your handler answers within 30 seconds and does slow work afterwards. See [the 202 acknowledgement](../concepts/synchronous-acknowledgement.md). +- Your handler for this path accepts a plain JSON body. It does not expect a sealed payload. +- You store the `x-hcx-correlation_id` of every request you send, so a report can find its case. + +## What happens + +```mermaid +sequenceDiagram + participant Y as Your system + participant N as NHCX gateway + participant R as Recipient system + Y->>N: POST a request (sealed) + N-->>Y: 202 Accepted + loop Up to 5 attempts + N->>R: POST the same request + R-->>N: No valid receipt within 30 seconds + end + Note over N: Deletes the request and retires its correlation id + N->>Y: POST /v1/error (reject details) + Y-->>N: 202 Accepted with receipt, within 30 seconds +``` + +### Why it arrives + +- A recipient must return 202 with the receipt for every delivery. A rejection, a late answer or a receipt in another shape counts as a failure. +- NHCX tries the same request 5 times. Then it deletes the request identified by the correlation id. +- The reject details come back to you, the sender, on `/v1/error`. +- The gateway validates protocol headers too, and can report a header failure to you asynchronously. + +### What arrives + +[NHCX](../../shared/glossary/nhcx.md) sends `POST /v1/error`. The body is a protocol response in plain JSON, not a sealed payload: + +```json +{ + "type": "ProtocolResponse", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-correlation_id": "", + "x-hcx-workflow_id": "", + "x-hcx-timestamp": "", + "x-hcx-debug_flag": "Error", + "x-hcx-status": "response.error", + "x-hcx-redirect_to": "", + "x-hcx-error_details": { + "code": "", + "message": "", + "trace": "" + }, + "x-hcx-debug_details": { + "code": "", + "message": "", + "trace": "" + }, + "x-hcx-domain-header": { + "use_case_name": "", + "amt_processed": "" + }, + "x-hcx-entity-type": "", + "x-hcx-ben-abha-id": "" +} +``` + +- `x-hcx-correlation_id` names your failed request. +- `x-hcx-error_details.code` names the failure. Codes that start `NHCX-` come from the gateway; see [error code spaces](../concepts/error-code-spaces.md). +- [NHCX-1001](../errors/nhcx-1001.md) means the receiver system is not reachable. +- `x-hcx-entity-type` names the exchange: `coverageeligibility`, `payment`, `insuranceplan`, `task`, `claim` or `preauth`. + +Store the body whole before you parse it. Do not refuse a body because it has fields you do not expect. + +### What you send back + +Answer the report first, before you act on it. Return HTTP status `202 Accepted` with this receipt: + +```json +{ + "timestamp": "", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `api_call_id` and `correlation_id` repeat the values in this delivery. +- `result.sender_code` is the sender's code. `result.recipient_code` is yours. +- `result.entity_type` repeats `x-hcx-entity-type` from the report. +- `result.protocol_status` is one of `request.queued`, `request.dispatched` or `request.error`. +- `error.code` and `error.message` stay empty when you accept the message. +- `timestamp` takes the form `DD/MM/YYYY hh:mm:ss:sss`. + +### Repeat reports + +NHCX expects your 202 and receipt within 30 seconds, as for every delivery. If the same report arrives twice, store it once and return the same receipt. + +### What you do next + +- Mark the case named by the correlation id as undelivered, so nobody waits for a decision that will not come. +- Fix the cause. For an unreachable recipient, wait until it is reachable, or contact [NHCX support](../sandbox/support-contacts.md). +- Send a fresh request with a new correlation id. The old one is inactive; reusing it is refused as [NHCX-1006](../errors/nhcx-1006.md). + +## How you know it worked + +- NHCX receives your HTTP 202 and receipt within 30 seconds of the report. +- The case named by `x-hcx-correlation_id` shows as undelivered in your system, with the error code stored. +- Your resubmission, under a new correlation id, gets a 202 from NHCX and later its answer on your callback. + +## When it goes wrong + +- **It never arrives.** The most common cause is that you do not host `/v1/error` at all, so failures pass unseen. Host it before any other asynchronous path. Then check the registration. The `endpoint_url` uses a domain name with no IP address or port. The server is in India, and your firewall accepts the addresses in [callback URL rules](../sandbox/callback-url-requirements.md). NHCX names a failure to deliver a protocol response to you as [NHCX-1014](../errors/nhcx-1014.md): unable to send protocol response to sender. If a case goes quiet with no report, ask with [`/v1/status`](../endpoints/status.md). `request.stopped` means the request is dead. +- **Your handler refuses the report.** It parsed the body against a fixed schema and returned an error. Store the body whole, return 202 with the receipt, and parse afterwards. +- **Your retry is refused as a duplicate.** You resent the request on its retired correlation id. That is [NHCX-1006](../errors/nhcx-1006.md). Send it again under a new correlation id. +- **The same recipient keeps failing.** Its endpoint is down or rejects deliveries. [NHCX-1001](../errors/nhcx-1001.md) and [NHCX-1015](../errors/nhcx-1015.md) name these conditions. Contact the recipient, or [NHCX support](../sandbox/support-contacts.md). diff --git a/catalogue/nhcx/callbacks/insuranceplan-on-request.md b/catalogue/nhcx/callbacks/insuranceplan-on-request.md new file mode 100644 index 000000000..d47d34d9b --- /dev/null +++ b/catalogue/nhcx/callbacks/insuranceplan-on-request.md @@ -0,0 +1,287 @@ +--- +id: nhcx.callback.insuranceplan-on-request +type: callback +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Receiving POST /v1/insuranceplan/on_request +summary: >- + What your hospital system receives when the payer returns the insurance plan for + a patient's policy, and how to acknowledge and read it. +sources: +- url: https://hcxsbx.abdm.gov.in/insuranceplanhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/insuranceplanhcxservice.json + hash: sha256:03665c6e6a5c8d86e3d621ab577dd683cf13c155d5b9529f5be6ca70fef13dee + fetched: '2026-09-14' + note: 'API specification: insuranceplanhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/insuranceplan/on_request.' +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Insurance Plan, on_request. +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use case 6 Callback API logic. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Q14, Q15 and Q21. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Message Structure, Status Description. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item 8. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.insuranceplan-on-request + - nhcx.endpoint.insuranceplan-request + - nhcx.endpoint.status + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.participant-update + callbacks: + - nhcx.callback.insuranceplan-request + - nhcx.callback.on-status + - nhcx.callback.error + flows: + - nhcx.flow.insurance-plan-request + - nhcx.flow.status-check + - nhcx.flow.receive-a-sealed-callback + fhir: + - nhcx.fhir.insurance-plan-bundle + - nhcx.fhir.pmjay-insurance-plan + tests: + - nhcx.test.provider-uc-06 + errors: + - nhcx.error.nhcx-1001 + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1015 + - nhcx.error.payr-1001 + - nhcx.error.payr-1002 + concepts: + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.retries-and-expiry + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.participant-registry + - nhcx.concept.encryption-certificate + - nhcx.concept.four-message-legs + - nhcx.concept.insurance-plan + - nhcx.concept.status-lifecycle + troubleshooting: + - nhcx.troubleshooting.callback-url-rejected + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.accepted-then-no-callback + sandbox: + - nhcx.sandbox.callback-url-requirements + decisions: + - nhcx.decision.key-encryption-algorithm + - nhcx.decision.status-poll-or-wait + glossary: + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - nhcx.glossary.api-call-id + - nhcx.glossary.protected-header + - nhcx.glossary.participant-code + - nhcx.glossary.payer + - nhcx.glossary.provider + - nhcx.glossary.insurance-plan + - nhcx.glossary.pmjay + - shared.glossary.fhir + - shared.glossary.abha +--- + +# Receiving POST /v1/insuranceplan/on_request + +## In plain words + +After you request a patient's insurance plan, the [payer](../glossary/payer.md) answers through [NHCX](../../shared/glossary/nhcx.md). NHCX delivers the plan to your system as `POST /v1/insuranceplan/on_request`. You receive it as the [provider](../glossary/provider.md) that asked. The plan shows the benefit rules and the documents a preauthorisation will need, before you submit one. Acknowledge it within 30 seconds. + +## Before you start + +**Who receives it:** the provider that sent `/v1/insuranceplan/request`. **Who sends it:** the payer, through NHCX. + +- Your participant record in the [participant registry](../concepts/participant-registry.md) holds an `endpoint_url`. [NHCX](../../shared/glossary/nhcx.md) posts to that address with `/v1/insuranceplan/on_request` appended. +- You set `endpoint_url` when you register, in [sandbox onboarding](../flows/sandbox-onboarding.md). You change it with [`/participant/update`](../endpoints/participant-update.md). +- The URL uses a domain name over HTTPS. It has no IP address and no port number. +- The server behind it is in India. Your firewall accepts calls from the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). +- Your handler can open a [JWE](../glossary/jwe.md) with your private key. That key pairs with the certificate in your registry record. See [your encryption certificate](../concepts/encryption-certificate.md). +- Your handler answers within 30 seconds and does slow work afterwards. See [the 202 acknowledgement](../concepts/synchronous-acknowledgement.md). +- You sent the request with [`/v1/insuranceplan/request`](../endpoints/insuranceplan-request.md). You stored its `x-hcx-api_call_id` and `x-hcx-correlation_id` before sending it. +- You also host [`/v1/error`](error.md), so a request that dies is never silent. + +## What happens + +```mermaid +sequenceDiagram + participant Y as Your provider system + participant N as NHCX gateway + participant O as Payer system + Y->>N: POST /v1/insuranceplan/request + N-->>Y: 202 Accepted + N->>O: POST /v1/insuranceplan/request + O->>N: POST /v1/insuranceplan/on_request (sealed answer) + N->>Y: POST /v1/insuranceplan/on_request + Y-->>N: 202 Accepted with receipt, within 30 seconds +``` + +### What arrives + +[NHCX](../../shared/glossary/nhcx.md) sends `POST /v1/insuranceplan/on_request`. The body takes one of two forms. Branch on its `type` field. + +- `ProtocolResponse`: the payer could not process your request. The body is plain JSON with the error details, and nothing is sealed. +- Any other body carries the payer's answer sealed in `payload`, with `type` set to `JWEPayload`. + +```json +{ + "type": "JWEPayload", + "payload": "" +} +``` + +The payload is a JWE in compact form: five base64url parts joined by dots. Decode the first part to read the protected header. You do not need your private key for that step. + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-correlation_id": "", + "x-hcx-timestamp": "", + "x-hcx-status": "response.complete", + "x-hcx-ben-abha-id": "" +} +``` + +| Protected header | What it tells you | +|---|---| +| `x-hcx-sender_code` | The payer that answered. | +| `x-hcx-recipient_code` | Your participant code. | +| `x-hcx-api_call_id` | This one message. Each answer has its own value. A repeat delivery carries the same value. | +| `x-hcx-correlation_id` | The exchange you started. Match it to the request you stored. | +| `x-hcx-workflow_id` | The step the answer reports. Read it when present. See [workflow codes](../concepts/workflow-codes.md). | +| `x-hcx-status` | Where the exchange stands. See the status list below. | +| `x-hcx-error_details` | An object with `code`, `message` and `trace` when something failed. | +| `x-hcx-ben-abha-id` | The beneficiary's [ABHA](../../shared/glossary/abha.md) number. Accept it with or without hyphens. | + +Look up `x-hcx-correlation_id` against the correlation ids you sent. If nothing matches, look it up against the `x-hcx-api_call_id` values you sent. + +`x-hcx-status` takes these values: + +- `response.complete`: the payer's answer. +- `response.error`: the request failed on protocol grounds. Treat `response.fail` the same way. + +Decrypt the payload with your private key. Use the algorithm the header names in `alg`. [RSA-OAEP or RSA-OAEP-256](../decisions/key-encryption-algorithm.md) covers both values. The plaintext is a [FHIR](../../shared/glossary/fhir.md) bundle that carries the payer's InsurancePlan resources. When it is a Task bundle, the Task output holds the InsurancePlan bundle. See [InsurancePlan request and response bundles](../fhir/insurance-plan-bundle.md). For [PMJAY](../glossary/pmjay.md), see [the PMJAY InsurancePlan profile](../fhir/pmjay-insurance-plan.md). + +#### When `type` is `ProtocolResponse` + +The body is plain JSON. Read `x-hcx-error_details` for the reason. + +```json +{ + "type": "ProtocolResponse", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-correlation_id": "", + "x-hcx-workflow_id": "", + "x-hcx-timestamp": "", + "x-hcx-debug_flag": "Error", + "x-hcx-status": "response.error", + "x-hcx-redirect_to": "", + "x-hcx-error_details": { + "code": "", + "message": "", + "trace": "" + }, + "x-hcx-debug_details": { + "code": "", + "message": "", + "trace": "" + }, + "x-hcx-domain-header": { + "use_case_name": "", + "amt_processed": "" + }, + "x-hcx-entity-type": "insuranceplan", + "x-hcx-ben-abha-id": "" +} +``` + +### What you send back + +Answer the delivery first, before you decrypt or act on it. Return HTTP status `202 Accepted` with this receipt: + +```json +{ + "timestamp": "", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "insuranceplan", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `api_call_id` and `correlation_id` repeat the values in this delivery. +- `result.sender_code` is the sender's code. `result.recipient_code` is yours. +- `result.entity_type` is `insuranceplan` for this exchange. +- `result.protocol_status` is one of `request.queued`, `request.dispatched` or `request.error`. +- `error.code` and `error.message` stay empty when you accept the message. +- `timestamp` takes the form `DD/MM/YYYY hh:mm:ss:sss`. + +### Retries and repeat deliveries + +- NHCX waits 30 seconds for your 202 and receipt. +- A late answer, another status code or a receipt in another shape counts as a failed delivery. NHCX sends the same message again. +- After 5 attempts NHCX stops. It deletes the request and retires its correlation id. The original sender learns of it on its own `/v1/error`. +- A repeat delivery is the same sealed message, so it carries the same `x-hcx-api_call_id`. Record every `x-hcx-api_call_id` you accept. +- On a repeat, return 202 with the same receipt and do not process the message again. +- Never deduplicate on `x-hcx-correlation_id`. Every message in one exchange shares it. +- An interim answer and a final answer share `x-hcx-correlation_id`. They differ in `x-hcx-api_call_id`. + +## How you know it worked + +- NHCX receives your HTTP 202 and receipt within 30 seconds of the delivery. +- Your log shows one delivery per `x-hcx-api_call_id`. A second delivery with the same value means NHCX did not accept your receipt. +- The `x-hcx-correlation_id` matches a request you sent. +- Your system holds the InsurancePlan resources for the policy, and shows the benefits and required documents before preauthorisation. + +## When it goes wrong + +- **It never arrives.** Check these in order. + 1. Your `/v1/insuranceplan/request` call got a 202 from NHCX. Without it, NHCX never forwarded the request. + 2. Your `/v1/error` endpoint holds no report for this correlation id. A report means the payer never received your request. + 3. The `endpoint_url` in your registry record is right. It uses a domain name, with no IP address and no port number. + 4. Your server is in India, and your firewall accepts the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). + 5. Your application routes the path to the handler: load balancer rules, service routes and endpoint versions. + 6. Ask NHCX with [`/v1/status`](../endpoints/status.md). `request.dispatched` means the payer has your request, so wait. `request.stopped` means it is dead. + If the payer cannot seal its answer to your certificate, it reports [PAYR-1002](../errors/payr-1002.md). Update the certificate in your registry record. See [accepted with 202 and no callback arrives](../troubleshooting/accepted-then-no-callback.md). +- **It arrives as a `ProtocolResponse`.** The payer could not open or validate your request. Read `x-hcx-error_details.code` and open its error atom. [PAYR-1001](../errors/payr-1001.md) means your payload could not be decrypted: fetch the recipient's certificate again with [`/fetch/certs`](../endpoints/fetch-certs.md). The correlation id of a failed request is inactive. Send a fresh request with a new correlation id; reusing the old one is refused as [NHCX-1006](../errors/nhcx-1006.md). +- **The same message arrives again and again.** NHCX did not accept your receipt. It was later than 30 seconds, used another status code, or had another shape. Fix the receipt, and keep processing each `x-hcx-api_call_id` once. An invalid answer from a receiver is reported as [NHCX-1015](../errors/nhcx-1015.md), "Invalid response received from receiver." +- **The correlation id matches nothing you sent.** You stored the ids after sending instead of before, or you looked in one field only. Look up `x-hcx-correlation_id` against the correlation ids you sent. If nothing matches, look it up against the `x-hcx-api_call_id` values you sent. See [responses arrive against the wrong request](../troubleshooting/duplicate-or-mismatched-correlation.md). diff --git a/catalogue/nhcx/callbacks/insuranceplan-request.md b/catalogue/nhcx/callbacks/insuranceplan-request.md new file mode 100644 index 000000000..ad9432bf4 --- /dev/null +++ b/catalogue/nhcx/callbacks/insuranceplan-request.md @@ -0,0 +1,257 @@ +--- +id: nhcx.callback.insuranceplan-request +type: callback +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Receiving POST /v1/insuranceplan/request +summary: >- + What your payer system receives when a hospital asks for the insurance plan behind + a patient's policy, and how to acknowledge it. +sources: +- url: https://hcxsbx.abdm.gov.in/insuranceplanhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/insuranceplanhcxservice.json + hash: sha256:03665c6e6a5c8d86e3d621ab577dd683cf13c155d5b9529f5be6ca70fef13dee + fetched: '2026-09-14' + note: 'API specification: insuranceplanhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/insuranceplan/request.' +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Insurance Plan, request. +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use case 8 Response to the insurance plan request. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Message Structure, Status Description. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Q14 and Q21 (Not getting call back). +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. items 4, 7 and 8. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.insuranceplan-request + - nhcx.endpoint.insuranceplan-on-request + - nhcx.endpoint.participant-update + callbacks: + - nhcx.callback.insuranceplan-on-request + - nhcx.callback.error + flows: + - nhcx.flow.insurance-plan-request + - nhcx.flow.payer-process-a-request + - nhcx.flow.receive-a-sealed-callback + fhir: + - nhcx.fhir.insurance-plan-bundle + - nhcx.fhir.pmjay-insurance-plan + tests: + - nhcx.test.payer-uc-08 + errors: + - nhcx.error.nhcx-1001 + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1015 + - nhcx.error.nhcx-1016 + - nhcx.error.payr-1001 + concepts: + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.retries-and-expiry + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.participant-registry + - nhcx.concept.encryption-certificate + - nhcx.concept.four-message-legs + - nhcx.concept.insurance-plan + troubleshooting: + - nhcx.troubleshooting.callback-url-rejected + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.recipient-cannot-decrypt + sandbox: + - nhcx.sandbox.callback-url-requirements + decisions: + - nhcx.decision.key-encryption-algorithm + glossary: + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - nhcx.glossary.api-call-id + - nhcx.glossary.protected-header + - nhcx.glossary.participant-code + - nhcx.glossary.payer + - nhcx.glossary.provider + - nhcx.glossary.insurance-plan + - nhcx.glossary.pmjay + - shared.glossary.fhir + - shared.glossary.abha +--- + +# Receiving POST /v1/insuranceplan/request + +## In plain words + +A [provider](../glossary/provider.md) asks for the insurance plan behind a patient's policy: the benefits, rules and documents it sets. [NHCX](../../shared/glossary/nhcx.md) delivers that request to your system as `POST /v1/insuranceplan/request`. You receive it as the [payer](../glossary/payer.md). Acknowledge the delivery within 30 seconds. Then answer on [`/v1/insuranceplan/on_request`](../endpoints/insuranceplan-on-request.md) with the plan. + +## Before you start + +**Who receives it:** the payer, as the system that processes the request for the policy. **Who sends it:** a provider, through NHCX. + +- Your participant record in the [participant registry](../concepts/participant-registry.md) holds an `endpoint_url`. [NHCX](../../shared/glossary/nhcx.md) posts to that address with `/v1/insuranceplan/request` appended. +- You set `endpoint_url` when you register, in [sandbox onboarding](../flows/sandbox-onboarding.md). You change it with [`/participant/update`](../endpoints/participant-update.md). +- The URL uses a domain name over HTTPS. It has no IP address and no port number. +- The server behind it is in India. Your firewall accepts calls from the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). +- Your handler can open a [JWE](../glossary/jwe.md) with your private key. That key pairs with the certificate in your registry record. See [your encryption certificate](../concepts/encryption-certificate.md). +- Your handler answers within 30 seconds and does slow work afterwards. See [the 202 acknowledgement](../concepts/synchronous-acknowledgement.md). +- Your system can call [`/v1/insuranceplan/on_request`](../endpoints/insuranceplan-on-request.md) to answer. +- You also host [`/v1/error`](error.md), so a request that dies is never silent. + +## What happens + +```mermaid +sequenceDiagram + participant S as Provider system + participant N as NHCX gateway + participant Y as Your payer system + S->>N: POST /v1/insuranceplan/request (sealed) + N-->>S: 202 Accepted + N->>Y: POST /v1/insuranceplan/request (same sealed message) + Y-->>N: 202 Accepted with receipt, within 30 seconds + Note over Y: Decrypt, validate, process + Y->>N: POST /v1/insuranceplan/on_request (your answer) + N->>S: POST /v1/insuranceplan/on_request +``` + +### What arrives + +[NHCX](../../shared/glossary/nhcx.md) sends `POST /v1/insuranceplan/request`. The JSON body carries one field, `payload`: + +```json +{ + "payload": "" +} +``` + +The payload is a JWE in compact form: five base64url parts joined by dots. Decode the first part to read the protected header. You do not need your private key for that step. + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-request_id": "", + "x-hcx-correlation_id": "", + "x-hcx-timestamp": "", + "x-hcx-status": "request.initiated", + "x-hcx-ben-abha-id": "" +} +``` + +| Protected header | What it tells you | +|---|---| +| `x-hcx-sender_code` | The provider that sent it. Your answer goes back to this code. | +| `x-hcx-recipient_code` | Your participant code. | +| `x-hcx-api_call_id` | This one message. A repeat delivery carries the same value. | +| `x-hcx-request_id` | The originating request. Read it when present. | +| `x-hcx-correlation_id` | The whole exchange. Copy it into your answer. | +| `x-hcx-workflow_id` | The business step. Read it when present. See [workflow codes](../concepts/workflow-codes.md). | +| `x-hcx-timestamp` | When the sender sealed the message. | +| `x-hcx-status` | `request.initiated` for a new request. Accept `request.initiate` as the same value. | +| `x-hcx-ben-abha-id` | The beneficiary's [ABHA](../../shared/glossary/abha.md) number. Accept it with or without hyphens. | + +Decrypt the payload with your private key. Use the algorithm the header names in `alg`. [RSA-OAEP or RSA-OAEP-256](../decisions/key-encryption-algorithm.md) covers both values. The plaintext is a [FHIR](../../shared/glossary/fhir.md) Task with `code` `poll`. Its inputs name what to look up: + +| Task input | Required | +|---|---| +| `PolicyNumber` | Yes | +| `ProductNumber` | No | +| `ProviderId` | No | + +See [InsurancePlan request and response bundles](../fhir/insurance-plan-bundle.md). + +### What you send back + +Answer the delivery first, before you decrypt or act on it. Return HTTP status `202 Accepted` with this receipt: + +```json +{ + "timestamp": "", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "insuranceplan", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `api_call_id` and `correlation_id` repeat the values in this delivery. +- `result.sender_code` is the sender's code. `result.recipient_code` is yours. +- `result.entity_type` is `insuranceplan` for this exchange. +- `result.protocol_status` is one of `request.queued`, `request.dispatched` or `request.error`. +- `error.code` and `error.message` stay empty when you accept the message. +- `timestamp` takes the form `DD/MM/YYYY hh:mm:ss:sss`. + +### Retries and repeat deliveries + +- NHCX waits 30 seconds for your 202 and receipt. +- A late answer, another status code or a receipt in another shape counts as a failed delivery. NHCX sends the same message again. +- After 5 attempts NHCX stops. It deletes the request and retires its correlation id. The original sender learns of it on its own `/v1/error`. +- A repeat delivery is the same sealed message, so it carries the same `x-hcx-api_call_id`. Record every `x-hcx-api_call_id` you accept. +- On a repeat, return 202 with the same receipt and do not process the message again. +- Never deduplicate on `x-hcx-correlation_id`. Every message in one exchange shares it. + +### What you do next + +Process the message, then answer on [`/v1/insuranceplan/on_request`](../endpoints/insuranceplan-on-request.md): + +- Copy `x-hcx-correlation_id` from this message. +- Give your answer its own fresh `x-hcx-api_call_id`. +- Send it to the sender: its `x-hcx-sender_code` becomes your `x-hcx-recipient_code`. +- Set `x-hcx-status` to `response.complete` for your answer. +- Seal a Task bundle whose output is an InsurancePlan bundle holding your InsurancePlan resources. For a [PMJAY](../glossary/pmjay.md) plan, see [the PMJAY InsurancePlan profile](../fhir/pmjay-insurance-plan.md). +- If you cannot decrypt or validate this message, answer with a protocol response instead. Set `type` to `ProtocolResponse`, `x-hcx-status` to `response.error`, and fill `x-hcx-error_details`. + +## How you know it worked + +- NHCX receives your HTTP 202 and receipt within 30 seconds of the delivery. +- Your log shows one delivery per `x-hcx-api_call_id`. A second delivery with the same value means NHCX did not accept your receipt. +- You decrypted the payload and hold the Task with its `PolicyNumber`, stored against its `x-hcx-correlation_id`. +- Your answer on `/v1/insuranceplan/on_request` gets its own 202 from NHCX. No NHCX error names its correlation id. + +## When it goes wrong + +- **It never arrives.** Check these in order. + 1. The `endpoint_url` in your registry record is the address you expect. + 2. It uses a domain name, with no IP address and no port number. + 3. Your server is in India, and your firewall accepts the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). + 4. Your application routes the path to the handler: load balancer rules, service routes and endpoint versions. + 5. The provider addressed the message to your participant code. Providers address the processor code from their policy lookup, so check that code is yours. + When NHCX cannot reach you, the sender is told [NHCX-1001](../errors/nhcx-1001.md), "Receiver system is not reachable." See [your callback URL is rejected or never called](../troubleshooting/callback-url-rejected.md). +- **The same message arrives again and again.** NHCX did not accept your receipt. It was later than 30 seconds, used another status code, or had another shape. Fix the receipt, and keep processing each `x-hcx-api_call_id` once. An invalid answer from a receiver is reported as [NHCX-1015](../errors/nhcx-1015.md), "Invalid response received from receiver." +- **You cannot decrypt it.** The sender sealed it to an old certificate, or your registry certificate does not match your private key. Still return 202 with the receipt. Then answer on `/v1/insuranceplan/on_request` with a protocol response. [PAYR-1001](../errors/payr-1001.md) names a decryption failure. See [the recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). +- **Your answer is refused.** [NHCX-1010](../errors/nhcx-1010.md) means NHCX holds no exchange with that correlation id. [NHCX-1016](../errors/nhcx-1016.md) means the action does not fit that correlation id. [NHCX-1011](../errors/nhcx-1011.md) means the `x-hcx-status` value is invalid. Copy the correlation id from this message, answer on the paired path, and use a documented status. See [responses arrive against the wrong request](../troubleshooting/duplicate-or-mismatched-correlation.md). diff --git a/catalogue/nhcx/callbacks/notification-delivery.md b/catalogue/nhcx/callbacks/notification-delivery.md new file mode 100644 index 000000000..a80a1a766 --- /dev/null +++ b/catalogue/nhcx/callbacks/notification-delivery.md @@ -0,0 +1,160 @@ +--- +id: nhcx.callback.notification-delivery +type: callback +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Receiving a notification on a patient app +summary: >- + What a patient app receives when the claims exchange pushes a claim update for + a patient who logged in to it, and how to handle it. +sources: +- url: https://hcxsbx.abdm.gov.in/images/01db86335b7c226eb745.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Notification Integration.docx + hash: sha256:05908862c103522fac0dbb482f8eb6a0f8536fc12b1ae3bdb0e98615f30812aa + fetched: '2026-09-14' + note: NHCX Notification Integration, listed on https://hcxsbx.abdm.gov.in/#/documents, not named in the NHCX document sheet. sections 2-7. +- url: https://hcxsbx.abdm.gov.in/subscriptionhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/subscriptionhcxservice.json + hash: sha256:0d0d4781aa96017c06c8c2533e63dd1a6b36bb2342ebb51aeefca3349d892029 + fetched: '2026-09-14' + note: 'API specification: subscriptionhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/notification/on_subscribe and /v1/notification/subscribe.' +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.notification-subscribe + flows: + - nhcx.flow.notification-subscribe + concepts: + - nhcx.concept.notifications + - nhcx.concept.beneficiary-consent + - nhcx.concept.jwe-envelope + errors: + - nhcx.error.nhcx-401 + sandbox: + - nhcx.sandbox.callback-url-requirements + glossary: + - shared.glossary.nhcx + - shared.glossary.phr + - shared.glossary.abha + - shared.glossary.abha-address + - shared.glossary.abdm + - shared.glossary.m1 + - nhcx.glossary.jwe +--- + +# Receiving a notification on a patient app + +## In plain words + +A patient app can follow a patient's claims on [NHCX](../../shared/glossary/nhcx.md). After it subscribes, NHCX pushes each claim event to the app as a notification. You receive it as the [PHR](../../shared/glossary/phr.md) app the patient last logged in to. Each notification carries a ready-to-show message, such as a preauthorisation approval, and optional detail for audit. Only one app receives a patient's notifications at a time: the one that subscribed last. + +## Before you start + +**Who receives it:** the patient app, registered in NHCX as a beneficiary service provider. **Who sends it:** NHCX. + +- Your app has completed [ABHA](../../shared/glossary/abha.md) integration, milestone [M1](../../shared/glossary/m1.md) of [ABDM](../../shared/glossary/abdm.md). +- Your app is registered in NHCX as a beneficiary service provider: sandbox testing, sandbox certification, then onboarding to the production registry. +- Your notification endpoint is an HTTPS address with TLS 1.2 or newer. +- When the patient logs in and consents, your app calls [`/v1/notification/subscribe`](../endpoints/notification-subscribe.md). The call names the patient's [ABHA address](../../shared/glossary/abha-address.md) in `subscriber.id` and your endpoint in `on_notification_url`. See [subscribe a patient app to notifications](../flows/notification-subscribe.md). +- Your app stored the `subscription_id` it sent. +- The subscription is the registration that makes notifications arrive. A later subscription for the same patient by another app replaces yours. + +## What happens + +```mermaid +sequenceDiagram + participant P as Patient + participant A as Your patient app + participant N as NHCX gateway + P->>A: Logs in with ABHA address and consents + A->>N: POST /v1/notification/subscribe + N-->>A: Subscription accepted, older subscriptions replaced + Note over N: Later, a payer answers a preauthorisation + N->>A: POST + A-->>N: Success status + A->>P: Shows the message +``` + +### What arrives + +NHCX sends `POST `. The notification carries these fields: + +| Field | Meaning | +|---|---| +| `notification_id` | This notification. Unique to it. | +| `topic_code` | The topic, for example `workflow_events`. | +| `timestamp` | When the event happened, in ISO 8601. | +| `subscriber.id` | The patient's ABHA address. | +| `message` | A human-readable message to show the patient as it is. | +| `domain_values` | Optional. The `x-hcx-*` values of the underlying exchange, for audit or custom formatting. | + +```json +{ + "notification_id": "", + "topic_code": "workflow_events", + "timestamp": "", + "subscriber": { + "id": "" + }, + "message": "", + "domain_values": { + "x-hcx-workflow_id": "", + "x-hcx-correlation_id": "", + "x-hcx-timestamp": "", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-status": "response.complete", + "x-hcx-action": "preauth_response", + "x-hcx-amount_submitted": "" + } +} +``` + +Show `message` to the patient without parsing anything else. You can ignore `domain_values` if you only display messages. + +Under `workflow_events`, these events arrive: + +| Event | Trigger | Status values | +|---|---|---| +| `preauth_request` | The provider submitted a preauthorisation | `queued`, `processing` | +| `preauth_response` | The payer decided a preauthorisation | `approved`, `rejected` | +| `claim_request` | The provider submitted a claim | `queued`, `processing` | +| `claim_response` | The payer adjudicated a claim | `approved`, `rejected` | +| `payment_notice` | The payment was processed | `paid`, `pending` | +| `communication` | Information was requested | `information_required` | + +Notifications and subscriptions use [JWE](../glossary/jwe.md) with `RSA-OAEP` and `A256GCM`. If the body arrives sealed, decrypt it with your private key first. The fields above are its content. + +### Checks on every delivery + +- Validate the token NHCX presents against the NHCX public certificate. +- Check that the sender code is the NHCX gateway's. +- Rate-limit the endpoint. + +### What you send back + +An acknowledgement body for a notification is not yet published. Answer with an HTTP success status as soon as you have stored the notification. Do the display work afterwards. + +### Repeat deliveries + +Each notification has its own `notification_id`. Store the ids you have shown. If one arrives again, answer with success and do not show it twice. + +## How you know it worked + +- Your endpoint stored the notification and answered with a success status. +- `subscriber.id` matches a patient whose subscription you hold. +- The patient sees `message` in your app once for each `notification_id`. + +## When it goes wrong + +- **It never arrives.** Check these in order. + 1. The patient has not logged in to another app since. A later subscription by another app replaced yours. Subscribe again at the patient's next login. + 2. Your subscribe call succeeded. A 401 means your token expired: generate a new one and subscribe again. See [NHCX-401](../errors/nhcx-401.md). + 3. A 403 means your app is not authorised. Check your beneficiary service provider registration in the NHCX registry. + 4. A 500 means a gateway failure. Retry the subscription with backoff. + 5. `on_notification_url` is exact, with no trailing space, and serves HTTPS with TLS 1.2 or newer. + 6. Your `topic_code` array includes `workflow_events`. +- **The subscribe call returns 409.** A subscription for this patient already exists. Check your subscription parameters. +- **The same notification shows twice.** You did not store `notification_id`. Show each id once. diff --git a/catalogue/nhcx/callbacks/on-status.md b/catalogue/nhcx/callbacks/on-status.md new file mode 100644 index 000000000..107a5332b --- /dev/null +++ b/catalogue/nhcx/callbacks/on-status.md @@ -0,0 +1,208 @@ +--- +id: nhcx.callback.on-status +type: callback +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Receiving POST /v1/on_status +summary: >- + What your system receives when the claims exchange answers your question about + where one of your messages stands, and how to act on it. +sources: +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Status, /v1/on_status. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Status Description (Protected Header). +- url: https://hcxsbx.abdm.gov.in/statushcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/statushcxservice.json + hash: sha256:93b6355a234ef56607427fcdfa32da4921124180c9df08ecd73c8af8955c2adf + fetched: '2026-09-14' + note: 'API specification: statushcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/status description.' +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Acceptance and Error scenario. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Q14 and Q21 (Not getting call back). +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item 8. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.on-status + - nhcx.endpoint.status + - nhcx.endpoint.participant-update + callbacks: + - nhcx.callback.status + - nhcx.callback.error + flows: + - nhcx.flow.status-check + - nhcx.flow.send-a-sealed-request + - nhcx.flow.receive-a-sealed-callback + tests: + - nhcx.test.provider-uc-13 + - nhcx.test.payer-uc-15 + errors: + - nhcx.error.nhcx-1001 + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1012 + - nhcx.error.nhcx-1015 + concepts: + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.retries-and-expiry + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.participant-registry + - nhcx.concept.encryption-certificate + - nhcx.concept.four-message-legs + - nhcx.concept.status-lifecycle + troubleshooting: + - nhcx.troubleshooting.callback-url-rejected + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.accepted-then-no-callback + sandbox: + - nhcx.sandbox.callback-url-requirements + decisions: + - nhcx.decision.key-encryption-algorithm + - nhcx.decision.status-poll-or-wait + glossary: + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - nhcx.glossary.api-call-id + - nhcx.glossary.protected-header + - nhcx.glossary.participant-code + - nhcx.glossary.payer + - nhcx.glossary.provider + - shared.glossary.abha +--- + +# Receiving POST /v1/on_status + +## In plain words + +When a case goes quiet, you can ask [NHCX](../../shared/glossary/nhcx.md) where one of your own messages stands. You ask with [`/v1/status`](../endpoints/status.md). NHCX answers from its own records and delivers the answer to your system as `POST /v1/on_status`. You receive it as the participant that asked: usually a [provider](../glossary/provider.md), sometimes a [payer](../glossary/payer.md) checking a message it sent. The answer says whether NHCX still holds the message, delivered it, or gave up. + +## Before you start + +**Who receives it:** the participant that sent `/v1/status`. **Who sends it:** NHCX, which answers status requests itself. + +- Your participant record in the [participant registry](../concepts/participant-registry.md) holds an `endpoint_url`. [NHCX](../../shared/glossary/nhcx.md) posts to that address with `/v1/on_status` appended. +- You set `endpoint_url` when you register, in [sandbox onboarding](../flows/sandbox-onboarding.md). You change it with [`/participant/update`](../endpoints/participant-update.md). +- The URL uses a domain name over HTTPS. It has no IP address and no port number. +- The server behind it is in India. Your firewall accepts calls from the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). +- Your handler can open a [JWE](../glossary/jwe.md) with your private key. That key pairs with the certificate in your registry record. See [your encryption certificate](../concepts/encryption-certificate.md). +- Your handler answers within 30 seconds and does slow work afterwards. See [the 202 acknowledgement](../concepts/synchronous-acknowledgement.md). +- You sent [`/v1/status`](../endpoints/status.md) with `x-hcx-correlation_id` set to the `x-hcx-api_call_id` of the message you asked about. +- You keep every `x-hcx-api_call_id` you send. Without it you cannot ask, and you cannot match the answer. +- You also host [`/v1/error`](error.md), so a request that dies is never silent. + +## What happens + +```mermaid +sequenceDiagram + participant Y as Your system + participant N as NHCX gateway + Y->>N: POST /v1/status (correlation id = API call id of the message in question) + N-->>Y: 202 Accepted + Note over N: Looks up the message in its own records + N->>Y: POST /v1/on_status + Y-->>N: 202 Accepted with receipt, within 30 seconds +``` + +### What arrives + +[NHCX](../../shared/glossary/nhcx.md) sends `POST /v1/on_status`. The answer travels in the protocol header attributes. There is no FHIR bundle. + +- If the body carries a sealed `payload`, decode the first part of the JWE to read the protected header. +- If the body is a plain object of `x-hcx-*` attributes, read them directly. + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-correlation_id": "", + "x-hcx-timestamp": "", + "x-hcx-status": "request.dispatched", + "x-hcx-ben-abha-id": "" +} +``` + +Match the answer by `x-hcx-correlation_id`. It equals the `x-hcx-api_call_id` of the message you asked about. `x-hcx-error_details`, with `code`, `message` and `trace`, reports a failure when there is one. + +| `x-hcx-status` | Meaning | What you do | +|---|---|---| +| `request.queued` | NHCX holds the message and has not delivered it yet. | Wait, then ask again later. | +| `request.dispatched` | The message reached the recipient's system. | Wait for the recipient's answer on your callback. | +| `request.stopped` | NHCX stopped after failed attempts to reach the recipient. | Treat the request as dead. Fix the cause and send a fresh request with a new correlation id. | + +### What you send back + +Answer the delivery first, before you decrypt or act on it. Return HTTP status `202 Accepted` with this receipt: + +```json +{ + "timestamp": "", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `api_call_id` and `correlation_id` repeat the values in this delivery. +- `result.sender_code` is the sender's code. `result.recipient_code` is yours. +- An `entity_type` value for this exchange is not yet published. The published values are `coverageeligibility`, `preauth`, `claim`, `task`, `payment` and `insuranceplan`. +- `result.protocol_status` is one of `request.queued`, `request.dispatched` or `request.error`. +- `error.code` and `error.message` stay empty when you accept the message. +- `timestamp` takes the form `DD/MM/YYYY hh:mm:ss:sss`. + +### Retries and repeat deliveries + +- NHCX waits 30 seconds for your 202 and receipt. +- A late answer, another status code or a receipt in another shape counts as a failed delivery. NHCX sends the same message again. +- After 5 attempts NHCX stops. It deletes the request and retires its correlation id. The original sender learns of it on its own `/v1/error`. +- A repeat delivery is the same sealed message, so it carries the same `x-hcx-api_call_id`. Record every `x-hcx-api_call_id` you accept. +- On a repeat, return 202 with the same receipt and do not process the message again. +- Never deduplicate on `x-hcx-correlation_id`. Every message in one exchange shares it. + +## How you know it worked + +- NHCX receives your HTTP 202 and receipt within 30 seconds of the delivery. +- Your log shows one delivery per `x-hcx-api_call_id`. A second delivery with the same value means NHCX did not accept your receipt. +- `x-hcx-correlation_id` equals the `x-hcx-api_call_id` of a message you sent. You recorded the `x-hcx-status` against that message. +- After `request.stopped`, your fresh request under a new correlation id gets a 202 from NHCX. + +## When it goes wrong + +- **It never arrives.** Check that your `/v1/status` call got a 202 from NHCX. [NHCX-1012](../errors/nhcx-1012.md), "No records found with the requested api caller id", means the id you asked about is not one NHCX holds. Put the `x-hcx-api_call_id` of your original message in `x-hcx-correlation_id`. Then check your registration. The `endpoint_url` uses a domain name with no IP address or port. The server is in India, and your firewall accepts the addresses in [callback URL rules](../sandbox/callback-url-requirements.md). +- **You matched it to the wrong case.** The correlation id of this answer is the API call id of the message you asked about. Compare it with the API call ids you stored, not with correlation ids. +- **You retried a stopped request on its old correlation id.** That correlation id is inactive. A new request under it is refused as [NHCX-1006](../errors/nhcx-1006.md). Send a fresh request with a new correlation id. +- **You expected a bundle.** The status answer has no FHIR payload. Everything you need is in the header attributes. +- **The same message arrives again and again.** NHCX did not accept your receipt. It was later than 30 seconds, used another status code, or had another shape. Fix the receipt, and keep processing each `x-hcx-api_call_id` once. An invalid answer from a receiver is reported as [NHCX-1015](../errors/nhcx-1015.md), "Invalid response received from receiver." diff --git a/catalogue/nhcx/callbacks/paymentnotice-on-request.md b/catalogue/nhcx/callbacks/paymentnotice-on-request.md new file mode 100644 index 000000000..b03753ea9 --- /dev/null +++ b/catalogue/nhcx/callbacks/paymentnotice-on-request.md @@ -0,0 +1,289 @@ +--- +id: nhcx.callback.paymentnotice-on-request +type: callback +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Receiving POST /v1/paymentnotice/on_request +summary: >- + What your payer system receives when a hospital acknowledges your payment notice, + and how to acknowledge it in turn. +sources: +- url: https://hcxsbx.abdm.gov.in/servicehcxpayment/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/servicehcxpayment.json + hash: sha256:f5c9e3728efbbeaa5e0e8083334b0ae60a05930e5a1e096ca06d40abb235d658 + fetched: '2026-09-14' + note: 'API specification: servicehcxpayment, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/paymentnotice/on_request.' +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sections 11.1, 11.4, 11.6 and implementation notes. +- url: https://hcxsbx.abdm.gov.in/images/b7260763ce8270b6baac.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Payment.pdf + hash: sha256:6d372cdeec0abaea66b4d267c5ee6137a01830c577360dba7699e0244e49615f + fetched: '2026-09-14' + note: Payment, listed on https://hcxsbx.abdm.gov.in/#/documents, not named in the NHCX document sheet. pages 1-2. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Message Structure, Status Description. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Q14 and Q21 (Not getting call back). +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item 8. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.paymentnotice-on-request + - nhcx.endpoint.paymentnotice-request + - nhcx.endpoint.status + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.participant-update + callbacks: + - nhcx.callback.paymentnotice-request + - nhcx.callback.task-submit + - nhcx.callback.on-status + - nhcx.callback.error + flows: + - nhcx.flow.payment-notice + - nhcx.flow.status-check + - nhcx.flow.receive-a-sealed-callback + fhir: + - nhcx.fhir.payment-notice + - nhcx.fhir.task + tests: + - nhcx.test.payer-uc-13 + - nhcx.test.provider-uc-11 + errors: + - nhcx.error.nhcx-1001 + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1015 + - nhcx.error.payr-1001 + - nhcx.error.payr-1002 + concepts: + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.retries-and-expiry + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.participant-registry + - nhcx.concept.encryption-certificate + - nhcx.concept.four-message-legs + - nhcx.concept.claim-cycle + troubleshooting: + - nhcx.troubleshooting.callback-url-rejected + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.accepted-then-no-callback + sandbox: + - nhcx.sandbox.callback-url-requirements + decisions: + - nhcx.decision.key-encryption-algorithm + glossary: + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - nhcx.glossary.api-call-id + - nhcx.glossary.protected-header + - nhcx.glossary.participant-code + - nhcx.glossary.payer + - nhcx.glossary.provider + - nhcx.glossary.payment-notice + - nhcx.glossary.pmjay + - shared.glossary.fhir + - shared.glossary.abha +--- + +# Receiving POST /v1/paymentnotice/on_request + +## In plain words + +After you send a payment notice, the [provider](../glossary/provider.md) acknowledges it through [NHCX](../../shared/glossary/nhcx.md). NHCX delivers the acknowledgement to your system as `POST /v1/paymentnotice/on_request`. You receive it as the [payer](../glossary/payer.md) that sent the notice. It confirms the provider received the payment details. Acknowledge the delivery within 30 seconds, then close the payment record. + +## Before you start + +**Who receives it:** the payer that sent `/v1/paymentnotice/request`. **Who sends it:** the provider, through NHCX. + +- Your participant record in the [participant registry](../concepts/participant-registry.md) holds an `endpoint_url`. [NHCX](../../shared/glossary/nhcx.md) posts to that address with `/v1/paymentnotice/on_request` appended. +- You set `endpoint_url` when you register, in [sandbox onboarding](../flows/sandbox-onboarding.md). You change it with [`/participant/update`](../endpoints/participant-update.md). +- The URL uses a domain name over HTTPS. It has no IP address and no port number. +- The server behind it is in India. Your firewall accepts calls from the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). +- Your handler can open a [JWE](../glossary/jwe.md) with your private key. That key pairs with the certificate in your registry record. See [your encryption certificate](../concepts/encryption-certificate.md). +- Your handler answers within 30 seconds and does slow work afterwards. See [the 202 acknowledgement](../concepts/synchronous-acknowledgement.md). +- You sent the request with [`/v1/paymentnotice/request`](../endpoints/paymentnotice-request.md). You stored its `x-hcx-api_call_id` and `x-hcx-correlation_id` before sending it. +- You also host [`/v1/error`](error.md), so a request that dies is never silent. + +## What happens + +```mermaid +sequenceDiagram + participant Y as Your payer system + participant N as NHCX gateway + participant O as Provider system + Y->>N: POST /v1/paymentnotice/request + N-->>Y: 202 Accepted + N->>O: POST /v1/paymentnotice/request + O->>N: POST /v1/paymentnotice/on_request (sealed answer) + N->>Y: POST /v1/paymentnotice/on_request + Y-->>N: 202 Accepted with receipt, within 30 seconds +``` + +### What arrives + +[NHCX](../../shared/glossary/nhcx.md) sends `POST /v1/paymentnotice/on_request`. The body takes one of two forms. Branch on its `type` field. + +- `ProtocolResponse`: the provider could not process your request. The body is plain JSON with the error details, and nothing is sealed. +- Any other body carries the provider's answer sealed in `payload`, with `type` set to `JWEPayload`. + +```json +{ + "type": "JWEPayload", + "payload": "" +} +``` + +The payload is a JWE in compact form: five base64url parts joined by dots. Decode the first part to read the protected header. You do not need your private key for that step. + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-correlation_id": "", + "x-hcx-workflow_id": "17", + "x-hcx-timestamp": "", + "x-hcx-status": "response.complete", + "x-hcx-ben-abha-id": "" +} +``` + +| Protected header | What it tells you | +|---|---| +| `x-hcx-sender_code` | The provider that answered. | +| `x-hcx-recipient_code` | Your participant code. | +| `x-hcx-api_call_id` | This one message. Each answer has its own value. A repeat delivery carries the same value. | +| `x-hcx-correlation_id` | The exchange you started. Match it to the request you stored. | +| `x-hcx-workflow_id` | The step the answer reports. Read it when present. See [workflow codes](../concepts/workflow-codes.md). | +| `x-hcx-status` | Where the exchange stands. See the status list below. | +| `x-hcx-error_details` | An object with `code`, `message` and `trace` when something failed. | +| `x-hcx-ben-abha-id` | The beneficiary's [ABHA](../../shared/glossary/abha.md) number. Accept it with or without hyphens. | + +Look up `x-hcx-correlation_id` against the correlation ids you sent. If nothing matches, look it up against the `x-hcx-api_call_id` values you sent. + +`x-hcx-status` takes these values: + +- `response.complete`: the provider's answer. Accept `response.completed` as the same value. +- `response.error`: the request failed on protocol grounds. Treat `response.fail` the same way. + +Decrypt the payload with your private key. Use the algorithm the header names in `alg`. [RSA-OAEP or RSA-OAEP-256](../decisions/key-encryption-algorithm.md) covers both values. The plaintext is a [FHIR](../../shared/glossary/fhir.md) Task bundle: see [the payment notice bundle](../fhir/payment-notice.md). A completed Task is the acknowledgement. Its output carries the code `paymentack` and the claim number. `x-hcx-workflow_id` `17` means payment received. + +#### When `type` is `ProtocolResponse` + +The body is plain JSON. Read `x-hcx-error_details` for the reason. + +```json +{ + "type": "ProtocolResponse", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-correlation_id": "", + "x-hcx-workflow_id": "", + "x-hcx-timestamp": "", + "x-hcx-debug_flag": "Error", + "x-hcx-status": "response.error", + "x-hcx-redirect_to": "", + "x-hcx-error_details": { + "code": "", + "message": "", + "trace": "" + }, + "x-hcx-debug_details": { + "code": "", + "message": "", + "trace": "" + }, + "x-hcx-domain-header": { + "use_case_name": "", + "amt_processed": "" + }, + "x-hcx-entity-type": "payment", + "x-hcx-ben-abha-id": "" +} +``` + +### What you send back + +Answer the delivery first, before you decrypt or act on it. Return HTTP status `202 Accepted` with this receipt: + +```json +{ + "timestamp": "", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "payment", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `api_call_id` and `correlation_id` repeat the values in this delivery. +- `result.sender_code` is the sender's code. `result.recipient_code` is yours. +- `result.entity_type` is `payment` for this exchange. +- `result.protocol_status` is one of `request.queued`, `request.dispatched` or `request.error`. +- `error.code` and `error.message` stay empty when you accept the message. +- `timestamp` takes the form `DD/MM/YYYY hh:mm:ss:sss`. + +### Retries and repeat deliveries + +- NHCX waits 30 seconds for your 202 and receipt. +- A late answer, another status code or a receipt in another shape counts as a failed delivery. NHCX sends the same message again. +- After 5 attempts NHCX stops. It deletes the request and retires its correlation id. The original sender learns of it on its own `/v1/error`. +- A repeat delivery is the same sealed message, so it carries the same `x-hcx-api_call_id`. Record every `x-hcx-api_call_id` you accept. +- On a repeat, return 202 with the same receipt and do not process the message again. +- Never deduplicate on `x-hcx-correlation_id`. Every message in one exchange shares it. + +## How you know it worked + +- NHCX receives your HTTP 202 and receipt within 30 seconds of the delivery. +- Your log shows one delivery per `x-hcx-api_call_id`. A second delivery with the same value means NHCX did not accept your receipt. +- The `x-hcx-correlation_id` matches a request you sent. +- The payment record for that claim is closed with the provider's acknowledgement. + +## When it goes wrong + +- **It never arrives.** Check these in order. + 1. Your `/v1/paymentnotice/request` call got a 202 from NHCX. Without it, NHCX never forwarded the request. + 2. Your `/v1/error` endpoint holds no report for this correlation id. A report means the provider never received your request. + 3. The `endpoint_url` in your registry record is right. It uses a domain name, with no IP address and no port number. + 4. Your server is in India, and your firewall accepts the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). + 5. Your application routes the path to the handler: load balancer rules, service routes and endpoint versions. + 6. Ask NHCX with [`/v1/status`](../endpoints/status.md). `request.dispatched` means the provider has your request, so wait. `request.stopped` means it is dead. + If the provider cannot seal its answer to your certificate, it reports [PAYR-1002](../errors/payr-1002.md). Update the certificate in your registry record. See [accepted with 202 and no callback arrives](../troubleshooting/accepted-then-no-callback.md). +- **It arrives as a `ProtocolResponse`.** The provider could not open or validate your request. Read `x-hcx-error_details.code` and open its error atom. [PAYR-1001](../errors/payr-1001.md) means your payload could not be decrypted: fetch the recipient's certificate again with [`/fetch/certs`](../endpoints/fetch-certs.md). The correlation id of a failed request is inactive. Send a fresh request with a new correlation id; reusing the old one is refused as [NHCX-1006](../errors/nhcx-1006.md). +- **The same message arrives again and again.** NHCX did not accept your receipt. It was later than 30 seconds, used another status code, or had another shape. Fix the receipt, and keep processing each `x-hcx-api_call_id` once. An invalid answer from a receiver is reported as [NHCX-1015](../errors/nhcx-1015.md), "Invalid response received from receiver." +- **The correlation id matches nothing you sent.** You stored the ids after sending instead of before, or you looked in one field only. Look up `x-hcx-correlation_id` against the correlation ids you sent. If nothing matches, look it up against the `x-hcx-api_call_id` values you sent. See [responses arrive against the wrong request](../troubleshooting/duplicate-or-mismatched-correlation.md). +- **No acknowledgement comes at all.** A missing acknowledgement does not block your payment. You need it for complete lifecycle tracking, so follow up with the provider. +- **The acknowledgement comes on another path.** A [PMJAY](../glossary/pmjay.md) provider can send it to `/v1/task/submit`. Accept a `paymentack` Task there too; see [receiving `/v1/task/submit`](task-submit.md). diff --git a/catalogue/nhcx/callbacks/paymentnotice-request.md b/catalogue/nhcx/callbacks/paymentnotice-request.md new file mode 100644 index 000000000..3972e14fe --- /dev/null +++ b/catalogue/nhcx/callbacks/paymentnotice-request.md @@ -0,0 +1,259 @@ +--- +id: nhcx.callback.paymentnotice-request +type: callback +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Receiving POST /v1/paymentnotice/request +summary: >- + What your hospital system receives when a payer reports a payment against your + claim, and how to acknowledge it. +sources: +- url: https://hcxsbx.abdm.gov.in/servicehcxpayment/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/servicehcxpayment.json + hash: sha256:f5c9e3728efbbeaa5e0e8083334b0ae60a05930e5a1e096ca06d40abb235d658 + fetched: '2026-09-14' + note: 'API specification: servicehcxpayment, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/paymentnotice/request.' +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sections 11.1-11.5. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Erroneous Claim Q6 and Q12; Q14; Q21. +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use case 11 Acknowledge Payment notice. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Message Structure, Status Description. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. items 4, 7 and 8. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.paymentnotice-request + - nhcx.endpoint.paymentnotice-on-request + - nhcx.endpoint.participant-update + callbacks: + - nhcx.callback.paymentnotice-on-request + - nhcx.callback.error + flows: + - nhcx.flow.payment-notice + - nhcx.flow.claim-reprocess + - nhcx.flow.receive-a-sealed-callback + fhir: + - nhcx.fhir.payment-notice + tests: + - nhcx.test.provider-uc-11 + - nhcx.test.payer-uc-13 + errors: + - nhcx.error.nhcx-1001 + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1015 + - nhcx.error.nhcx-1016 + - nhcx.error.payr-1001 + concepts: + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.retries-and-expiry + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.participant-registry + - nhcx.concept.encryption-certificate + - nhcx.concept.four-message-legs + - nhcx.concept.claim-cycle + - nhcx.concept.workflow-codes + troubleshooting: + - nhcx.troubleshooting.callback-url-rejected + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.recipient-cannot-decrypt + sandbox: + - nhcx.sandbox.callback-url-requirements + decisions: + - nhcx.decision.key-encryption-algorithm + glossary: + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - nhcx.glossary.api-call-id + - nhcx.glossary.protected-header + - nhcx.glossary.participant-code + - nhcx.glossary.payer + - nhcx.glossary.provider + - nhcx.glossary.payment-notice + - shared.glossary.fhir + - shared.glossary.abha +--- + +# Receiving POST /v1/paymentnotice/request + +## In plain words + +After a [payer](../glossary/payer.md) approves your claim and pays, it sends a payment notice. [NHCX](../../shared/glossary/nhcx.md) delivers it to your system as `POST /v1/paymentnotice/request`. You receive it as the [provider](../glossary/provider.md). It carries the amount paid, the deductions, the payment date and the bank's transaction reference. Several notices can arrive for one claim: payment initiated, processed, then settled. Acknowledge each delivery within 30 seconds. Then acknowledge the payment on [`/v1/paymentnotice/on_request`](../endpoints/paymentnotice-on-request.md). + +## Before you start + +**Who receives it:** the provider. **Who sends it:** a payer, through NHCX. + +- Your participant record in the [participant registry](../concepts/participant-registry.md) holds an `endpoint_url`. [NHCX](../../shared/glossary/nhcx.md) posts to that address with `/v1/paymentnotice/request` appended. +- You set `endpoint_url` when you register, in [sandbox onboarding](../flows/sandbox-onboarding.md). You change it with [`/participant/update`](../endpoints/participant-update.md). +- The URL uses a domain name over HTTPS. It has no IP address and no port number. +- The server behind it is in India. Your firewall accepts calls from the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). +- Your handler can open a [JWE](../glossary/jwe.md) with your private key. That key pairs with the certificate in your registry record. See [your encryption certificate](../concepts/encryption-certificate.md). +- Your handler answers within 30 seconds and does slow work afterwards. See [the 202 acknowledgement](../concepts/synchronous-acknowledgement.md). +- Your system can call [`/v1/paymentnotice/on_request`](../endpoints/paymentnotice-on-request.md) to acknowledge the payment. +- You also host [`/v1/error`](error.md), so a request that dies is never silent. + +## What happens + +```mermaid +sequenceDiagram + participant S as Payer system + participant N as NHCX gateway + participant Y as Your provider system + S->>N: POST /v1/paymentnotice/request (sealed) + N-->>S: 202 Accepted + N->>Y: POST /v1/paymentnotice/request (same sealed message) + Y-->>N: 202 Accepted with receipt, within 30 seconds + Note over Y: Decrypt, validate, process + Y->>N: POST /v1/paymentnotice/on_request (your answer) + N->>S: POST /v1/paymentnotice/on_request +``` + +### What arrives + +[NHCX](../../shared/glossary/nhcx.md) sends `POST /v1/paymentnotice/request`. The JSON body carries one field, `payload`: + +```json +{ + "payload": "" +} +``` + +The payload is a JWE in compact form: five base64url parts joined by dots. Decode the first part to read the protected header. You do not need your private key for that step. + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-request_id": "", + "x-hcx-correlation_id": "", + "x-hcx-workflow_id": "30", + "x-hcx-timestamp": "", + "x-hcx-status": "request.initiated", + "x-hcx-ben-abha-id": "" +} +``` + +| Protected header | What it tells you | +|---|---| +| `x-hcx-sender_code` | The payer that sent it. Your answer goes back to this code. | +| `x-hcx-recipient_code` | Your participant code. | +| `x-hcx-api_call_id` | This one message. A repeat delivery carries the same value. | +| `x-hcx-request_id` | The originating request. Read it when present. | +| `x-hcx-correlation_id` | The whole exchange. Copy it into your answer. | +| `x-hcx-workflow_id` | The business step. Read it when present. See [workflow codes](../concepts/workflow-codes.md). | +| `x-hcx-timestamp` | When the sender sealed the message. | +| `x-hcx-status` | `request.initiated` for a new request. Accept `request.initiate` as the same value. | +| `x-hcx-ben-abha-id` | The beneficiary's [ABHA](../../shared/glossary/abha.md) number. Accept it with or without hyphens. | + +Decrypt the payload with your private key. Use the algorithm the header names in `alg`. [RSA-OAEP or RSA-OAEP-256](../decisions/key-encryption-algorithm.md) covers both values. The plaintext is a [FHIR](../../shared/glossary/fhir.md) Task bundle: see [the payment notice bundle](../fhir/payment-notice.md). The Task has `code` `deliver` and a PaymentNotice as input. The bundle also holds a PaymentReconciliation and the provider and payer Organizations. The PaymentReconciliation carries `status`, `paymentDate`, `paymentAmount` and `paymentIdentifier`. `paymentIdentifier.value` is the bank's unique transaction reference. Store it for audit. + +The workflow code says which stage the notice reports: + +| `x-hcx-workflow_id` | Meaning | +|---|---| +| `30` | Payment initiated to the bank | +| `31` | Payment processed | +| `33` | Payment settled: the bank confirmed clearance | + +### What you send back + +Answer the delivery first, before you decrypt or act on it. Return HTTP status `202 Accepted` with this receipt: + +```json +{ + "timestamp": "", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "payment", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `api_call_id` and `correlation_id` repeat the values in this delivery. +- `result.sender_code` is the sender's code. `result.recipient_code` is yours. +- `result.entity_type` is `payment` for this exchange. +- `result.protocol_status` is one of `request.queued`, `request.dispatched` or `request.error`. +- `error.code` and `error.message` stay empty when you accept the message. +- `timestamp` takes the form `DD/MM/YYYY hh:mm:ss:sss`. + +### Retries and repeat deliveries + +- NHCX waits 30 seconds for your 202 and receipt. +- A late answer, another status code or a receipt in another shape counts as a failed delivery. NHCX sends the same message again. +- After 5 attempts NHCX stops. It deletes the request and retires its correlation id. The original sender learns of it on its own `/v1/error`. +- A repeat delivery is the same sealed message, so it carries the same `x-hcx-api_call_id`. Record every `x-hcx-api_call_id` you accept. +- On a repeat, return 202 with the same receipt and do not process the message again. +- Never deduplicate on `x-hcx-correlation_id`. Every message in one exchange shares it. + +### What you do next + +Process the message, then answer on [`/v1/paymentnotice/on_request`](../endpoints/paymentnotice-on-request.md): + +- Copy `x-hcx-correlation_id` from this message. +- Give your answer its own fresh `x-hcx-api_call_id`. +- Send it to the sender: its `x-hcx-sender_code` becomes your `x-hcx-recipient_code`. +- Set `x-hcx-workflow_id` to `17`, payment received, and `x-hcx-status` to `response.complete`. After a `33` notice, verify the cleared payment before you acknowledge it. +- Seal a Task bundle whose Task has `status` `completed` and output `paymentack`. Name the claim number in the output too. +- If you cannot decrypt or validate this message, answer with a protocol response instead. Set `type` to `ProtocolResponse`, `x-hcx-status` to `response.error`, and fill `x-hcx-error_details`. + +## How you know it worked + +- NHCX receives your HTTP 202 and receipt within 30 seconds of the delivery. +- Your log shows one delivery per `x-hcx-api_call_id`. A second delivery with the same value means NHCX did not accept your receipt. +- You decrypted the payload and stored the amount, date and transaction reference against the claim. +- Your acknowledgement on `/v1/paymentnotice/on_request` gets its own 202 from NHCX. + +## When it goes wrong + +- **It never arrives.** Check these in order. + 1. The `endpoint_url` in your registry record is the address you expect. + 2. It uses a domain name, with no IP address and no port number. + 3. Your server is in India, and your firewall accepts the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). + 4. Your application routes the path to the handler: load balancer rules, service routes and endpoint versions. + 5. The payer addressed the message to your participant code. + When NHCX cannot reach you, the sender is told [NHCX-1001](../errors/nhcx-1001.md), "Receiver system is not reachable." See [your callback URL is rejected or never called](../troubleshooting/callback-url-rejected.md). +- **The same message arrives again and again.** NHCX did not accept your receipt. It was later than 30 seconds, used another status code, or had another shape. Fix the receipt, and keep processing each `x-hcx-api_call_id` once. An invalid answer from a receiver is reported as [NHCX-1015](../errors/nhcx-1015.md), "Invalid response received from receiver." +- **You cannot decrypt it.** The sender sealed it to an old certificate, or your registry certificate does not match your private key. Still return 202 with the receipt. Then answer on `/v1/paymentnotice/on_request` with a protocol response. [PAYR-1001](../errors/payr-1001.md) names a decryption failure. See [the recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). +- **Your answer is refused.** [NHCX-1010](../errors/nhcx-1010.md) means NHCX holds no exchange with that correlation id. [NHCX-1016](../errors/nhcx-1016.md) means the action does not fit that correlation id. [NHCX-1011](../errors/nhcx-1011.md) means the `x-hcx-status` value is invalid. Copy the correlation id from this message, answer on the paired path, and use a documented status. See [responses arrive against the wrong request](../troubleshooting/duplicate-or-mismatched-correlation.md). +- **You need to claim a shortfall.** Wait for workflow `33`, verify the payment and acknowledge it first. Then raise the shortfall as a task; see [ask the payer to reprocess a claim](../flows/claim-reprocess.md). diff --git a/catalogue/nhcx/callbacks/preauth-on-submit.md b/catalogue/nhcx/callbacks/preauth-on-submit.md new file mode 100644 index 000000000..f3b095b31 --- /dev/null +++ b/catalogue/nhcx/callbacks/preauth-on-submit.md @@ -0,0 +1,314 @@ +--- +id: nhcx.callback.preauth-on-submit +type: callback +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Receiving POST /v1/preauth/on_submit +summary: >- + What your hospital system receives when the payer answers a request to authorise + treatment, and how to acknowledge and read it. +sources: +- url: https://hcxsbx.abdm.gov.in/preauthhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/preauthhcxservice.json + hash: sha256:2e8c594c51d9640ae4a576be34a5d190614918d1e7697d6718bc91c31fa66948 + fetched: '2026-09-14' + note: 'API specification: preauthhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/preauth/on_submit.' +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sections 4.2 and 8.5. +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use case 7 Callback API logic. +- url: https://hcxsbx.abdm.gov.in/images/3799f26f2a0b2c9a80c5.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Preauthorization.pdf + hash: sha256:75d5628e7dd8a8e1a55c4ab3836c0591088ba378a8cd498e8277d83911129439 + fetched: '2026-09-14' + note: Preauthorization, listed on https://hcxsbx.abdm.gov.in/#/documents, not named in the NHCX document sheet. pages 1-2. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Message Structure, Status Description. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Q14 and Q21 (Not getting call back). +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item 8. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.preauth-on-submit + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.status + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.participant-update + callbacks: + - nhcx.callback.preauth-submit + - nhcx.callback.on-status + - nhcx.callback.error + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.status-check + - nhcx.flow.receive-a-sealed-callback + fhir: + - nhcx.fhir.preauth-response + - nhcx.fhir.preauth-enhancement + - nhcx.fhir.query-update + tests: + - nhcx.test.provider-uc-07 + - nhcx.test.tc-pa-01 + - nhcx.test.tc-pa-02 + errors: + - nhcx.error.nhcx-1001 + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1015 + - nhcx.error.payr-1001 + - nhcx.error.payr-1002 + concepts: + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.retries-and-expiry + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.participant-registry + - nhcx.concept.encryption-certificate + - nhcx.concept.four-message-legs + - nhcx.concept.claim-cycle + - nhcx.concept.workflow-codes + - nhcx.concept.status-lifecycle + troubleshooting: + - nhcx.troubleshooting.callback-url-rejected + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.accepted-then-no-callback + sandbox: + - nhcx.sandbox.callback-url-requirements + decisions: + - nhcx.decision.key-encryption-algorithm + - nhcx.decision.status-poll-or-wait + glossary: + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - nhcx.glossary.api-call-id + - nhcx.glossary.protected-header + - nhcx.glossary.participant-code + - nhcx.glossary.payer + - nhcx.glossary.provider + - nhcx.glossary.preauthorisation + - nhcx.glossary.enhancement + - shared.glossary.fhir + - shared.glossary.abha +--- + +# Receiving POST /v1/preauth/on_submit + +## In plain words + +After you submit a preauthorisation, the [payer](../glossary/payer.md) answers through [NHCX](../../shared/glossary/nhcx.md). NHCX delivers the answer to your system as `POST /v1/preauth/on_submit`. You receive it as the [provider](../glossary/provider.md) that asked. The decision can be an approval, a partial approval, a query or a rejection. The same path brings the answer to an enhancement or a resubmission. Acknowledge each delivery within 30 seconds, then update the case. + +## Before you start + +**Who receives it:** the provider that sent `/v1/preauth/submit`. **Who sends it:** the payer, through NHCX. + +- Your participant record in the [participant registry](../concepts/participant-registry.md) holds an `endpoint_url`. [NHCX](../../shared/glossary/nhcx.md) posts to that address with `/v1/preauth/on_submit` appended. +- You set `endpoint_url` when you register, in [sandbox onboarding](../flows/sandbox-onboarding.md). You change it with [`/participant/update`](../endpoints/participant-update.md). +- The URL uses a domain name over HTTPS. It has no IP address and no port number. +- The server behind it is in India. Your firewall accepts calls from the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). +- Your handler can open a [JWE](../glossary/jwe.md) with your private key. That key pairs with the certificate in your registry record. See [your encryption certificate](../concepts/encryption-certificate.md). +- Your handler answers within 30 seconds and does slow work afterwards. See [the 202 acknowledgement](../concepts/synchronous-acknowledgement.md). +- You sent the request with [`/v1/preauth/submit`](../endpoints/preauth-submit.md). You stored its `x-hcx-api_call_id` and `x-hcx-correlation_id` before sending it. +- You also host [`/v1/error`](error.md), so a request that dies is never silent. + +## What happens + +```mermaid +sequenceDiagram + participant Y as Your provider system + participant N as NHCX gateway + participant O as Payer system + Y->>N: POST /v1/preauth/submit + N-->>Y: 202 Accepted + N->>O: POST /v1/preauth/submit + O->>N: POST /v1/preauth/on_submit (sealed answer) + N->>Y: POST /v1/preauth/on_submit + Y-->>N: 202 Accepted with receipt, within 30 seconds +``` + +### What arrives + +[NHCX](../../shared/glossary/nhcx.md) sends `POST /v1/preauth/on_submit`. The body takes one of two forms. Branch on its `type` field. + +- `ProtocolResponse`: the payer could not process your request. The body is plain JSON with the error details, and nothing is sealed. +- Any other body carries the payer's answer sealed in `payload`, with `type` set to `JWEPayload`. + +```json +{ + "type": "JWEPayload", + "payload": "" +} +``` + +The payload is a JWE in compact form: five base64url parts joined by dots. Decode the first part to read the protected header. You do not need your private key for that step. + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-correlation_id": "", + "x-hcx-workflow_id": "21", + "x-hcx-timestamp": "", + "x-hcx-status": "response.complete", + "x-hcx-ben-abha-id": "" +} +``` + +| Protected header | What it tells you | +|---|---| +| `x-hcx-sender_code` | The payer that answered. | +| `x-hcx-recipient_code` | Your participant code. | +| `x-hcx-api_call_id` | This one message. Each answer has its own value. A repeat delivery carries the same value. | +| `x-hcx-correlation_id` | The exchange you started. Match it to the request you stored. | +| `x-hcx-workflow_id` | The step the answer reports. Read it when present. See [workflow codes](../concepts/workflow-codes.md). | +| `x-hcx-status` | Where the exchange stands. See the status list below. | +| `x-hcx-error_details` | An object with `code`, `message` and `trace` when something failed. | +| `x-hcx-ben-abha-id` | The beneficiary's [ABHA](../../shared/glossary/abha.md) number. Accept it with or without hyphens. | + +Look up `x-hcx-correlation_id` against the correlation ids you sent. If nothing matches, look it up against the `x-hcx-api_call_id` values you sent. + +`x-hcx-status` takes these values: + +- `response.partial`: an interim answer, such as received and acknowledged. More follows on the same correlation id. +- `response.complete`: the final answer. The case is closed on this exchange. +- `response.error`: the request failed on protocol grounds. Treat `response.fail` the same way. + +The payer's workflow code says which step the answer reports: + +| `x-hcx-workflow_id` | Meaning | +|---|---| +| `20` | Preauthorisation received and acknowledged | +| `21` | Preauthorisation approved: proceed with treatment | +| `22` | Enhancement approved | +| `23` | Preauthorisation rejected: read the reason in the ClaimResponse | +| `24` | Preauthorisation queried: answer with workflow `19` | +| `241` | Enhancement queried | + +Answer a query on [`/v1/preauth/submit`](../endpoints/preauth-submit.md). See [answer a payer query on a preauthorisation](../flows/preauth-query-response.md). + +Decrypt the payload with your private key. Use the algorithm the header names in `alg`. [RSA-OAEP or RSA-OAEP-256](../decisions/key-encryption-algorithm.md) covers both values. The plaintext is a [FHIR](../../shared/glossary/fhir.md) collection bundle: see [the preauthorisation response bundle](../fhir/preauth-response.md). The ClaimResponse carries the decision, the approved amount and any reason. For enhancements, see [enhancement bundles](../fhir/preauth-enhancement.md). + +#### When `type` is `ProtocolResponse` + +The body is plain JSON. Read `x-hcx-error_details` for the reason. + +```json +{ + "type": "ProtocolResponse", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-correlation_id": "", + "x-hcx-workflow_id": "", + "x-hcx-timestamp": "", + "x-hcx-debug_flag": "Error", + "x-hcx-status": "response.error", + "x-hcx-redirect_to": "", + "x-hcx-error_details": { + "code": "", + "message": "", + "trace": "" + }, + "x-hcx-debug_details": { + "code": "", + "message": "", + "trace": "" + }, + "x-hcx-domain-header": { + "use_case_name": "", + "amt_processed": "" + }, + "x-hcx-entity-type": "preauth", + "x-hcx-ben-abha-id": "" +} +``` + +### What you send back + +Answer the delivery first, before you decrypt or act on it. Return HTTP status `202 Accepted` with this receipt: + +```json +{ + "timestamp": "", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "preauth", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `api_call_id` and `correlation_id` repeat the values in this delivery. +- `result.sender_code` is the sender's code. `result.recipient_code` is yours. +- `result.entity_type` is `preauth` for this exchange. +- `result.protocol_status` is one of `request.queued`, `request.dispatched` or `request.error`. +- `error.code` and `error.message` stay empty when you accept the message. +- `timestamp` takes the form `DD/MM/YYYY hh:mm:ss:sss`. + +### Retries and repeat deliveries + +- NHCX waits 30 seconds for your 202 and receipt. +- A late answer, another status code or a receipt in another shape counts as a failed delivery. NHCX sends the same message again. +- After 5 attempts NHCX stops. It deletes the request and retires its correlation id. The original sender learns of it on its own `/v1/error`. +- A repeat delivery is the same sealed message, so it carries the same `x-hcx-api_call_id`. Record every `x-hcx-api_call_id` you accept. +- On a repeat, return 202 with the same receipt and do not process the message again. +- Never deduplicate on `x-hcx-correlation_id`. Every message in one exchange shares it. +- An interim answer and a final answer share `x-hcx-correlation_id`. They differ in `x-hcx-api_call_id`. + +## How you know it worked + +- NHCX receives your HTTP 202 and receipt within 30 seconds of the delivery. +- Your log shows one delivery per `x-hcx-api_call_id`. A second delivery with the same value means NHCX did not accept your receipt. +- The `x-hcx-correlation_id` matches a request you sent. +- The case holds the payer's latest answer. It is final when `x-hcx-status` is `response.complete`. + +## When it goes wrong + +- **It never arrives.** Check these in order. + 1. Your `/v1/preauth/submit` call got a 202 from NHCX. Without it, NHCX never forwarded the request. + 2. Your `/v1/error` endpoint holds no report for this correlation id. A report means the payer never received your request. + 3. The `endpoint_url` in your registry record is right. It uses a domain name, with no IP address and no port number. + 4. Your server is in India, and your firewall accepts the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). + 5. Your application routes the path to the handler: load balancer rules, service routes and endpoint versions. + 6. Ask NHCX with [`/v1/status`](../endpoints/status.md). `request.dispatched` means the payer has your request, so wait. `request.stopped` means it is dead. + If the payer cannot seal its answer to your certificate, it reports [PAYR-1002](../errors/payr-1002.md). Update the certificate in your registry record. See [accepted with 202 and no callback arrives](../troubleshooting/accepted-then-no-callback.md). +- **It arrives as a `ProtocolResponse`.** The payer could not open or validate your request. Read `x-hcx-error_details.code` and open its error atom. [PAYR-1001](../errors/payr-1001.md) means your payload could not be decrypted: fetch the recipient's certificate again with [`/fetch/certs`](../endpoints/fetch-certs.md). The correlation id of a failed request is inactive. Send a fresh request with a new correlation id; reusing the old one is refused as [NHCX-1006](../errors/nhcx-1006.md). +- **The same message arrives again and again.** NHCX did not accept your receipt. It was later than 30 seconds, used another status code, or had another shape. Fix the receipt, and keep processing each `x-hcx-api_call_id` once. An invalid answer from a receiver is reported as [NHCX-1015](../errors/nhcx-1015.md), "Invalid response received from receiver." +- **The correlation id matches nothing you sent.** You stored the ids after sending instead of before, or you looked in one field only. Look up `x-hcx-correlation_id` against the correlation ids you sent. If nothing matches, look it up against the `x-hcx-api_call_id` values you sent. See [responses arrive against the wrong request](../troubleshooting/duplicate-or-mismatched-correlation.md). +- **The answer is a rejection.** A rejection is not a protocol error. It arrives sealed, like an approval. The reason sits inside the decrypted resource, not in `x-hcx-error_details`. diff --git a/catalogue/nhcx/callbacks/preauth-submit.md b/catalogue/nhcx/callbacks/preauth-submit.md new file mode 100644 index 000000000..3f04b3c72 --- /dev/null +++ b/catalogue/nhcx/callbacks/preauth-submit.md @@ -0,0 +1,285 @@ +--- +id: nhcx.callback.preauth-submit +type: callback +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Receiving POST /v1/preauth/submit +summary: >- + What your payer system receives when a hospital asks you to authorise treatment + in advance, and how to acknowledge it before you adjudicate. +sources: +- url: https://hcxsbx.abdm.gov.in/preauthhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/preauthhcxservice.json + hash: sha256:2e8c594c51d9640ae4a576be34a5d190614918d1e7697d6718bc91c31fa66948 + fetched: '2026-09-14' + note: 'API specification: preauthhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/preauth/submit.' +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sections 4.1 and 8.6. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Value sets (Use case) and sheet Status. +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use case 9 Respond to the Preauthorization Submitted. +- url: https://hcxsbx.abdm.gov.in/images/3799f26f2a0b2c9a80c5.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Preauthorization.pdf + hash: sha256:75d5628e7dd8a8e1a55c4ab3836c0591088ba378a8cd498e8277d83911129439 + fetched: '2026-09-14' + note: Preauthorization, listed on https://hcxsbx.abdm.gov.in/#/documents, not named in the NHCX document sheet. page 2, items 5-6. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Message Structure, Status Description. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Q14 and Q21 (Not getting call back). +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. items 4, 7 and 8. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.preauth-on-submit + - nhcx.endpoint.participant-update + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.task-submit + - nhcx.callback.error + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.payer-process-a-request + - nhcx.flow.receive-a-sealed-callback + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.preauth-enhancement + - nhcx.fhir.query-update + - nhcx.fhir.preauth-response + - nhcx.fhir.validation + tests: + - nhcx.test.payer-uc-09 + - nhcx.test.tc-pa-01 + - nhcx.test.tc-pa-02 + errors: + - nhcx.error.nhcx-1001 + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1015 + - nhcx.error.nhcx-1016 + - nhcx.error.payr-1001 + concepts: + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.retries-and-expiry + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.participant-registry + - nhcx.concept.encryption-certificate + - nhcx.concept.four-message-legs + - nhcx.concept.claim-cycle + - nhcx.concept.workflow-codes + troubleshooting: + - nhcx.troubleshooting.callback-url-rejected + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.recipient-cannot-decrypt + sandbox: + - nhcx.sandbox.callback-url-requirements + decisions: + - nhcx.decision.key-encryption-algorithm + glossary: + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - nhcx.glossary.api-call-id + - nhcx.glossary.protected-header + - nhcx.glossary.participant-code + - nhcx.glossary.payer + - nhcx.glossary.provider + - nhcx.glossary.preauthorisation + - nhcx.glossary.enhancement + - shared.glossary.fhir + - shared.glossary.abha + - shared.glossary.nrces +--- + +# Receiving POST /v1/preauth/submit + +## In plain words + +Before planned treatment, a [provider](../glossary/provider.md) asks you to authorise the cost. [NHCX](../../shared/glossary/nhcx.md) delivers the request to your system as `POST /v1/preauth/submit`. You receive it as the [payer](../glossary/payer.md), or as the entity that processes the policy. The same path carries an enhancement, a resubmission and the provider's answer to your query. Acknowledge each delivery within 30 seconds. Then adjudicate and answer on [`/v1/preauth/on_submit`](../endpoints/preauth-on-submit.md). + +## Before you start + +**Who receives it:** the payer, as the system that processes the request for the policy. **Who sends it:** a provider, through NHCX. + +- Your participant record in the [participant registry](../concepts/participant-registry.md) holds an `endpoint_url`. [NHCX](../../shared/glossary/nhcx.md) posts to that address with `/v1/preauth/submit` appended. +- You set `endpoint_url` when you register, in [sandbox onboarding](../flows/sandbox-onboarding.md). You change it with [`/participant/update`](../endpoints/participant-update.md). +- The URL uses a domain name over HTTPS. It has no IP address and no port number. +- The server behind it is in India. Your firewall accepts calls from the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). +- Your handler can open a [JWE](../glossary/jwe.md) with your private key. That key pairs with the certificate in your registry record. See [your encryption certificate](../concepts/encryption-certificate.md). +- Your handler answers within 30 seconds and does slow work afterwards. See [the 202 acknowledgement](../concepts/synchronous-acknowledgement.md). +- Your system can call [`/v1/preauth/on_submit`](../endpoints/preauth-on-submit.md) to answer. +- You also host [`/v1/error`](error.md), so a request that dies is never silent. + +## What happens + +```mermaid +sequenceDiagram + participant S as Provider system + participant N as NHCX gateway + participant Y as Your payer system + S->>N: POST /v1/preauth/submit (sealed) + N-->>S: 202 Accepted + N->>Y: POST /v1/preauth/submit (same sealed message) + Y-->>N: 202 Accepted with receipt, within 30 seconds + Note over Y: Decrypt, validate, process + Y->>N: POST /v1/preauth/on_submit (your answer) + N->>S: POST /v1/preauth/on_submit +``` + +### What arrives + +[NHCX](../../shared/glossary/nhcx.md) sends `POST /v1/preauth/submit`. The JSON body carries one field, `payload`: + +```json +{ + "payload": "" +} +``` + +The payload is a JWE in compact form: five base64url parts joined by dots. Decode the first part to read the protected header. You do not need your private key for that step. + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-request_id": "", + "x-hcx-correlation_id": "", + "x-hcx-workflow_id": "12", + "x-hcx-timestamp": "", + "x-hcx-status": "request.initiated", + "x-hcx-ben-abha-id": "", + "x-hcx-use_case": "New" +} +``` + +| Protected header | What it tells you | +|---|---| +| `x-hcx-sender_code` | The provider that sent it. Your answer goes back to this code. | +| `x-hcx-recipient_code` | Your participant code. | +| `x-hcx-api_call_id` | This one message. A repeat delivery carries the same value. | +| `x-hcx-request_id` | The originating request. Read it when present. | +| `x-hcx-correlation_id` | The whole exchange. Copy it into your answer. | +| `x-hcx-workflow_id` | The business step. Read it when present. See [workflow codes](../concepts/workflow-codes.md). | +| `x-hcx-timestamp` | When the sender sealed the message. | +| `x-hcx-status` | `request.initiated` for a new request. Accept `request.initiate` as the same value. | +| `x-hcx-ben-abha-id` | The beneficiary's [ABHA](../../shared/glossary/abha.md) number. Accept it with or without hyphens. | +| `x-hcx-use_case` | `New`, `Enhancement` or `Resubmit`. Optional. | + +Decrypt the payload with your private key. Use the algorithm the header names in `alg`. [RSA-OAEP or RSA-OAEP-256](../decisions/key-encryption-algorithm.md) covers both values. The plaintext is a [FHIR](../../shared/glossary/fhir.md) collection bundle with a Claim whose `use` is `preauthorization`. See [the preauthorisation request bundle](../fhir/preauth-request.md) and [enhancement bundles](../fhir/preauth-enhancement.md). Validate it against the [NRCeS](../../shared/glossary/nrces.md) profiles before you adjudicate; see [validating a bundle](../fhir/validation.md). + +The workflow code says what the provider sends: + +| `x-hcx-workflow_id` | What the provider sends | +|---|---| +| `12` | A new preauthorisation | +| `121` | A resubmission after a query or rejection | +| `13` | An enhancement: a request for more amount | +| `19` | An answer to your query on a preauthorisation | +| `131` | An answer to your query on an enhancement | + +A cancellation does not come here. It arrives as a task on [`/v1/task/submit`](task-submit.md). + +### What you send back + +Answer the delivery first, before you decrypt or act on it. Return HTTP status `202 Accepted` with this receipt: + +```json +{ + "timestamp": "", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "preauth", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `api_call_id` and `correlation_id` repeat the values in this delivery. +- `result.sender_code` is the sender's code. `result.recipient_code` is yours. +- `result.entity_type` is `preauth` for this exchange. +- `result.protocol_status` is one of `request.queued`, `request.dispatched` or `request.error`. +- `error.code` and `error.message` stay empty when you accept the message. +- `timestamp` takes the form `DD/MM/YYYY hh:mm:ss:sss`. + +### Retries and repeat deliveries + +- NHCX waits 30 seconds for your 202 and receipt. +- A late answer, another status code or a receipt in another shape counts as a failed delivery. NHCX sends the same message again. +- After 5 attempts NHCX stops. It deletes the request and retires its correlation id. The original sender learns of it on its own `/v1/error`. +- A repeat delivery is the same sealed message, so it carries the same `x-hcx-api_call_id`. Record every `x-hcx-api_call_id` you accept. +- On a repeat, return 202 with the same receipt and do not process the message again. +- Never deduplicate on `x-hcx-correlation_id`. Every message in one exchange shares it. + +### What you do next + +Process the message, then answer on [`/v1/preauth/on_submit`](../endpoints/preauth-on-submit.md): + +- Copy `x-hcx-correlation_id` from this message. +- Give your answer its own fresh `x-hcx-api_call_id`. +- Send it to the sender: its `x-hcx-sender_code` becomes your `x-hcx-recipient_code`. +- Set `x-hcx-status` to `response.partial` for an interim answer, such as received. Use `response.complete` for the decision. +- Seal a ClaimResponse bundle to the provider's certificate. See [the preauthorisation response bundle](../fhir/preauth-response.md). +- If you cannot decrypt or validate this message, answer with a protocol response instead. Set `type` to `ProtocolResponse`, `x-hcx-status` to `response.error`, and fill `x-hcx-error_details`. + +## How you know it worked + +- NHCX receives your HTTP 202 and receipt within 30 seconds of the delivery. +- Your log shows one delivery per `x-hcx-api_call_id`. A second delivery with the same value means NHCX did not accept your receipt. +- You decrypted the payload and hold a Claim bundle with `Claim.use` `preauthorization`, stored against its `x-hcx-correlation_id`. +- Your answer on `/v1/preauth/on_submit` gets its own 202 from NHCX. No NHCX error names its correlation id. + +## When it goes wrong + +- **It never arrives.** Check these in order. + 1. The `endpoint_url` in your registry record is the address you expect. + 2. It uses a domain name, with no IP address and no port number. + 3. Your server is in India, and your firewall accepts the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). + 4. Your application routes the path to the handler: load balancer rules, service routes and endpoint versions. + 5. The provider addressed the message to your participant code. Providers address the processor code from their policy lookup, so check that code is yours. + When NHCX cannot reach you, the sender is told [NHCX-1001](../errors/nhcx-1001.md), "Receiver system is not reachable." See [your callback URL is rejected or never called](../troubleshooting/callback-url-rejected.md). +- **The same message arrives again and again.** NHCX did not accept your receipt. It was later than 30 seconds, used another status code, or had another shape. Fix the receipt, and keep processing each `x-hcx-api_call_id` once. An invalid answer from a receiver is reported as [NHCX-1015](../errors/nhcx-1015.md), "Invalid response received from receiver." +- **You cannot decrypt it.** The sender sealed it to an old certificate, or your registry certificate does not match your private key. Still return 202 with the receipt. Then answer on `/v1/preauth/on_submit` with a protocol response. [PAYR-1001](../errors/payr-1001.md) names a decryption failure. See [the recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). +- **Your answer is refused.** [NHCX-1010](../errors/nhcx-1010.md) means NHCX holds no exchange with that correlation id. [NHCX-1016](../errors/nhcx-1016.md) means the action does not fit that correlation id. [NHCX-1011](../errors/nhcx-1011.md) means the `x-hcx-status` value is invalid. Copy the correlation id from this message, answer on the paired path, and use a documented status. See [responses arrive against the wrong request](../troubleshooting/duplicate-or-mismatched-correlation.md). +- **The request fails your business rules.** That is not a protocol error. Answer with a sealed ClaimResponse that carries the decision and the reason. Keep protocol responses for messages you cannot open or validate. diff --git a/catalogue/nhcx/callbacks/predetermination-on-submit.md b/catalogue/nhcx/callbacks/predetermination-on-submit.md new file mode 100644 index 000000000..da05598fb --- /dev/null +++ b/catalogue/nhcx/callbacks/predetermination-on-submit.md @@ -0,0 +1,280 @@ +--- +id: nhcx.callback.predetermination-on-submit +type: callback +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Receiving POST /v1/predetermination/on_submit +summary: >- + What your hospital system receives when the payer returns an estimate for a proposed + treatment, and how to acknowledge and read it. +sources: +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. API Structure, use case table. +- url: https://hcxsbx.abdm.gov.in/images/2c3fbb4e6b09f0834f69.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Implementation Guide for Adoption of FHIR in ABDM and NHCX.pdf + hash: sha256:549377c9c26b1bd23decac3a1b9e5ebedfdc8e0fe99e53ef733859b188f51366 + fetched: '2026-09-14' + note: Implementation Guide for Adoption of FHIR in ABDM and NHCX, row 14 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 21, Annexure. +- url: https://hcxsbx.abdm.gov.in/images/bc1e7d077857fc0fa071.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-NHCX USECASE Postman Collection.zip + hash: sha256:9d15daafa813d6d57e688fe800baa5a73d2540b8d0d12c6a1315f86a424817e4 + fetched: '2026-09-14' + note: AWS(Sandbox)-NHCX USECASE Postman Collection, row 17 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. request /v1/predetermination/on_submit. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Q14 and Q21 (Not getting call back). +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item 8. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.predetermination-on-submit + - nhcx.endpoint.predetermination-submit + - nhcx.endpoint.status + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.participant-update + callbacks: + - nhcx.callback.predetermination-submit + - nhcx.callback.on-status + - nhcx.callback.error + flows: + - nhcx.flow.predetermination + - nhcx.flow.status-check + - nhcx.flow.receive-a-sealed-callback + fhir: + - nhcx.fhir.preauth-response + - nhcx.fhir.collection-bundle + errors: + - nhcx.error.nhcx-1001 + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1015 + - nhcx.error.payr-1001 + - nhcx.error.payr-1002 + concepts: + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.retries-and-expiry + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.participant-registry + - nhcx.concept.encryption-certificate + - nhcx.concept.four-message-legs + - nhcx.concept.status-lifecycle + troubleshooting: + - nhcx.troubleshooting.callback-url-rejected + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.accepted-then-no-callback + sandbox: + - nhcx.sandbox.callback-url-requirements + decisions: + - nhcx.decision.key-encryption-algorithm + - nhcx.decision.preauth-or-predetermination + - nhcx.decision.status-poll-or-wait + glossary: + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - nhcx.glossary.api-call-id + - nhcx.glossary.protected-header + - nhcx.glossary.participant-code + - nhcx.glossary.payer + - nhcx.glossary.provider + - nhcx.glossary.predetermination + - shared.glossary.fhir + - shared.glossary.abha +--- + +# Receiving POST /v1/predetermination/on_submit + +## In plain words + +After you send a predetermination request, the [payer](../glossary/payer.md) answers through [NHCX](../../shared/glossary/nhcx.md) with an estimate. NHCX delivers it to your system as `POST /v1/predetermination/on_submit`. You receive it as the [provider](../glossary/provider.md) that asked. It tells you what the payer would approve for the proposed treatment. Use it to decide whether to go ahead with a preauthorisation. Acknowledge it within 30 seconds. + +## Before you start + +**Who receives it:** the provider that sent `/v1/predetermination/submit`. **Who sends it:** the payer, through NHCX. + +- Your participant record in the [participant registry](../concepts/participant-registry.md) holds an `endpoint_url`. [NHCX](../../shared/glossary/nhcx.md) posts to that address with `/v1/predetermination/on_submit` appended. +- You set `endpoint_url` when you register, in [sandbox onboarding](../flows/sandbox-onboarding.md). You change it with [`/participant/update`](../endpoints/participant-update.md). +- The URL uses a domain name over HTTPS. It has no IP address and no port number. +- The server behind it is in India. Your firewall accepts calls from the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). +- Your handler can open a [JWE](../glossary/jwe.md) with your private key. That key pairs with the certificate in your registry record. See [your encryption certificate](../concepts/encryption-certificate.md). +- Your handler answers within 30 seconds and does slow work afterwards. See [the 202 acknowledgement](../concepts/synchronous-acknowledgement.md). +- You sent the request with [`/v1/predetermination/submit`](../endpoints/predetermination-submit.md). You stored its `x-hcx-api_call_id` and `x-hcx-correlation_id` before sending it. +- You also host [`/v1/error`](error.md), so a request that dies is never silent. + +## What happens + +```mermaid +sequenceDiagram + participant Y as Your provider system + participant N as NHCX gateway + participant O as Payer system + Y->>N: POST /v1/predetermination/submit + N-->>Y: 202 Accepted + N->>O: POST /v1/predetermination/submit + O->>N: POST /v1/predetermination/on_submit (sealed answer) + N->>Y: POST /v1/predetermination/on_submit + Y-->>N: 202 Accepted with receipt, within 30 seconds +``` + +### What arrives + +[NHCX](../../shared/glossary/nhcx.md) sends `POST /v1/predetermination/on_submit`. The body takes one of two forms. Branch on its `type` field. + +- `ProtocolResponse`: the payer could not process your request. The body is plain JSON with the error details, and nothing is sealed. +- Any other body carries the payer's answer sealed in `payload`, with `type` set to `JWEPayload`. + +```json +{ + "type": "JWEPayload", + "payload": "" +} +``` + +The payload is a JWE in compact form: five base64url parts joined by dots. Decode the first part to read the protected header. You do not need your private key for that step. + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-correlation_id": "", + "x-hcx-timestamp": "", + "x-hcx-status": "response.complete", + "x-hcx-ben-abha-id": "" +} +``` + +| Protected header | What it tells you | +|---|---| +| `x-hcx-sender_code` | The payer that answered. | +| `x-hcx-recipient_code` | Your participant code. | +| `x-hcx-api_call_id` | This one message. Each answer has its own value. A repeat delivery carries the same value. | +| `x-hcx-correlation_id` | The exchange you started. Match it to the request you stored. | +| `x-hcx-workflow_id` | The step the answer reports. Read it when present. See [workflow codes](../concepts/workflow-codes.md). | +| `x-hcx-status` | Where the exchange stands. See the status list below. | +| `x-hcx-error_details` | An object with `code`, `message` and `trace` when something failed. | +| `x-hcx-ben-abha-id` | The beneficiary's [ABHA](../../shared/glossary/abha.md) number. Accept it with or without hyphens. | + +Look up `x-hcx-correlation_id` against the correlation ids you sent. If nothing matches, look it up against the `x-hcx-api_call_id` values you sent. + +`x-hcx-status` takes these values: + +- `response.partial`: an interim answer, such as received or in process. More follows on the same correlation id. +- `response.complete`: the final answer. The case is closed on this exchange. +- `response.error`: the request failed on protocol grounds. Treat `response.fail` the same way. + +Decrypt the payload with your private key. Use the algorithm the header names in `alg`. [RSA-OAEP or RSA-OAEP-256](../decisions/key-encryption-algorithm.md) covers both values. The plaintext is a [FHIR](../../shared/glossary/fhir.md) collection bundle with a ClaimResponse whose `use` is `predetermination`. It carries the benefit the payer would approve. + +#### When `type` is `ProtocolResponse` + +The body is plain JSON. Read `x-hcx-error_details` for the reason. + +```json +{ + "type": "ProtocolResponse", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-correlation_id": "", + "x-hcx-workflow_id": "", + "x-hcx-timestamp": "", + "x-hcx-debug_flag": "Error", + "x-hcx-status": "response.error", + "x-hcx-redirect_to": "", + "x-hcx-error_details": { + "code": "", + "message": "", + "trace": "" + }, + "x-hcx-debug_details": { + "code": "", + "message": "", + "trace": "" + }, + "x-hcx-domain-header": { + "use_case_name": "", + "amt_processed": "" + }, + "x-hcx-entity-type": "", + "x-hcx-ben-abha-id": "" +} +``` + +### What you send back + +Answer the delivery first, before you decrypt or act on it. Return HTTP status `202 Accepted` with this receipt: + +```json +{ + "timestamp": "", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `api_call_id` and `correlation_id` repeat the values in this delivery. +- `result.sender_code` is the sender's code. `result.recipient_code` is yours. +- An `entity_type` value for this exchange is not yet published. The published values are `coverageeligibility`, `preauth`, `claim`, `task`, `payment` and `insuranceplan`. +- `result.protocol_status` is one of `request.queued`, `request.dispatched` or `request.error`. +- `error.code` and `error.message` stay empty when you accept the message. +- `timestamp` takes the form `DD/MM/YYYY hh:mm:ss:sss`. + +### Retries and repeat deliveries + +- NHCX waits 30 seconds for your 202 and receipt. +- A late answer, another status code or a receipt in another shape counts as a failed delivery. NHCX sends the same message again. +- After 5 attempts NHCX stops. It deletes the request and retires its correlation id. The original sender learns of it on its own `/v1/error`. +- A repeat delivery is the same sealed message, so it carries the same `x-hcx-api_call_id`. Record every `x-hcx-api_call_id` you accept. +- On a repeat, return 202 with the same receipt and do not process the message again. +- Never deduplicate on `x-hcx-correlation_id`. Every message in one exchange shares it. +- An interim answer and a final answer share `x-hcx-correlation_id`. They differ in `x-hcx-api_call_id`. + +## How you know it worked + +- NHCX receives your HTTP 202 and receipt within 30 seconds of the delivery. +- Your log shows one delivery per `x-hcx-api_call_id`. A second delivery with the same value means NHCX did not accept your receipt. +- The `x-hcx-correlation_id` matches a request you sent. +- You hold the payer's estimate, stored against the request, ready for the preauthorisation decision. + +## When it goes wrong + +- **It never arrives.** Check these in order. + 1. Your `/v1/predetermination/submit` call got a 202 from NHCX. Without it, NHCX never forwarded the request. + 2. Your `/v1/error` endpoint holds no report for this correlation id. A report means the payer never received your request. + 3. The `endpoint_url` in your registry record is right. It uses a domain name, with no IP address and no port number. + 4. Your server is in India, and your firewall accepts the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). + 5. Your application routes the path to the handler: load balancer rules, service routes and endpoint versions. + 6. Ask NHCX with [`/v1/status`](../endpoints/status.md). `request.dispatched` means the payer has your request, so wait. `request.stopped` means it is dead. + If the payer cannot seal its answer to your certificate, it reports [PAYR-1002](../errors/payr-1002.md). Update the certificate in your registry record. See [accepted with 202 and no callback arrives](../troubleshooting/accepted-then-no-callback.md). +- **It arrives as a `ProtocolResponse`.** The payer could not open or validate your request. Read `x-hcx-error_details.code` and open its error atom. [PAYR-1001](../errors/payr-1001.md) means your payload could not be decrypted: fetch the recipient's certificate again with [`/fetch/certs`](../endpoints/fetch-certs.md). The correlation id of a failed request is inactive. Send a fresh request with a new correlation id; reusing the old one is refused as [NHCX-1006](../errors/nhcx-1006.md). +- **The same message arrives again and again.** NHCX did not accept your receipt. It was later than 30 seconds, used another status code, or had another shape. Fix the receipt, and keep processing each `x-hcx-api_call_id` once. An invalid answer from a receiver is reported as [NHCX-1015](../errors/nhcx-1015.md), "Invalid response received from receiver." +- **The correlation id matches nothing you sent.** You stored the ids after sending instead of before, or you looked in one field only. Look up `x-hcx-correlation_id` against the correlation ids you sent. If nothing matches, look it up against the `x-hcx-api_call_id` values you sent. See [responses arrive against the wrong request](../troubleshooting/duplicate-or-mismatched-correlation.md). diff --git a/catalogue/nhcx/callbacks/predetermination-submit.md b/catalogue/nhcx/callbacks/predetermination-submit.md new file mode 100644 index 000000000..8198ab130 --- /dev/null +++ b/catalogue/nhcx/callbacks/predetermination-submit.md @@ -0,0 +1,246 @@ +--- +id: nhcx.callback.predetermination-submit +type: callback +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Receiving POST /v1/predetermination/submit +summary: >- + What your payer system receives when a hospital asks what you would approve for + a proposed treatment, and how to acknowledge it. +sources: +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. API Structure, use case table. +- url: https://hcxsbx.abdm.gov.in/images/af8d243edcc2139a515d.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Usecases.pdf + hash: sha256:8709b2907a0d5a0dbb36f5e63ed8deae269e0c75372b05d71ce7380c8a0929e7 + fetched: '2026-09-14' + note: NHCX Usecases, row 1 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Table 1.1, Predetermination Request Submission. +- url: https://hcxsbx.abdm.gov.in/images/2c3fbb4e6b09f0834f69.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Implementation Guide for Adoption of FHIR in ABDM and NHCX.pdf + hash: sha256:549377c9c26b1bd23decac3a1b9e5ebedfdc8e0fe99e53ef733859b188f51366 + fetched: '2026-09-14' + note: Implementation Guide for Adoption of FHIR in ABDM and NHCX, row 14 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 21, Annexure. +- url: https://hcxsbx.abdm.gov.in/images/bc1e7d077857fc0fa071.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-NHCX USECASE Postman Collection.zip + hash: sha256:9d15daafa813d6d57e688fe800baa5a73d2540b8d0d12c6a1315f86a424817e4 + fetched: '2026-09-14' + note: AWS(Sandbox)-NHCX USECASE Postman Collection, row 17 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. request /v1/predetermination/submit. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Q14 and Q21 (Not getting call back). +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. items 4, 7 and 8. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.predetermination-submit + - nhcx.endpoint.predetermination-on-submit + - nhcx.endpoint.participant-update + callbacks: + - nhcx.callback.predetermination-on-submit + - nhcx.callback.error + flows: + - nhcx.flow.predetermination + - nhcx.flow.payer-process-a-request + - nhcx.flow.receive-a-sealed-callback + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.collection-bundle + errors: + - nhcx.error.nhcx-1001 + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1015 + - nhcx.error.nhcx-1016 + - nhcx.error.payr-1001 + concepts: + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.retries-and-expiry + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.participant-registry + - nhcx.concept.encryption-certificate + - nhcx.concept.four-message-legs + troubleshooting: + - nhcx.troubleshooting.callback-url-rejected + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.recipient-cannot-decrypt + sandbox: + - nhcx.sandbox.callback-url-requirements + decisions: + - nhcx.decision.key-encryption-algorithm + - nhcx.decision.preauth-or-predetermination + glossary: + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - nhcx.glossary.api-call-id + - nhcx.glossary.protected-header + - nhcx.glossary.participant-code + - nhcx.glossary.payer + - nhcx.glossary.provider + - nhcx.glossary.predetermination + - shared.glossary.fhir + - shared.glossary.abha +--- + +# Receiving POST /v1/predetermination/submit + +## In plain words + +A [provider](../glossary/provider.md) can ask what you would approve for a proposed treatment, before it commits to a preauthorisation. [NHCX](../../shared/glossary/nhcx.md) delivers that request to your system as `POST /v1/predetermination/submit`. You receive it as the [payer](../glossary/payer.md). Acknowledge the delivery within 30 seconds. Then answer on [`/v1/predetermination/on_submit`](../endpoints/predetermination-on-submit.md) with your estimate. + +## Before you start + +**Who receives it:** the payer, as the system that processes the request for the policy. **Who sends it:** a provider, through NHCX. + +- Your participant record in the [participant registry](../concepts/participant-registry.md) holds an `endpoint_url`. [NHCX](../../shared/glossary/nhcx.md) posts to that address with `/v1/predetermination/submit` appended. +- You set `endpoint_url` when you register, in [sandbox onboarding](../flows/sandbox-onboarding.md). You change it with [`/participant/update`](../endpoints/participant-update.md). +- The URL uses a domain name over HTTPS. It has no IP address and no port number. +- The server behind it is in India. Your firewall accepts calls from the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). +- Your handler can open a [JWE](../glossary/jwe.md) with your private key. That key pairs with the certificate in your registry record. See [your encryption certificate](../concepts/encryption-certificate.md). +- Your handler answers within 30 seconds and does slow work afterwards. See [the 202 acknowledgement](../concepts/synchronous-acknowledgement.md). +- Your system can call [`/v1/predetermination/on_submit`](../endpoints/predetermination-on-submit.md) to answer. +- You also host [`/v1/error`](error.md), so a request that dies is never silent. + +## What happens + +```mermaid +sequenceDiagram + participant S as Provider system + participant N as NHCX gateway + participant Y as Your payer system + S->>N: POST /v1/predetermination/submit (sealed) + N-->>S: 202 Accepted + N->>Y: POST /v1/predetermination/submit (same sealed message) + Y-->>N: 202 Accepted with receipt, within 30 seconds + Note over Y: Decrypt, validate, process + Y->>N: POST /v1/predetermination/on_submit (your answer) + N->>S: POST /v1/predetermination/on_submit +``` + +### What arrives + +[NHCX](../../shared/glossary/nhcx.md) sends `POST /v1/predetermination/submit`. The JSON body carries one field, `payload`: + +```json +{ + "payload": "" +} +``` + +The payload is a JWE in compact form: five base64url parts joined by dots. Decode the first part to read the protected header. You do not need your private key for that step. + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-request_id": "", + "x-hcx-correlation_id": "", + "x-hcx-timestamp": "", + "x-hcx-status": "request.initiated", + "x-hcx-ben-abha-id": "" +} +``` + +| Protected header | What it tells you | +|---|---| +| `x-hcx-sender_code` | The provider that sent it. Your answer goes back to this code. | +| `x-hcx-recipient_code` | Your participant code. | +| `x-hcx-api_call_id` | This one message. A repeat delivery carries the same value. | +| `x-hcx-request_id` | The originating request. Read it when present. | +| `x-hcx-correlation_id` | The whole exchange. Copy it into your answer. | +| `x-hcx-workflow_id` | The business step. Read it when present. See [workflow codes](../concepts/workflow-codes.md). | +| `x-hcx-timestamp` | When the sender sealed the message. | +| `x-hcx-status` | `request.initiated` for a new request. Accept `request.initiate` as the same value. | +| `x-hcx-ben-abha-id` | The beneficiary's [ABHA](../../shared/glossary/abha.md) number. Accept it with or without hyphens. | + +Decrypt the payload with your private key. Use the algorithm the header names in `alg`. [RSA-OAEP or RSA-OAEP-256](../decisions/key-encryption-algorithm.md) covers both values. The plaintext is a [FHIR](../../shared/glossary/fhir.md) collection bundle with the shape of a preauthorisation request. Its Claim has `use` `predetermination`. See [the preauthorisation request bundle](../fhir/preauth-request.md). + +### What you send back + +Answer the delivery first, before you decrypt or act on it. Return HTTP status `202 Accepted` with this receipt: + +```json +{ + "timestamp": "", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `api_call_id` and `correlation_id` repeat the values in this delivery. +- `result.sender_code` is the sender's code. `result.recipient_code` is yours. +- An `entity_type` value for this exchange is not yet published. The published values are `coverageeligibility`, `preauth`, `claim`, `task`, `payment` and `insuranceplan`. +- `result.protocol_status` is one of `request.queued`, `request.dispatched` or `request.error`. +- `error.code` and `error.message` stay empty when you accept the message. +- `timestamp` takes the form `DD/MM/YYYY hh:mm:ss:sss`. + +### Retries and repeat deliveries + +- NHCX waits 30 seconds for your 202 and receipt. +- A late answer, another status code or a receipt in another shape counts as a failed delivery. NHCX sends the same message again. +- After 5 attempts NHCX stops. It deletes the request and retires its correlation id. The original sender learns of it on its own `/v1/error`. +- A repeat delivery is the same sealed message, so it carries the same `x-hcx-api_call_id`. Record every `x-hcx-api_call_id` you accept. +- On a repeat, return 202 with the same receipt and do not process the message again. +- Never deduplicate on `x-hcx-correlation_id`. Every message in one exchange shares it. + +### What you do next + +Process the message, then answer on [`/v1/predetermination/on_submit`](../endpoints/predetermination-on-submit.md): + +- Copy `x-hcx-correlation_id` from this message. +- Give your answer its own fresh `x-hcx-api_call_id`. +- Send it to the sender: its `x-hcx-sender_code` becomes your `x-hcx-recipient_code`. +- Set `x-hcx-status` to `response.complete` for your estimate. +- Seal a ClaimResponse with `use` `predetermination`, carrying the benefit you would approve. Base it on the policy and the beneficiary's past history. +- If you cannot decrypt or validate this message, answer with a protocol response instead. Set `type` to `ProtocolResponse`, `x-hcx-status` to `response.error`, and fill `x-hcx-error_details`. + +## How you know it worked + +- NHCX receives your HTTP 202 and receipt within 30 seconds of the delivery. +- Your log shows one delivery per `x-hcx-api_call_id`. A second delivery with the same value means NHCX did not accept your receipt. +- You decrypted the payload and hold a Claim with `use` `predetermination`, stored against its `x-hcx-correlation_id`. +- Your estimate on `/v1/predetermination/on_submit` gets its own 202 from NHCX. + +## When it goes wrong + +- **It never arrives.** Check these in order. + 1. The `endpoint_url` in your registry record is the address you expect. + 2. It uses a domain name, with no IP address and no port number. + 3. Your server is in India, and your firewall accepts the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). + 4. Your application routes the path to the handler: load balancer rules, service routes and endpoint versions. + 5. The provider addressed the message to your participant code. Providers address the processor code from their policy lookup, so check that code is yours. + When NHCX cannot reach you, the sender is told [NHCX-1001](../errors/nhcx-1001.md), "Receiver system is not reachable." See [your callback URL is rejected or never called](../troubleshooting/callback-url-rejected.md). +- **The same message arrives again and again.** NHCX did not accept your receipt. It was later than 30 seconds, used another status code, or had another shape. Fix the receipt, and keep processing each `x-hcx-api_call_id` once. An invalid answer from a receiver is reported as [NHCX-1015](../errors/nhcx-1015.md), "Invalid response received from receiver." +- **You cannot decrypt it.** The sender sealed it to an old certificate, or your registry certificate does not match your private key. Still return 202 with the receipt. Then answer on `/v1/predetermination/on_submit` with a protocol response. [PAYR-1001](../errors/payr-1001.md) names a decryption failure. See [the recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). +- **Your answer is refused.** [NHCX-1010](../errors/nhcx-1010.md) means NHCX holds no exchange with that correlation id. [NHCX-1016](../errors/nhcx-1016.md) means the action does not fit that correlation id. [NHCX-1011](../errors/nhcx-1011.md) means the `x-hcx-status` value is invalid. Copy the correlation id from this message, answer on the paired path, and use a documented status. See [responses arrive against the wrong request](../troubleshooting/duplicate-or-mismatched-correlation.md). diff --git a/catalogue/nhcx/callbacks/search-on-submit.md b/catalogue/nhcx/callbacks/search-on-submit.md new file mode 100644 index 000000000..8bdb0a51d --- /dev/null +++ b/catalogue/nhcx/callbacks/search-on-submit.md @@ -0,0 +1,285 @@ +--- +id: nhcx.callback.search-on-submit +type: callback +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Receiving POST /v1/search/on_submit +summary: >- + What your system receives when a payer returns the claim information you searched + for, and how to acknowledge and read it. +sources: +- url: https://hcxsbx.abdm.gov.in/searchhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/searchhcxservice.json + hash: sha256:21749dd2ba84a19c5523772da359d76293493d44b48651f1af2e6042d78fa296 + fetched: '2026-09-14' + note: 'API specification: searchhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/search/on_submit.' +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Search, /v1/search/on_submit. +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use case 10 Claim Search. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Message Structure, Status Description. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Q14 and Q21 (Not getting call back). +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item 8. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.search-on-submit + - nhcx.endpoint.search-submit + - nhcx.endpoint.status + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.participant-update + callbacks: + - nhcx.callback.search-submit + - nhcx.callback.on-status + - nhcx.callback.error + flows: + - nhcx.flow.claim-search + - nhcx.flow.status-check + - nhcx.flow.receive-a-sealed-callback + fhir: + - nhcx.fhir.task + - nhcx.fhir.claim-response + tests: + - nhcx.test.provider-uc-10 + errors: + - nhcx.error.nhcx-1001 + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1015 + - nhcx.error.payr-1001 + - nhcx.error.payr-1002 + concepts: + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.retries-and-expiry + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.participant-registry + - nhcx.concept.encryption-certificate + - nhcx.concept.four-message-legs + - nhcx.concept.status-lifecycle + troubleshooting: + - nhcx.troubleshooting.callback-url-rejected + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.accepted-then-no-callback + sandbox: + - nhcx.sandbox.callback-url-requirements + decisions: + - nhcx.decision.key-encryption-algorithm + - nhcx.decision.status-poll-or-wait + glossary: + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - nhcx.glossary.api-call-id + - nhcx.glossary.protected-header + - nhcx.glossary.participant-code + - nhcx.glossary.payer + - nhcx.glossary.provider + - shared.glossary.fhir + - shared.glossary.abha +--- + +# Receiving POST /v1/search/on_submit + +## In plain words + +After you search for claim information, the [payer](../glossary/payer.md) answers through [NHCX](../../shared/glossary/nhcx.md). NHCX delivers the result to your system as `POST /v1/search/on_submit`. You receive it as the participant that searched, usually a [provider](../glossary/provider.md). The result carries the claim responses that match your search. Acknowledge it within 30 seconds. + +## Before you start + +**Who receives it:** the participant, usually a provider, that sent `/v1/search/submit`. **Who sends it:** the payer, through NHCX. + +- Your participant record in the [participant registry](../concepts/participant-registry.md) holds an `endpoint_url`. [NHCX](../../shared/glossary/nhcx.md) posts to that address with `/v1/search/on_submit` appended. +- You set `endpoint_url` when you register, in [sandbox onboarding](../flows/sandbox-onboarding.md). You change it with [`/participant/update`](../endpoints/participant-update.md). +- The URL uses a domain name over HTTPS. It has no IP address and no port number. +- The server behind it is in India. Your firewall accepts calls from the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). +- Your handler can open a [JWE](../glossary/jwe.md) with your private key. That key pairs with the certificate in your registry record. See [your encryption certificate](../concepts/encryption-certificate.md). +- Your handler answers within 30 seconds and does slow work afterwards. See [the 202 acknowledgement](../concepts/synchronous-acknowledgement.md). +- You sent the request with [`/v1/search/submit`](../endpoints/search-submit.md). You stored its `x-hcx-api_call_id` and `x-hcx-correlation_id` before sending it. +- You also host [`/v1/error`](error.md), so a request that dies is never silent. + +## What happens + +```mermaid +sequenceDiagram + participant Y as Your system + participant N as NHCX gateway + participant O as Payer system + Y->>N: POST /v1/search/submit + N-->>Y: 202 Accepted + N->>O: POST /v1/search/submit + O->>N: POST /v1/search/on_submit (sealed answer) + N->>Y: POST /v1/search/on_submit + Y-->>N: 202 Accepted with receipt, within 30 seconds +``` + +### What arrives + +[NHCX](../../shared/glossary/nhcx.md) sends `POST /v1/search/on_submit`. The body takes one of two forms. Branch on its `type` field. + +- `ProtocolResponse`: the payer could not process your request. The body is plain JSON with the error details, and nothing is sealed. +- Any other body carries the payer's answer sealed in `payload`, with `type` set to `JWEPayload`. + +```json +{ + "type": "JWEPayload", + "payload": "" +} +``` + +The payload is a JWE in compact form: five base64url parts joined by dots. Decode the first part to read the protected header. You do not need your private key for that step. + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-correlation_id": "", + "x-hcx-timestamp": "", + "x-hcx-status": "response.complete", + "x-hcx-ben-abha-id": "" +} +``` + +| Protected header | What it tells you | +|---|---| +| `x-hcx-sender_code` | The payer that answered. | +| `x-hcx-recipient_code` | Your participant code. | +| `x-hcx-api_call_id` | This one message. Each answer has its own value. A repeat delivery carries the same value. | +| `x-hcx-correlation_id` | The exchange you started. Match it to the request you stored. | +| `x-hcx-workflow_id` | The step the answer reports. Read it when present. See [workflow codes](../concepts/workflow-codes.md). | +| `x-hcx-status` | Where the exchange stands. See the status list below. | +| `x-hcx-error_details` | An object with `code`, `message` and `trace` when something failed. | +| `x-hcx-ben-abha-id` | The beneficiary's [ABHA](../../shared/glossary/abha.md) number. Accept it with or without hyphens. | + +Look up `x-hcx-correlation_id` against the correlation ids you sent. If nothing matches, look it up against the `x-hcx-api_call_id` values you sent. + +`x-hcx-status` takes these values: + +- `response.partial`: an interim answer, such as received or in process. More follows on the same correlation id. +- `response.complete`: the final answer. The case is closed on this exchange. +- `response.error`: the request failed on protocol grounds. Treat `response.fail` the same way. + +Decrypt the payload with your private key. Use the algorithm the header names in `alg`. [RSA-OAEP or RSA-OAEP-256](../decisions/key-encryption-algorithm.md) covers both values. The plaintext is a [FHIR](../../shared/glossary/fhir.md) Task bundle: see [the Task bundle](../fhir/task.md). The Task output carries the ClaimResponse resources that match your inputs. See [the claim response bundle](../fhir/claim-response.md). + +#### When `type` is `ProtocolResponse` + +The body is plain JSON. Read `x-hcx-error_details` for the reason. + +```json +{ + "type": "ProtocolResponse", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-correlation_id": "", + "x-hcx-workflow_id": "", + "x-hcx-timestamp": "", + "x-hcx-debug_flag": "Error", + "x-hcx-status": "response.error", + "x-hcx-redirect_to": "", + "x-hcx-error_details": { + "code": "", + "message": "", + "trace": "" + }, + "x-hcx-debug_details": { + "code": "", + "message": "", + "trace": "" + }, + "x-hcx-domain-header": { + "use_case_name": "", + "amt_processed": "" + }, + "x-hcx-entity-type": "", + "x-hcx-ben-abha-id": "" +} +``` + +### What you send back + +Answer the delivery first, before you decrypt or act on it. Return HTTP status `202 Accepted` with this receipt: + +```json +{ + "timestamp": "", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `api_call_id` and `correlation_id` repeat the values in this delivery. +- `result.sender_code` is the sender's code. `result.recipient_code` is yours. +- An `entity_type` value for this exchange is not yet published. The published values are `coverageeligibility`, `preauth`, `claim`, `task`, `payment` and `insuranceplan`. +- `result.protocol_status` is one of `request.queued`, `request.dispatched` or `request.error`. +- `error.code` and `error.message` stay empty when you accept the message. +- `timestamp` takes the form `DD/MM/YYYY hh:mm:ss:sss`. + +### Retries and repeat deliveries + +- NHCX waits 30 seconds for your 202 and receipt. +- A late answer, another status code or a receipt in another shape counts as a failed delivery. NHCX sends the same message again. +- After 5 attempts NHCX stops. It deletes the request and retires its correlation id. The original sender learns of it on its own `/v1/error`. +- A repeat delivery is the same sealed message, so it carries the same `x-hcx-api_call_id`. Record every `x-hcx-api_call_id` you accept. +- On a repeat, return 202 with the same receipt and do not process the message again. +- Never deduplicate on `x-hcx-correlation_id`. Every message in one exchange shares it. +- An interim answer and a final answer share `x-hcx-correlation_id`. They differ in `x-hcx-api_call_id`. + +## How you know it worked + +- NHCX receives your HTTP 202 and receipt within 30 seconds of the delivery. +- Your log shows one delivery per `x-hcx-api_call_id`. A second delivery with the same value means NHCX did not accept your receipt. +- The `x-hcx-correlation_id` matches a request you sent. +- You hold the matching ClaimResponse resources, stored against your search. + +## When it goes wrong + +- **It never arrives.** Check these in order. + 1. Your `/v1/search/submit` call got a 202 from NHCX. Without it, NHCX never forwarded the request. + 2. Your `/v1/error` endpoint holds no report for this correlation id. A report means the payer never received your request. + 3. The `endpoint_url` in your registry record is right. It uses a domain name, with no IP address and no port number. + 4. Your server is in India, and your firewall accepts the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). + 5. Your application routes the path to the handler: load balancer rules, service routes and endpoint versions. + 6. Ask NHCX with [`/v1/status`](../endpoints/status.md). `request.dispatched` means the payer has your request, so wait. `request.stopped` means it is dead. + If the payer cannot seal its answer to your certificate, it reports [PAYR-1002](../errors/payr-1002.md). Update the certificate in your registry record. See [accepted with 202 and no callback arrives](../troubleshooting/accepted-then-no-callback.md). +- **It arrives as a `ProtocolResponse`.** The payer could not open or validate your request. Read `x-hcx-error_details.code` and open its error atom. [PAYR-1001](../errors/payr-1001.md) means your payload could not be decrypted: fetch the recipient's certificate again with [`/fetch/certs`](../endpoints/fetch-certs.md). The correlation id of a failed request is inactive. Send a fresh request with a new correlation id; reusing the old one is refused as [NHCX-1006](../errors/nhcx-1006.md). +- **The same message arrives again and again.** NHCX did not accept your receipt. It was later than 30 seconds, used another status code, or had another shape. Fix the receipt, and keep processing each `x-hcx-api_call_id` once. An invalid answer from a receiver is reported as [NHCX-1015](../errors/nhcx-1015.md), "Invalid response received from receiver." +- **The correlation id matches nothing you sent.** You stored the ids after sending instead of before, or you looked in one field only. Look up `x-hcx-correlation_id` against the correlation ids you sent. If nothing matches, look it up against the `x-hcx-api_call_id` values you sent. See [responses arrive against the wrong request](../troubleshooting/duplicate-or-mismatched-correlation.md). diff --git a/catalogue/nhcx/callbacks/search-submit.md b/catalogue/nhcx/callbacks/search-submit.md new file mode 100644 index 000000000..4d7f59e51 --- /dev/null +++ b/catalogue/nhcx/callbacks/search-submit.md @@ -0,0 +1,254 @@ +--- +id: nhcx.callback.search-submit +type: callback +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Receiving POST /v1/search/submit +summary: >- + What your payer system receives when a hospital or an authorised body searches + for claim information, and how to acknowledge it. +sources: +- url: https://hcxsbx.abdm.gov.in/searchhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/searchhcxservice.json + hash: sha256:21749dd2ba84a19c5523772da359d76293493d44b48651f1af2e6042d78fa296 + fetched: '2026-09-14' + note: 'API specification: searchhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/search/submit.' +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Search; sheet Value sets, Task Codes. +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use case 12 Respond to search request. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Message Structure, Status Description. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Q14 and Q21 (Not getting call back). +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. items 4, 7 and 8. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.search-submit + - nhcx.endpoint.search-on-submit + - nhcx.endpoint.participant-update + callbacks: + - nhcx.callback.search-on-submit + - nhcx.callback.error + flows: + - nhcx.flow.claim-search + - nhcx.flow.payer-process-a-request + - nhcx.flow.receive-a-sealed-callback + fhir: + - nhcx.fhir.task + - nhcx.fhir.claim-response + tests: + - nhcx.test.payer-uc-12 + errors: + - nhcx.error.nhcx-1001 + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1015 + - nhcx.error.nhcx-1016 + - nhcx.error.payr-1001 + concepts: + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.retries-and-expiry + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.participant-registry + - nhcx.concept.encryption-certificate + - nhcx.concept.four-message-legs + troubleshooting: + - nhcx.troubleshooting.callback-url-rejected + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.recipient-cannot-decrypt + sandbox: + - nhcx.sandbox.callback-url-requirements + decisions: + - nhcx.decision.key-encryption-algorithm + glossary: + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - nhcx.glossary.api-call-id + - nhcx.glossary.protected-header + - nhcx.glossary.participant-code + - nhcx.glossary.payer + - nhcx.glossary.provider + - shared.glossary.nha + - shared.glossary.fhir + - shared.glossary.abha +--- + +# Receiving POST /v1/search/submit + +## In plain words + +A [provider](../glossary/provider.md), a regulator or NHA can search for claim information that a payer holds. [NHCX](../../shared/glossary/nhcx.md) delivers the search to your system as `POST /v1/search/submit`. You receive it as the [payer](../glossary/payer.md). It names the claims to look for, by claim number, policy, product or date range. Acknowledge the delivery within 30 seconds. Then answer on [`/v1/search/on_submit`](../endpoints/search-on-submit.md) with the matching claim responses. + +## Before you start + +**Who receives it:** the payer, as the system that processes the request for the policy. **Who sends it:** a provider, a regulator or NHA, through NHCX. + +- Your participant record in the [participant registry](../concepts/participant-registry.md) holds an `endpoint_url`. [NHCX](../../shared/glossary/nhcx.md) posts to that address with `/v1/search/submit` appended. +- You set `endpoint_url` when you register, in [sandbox onboarding](../flows/sandbox-onboarding.md). You change it with [`/participant/update`](../endpoints/participant-update.md). +- The URL uses a domain name over HTTPS. It has no IP address and no port number. +- The server behind it is in India. Your firewall accepts calls from the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). +- Your handler can open a [JWE](../glossary/jwe.md) with your private key. That key pairs with the certificate in your registry record. See [your encryption certificate](../concepts/encryption-certificate.md). +- Your handler answers within 30 seconds and does slow work afterwards. See [the 202 acknowledgement](../concepts/synchronous-acknowledgement.md). +- Your system can call [`/v1/search/on_submit`](../endpoints/search-on-submit.md) to answer. +- You also host [`/v1/error`](error.md), so a request that dies is never silent. + +## What happens + +```mermaid +sequenceDiagram + participant S as Searching system + participant N as NHCX gateway + participant Y as Your payer system + S->>N: POST /v1/search/submit (sealed) + N-->>S: 202 Accepted + N->>Y: POST /v1/search/submit (same sealed message) + Y-->>N: 202 Accepted with receipt, within 30 seconds + Note over Y: Decrypt, validate, process + Y->>N: POST /v1/search/on_submit (your answer) + N->>S: POST /v1/search/on_submit +``` + +### What arrives + +[NHCX](../../shared/glossary/nhcx.md) sends `POST /v1/search/submit`. The JSON body carries one field, `payload`: + +```json +{ + "payload": "" +} +``` + +The payload is a JWE in compact form: five base64url parts joined by dots. Decode the first part to read the protected header. You do not need your private key for that step. + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-request_id": "", + "x-hcx-correlation_id": "", + "x-hcx-timestamp": "", + "x-hcx-status": "request.initiated", + "x-hcx-ben-abha-id": "" +} +``` + +| Protected header | What it tells you | +|---|---| +| `x-hcx-sender_code` | The participant that searched. Your answer goes back to this code. | +| `x-hcx-recipient_code` | Your participant code. | +| `x-hcx-api_call_id` | This one message. A repeat delivery carries the same value. | +| `x-hcx-request_id` | The originating request. Read it when present. | +| `x-hcx-correlation_id` | The whole exchange. Copy it into your answer. | +| `x-hcx-workflow_id` | The business step. Read it when present. See [workflow codes](../concepts/workflow-codes.md). | +| `x-hcx-timestamp` | When the sender sealed the message. | +| `x-hcx-status` | `request.initiated` for a new request. Accept `request.initiate` as the same value. | +| `x-hcx-ben-abha-id` | The beneficiary's [ABHA](../../shared/glossary/abha.md) number. Accept it with or without hyphens. | + +Decrypt the payload with your private key. Use the algorithm the header names in `alg`. [RSA-OAEP or RSA-OAEP-256](../decisions/key-encryption-algorithm.md) covers both values. The plaintext is a [FHIR](../../shared/glossary/fhir.md) Task bundle: see [the Task bundle](../fhir/task.md). Read the Task inputs to learn what is asked. Do not refuse a search on its Task code alone; codes in use include `search`, `status` and `poll`. + +| Task input | What it narrows | +|---|---| +| `ClaimNumber` | One claim | +| `PolicyNumber` | Claims under a policy | +| `ProductNumber` | Claims under a product | +| `FromDate` and `ToDate` | Claims in a date range | + +### What you send back + +Answer the delivery first, before you decrypt or act on it. Return HTTP status `202 Accepted` with this receipt: + +```json +{ + "timestamp": "", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `api_call_id` and `correlation_id` repeat the values in this delivery. +- `result.sender_code` is the sender's code. `result.recipient_code` is yours. +- An `entity_type` value for this exchange is not yet published. The published values are `coverageeligibility`, `preauth`, `claim`, `task`, `payment` and `insuranceplan`. +- `result.protocol_status` is one of `request.queued`, `request.dispatched` or `request.error`. +- `error.code` and `error.message` stay empty when you accept the message. +- `timestamp` takes the form `DD/MM/YYYY hh:mm:ss:sss`. + +### Retries and repeat deliveries + +- NHCX waits 30 seconds for your 202 and receipt. +- A late answer, another status code or a receipt in another shape counts as a failed delivery. NHCX sends the same message again. +- After 5 attempts NHCX stops. It deletes the request and retires its correlation id. The original sender learns of it on its own `/v1/error`. +- A repeat delivery is the same sealed message, so it carries the same `x-hcx-api_call_id`. Record every `x-hcx-api_call_id` you accept. +- On a repeat, return 202 with the same receipt and do not process the message again. +- Never deduplicate on `x-hcx-correlation_id`. Every message in one exchange shares it. + +### What you do next + +Process the message, then answer on [`/v1/search/on_submit`](../endpoints/search-on-submit.md): + +- Copy `x-hcx-correlation_id` from this message. +- Give your answer its own fresh `x-hcx-api_call_id`. +- Send it to the sender: its `x-hcx-sender_code` becomes your `x-hcx-recipient_code`. +- Set `x-hcx-status` to `response.partial` for an interim answer, or `response.complete` for the final one. +- Seal a Task bundle to the sender's certificate. Its output carries the ClaimResponse resources that match the inputs. See [the claim response bundle](../fhir/claim-response.md). +- If you cannot decrypt or validate this message, answer with a protocol response instead. Set `type` to `ProtocolResponse`, `x-hcx-status` to `response.error`, and fill `x-hcx-error_details`. + +## How you know it worked + +- NHCX receives your HTTP 202 and receipt within 30 seconds of the delivery. +- Your log shows one delivery per `x-hcx-api_call_id`. A second delivery with the same value means NHCX did not accept your receipt. +- You decrypted the payload and hold the Task inputs, stored against its `x-hcx-correlation_id`. +- Your answer on `/v1/search/on_submit` gets its own 202 from NHCX. No NHCX error names its correlation id. + +## When it goes wrong + +- **It never arrives.** Check these in order. + 1. The `endpoint_url` in your registry record is the address you expect. + 2. It uses a domain name, with no IP address and no port number. + 3. Your server is in India, and your firewall accepts the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). + 4. Your application routes the path to the handler: load balancer rules, service routes and endpoint versions. + 5. The sender addressed the search to your participant code. + When NHCX cannot reach you, the sender is told [NHCX-1001](../errors/nhcx-1001.md), "Receiver system is not reachable." See [your callback URL is rejected or never called](../troubleshooting/callback-url-rejected.md). +- **The same message arrives again and again.** NHCX did not accept your receipt. It was later than 30 seconds, used another status code, or had another shape. Fix the receipt, and keep processing each `x-hcx-api_call_id` once. An invalid answer from a receiver is reported as [NHCX-1015](../errors/nhcx-1015.md), "Invalid response received from receiver." +- **You cannot decrypt it.** The sender sealed it to an old certificate, or your registry certificate does not match your private key. Still return 202 with the receipt. Then answer on `/v1/search/on_submit` with a protocol response. [PAYR-1001](../errors/payr-1001.md) names a decryption failure. See [the recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). +- **Your answer is refused.** [NHCX-1010](../errors/nhcx-1010.md) means NHCX holds no exchange with that correlation id. [NHCX-1016](../errors/nhcx-1016.md) means the action does not fit that correlation id. [NHCX-1011](../errors/nhcx-1011.md) means the `x-hcx-status` value is invalid. Copy the correlation id from this message, answer on the paired path, and use a documented status. See [responses arrive against the wrong request](../troubleshooting/duplicate-or-mismatched-correlation.md). diff --git a/catalogue/nhcx/callbacks/status.md b/catalogue/nhcx/callbacks/status.md new file mode 100644 index 000000000..ff8859bfb --- /dev/null +++ b/catalogue/nhcx/callbacks/status.md @@ -0,0 +1,156 @@ +--- +id: nhcx.callback.status +type: callback +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Receiving POST /v1/status +summary: >- + Why the claims exchange answers status questions itself, so your system never + needs to handle one, and what to do if one reaches you. +sources: +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Status, /v1/status. +- url: https://hcxsbx.abdm.gov.in/statushcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/statushcxservice.json + hash: sha256:93b6355a234ef56607427fcdfa32da4921124180c9df08ecd73c8af8955c2adf + fetched: '2026-09-14' + note: 'API specification: statushcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/status description.' +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. API Structure, Status Check rows. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Acceptance and Error scenario. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Q14. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.status + - nhcx.endpoint.on-status + callbacks: + - nhcx.callback.on-status + flows: + - nhcx.flow.status-check + tests: + - nhcx.test.provider-uc-13 + - nhcx.test.payer-uc-15 + errors: + - nhcx.error.nhcx-1012 + concepts: + - nhcx.concept.status-lifecycle + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + decisions: + - nhcx.decision.status-poll-or-wait + glossary: + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.payer + - nhcx.glossary.provider + - nhcx.glossary.api-call-id +--- + +# Receiving POST /v1/status + +## In plain words + +`/v1/status` is the question a sender asks [NHCX](../../shared/glossary/nhcx.md) about one of its own messages. NHCX answers it from its own records. It does not forward the question to a [payer](../glossary/payer.md) or a [provider](../glossary/provider.md). The answer goes back to the sender on [`/v1/on_status`](on-status.md). In normal operation, no participant receives `/v1/status`. + +## Before you start + +**Who receives it:** NHCX, which implements `/v1/status` for providers and payers alike. **Who sends it:** any participant asking about a message it sent. + +- Your registered `endpoint_url` stays as it is for every other path. You need no business logic for `/v1/status`. +- To ask about your own messages, see [`/v1/status`](../endpoints/status.md) and [receiving `/v1/on_status`](on-status.md). +- Every path under your `endpoint_url` answers a delivery within 30 seconds. See [the 202 acknowledgement](../concepts/synchronous-acknowledgement.md). + +## What happens + +```mermaid +sequenceDiagram + participant S as Sender system + participant N as NHCX gateway + S->>N: POST /v1/status + N-->>S: 202 Accepted + Note over N: Looks up the message in its own records + N->>S: POST /v1/on_status + S-->>N: 202 Accepted with receipt +``` + +### What a status request carries + +A status request is sealed as a [JWE](../glossary/jwe.md) like any other message. Its payload is an empty string. Its protected header names the message in question: + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-correlation_id": "", + "x-hcx-timestamp": "", + "x-hcx-status": "request.initiated", + "x-hcx-ben-abha-id": "" +} +``` + +`x-hcx-correlation_id` holds the `x-hcx-api_call_id` of the message the sender asks about. Everything else follows [the x-hcx protocol headers](../concepts/protocol-headers.md). + +### If one reaches your endpoint + +Answer it like any other delivery: HTTP 202 with the receipt, within 30 seconds. Take no further action. NHCX, not you, reports the status on `/v1/on_status`. + +Answer the delivery first, before you decrypt or act on it. Return HTTP status `202 Accepted` with this receipt: + +```json +{ + "timestamp": "", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `api_call_id` and `correlation_id` repeat the values in this delivery. +- `result.sender_code` is the sender's code. `result.recipient_code` is yours. +- An `entity_type` value for this exchange is not yet published. The published values are `coverageeligibility`, `preauth`, `claim`, `task`, `payment` and `insuranceplan`. +- `result.protocol_status` is one of `request.queued`, `request.dispatched` or `request.error`. +- `error.code` and `error.message` stay empty when you accept the message. +- `timestamp` takes the form `DD/MM/YYYY hh:mm:ss:sss`. + +## How you know it worked + +- You have nothing to build for this path. +- Your own `/v1/status` calls are answered on `/v1/on_status`, with `x-hcx-status` `request.queued`, `request.dispatched` or `request.stopped`. +- If your endpoint ever logs a delivery at `/v1/status`, it returned 202 with the receipt within 30 seconds. + +## When it goes wrong + +- **It never arrives.** That is expected. NHCX answers status requests itself. +- **You are waiting for a status answer.** It comes on `/v1/on_status`. See [receiving `/v1/on_status`](on-status.md). +- **Your status call is refused with [NHCX-1012](../errors/nhcx-1012.md).** NHCX holds no message with that API call id. Put the `x-hcx-api_call_id` of your original message in `x-hcx-correlation_id`. +- **Your server answers `/v1/status` with a 404.** Route the path to a handler that returns the receipt. NHCX then stops sending it again. diff --git a/catalogue/nhcx/callbacks/task-on-submit.md b/catalogue/nhcx/callbacks/task-on-submit.md new file mode 100644 index 000000000..53583693a --- /dev/null +++ b/catalogue/nhcx/callbacks/task-on-submit.md @@ -0,0 +1,306 @@ +--- +id: nhcx.callback.task-on-submit +type: callback +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Receiving POST /v1/task/on_submit +summary: >- + What your hospital system receives when the payer answers a reprocess or cancel + task, and how to acknowledge and read it. +sources: +- url: https://hcxsbx.abdm.gov.in/taskhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/taskhcxservice.json + hash: sha256:0418eca6478dece4d72c5a49a6547d50772511f7ffaf32f901f245591ba84656 + fetched: '2026-09-14' + note: 'API specification: taskhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/task/on_submit.' +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sections 4.2, 10.4 workflow table and 10.5. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Reprocess, /v1/task/on_submit. +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use case 12 Request for Reprocess/Cancel. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Message Structure, Status Description. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Q14 and Q21 (Not getting call back). +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item 8. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.task-on-submit + - nhcx.endpoint.task-submit + - nhcx.endpoint.status + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.participant-update + callbacks: + - nhcx.callback.task-submit + - nhcx.callback.on-status + - nhcx.callback.error + flows: + - nhcx.flow.claim-reprocess + - nhcx.flow.preauth-cancel + - nhcx.flow.status-check + - nhcx.flow.receive-a-sealed-callback + fhir: + - nhcx.fhir.task + - nhcx.fhir.claim-response + tests: + - nhcx.test.provider-uc-12 + - nhcx.test.tc-cl-03 + errors: + - nhcx.error.nhcx-1001 + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1015 + - nhcx.error.payr-1001 + - nhcx.error.payr-1002 + concepts: + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.retries-and-expiry + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.participant-registry + - nhcx.concept.encryption-certificate + - nhcx.concept.four-message-legs + - nhcx.concept.reprocess-and-cancel + - nhcx.concept.workflow-codes + - nhcx.concept.status-lifecycle + troubleshooting: + - nhcx.troubleshooting.callback-url-rejected + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.accepted-then-no-callback + sandbox: + - nhcx.sandbox.callback-url-requirements + decisions: + - nhcx.decision.key-encryption-algorithm + - nhcx.decision.status-poll-or-wait + glossary: + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - nhcx.glossary.api-call-id + - nhcx.glossary.protected-header + - nhcx.glossary.participant-code + - nhcx.glossary.payer + - nhcx.glossary.provider + - nhcx.glossary.reprocess + - shared.glossary.fhir + - shared.glossary.abha +--- + +# Receiving POST /v1/task/on_submit + +## In plain words + +After you send a reprocess or cancel task, the [payer](../glossary/payer.md) answers through [NHCX](../../shared/glossary/nhcx.md). NHCX delivers the outcome to your system as `POST /v1/task/on_submit`. You receive it as the [provider](../glossary/provider.md) that sent the task. Acknowledge it within 30 seconds, then update the claim or preauthorisation it names. + +## Before you start + +**Who receives it:** the provider that sent `/v1/task/submit`. **Who sends it:** the payer, through NHCX. + +- Your participant record in the [participant registry](../concepts/participant-registry.md) holds an `endpoint_url`. [NHCX](../../shared/glossary/nhcx.md) posts to that address with `/v1/task/on_submit` appended. +- You set `endpoint_url` when you register, in [sandbox onboarding](../flows/sandbox-onboarding.md). You change it with [`/participant/update`](../endpoints/participant-update.md). +- The URL uses a domain name over HTTPS. It has no IP address and no port number. +- The server behind it is in India. Your firewall accepts calls from the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). +- Your handler can open a [JWE](../glossary/jwe.md) with your private key. That key pairs with the certificate in your registry record. See [your encryption certificate](../concepts/encryption-certificate.md). +- Your handler answers within 30 seconds and does slow work afterwards. See [the 202 acknowledgement](../concepts/synchronous-acknowledgement.md). +- You sent the request with [`/v1/task/submit`](../endpoints/task-submit.md). You stored its `x-hcx-api_call_id` and `x-hcx-correlation_id` before sending it. +- You also host [`/v1/error`](error.md), so a request that dies is never silent. + +## What happens + +```mermaid +sequenceDiagram + participant Y as Your provider system + participant N as NHCX gateway + participant O as Payer system + Y->>N: POST /v1/task/submit + N-->>Y: 202 Accepted + N->>O: POST /v1/task/submit + O->>N: POST /v1/task/on_submit (sealed answer) + N->>Y: POST /v1/task/on_submit + Y-->>N: 202 Accepted with receipt, within 30 seconds +``` + +### What arrives + +[NHCX](../../shared/glossary/nhcx.md) sends `POST /v1/task/on_submit`. The body takes one of two forms. Branch on its `type` field. + +- `ProtocolResponse`: the payer could not process your request. The body is plain JSON with the error details, and nothing is sealed. +- Any other body carries the payer's answer sealed in `payload`, with `type` set to `JWEPayload`. + +```json +{ + "type": "JWEPayload", + "payload": "" +} +``` + +The payload is a JWE in compact form: five base64url parts joined by dots. Decode the first part to read the protected header. You do not need your private key for that step. + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-correlation_id": "", + "x-hcx-workflow_id": "252", + "x-hcx-timestamp": "", + "x-hcx-status": "response.complete", + "x-hcx-ben-abha-id": "" +} +``` + +| Protected header | What it tells you | +|---|---| +| `x-hcx-sender_code` | The payer that answered. | +| `x-hcx-recipient_code` | Your participant code. | +| `x-hcx-api_call_id` | This one message. Each answer has its own value. A repeat delivery carries the same value. | +| `x-hcx-correlation_id` | The exchange you started. Match it to the request you stored. | +| `x-hcx-workflow_id` | The step the answer reports. Read it when present. See [workflow codes](../concepts/workflow-codes.md). | +| `x-hcx-status` | Where the exchange stands. See the status list below. | +| `x-hcx-error_details` | An object with `code`, `message` and `trace` when something failed. | +| `x-hcx-ben-abha-id` | The beneficiary's [ABHA](../../shared/glossary/abha.md) number. Accept it with or without hyphens. | + +Look up `x-hcx-correlation_id` against the correlation ids you sent. If nothing matches, look it up against the `x-hcx-api_call_id` values you sent. + +`x-hcx-status` takes these values: + +- `response.partial`: an interim answer, such as received. More follows on the same correlation id. +- `response.complete`: the final answer. The case is closed on this exchange. +- `response.error`: the request failed on protocol grounds. Treat `response.fail` the same way. + +The payer's workflow code says which outcome the answer reports: + +| `x-hcx-workflow_id` | Meaning | +|---|---| +| `251` | Reprocess request received | +| `252` | Reprocess request approved | +| `253` | Reprocess request rejected | +| `254` | Reprocess request queried | + +Decrypt the payload with your private key. Use the algorithm the header names in `alg`. [RSA-OAEP or RSA-OAEP-256](../decisions/key-encryption-algorithm.md) covers both values. The plaintext is a [FHIR](../../shared/glossary/fhir.md) Task bundle: see [the Task bundle](../fhir/task.md). The Task has `status` `completed`. Its output references a ClaimResponse that carries the outcome. + +#### When `type` is `ProtocolResponse` + +The body is plain JSON. Read `x-hcx-error_details` for the reason. + +```json +{ + "type": "ProtocolResponse", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-correlation_id": "", + "x-hcx-workflow_id": "", + "x-hcx-timestamp": "", + "x-hcx-debug_flag": "Error", + "x-hcx-status": "response.error", + "x-hcx-redirect_to": "", + "x-hcx-error_details": { + "code": "", + "message": "", + "trace": "" + }, + "x-hcx-debug_details": { + "code": "", + "message": "", + "trace": "" + }, + "x-hcx-domain-header": { + "use_case_name": "", + "amt_processed": "" + }, + "x-hcx-entity-type": "task", + "x-hcx-ben-abha-id": "" +} +``` + +### What you send back + +Answer the delivery first, before you decrypt or act on it. Return HTTP status `202 Accepted` with this receipt: + +```json +{ + "timestamp": "", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "task", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `api_call_id` and `correlation_id` repeat the values in this delivery. +- `result.sender_code` is the sender's code. `result.recipient_code` is yours. +- `result.entity_type` is `task` for this exchange. +- `result.protocol_status` is one of `request.queued`, `request.dispatched` or `request.error`. +- `error.code` and `error.message` stay empty when you accept the message. +- `timestamp` takes the form `DD/MM/YYYY hh:mm:ss:sss`. + +### Retries and repeat deliveries + +- NHCX waits 30 seconds for your 202 and receipt. +- A late answer, another status code or a receipt in another shape counts as a failed delivery. NHCX sends the same message again. +- After 5 attempts NHCX stops. It deletes the request and retires its correlation id. The original sender learns of it on its own `/v1/error`. +- A repeat delivery is the same sealed message, so it carries the same `x-hcx-api_call_id`. Record every `x-hcx-api_call_id` you accept. +- On a repeat, return 202 with the same receipt and do not process the message again. +- Never deduplicate on `x-hcx-correlation_id`. Every message in one exchange shares it. +- An interim answer and a final answer share `x-hcx-correlation_id`. They differ in `x-hcx-api_call_id`. + +## How you know it worked + +- NHCX receives your HTTP 202 and receipt within 30 seconds of the delivery. +- Your log shows one delivery per `x-hcx-api_call_id`. A second delivery with the same value means NHCX did not accept your receipt. +- The `x-hcx-correlation_id` matches a request you sent. +- The claim or preauthorisation shows the payer's outcome from the referenced ClaimResponse. + +## When it goes wrong + +- **It never arrives.** Check these in order. + 1. Your `/v1/task/submit` call got a 202 from NHCX. Without it, NHCX never forwarded the request. + 2. Your `/v1/error` endpoint holds no report for this correlation id. A report means the payer never received your request. + 3. The `endpoint_url` in your registry record is right. It uses a domain name, with no IP address and no port number. + 4. Your server is in India, and your firewall accepts the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). + 5. Your application routes the path to the handler: load balancer rules, service routes and endpoint versions. + 6. Ask NHCX with [`/v1/status`](../endpoints/status.md). `request.dispatched` means the payer has your request, so wait. `request.stopped` means it is dead. + If the payer cannot seal its answer to your certificate, it reports [PAYR-1002](../errors/payr-1002.md). Update the certificate in your registry record. See [accepted with 202 and no callback arrives](../troubleshooting/accepted-then-no-callback.md). +- **It arrives as a `ProtocolResponse`.** The payer could not open or validate your request. Read `x-hcx-error_details.code` and open its error atom. [PAYR-1001](../errors/payr-1001.md) means your payload could not be decrypted: fetch the recipient's certificate again with [`/fetch/certs`](../endpoints/fetch-certs.md). The correlation id of a failed request is inactive. Send a fresh request with a new correlation id; reusing the old one is refused as [NHCX-1006](../errors/nhcx-1006.md). +- **The same message arrives again and again.** NHCX did not accept your receipt. It was later than 30 seconds, used another status code, or had another shape. Fix the receipt, and keep processing each `x-hcx-api_call_id` once. An invalid answer from a receiver is reported as [NHCX-1015](../errors/nhcx-1015.md), "Invalid response received from receiver." +- **The correlation id matches nothing you sent.** You stored the ids after sending instead of before, or you looked in one field only. Look up `x-hcx-correlation_id` against the correlation ids you sent. If nothing matches, look it up against the `x-hcx-api_call_id` values you sent. See [responses arrive against the wrong request](../troubleshooting/duplicate-or-mismatched-correlation.md). +- **The answer is a rejection.** A rejection is not a protocol error. It arrives sealed, like an approval. The reason sits inside the decrypted resource, not in `x-hcx-error_details`. diff --git a/catalogue/nhcx/callbacks/task-submit.md b/catalogue/nhcx/callbacks/task-submit.md new file mode 100644 index 000000000..89f6d7182 --- /dev/null +++ b/catalogue/nhcx/callbacks/task-submit.md @@ -0,0 +1,273 @@ +--- +id: nhcx.callback.task-submit +type: callback +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Receiving POST /v1/task/submit +summary: >- + What your payer system receives when a hospital asks you to reprocess a claim + or cancel a preauthorisation, and how to acknowledge it. +sources: +- url: https://hcxsbx.abdm.gov.in/taskhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/taskhcxservice.json + hash: sha256:0418eca6478dece4d72c5a49a6547d50772511f7ffaf32f901f245591ba84656 + fetched: '2026-09-14' + note: 'API specification: taskhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/task/submit.' +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Reprocess, /v1/task/submit. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sections 22 and 23 (PMJAY); Q14; Q21. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sections 10.4 and 11.1-11.2. +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use case 14 Respond to the Task request submitted. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Message Structure, Status Description. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. items 4, 7 and 8. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.task-submit + - nhcx.endpoint.task-on-submit + - nhcx.endpoint.paymentnotice-on-request + - nhcx.endpoint.participant-update + callbacks: + - nhcx.callback.task-on-submit + - nhcx.callback.paymentnotice-on-request + - nhcx.callback.error + flows: + - nhcx.flow.claim-reprocess + - nhcx.flow.preauth-cancel + - nhcx.flow.payment-notice + - nhcx.flow.payer-process-a-request + - nhcx.flow.receive-a-sealed-callback + fhir: + - nhcx.fhir.task + - nhcx.fhir.claim-response + - nhcx.fhir.payment-notice + tests: + - nhcx.test.payer-uc-14 + - nhcx.test.tc-cl-03 + errors: + - nhcx.error.nhcx-1001 + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1015 + - nhcx.error.nhcx-1016 + - nhcx.error.payr-1001 + concepts: + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.retries-and-expiry + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.participant-registry + - nhcx.concept.encryption-certificate + - nhcx.concept.four-message-legs + - nhcx.concept.reprocess-and-cancel + troubleshooting: + - nhcx.troubleshooting.callback-url-rejected + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.recipient-cannot-decrypt + sandbox: + - nhcx.sandbox.callback-url-requirements + decisions: + - nhcx.decision.key-encryption-algorithm + glossary: + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - nhcx.glossary.api-call-id + - nhcx.glossary.protected-header + - nhcx.glossary.participant-code + - nhcx.glossary.payer + - nhcx.glossary.provider + - nhcx.glossary.reprocess + - nhcx.glossary.crc + - nhcx.glossary.pmjay + - shared.glossary.fhir + - shared.glossary.abha +--- + +# Receiving POST /v1/task/submit + +## In plain words + +A [provider](../glossary/provider.md) uses a task to act on an earlier case. It can ask you to reprocess a rejected or short-paid claim, or to cancel a preauthorisation. [NHCX](../../shared/glossary/nhcx.md) delivers the task to your system as `POST /v1/task/submit`. You receive it as the [payer](../glossary/payer.md). Acknowledge the delivery within 30 seconds. Then answer on [`/v1/task/on_submit`](../endpoints/task-on-submit.md). + +## Before you start + +**Who receives it:** the payer, as the system that processes the request for the policy. **Who sends it:** a provider, through NHCX. + +- Your participant record in the [participant registry](../concepts/participant-registry.md) holds an `endpoint_url`. [NHCX](../../shared/glossary/nhcx.md) posts to that address with `/v1/task/submit` appended. +- You set `endpoint_url` when you register, in [sandbox onboarding](../flows/sandbox-onboarding.md). You change it with [`/participant/update`](../endpoints/participant-update.md). +- The URL uses a domain name over HTTPS. It has no IP address and no port number. +- The server behind it is in India. Your firewall accepts calls from the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). +- Your handler can open a [JWE](../glossary/jwe.md) with your private key. That key pairs with the certificate in your registry record. See [your encryption certificate](../concepts/encryption-certificate.md). +- Your handler answers within 30 seconds and does slow work afterwards. See [the 202 acknowledgement](../concepts/synchronous-acknowledgement.md). +- Your system can call [`/v1/task/on_submit`](../endpoints/task-on-submit.md) to answer. +- You also host [`/v1/error`](error.md), so a request that dies is never silent. + +## What happens + +```mermaid +sequenceDiagram + participant S as Provider system + participant N as NHCX gateway + participant Y as Your payer system + S->>N: POST /v1/task/submit (sealed) + N-->>S: 202 Accepted + N->>Y: POST /v1/task/submit (same sealed message) + Y-->>N: 202 Accepted with receipt, within 30 seconds + Note over Y: Decrypt, validate, process + Y->>N: POST /v1/task/on_submit (your answer) + N->>S: POST /v1/task/on_submit +``` + +### What arrives + +[NHCX](../../shared/glossary/nhcx.md) sends `POST /v1/task/submit`. The JSON body carries one field, `payload`: + +```json +{ + "payload": "" +} +``` + +The payload is a JWE in compact form: five base64url parts joined by dots. Decode the first part to read the protected header. You do not need your private key for that step. + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-request_id": "", + "x-hcx-correlation_id": "", + "x-hcx-timestamp": "", + "x-hcx-status": "request.initiated", + "x-hcx-ben-abha-id": "" +} +``` + +| Protected header | What it tells you | +|---|---| +| `x-hcx-sender_code` | The provider that sent it. Your answer goes back to this code. | +| `x-hcx-recipient_code` | Your participant code. | +| `x-hcx-api_call_id` | This one message. A repeat delivery carries the same value. | +| `x-hcx-request_id` | The originating request. Read it when present. | +| `x-hcx-correlation_id` | The whole exchange. Copy it into your answer. | +| `x-hcx-workflow_id` | The business step. Read it when present. See [workflow codes](../concepts/workflow-codes.md). | +| `x-hcx-timestamp` | When the sender sealed the message. | +| `x-hcx-status` | `request.initiated` for a new request. Accept `request.initiate` as the same value. | +| `x-hcx-ben-abha-id` | The beneficiary's [ABHA](../../shared/glossary/abha.md) number. Accept it with or without hyphens. | + +Decrypt the payload with your private key. Use the algorithm the header names in `alg`. [RSA-OAEP or RSA-OAEP-256](../decisions/key-encryption-algorithm.md) covers both values. The plaintext is a [FHIR](../../shared/glossary/fhir.md) Task bundle: see [the Task bundle](../fhir/task.md). The Task has `status` `requested`, and a `ClaimNumber` input names the claim or preauthorisation. + +| `Task.code` | What the provider asks | +|---|---| +| `reprocess` | Reprocess a rejected or short-paid claim | +| `cancel` | Cancel a claim or preauthorisation | +| `release` | Release, as the use case sets | +| `nullify` | Nullify, as the use case sets | + +`Task.reasonCode` says why. Codes in use include `claimrejected`, `rejectiondisputed` and `partialpayment`. In [PMJAY](../glossary/pmjay.md), a reprocess or shortfall task must carry a supporting document as `valueAttachment`. Reprocess cases go to the [CRC](../glossary/crc.md), whose decision is final. + +A PMJAY provider can also send its payment acknowledgement here: a completed Task whose output is `paymentack`. Accept it on this path as well as on [`/v1/paymentnotice/on_request`](paymentnotice-on-request.md). + +### What you send back + +Answer the delivery first, before you decrypt or act on it. Return HTTP status `202 Accepted` with this receipt: + +```json +{ + "timestamp": "", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "task", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `api_call_id` and `correlation_id` repeat the values in this delivery. +- `result.sender_code` is the sender's code. `result.recipient_code` is yours. +- `result.entity_type` is `task` for this exchange. +- `result.protocol_status` is one of `request.queued`, `request.dispatched` or `request.error`. +- `error.code` and `error.message` stay empty when you accept the message. +- `timestamp` takes the form `DD/MM/YYYY hh:mm:ss:sss`. + +### Retries and repeat deliveries + +- NHCX waits 30 seconds for your 202 and receipt. +- A late answer, another status code or a receipt in another shape counts as a failed delivery. NHCX sends the same message again. +- After 5 attempts NHCX stops. It deletes the request and retires its correlation id. The original sender learns of it on its own `/v1/error`. +- A repeat delivery is the same sealed message, so it carries the same `x-hcx-api_call_id`. Record every `x-hcx-api_call_id` you accept. +- On a repeat, return 202 with the same receipt and do not process the message again. +- Never deduplicate on `x-hcx-correlation_id`. Every message in one exchange shares it. + +### What you do next + +Process the message, then answer on [`/v1/task/on_submit`](../endpoints/task-on-submit.md): + +- Copy `x-hcx-correlation_id` from this message. +- Give your answer its own fresh `x-hcx-api_call_id`. +- Send it to the sender: its `x-hcx-sender_code` becomes your `x-hcx-recipient_code`. +- Set `x-hcx-status` to `response.complete` for your answer. +- Seal a Task bundle whose Task has `status` `completed` and whose output references a ClaimResponse with the outcome. See [the claim response bundle](../fhir/claim-response.md). +- If you cannot decrypt or validate this message, answer with a protocol response instead. Set `type` to `ProtocolResponse`, `x-hcx-status` to `response.error`, and fill `x-hcx-error_details`. + +## How you know it worked + +- NHCX receives your HTTP 202 and receipt within 30 seconds of the delivery. +- Your log shows one delivery per `x-hcx-api_call_id`. A second delivery with the same value means NHCX did not accept your receipt. +- You decrypted the payload and hold the Task with its `code`, `reasonCode` and `ClaimNumber`, stored against its `x-hcx-correlation_id`. +- Your answer on `/v1/task/on_submit` gets its own 202 from NHCX. No NHCX error names its correlation id. + +## When it goes wrong + +- **It never arrives.** Check these in order. + 1. The `endpoint_url` in your registry record is the address you expect. + 2. It uses a domain name, with no IP address and no port number. + 3. Your server is in India, and your firewall accepts the NHCX egress addresses in [callback URL rules](../sandbox/callback-url-requirements.md). + 4. Your application routes the path to the handler: load balancer rules, service routes and endpoint versions. + 5. The provider addressed the message to your participant code. Providers address the processor code from their policy lookup, so check that code is yours. + When NHCX cannot reach you, the sender is told [NHCX-1001](../errors/nhcx-1001.md), "Receiver system is not reachable." See [your callback URL is rejected or never called](../troubleshooting/callback-url-rejected.md). +- **The same message arrives again and again.** NHCX did not accept your receipt. It was later than 30 seconds, used another status code, or had another shape. Fix the receipt, and keep processing each `x-hcx-api_call_id` once. An invalid answer from a receiver is reported as [NHCX-1015](../errors/nhcx-1015.md), "Invalid response received from receiver." +- **You cannot decrypt it.** The sender sealed it to an old certificate, or your registry certificate does not match your private key. Still return 202 with the receipt. Then answer on `/v1/task/on_submit` with a protocol response. [PAYR-1001](../errors/payr-1001.md) names a decryption failure. See [the recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). +- **Your answer is refused.** [NHCX-1010](../errors/nhcx-1010.md) means NHCX holds no exchange with that correlation id. [NHCX-1016](../errors/nhcx-1016.md) means the action does not fit that correlation id. [NHCX-1011](../errors/nhcx-1011.md) means the `x-hcx-status` value is invalid. Copy the correlation id from this message, answer on the paired path, and use a documented status. See [responses arrive against the wrong request](../troubleshooting/duplicate-or-mismatched-correlation.md). +- **The request fails your business rules.** That is not a protocol error. Answer with a sealed ClaimResponse, referenced from the Task output, that carries the decision and the reason. Keep protocol responses for messages you cannot open or validate. diff --git a/catalogue/nhcx/concepts/access-control.md b/catalogue/nhcx/concepts/access-control.md new file mode 100644 index 000000000..acef3eedc --- /dev/null +++ b/catalogue/nhcx/concepts/access-control.md @@ -0,0 +1,126 @@ +--- +id: nhcx.concept.access-control +type: concept +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Who may call what: the NHCX access control matrix' +summary: >- + Each role on the exchange may send and receive only certain messages and search + only certain data, and the exchange and payers enforce this from the registry + and the session token. +sources: +- url: https://hcxsbx.abdm.gov.in/#/domain-specifications/healthcare-operation-policy/access-control + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__healthcare-operation-policy__access-control.md + hash: sha256:7c3d7b2cf396a9daaca76ade1c059a8d358d0686b7b7e041e96c5f7f239dae57 + fetched: '2026-09-14' + note: Site page /domain-specifications/healthcare-operation-policy/access-control, text as shown on the site. Access Controls role table. +- url: https://hcxsbx.abdm.gov.in/#/introduction-NHCX/guidlines-for-participant-onboarding + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/introduction-NHCX__guidlines-for-participant-onboarding.md + hash: sha256:58aaa762f2a04565e2060658b0eda95e3cac4cbb0819b6d865f04cf53066680d + fetched: '2026-09-14' + note: Site page /introduction-NHCX/guidlines-for-participant-onboarding, text as shown on the site. Deboarding scenarios. +- url: https://hcxsbx.abdm.gov.in/images/539853c50347b32b9a5e.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Policy Linking and De-Linking Process.pdf + hash: sha256:420115b9a54e15fa625312a56362164d92d23dd0d6ebf9195135bb00055d1911 + fetched: '2026-09-14' + note: Policy Linking and De-Linking Process, row 8 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 2, Validation for De-Linking. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/registries + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__registries.md + hash: sha256:04bf78739fa0c3807a8a5a49d8c3e004f8aba664f524d0344d7fc44c3b2baf42 + fetched: '2026-09-14' + note: Site page /technical-specifications/open-protocol/registries, text as shown on the site. Participating Organisations/Systems Registry, roles attribute. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 3, Q9 correct Role and Registry mapping. +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error, 'No user role found' row. +verified: + status: unverified +related: + concepts: + - nhcx.concept.participant-roles + - nhcx.concept.policy-linking + - nhcx.concept.beneficiary-consent + - nhcx.concept.audit-and-non-repudiation + - nhcx.concept.grievance-redressal + - nhcx.concept.session-token + endpoints: + - nhcx.endpoint.search-submit + - nhcx.endpoint.status + flows: + - nhcx.flow.claim-search + - nhcx.flow.status-check + glossary: + - nhcx.glossary.irdai + - nhcx.glossary.payer + - nhcx.glossary.provider +--- + +# Who may call what: the NHCX access control matrix + +## In plain words + +Not every participant may send every message. A hospital may submit claims but not payment notices. A payer may send payment notices but not claims. A regulator may search claims but not submit them. + +These rules follow from each participant's registered role. NHCX and the payers check them on every call. + +## Before you start + +Read [participant roles](./participant-roles.md). + +## What happens + +### The matrix, version 1 + +| Role | May send | May receive | May search | +|---|---|---|---| +| `provider` | Eligibility, preauthorisation and claim requests; payment acknowledgements | Their responses; payment notices | Status of preauthorisations and claims it sent | +| `payer`, `agency.tpa` | Responses to eligibility, preauthorisation and claim; payment notices | Those requests; payment acknowledgements | Payment confirmation for notices it sent | +| `agency.regulator` | Claim searches | Search results | Claims, forwarded by NHCX to all payers | +| `research` | Eligibility responses | Eligibility requests | Preauthorisations and claims, aggregate and anonymised only | +| `member.isnp` | As research | As research | As research, plus individual claims with the beneficiary's consent | +| `agency.sponsor` | As a payer | As a payer | As a payer | +| Other NHCX instances | As the use case needs | As the use case needs | Never the payload | + +A TPA acts exactly like a payer in version 1. A scheme sponsor, such as the owner of a government scheme, gets payer-level access. + +### How the rules are enforced + +```mermaid +graph LR + T["Session token
identifies the client"] --> X["NHCX"] + RG[("Registry
roles per participant")] --> X + X -->|allowed| P["Recipient"] + P -->|checks the sender's role| OK["Processes"] +``` + +- Your session token identifies your client. NHCX compares it with the participant that client registered. +- The registry records your role. NHCX and payers read it. +- Some actions are tied to one participant. Only the participant named as `payerid` or `processingid` on a policy link may de-link it. + +### Losing access + +A participant can be removed. A regulator may suspend a provider for fraud, or a payer or TPA. NHCX may remove a participant for serious policy breaches, hacking attempts, or traffic that harms the exchange. A participant may also leave on its own. Removal that is not voluntary comes with warnings, and the participant can appeal through [grievance redressal](./grievance-redressal.md). + +## How you know it worked + +You have understood this when you can answer both of these. + +1. A research body asks NHCX for a named patient's claim history. What does its role allow it to see? +2. Your hospital system tries to search claims raised by another hospital. What does the matrix allow? + +## When it goes wrong + +**Role and registry type do not match.** A wrong mapping at creation leads to refused calls and wrong routing later. + +**No role for the sender.** A payer refuses a sender with no role with the message "No user role found/associated for sender code". + +**De-linking with the wrong credentials.** The token must come from the client that created the `payerid` or `processingid` participant. + +**Individual data without consent.** An insurance self network platform may query an individual's claims only with that person's consent. See [beneficiary consent](./beneficiary-consent.md). diff --git a/catalogue/nhcx/concepts/audit-and-non-repudiation.md b/catalogue/nhcx/concepts/audit-and-non-repudiation.md new file mode 100644 index 000000000..c374e8438 --- /dev/null +++ b/catalogue/nhcx/concepts/audit-and-non-repudiation.md @@ -0,0 +1,130 @@ +--- +id: nhcx.concept.audit-and-non-repudiation +type: concept +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Audit logging and non-repudiation +summary: >- + The exchange logs the readable envelope of every call and never the sealed claim, + while the sealing itself proves a message was not altered, and each participant + keeps its own records of what it sent and received. +sources: +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/data-security-and-privacy/audit-and-reporting + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy__audit-and-reporting.md + hash: sha256:3805b33513ec0863294014053849d921b6fc4093d1cd0356a5e10b9eb54ef6c6 + fetched: '2026-09-14' + note: Site page /technical-specifications/open-protocol/data-security-and-privacy/audit-and-reporting, text as shown on the site. Audit and Reporting. +- url: https://hcxsbx.abdm.gov.in/#/domain-specifications/healthcare-operation-policy/guidelines-event-audits + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__healthcare-operation-policy__guidelines-event-audits.md + hash: sha256:2ad75de1a412e4f39b1a922a0d90fa8f7c76770ea55a42cb4b308d3ba534a9c7 + fetched: '2026-09-14' + note: Site page /domain-specifications/healthcare-operation-policy/guidelines-event-audits, text as shown on the site. Guidelines for Event Audits. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy__message-security-and-integrity.md + hash: sha256:3768fd89932e4081c9e03a8695619bcaf70c641e28bb55a77eec090bb926eeb3 + fetched: '2026-09-14' + note: Site page /technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity, text as shown on the site. Message Encryption and Decryption steps. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/healthclaims-exchange-protocol + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__healthclaims-exchange-protocol.md + hash: sha256:ff4b3aa02f2aa61e2b29e50699fe16bee82c3684908bc2be0815c07b97a83371 + fetched: '2026-09-14' + note: Site page /technical-specifications/open-protocol/healthclaims-exchange-protocol, text as shown on the site. Message Structure, Signatures. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section on Payment Notice, UTR note. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Page 16, Insurance Plan technical guidelines. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Section 26 Cyclic Procedure, Q10. +verified: + status: unverified +related: + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.access-control + - nhcx.concept.beneficiary-consent + - nhcx.concept.what-nhcx-is + - nhcx.concept.insurance-plan + - nhcx.concept.protocol-headers + glossary: + - nhcx.glossary.protected-header + - nhcx.glossary.jwe +--- + +# Audit logging and non-repudiation + +## In plain words + +Claims involve money and health data, so every party must be able to show later what happened. NHCX keeps a record of every call it receives. It records only what it can read: the envelope, never the sealed claim. + +The sealing does the rest. A message cannot be changed without breaking it, so a received message is provably the one that was sent. + +## Before you start + +Read [the JWE envelope](./jwe-envelope.md). + +## What happens + +### What NHCX records + +For every call it receives, NHCX logs: + +- the protocol and domain headers, +- the signature and encryption algorithm details, +- the sender and the recipient, +- the result of signature verification. + +It cannot log the payload, because it cannot open it. + +Each NHCX instance publishes the audit reports it offers for payers, providers, beneficiaries, regulators and observers. It publishes an archival policy for how long logs are kept, and it can limit how much each log holds. Participants can query the audit records about their own transactions through an API. Method and path for that API are not yet published. + +### Why a message cannot be denied + +```mermaid +graph LR + H["Protected header"] --> AE["AES-GCM
authenticated encryption"] + P["FHIR bundle"] --> AE + AE --> TAG["Authentication tag"] + TAG -->|any change breaks it| R["Recipient rejects"] +``` + +The authentication tag covers the protected header and the payload together. A changed header or payload fails the tag, and the recipient must reject it. So NHCX adds no separate signature to a message. + +### The event audit rules + +Every event in a claim, such as a claim created, forwarded, queried, authorised or paid, is to be logged and signed by the systems involved. Logs are append only and never edited. They are kept for the period the law sets, and the audit trail is open to the beneficiary it concerns. + +### What your system should keep + +| Record | Why | +|---|---| +| Every envelope you sent and received, with its identifiers and your 202 | To prove delivery and answer a dispute | +| The insurance plan version each preauthorisation and claim used | A rate dispute turns on it | +| The UTR from each payment notice | Reconciliation and payment disputes | +| Biometric capture times for each cycle of a cyclic treatment | The payer checks them against the claim | + +## How you know it worked + +You have understood this when you can answer both of these. + +1. A regulator asks NHCX for the diagnosis on a disputed claim. What can NHCX's audit log show, and who holds the diagnosis? +2. A payer says your preauthorisation arrived with a different amount. How does the envelope itself settle whether it was changed on the way? + +## When it goes wrong + +**Logs that can be edited.** Audit logs must be append only. A log you can rewrite proves nothing. + +**No record of the plan version.** Without it, a claim priced from an older tariff cannot be defended. + +**Discarded payment references.** Keep the UTR from every payment notice. It is the only link to the bank transfer. + +**Relying on NHCX to hold the payload.** NHCX never sees it. Keep your own copies of what you sent and received. diff --git a/catalogue/nhcx/concepts/beneficiary-consent.md b/catalogue/nhcx/concepts/beneficiary-consent.md new file mode 100644 index 000000000..0d6902e64 --- /dev/null +++ b/catalogue/nhcx/concepts/beneficiary-consent.md @@ -0,0 +1,138 @@ +--- +id: nhcx.concept.beneficiary-consent +type: concept +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Beneficiary consent and data rights +summary: >- + The patient's data stays sealed from the exchange, research sees only aggregates, + individual data needs the patient's consent, and the patient must agree before + an app subscribes to their claim updates. +sources: +- url: https://hcxsbx.abdm.gov.in/#/domain-specifications/healthcare-operation-policy/access-control + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__healthcare-operation-policy__access-control.md + hash: sha256:7c3d7b2cf396a9daaca76ade1c059a8d358d0686b7b7e041e96c5f7f239dae57 + fetched: '2026-09-14' + note: Site page /domain-specifications/healthcare-operation-policy/access-control, text as shown on the site. Access Controls, research and member.isnp rows. +- url: https://hcxsbx.abdm.gov.in/#/domain-specifications/healthcare-operation-policy/guidlines-beneficiary + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__healthcare-operation-policy__guidlines-beneficiary.md + hash: sha256:3eee6ea210a8711f953221c91f172513d9b0dd6a33c70367833d2755443fdb08 + fetched: '2026-09-14' + note: Site page /domain-specifications/healthcare-operation-policy/guidlines-beneficiary, text as shown on the site. Guidelines for Beneficiary Authentication. +- url: https://hcxsbx.abdm.gov.in/images/9f1e6b545a693d38a704.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Biometric Authentication Implementation Steps.docx + hash: sha256:fac8b14bfe8d518c0e651740537b9441c501d3cf2ab0f0482a07ab9f417e43a9 + fetched: '2026-09-14' + note: Biometric Authentication Implementation Steps, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments, not named in the NHCX document sheet. Handle Exemption and Biometric Authentication rows. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Page 5 section 1.2 and page 19 biometric table. +- url: https://hcxsbx.abdm.gov.in/images/01db86335b7c226eb745.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Notification Integration.docx + hash: sha256:05908862c103522fac0dbb482f8eb6a0f8536fc12b1ae3bdb0e98615f30812aa + fetched: '2026-09-14' + note: NHCX Notification Integration, listed on https://hcxsbx.abdm.gov.in/#/documents, not named in the NHCX document sheet. Section 7.3 Privacy. +- url: https://hcxsbx.abdm.gov.in/#/domain-specifications/healthcare-operation-policy/guidelines-event-audits + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__healthcare-operation-policy__guidelines-event-audits.md + hash: sha256:2ad75de1a412e4f39b1a922a0d90fa8f7c76770ea55a42cb4b308d3ba534a9c7 + fetched: '2026-09-14' + note: Site page /domain-specifications/healthcare-operation-policy/guidelines-event-audits, text as shown on the site. Guidelines for Event Audits. +- url: https://hcxsbx.abdm.gov.in/images/539853c50347b32b9a5e.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Policy Linking and De-Linking Process.pdf + hash: sha256:420115b9a54e15fa625312a56362164d92d23dd0d6ebf9195135bb00055d1911 + fetched: '2026-09-14' + note: Policy Linking and De-Linking Process, row 8 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1, Policy Linking Process. +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error, PAYR-1256 message. +verified: + status: unverified +related: + concepts: + - nhcx.concept.biometric-authentication + - nhcx.concept.notifications + - nhcx.concept.access-control + - nhcx.concept.audit-and-non-repudiation + - nhcx.concept.policy-linking + - nhcx.concept.jwe-envelope + glossary: + - shared.glossary.consent-manager + - shared.glossary.abha + - shared.glossary.kyc + - shared.glossary.otp + errors: + - nhcx.error.payr-1256 + - nhcx.error.payr-1363 +--- + +# Beneficiary consent and data rights + +## In plain words + +A claim carries a patient's diagnosis, treatment and money. The exchange is built so that this data reaches only the parties that need it. + +Some protections are technical: the exchange cannot read the claim at all. Others are rules about consent: some parties may see a patient's data only if the patient agrees. And the patient must prove who they are before a claim starts. + +## Before you start + +Read [access control](./access-control.md). + +## What happens + +### Where the patient's data can go + +| Who | What they may see | +|---|---| +| The hospital and the payer on the claim | The full claim, sealed for each other | +| NHCX | The envelope only, never the payload | +| Research bodies | Aggregate and anonymised data only | +| Insurance self network platforms | Individual claims only with the patient's consent | +| The patient | The audit trail of events on their claims | + +An insurance self network platform submits the patient's consent in the domain header of its request. The consent flow works with the existing [consent manager](../../shared/glossary/consent-manager.md) infrastructure. + +### Consent before notifications + +A patient app must get the patient's explicit consent before it subscribes to their claim updates. It must show the subscription status and let the patient turn it off. See [notifications](./notifications.md). + +### Proving the patient is present + +```mermaid +graph TD + P["Patient at the hospital"] --> K["Aadhaar eKYC"] + P --> A["Aadhaar OTP or biometric"] + A --> T["Token carried into preauth and claim"] + P --> X["Biometric not possible"] + X --> E["Exemption consent document
signed by patient and hospital"] + E --> QR["Authentication Consent Questionnaire
answered in the bundle"] +``` + +A provider verifies the patient with Aadhaar eKYC, or with Aadhaar [OTP](../../shared/glossary/otp.md) or biometric authentication. For PMJAY, biometric presence is required at registration, preauthorisation and discharge. See [biometric authentication](./biometric-authentication.md). + +When biometric authentication is not possible, the hospital obtains an Aadhaar exemption consent document signed by the patient and a hospital representative. It stores the document, links it to the patient's record, and answers the Authentication Consent Questionnaire in the bundle. + +### Linking the patient's policy + +A payer links a patient's [ABHA](../../shared/glossary/abha.md) to the policies the patient holds, so hospitals can find their cover. Only the payer or its TPA can change that link. See [policy linking](./policy-linking.md). + +## How you know it worked + +You have understood this when you can answer both of these. + +1. A patient cannot give a fingerprint after an accident. What must the hospital obtain and store, and what goes into the preauthorisation instead of the token? +2. A research body wants to study claim delays at one hospital. What data may it receive? + +## When it goes wrong + +**No authentication and no consent questionnaire.** The PMJAY payer refuses the preauthorisation with [PAYR-1256](../errors/payr-1256.md) and the claim with [PAYR-1363](../errors/payr-1363.md). + +**Subscribing without consent.** A patient app must ask first and must let the patient see and switch off the subscription. + +**Exemption without the signed document.** The questionnaire answer relies on a document signed by both the patient and the hospital. Keep it linked to the patient's record. + +**Individual data sent to a research body.** Research access is aggregate and anonymised only. diff --git a/catalogue/nhcx/concepts/biometric-authentication.md b/catalogue/nhcx/concepts/biometric-authentication.md new file mode 100644 index 000000000..a09978393 --- /dev/null +++ b/catalogue/nhcx/concepts/biometric-authentication.md @@ -0,0 +1,134 @@ +--- +id: nhcx.concept.biometric-authentication +type: concept +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Biometric authentication of the beneficiary +summary: >- + Under the government health assurance scheme a hospital proves the patient is + present by fingerprint, iris or face scan, and carries the resulting token or + a signed exemption into preauthorisation and claim. +sources: +- url: https://hcxsbx.abdm.gov.in/images/9f1e6b545a693d38a704.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Biometric Authentication Implementation Steps.docx + hash: sha256:fac8b14bfe8d518c0e651740537b9441c501d3cf2ab0f0482a07ab9f417e43a9 + fetched: '2026-09-14' + note: 'Biometric Authentication Implementation Steps, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments, not named in the NHCX document sheet. Whole document: policy table, Fingerprint/IRIS APIs, Face-Auth API curl.' +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Section 26 Cyclic Procedure Q2-Q13; Section 27 Q4; Q10 K-547. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 8.2 Biometric Authentication, pages 18-19. +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error, PAYR-1256 and PAYR-1366 messages. +verified: + status: unverified +related: + flows: + - nhcx.flow.biometric-fingerprint-iris + - nhcx.flow.biometric-face + endpoints: + - nhcx.endpoint.abha-biometric-auth-init + - nhcx.endpoint.abha-biometric-auth-verify + - nhcx.endpoint.abha-biometric-auth-refresh-token + - nhcx.endpoint.abha-biometric-faceauth-init + - nhcx.endpoint.abha-biometric-capture-pid + - nhcx.endpoint.abha-biometric-v2-auth-verify + decisions: + - nhcx.decision.biometric-modality + errors: + - nhcx.error.payr-1256 + - nhcx.error.payr-1271 + - nhcx.error.payr-1272 + - nhcx.error.payr-1363 + - nhcx.error.payr-1364 + - nhcx.error.payr-1366 + - nhcx.error.payr-1367 + - nhcx.error.payr-1369 + glossary: + - nhcx.glossary.rd-service + - nhcx.glossary.pid-block + - shared.glossary.abha-number + - shared.glossary.auth-modes + - shared.glossary.kyc + concepts: + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.beneficiary-consent +--- + +# Biometric authentication of the beneficiary + +## In plain words + +PMJAY pays only for patients who were really at the hospital. So the hospital proves it: the patient places a finger on a scanner, looks into an iris camera, or has their face scanned on a phone. The scan is checked against Aadhaar through the ABHA biometric service. + +A successful check gives the hospital a user token. The hospital carries that token, or a signed exemption, into the preauthorisation and the claim. + +## Before you start + +The patient's [ABHA number](../../shared/glossary/abha-number.md) must be linked to their PMJAY card. For patients without that link, the scheme's other [KYC](../../shared/glossary/kyc.md) procedures apply. Fingerprint and iris need a registered device with its [RD service](../glossary/rd-service.md) on the hospital computer. + +## What happens + +### When to authenticate + +| Moment | `process` header | +|---|---| +| Patient registration and preauthorisation | `Preauth` | +| Every cycle of a cyclic treatment, such as dialysis | `Discharge` | +| Discharge, before the claim | `Discharge` | + +Biometric authentication is not an NHCX use case call. The hospital system calls the ABHA biometric service directly, sending the payer's participant code in `payerid`. + +### The three modalities + +| Modality | `authMode` | `scope` | Evidence sent | +|---|---|---|---| +| Fingerprint | `FINGERPRINT` | `abha-login`, `aadhaar-bio-verify` | The device's [PID block](../glossary/pid-block.md) in `fingerPrintAuthPid` | +| Iris | `IRIS` | `abha-login`, `aadhaar-iris-verify` | The PID block in `irisAuthPid` | +| Face | `FACE_AUTH` | from the face auth init call | A phone scan through the ABHA app, then the Aadhaar number, RSA encrypted | + +Fingerprint and iris take two calls: init returns a `txnId`, and verify sends the PID block with it. Face takes four steps: init, show a QR code for the patient's phone, poll `capture/pid` until it returns `COMPLETE`, then verify. Which to use is covered in [choosing a modality](../decisions/biometric-modality.md). A PMJAY integration must support all three. + +### The tokens + +```mermaid +graph LR + S["Successful scan"] --> UT["User token
30 minutes"] + S --> RT["Refresh token
15 days"] + RT -->|refresh call| UT2["New user token
+ new refresh token"] +``` + +Refresh at least once every 10 days to keep a long stay covered without scanning again. A cyclic treatment cycle is the exception: every cycle needs a live scan, never a refresh, and two cycles of the same procedure need 24 hours between them. + +The request header that carries the user token on preauthorisation and claim is not yet published. + +### When a scan is impossible + +For trauma, amputations or unreadable biometrics, the hospital obtains an Aadhaar exemption consent document signed by the patient and a hospital representative. It stores the document, and answers the Authentication Consent Questionnaire from the insurance plan in the preauthorisation or claim instead of sending a token. Cyclic treatments cannot use this route. + +## How you know it worked + +You have understood this when you can answer both of these. + +1. A dialysis patient came in yesterday at 18:00. Can you scan them for the next cycle at 09:00 today? Can you use the refresh token instead? +2. A patient's fingerprints cannot be read at discharge. What does your claim carry in place of the discharge token? + +## When it goes wrong + +**Neither token nor questionnaire.** The PMJAY payer refuses a preauthorisation with [PAYR-1256](../errors/payr-1256.md) and a claim with [PAYR-1363](../errors/payr-1363.md). A questionnaire with a blank link id fails with [PAYR-1271](../errors/payr-1271.md) or [PAYR-1364](../errors/payr-1364.md). + +**Invalid or expired user token.** [PAYR-1272](../errors/payr-1272.md) at preauthorisation, [PAYR-1366](../errors/payr-1366.md) at claim. Scan again. + +**Missing cycle scans.** A cycle with no scan on its date fails with [PAYR-1367](../errors/payr-1367.md). Two scans for one date fail with [PAYR-1369](../errors/payr-1369.md). + +**Device error K-547 on fingerprint.** Set the `lr` attribute to `Y` when computing the WADH value. diff --git a/catalogue/nhcx/concepts/claim-cycle.md b/catalogue/nhcx/concepts/claim-cycle.md new file mode 100644 index 000000000..9f4dfe95d --- /dev/null +++ b/catalogue/nhcx/concepts/claim-cycle.md @@ -0,0 +1,149 @@ +--- +id: nhcx.concept.claim-cycle +type: concept +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: The claim cycle from eligibility to payment +summary: >- + A cashless claim moves through eligibility, insurance plan, preauthorisation, + claim, payment notice and, if needed, reprocess, and each stage is its own request + and response on the exchange. +sources: +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. API Structure table. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheets Value sets, Preauth, Claim, Payment, Task, InsurancePlan. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 8.4 page 32 and 8.5 page 35 functional points. +- url: https://hcxsbx.abdm.gov.in/images/13093b5f9b88fe826123.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Insurance Plan IG.docx + hash: sha256:e9c6c82b6d67fd8476d6d19a5961419beb04e3c0613533453ed1e16e2a569cc1 + fetched: '2026-09-14' + note: Insurance Plan IG, row 25 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Task request table. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 8.1 and Payment Notice section. +- url: https://hcxsbx.abdm.gov.in/images/2c3fbb4e6b09f0834f69.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Implementation Guide for Adoption of FHIR in ABDM and NHCX.pdf + hash: sha256:549377c9c26b1bd23decac3a1b9e5ebedfdc8e0fe99e53ef733859b188f51366 + fetched: '2026-09-14' + note: Implementation Guide for Adoption of FHIR in ABDM and NHCX, row 14 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. API table rows 5-6. +verified: + status: unverified +related: + concepts: + - nhcx.concept.coverage-eligibility-purposes + - nhcx.concept.insurance-plan + - nhcx.concept.queries-and-communication + - nhcx.concept.reprocess-and-cancel + - nhcx.concept.workflow-codes + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.policy-linking + - nhcx.concept.fhir-in-nhcx + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.insurance-plan-request + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.preauth-cancel + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + - nhcx.flow.claim-reprocess + - nhcx.flow.payment-notice + - nhcx.flow.status-check + - nhcx.flow.claim-search + - nhcx.flow.predetermination + glossary: + - nhcx.glossary.coverage-eligibility + - nhcx.glossary.preauthorisation + - nhcx.glossary.enhancement + - nhcx.glossary.predetermination + - nhcx.glossary.claim + - nhcx.glossary.payment-notice +--- + +# The claim cycle from eligibility to payment + +## In plain words + +A cashless hospital stay produces a series of exchanges between the hospital and the payer. First the hospital checks the patient's cover. Then it asks the payer to approve the treatment. After discharge it submits the claim. Finally the payer tells the hospital the money has been paid. + +Each of those steps is a separate request and response on NHCX. Together they are the claim cycle. + +## Before you start + +Read [the four message legs](./four-message-legs.md). Every stage below follows that pattern. + +## What happens + +```mermaid +graph TD + L["Policy linked to ABHA
get policies"] --> E["Coverage eligibility
/v1/coverageeligibility/check"] + IP["Insurance plan
/v1/insuranceplan/request"] --> PA + E --> PA["Preauthorisation
/v1/preauth/submit"] + PA -->|queried| QP["Query answered"] + QP --> PA + PA -->|approved| T["Treatment"] + T -->|more needed| EN["Enhancement
/v1/preauth/submit"] + EN --> T + PA -->|not going ahead| CX["Cancel
/v1/task/submit"] + T --> C["Claim after discharge
/v1/claim/submit"] + C -->|queried| QC["Query answered"] + QC --> C + C -->|approved| PN["Payment notice
payer sends /v1/paymentnotice/request"] + PN --> ACK["Provider acknowledges"] + C -->|rejected| RP["Reprocess
/v1/task/submit"] +``` + +| Stage | Who starts | Request path | Bundle | +|---|---|---|---| +| [Coverage eligibility](./coverage-eligibility-purposes.md) | Provider | `/v1/coverageeligibility/check` | CoverageEligibilityRequest | +| [Insurance plan](./insurance-plan.md) | Provider | `/v1/insuranceplan/request` | Task with code `poll` | +| Predetermination | Provider | `/v1/predetermination/submit` | Claim with use `predetermination` | +| Preauthorisation | Provider | `/v1/preauth/submit` | Claim with use `preauthorization` | +| Enhancement | Provider | `/v1/preauth/submit` | Claim, resubmitted with added items | +| Query | Payer | See [queries](./queries-and-communication.md) | ClaimResponse or CommunicationRequest | +| Claim | Provider | `/v1/claim/submit` | Claim with use `claim` | +| Payment notice | Payer | `/v1/paymentnotice/request` | Task with PaymentNotice | +| Reprocess or cancel | Provider | `/v1/task/submit` | Task | +| Status and search | Provider or regulator | `/v1/status`, `/v1/search/submit` | Protocol headers, Task | + +Every request path has an `on_` answer path, as described in [the four message legs](./four-message-legs.md). The [workflow id](./workflow-codes.md) on each message names the stage. + +### Rules that shape the cycle + +- Preauthorisation comes before planned treatment. Under PMJAY it cannot be raised more than one day before admission. +- An enhancement asks for more on an approved preauthorisation. It goes to the same path with workflow id `13`. +- The claim follows discharge. Under PMJAY, discharge details travel inside the claim, and a claim cannot be cancelled. +- A payment notice follows claim approval. The provider acknowledges it, which closes the cycle. +- A rejected or short-paid claim can be sent for reprocess. See [reprocess and cancel](./reprocess-and-cancel.md). + +## How you know it worked + +You have understood this when you can answer both of these. + +1. Your patient needs a further procedure during an approved stay. Which path do you call, with which workflow id, and what bundle? +2. The payer approved the claim. What message does the payer send next, and what must your system send back? + +## When it goes wrong + +**Claim before preauthorisation.** A standard payer refuses it with [PAYR-1010](../errors/payr-1010.md), preauthorisation required but not obtained. + +**Claiming more than was approved.** A standard payer refuses it with [PAYR-1012](../errors/payr-1012.md). + +**Answering a query with a fresh request.** A query is part of the same case. Answer it with the query response workflow id. See [queries and communication](./queries-and-communication.md). + +**Skipping the payment acknowledgement.** The cycle stays open on the payer's side until you acknowledge. diff --git a/catalogue/nhcx/concepts/coverage-eligibility-purposes.md b/catalogue/nhcx/concepts/coverage-eligibility-purposes.md new file mode 100644 index 000000000..c383151f5 --- /dev/null +++ b/catalogue/nhcx/concepts/coverage-eligibility-purposes.md @@ -0,0 +1,124 @@ +--- +id: nhcx.concept.coverage-eligibility-purposes +type: concept +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: The four coverage eligibility purposes +summary: >- + A coverage eligibility request asks one of four questions, discovery, validation, + benefits or auth-requirements, and the purpose decides what you must send and + what comes back. +sources: +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 7.3 to 7.6 Coverage Eligibility. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 8.3.1 to 8.3.4, page 32 functional points. +- url: https://hcxsbx.abdm.gov.in/images/13093b5f9b88fe826123.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Insurance Plan IG.docx + hash: sha256:e9c6c82b6d67fd8476d6d19a5961419beb04e3c0613533453ed1e16e2a569cc1 + fetched: '2026-09-14' + note: Insurance Plan IG, row 25 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. CoverageEligibility request and response tables. +verified: + status: unverified +related: + flows: + - nhcx.flow.coverage-eligibility-check + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.coverageeligibility-on-check + callbacks: + - nhcx.callback.coverageeligibility-check + - nhcx.callback.coverageeligibility-on-check + decisions: + - nhcx.decision.eligibility-purpose + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.coverage-eligibility-response + errors: + - nhcx.error.payr-1032 + - nhcx.error.payr-1033 + - nhcx.error.payr-1101 + - nhcx.error.payr-1005 + - nhcx.error.payr-1006 + - nhcx.error.payr-1007 + - nhcx.error.payr-1123 + concepts: + - nhcx.concept.insurance-plan + - nhcx.concept.policy-linking + - nhcx.concept.claim-cycle + glossary: + - nhcx.glossary.coverage-eligibility + - shared.glossary.abha-number + tests: + - nhcx.test.provider-uc-05 + - nhcx.test.payer-uc-07 +--- + +# The four coverage eligibility purposes + +## In plain words + +Before treatment, a hospital asks the payer about the patient's cover. That request is a [coverage eligibility](../glossary/coverage-eligibility.md) check. + +The check always asks one question, set in `CoverageEligibilityRequest.purpose`. Is there a policy at all? Is it in force? What does it cover? Does this treatment need approval first? The purpose you choose decides what you must send and what you get back. + +## Before you start + +You need the patient's policy code, or at least their beneficiary ID. See [policy linking](./policy-linking.md). For a PMJAY patient, fetch the [insurance plan](./insurance-plan.md) first, so you know the package codes. + +## What happens + +| Purpose | The question | Procedure or package items | What comes back | +|---|---|---|---| +| `discovery` | Does this beneficiary have an active policy? | Not used | The active policy code | +| `validation` | Is the policy in force today? | Not used | `insurance.inforce`, used and available amounts | +| `benefits` | What cover and limits apply to these items? | Required | Benefit lines with allowed amounts, and exclusions | +| `auth-requirements` | Does this treatment need preauthorisation? | Required | `authorizationRequired`, covered amount, required documents and questionnaires | + +Every purpose needs the beneficiary ID, the coverage or policy code, the payer and the provider. For a PMJAY patient the beneficiary ID is the PMJAY member ID, the [ABHA number](../../shared/glossary/abha-number.md), or both. + +```mermaid +graph LR + GP["Get policies"] -->|found| V["validation"] + GP -->|nothing found| D["discovery"] + D -->|policy code| V + V --> AR["auth-requirements
for the planned packages"] + AR -->|authorizationRequired true| PA["Preauthorisation"] + V -.-> B["benefits
for cover and limits"] +``` + +### Reading the response + +- `outcome` is `complete` when the payer processed the check. +- `disposition` is a sentence such as "Policy is currently in-force". +- `insurance[].inforce` is `true` when the policy is active. +- For each item, `excluded` says whether it is covered and `authorizationRequired` whether it needs approval first. +- `authorizationSupporting` lists the document codes the preauthorisation must carry, such as `MAND0409`. + +### When to check again + +Run an eligibility check whenever a new or additional treatment is planned, before you submit or enhance a preauthorisation. The choice between purposes is covered in [which eligibility purpose](../decisions/eligibility-purpose.md). + +## How you know it worked + +You have understood this when you can answer both of these. + +1. A patient arrives and the get policies call returns nothing. Which purpose do you send first, and what do you do with its answer? +2. You plan package `MG004A` for a patient. Which purpose tells you whether you need preauthorisation, and which response fields answer it? + +## When it goes wrong + +**Purpose not accepted.** The PMJAY payer refuses an unknown purpose with [PAYR-1101](../errors/payr-1101.md). Its structure checks use [PAYR-1032](../errors/payr-1032.md) for "Invalid purpose received". + +**Items missing for benefits or auth-requirements.** The PMJAY payer refuses the request with [PAYR-1033](../errors/payr-1033.md), no items received for the purpose. + +**Not covered, no policy, expired.** A standard payer answers with [PAYR-1005](../errors/payr-1005.md), [PAYR-1006](../errors/payr-1006.md) or [PAYR-1007](../errors/payr-1007.md). These codes carry other meanings from the PMJAY payer, so read the message text. See [error code spaces](./error-code-spaces.md). + +**Beneficiary not covered by this payer.** The PMJAY payer answers [PAYR-1123](../errors/payr-1123.md). diff --git a/catalogue/nhcx/concepts/encryption-certificate.md b/catalogue/nhcx/concepts/encryption-certificate.md new file mode 100644 index 000000000..22c86ee9b --- /dev/null +++ b/catalogue/nhcx/concepts/encryption-certificate.md @@ -0,0 +1,120 @@ +--- +id: nhcx.concept.encryption-certificate +type: concept +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Your encryption certificate and the recipient's +summary: >- + Each participant publishes a public certificate so others can seal messages for + it, and keeps the matching private key to open what it receives. +sources: +- url: https://hcxsbx.abdm.gov.in/images/ec361a6c3e90e766d227.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Steps to generate encryption Certificate.pdf + hash: sha256:94605e935f05ebb49e24dee50787cb4f3f1c401983a9616a5aaabdbc302f664b + fetched: '2026-09-14' + note: Steps to generate encryption Certificate, row 20 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1, Steps 1-3. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 2.4 and 3.3 Certificate Fetch. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy__message-security-and-integrity.md + hash: sha256:3768fd89932e4081c9e03a8695619bcaf70c641e28bb55a77eec090bb926eeb3 + fetched: '2026-09-14' + note: Site page /technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity, text as shown on the site. Message Encryption steps and key rotation note. +- url: https://hcxsbx.abdm.gov.in/images/260d0dec19a681e80262.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Production.pdf + hash: sha256:c38476fb90101f13fdfea447861292718d561e1dc088ae20950b193606500d2e + fetched: '2026-09-14' + note: Onboarding providers and payers in Production, row 5 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Step 3 and Participant Certificate Updation, page 4. +verified: + status: unverified +related: + flows: + - nhcx.flow.generate-and-register-certificate + - nhcx.flow.rotate-certificate + endpoints: + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.v2-update-cert + - nhcx.endpoint.participant-update + - nhcx.endpoint.v2-participant-update + errors: + - nhcx.error.payr-1001 + - nhcx.error.payr-1002 + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.participant-registry + - nhcx.concept.participant-code + glossary: + - nhcx.glossary.x509-certificate + - nhcx.glossary.jwe + troubleshooting: + - nhcx.troubleshooting.recipient-cannot-decrypt + tests: + - nhcx.test.provider-uc-03 + - nhcx.test.payer-uc-05 +--- + +# Your encryption certificate and the recipient's + +## In plain words + +Every message on NHCX is sealed for one recipient. To seal it, the sender needs the recipient's public key. To open it, the recipient needs its own private key. + +So every participant does two things. It publishes a public [X.509 certificate](../glossary/x509-certificate.md) in the participant registry. It keeps the matching private key secret on its own servers. + +## Before you start + +You need a participant record you can update. See [the participant registry](./participant-registry.md). + +## What happens + +### Two keys in every exchange + +```mermaid +graph LR + S["Sender"] -->|fetch recipient's certificate| RG[("Participant registry")] + S -->|seal with recipient's public key| M["Sealed message"] + M -->|via NHCX| R["Recipient"] + R -->|open with its own private key| B["FHIR bundle"] + R -->|seal response with the sender's public key| M2["Sealed response"] +``` + +Your certificate is how others reach you. The recipient's certificate is how you reach them. A response travels the same way in reverse: the payer seals it with your public key. + +### Your certificate + +- An RSA key pair of 2048 bits. +- A self-signed X.509 certificate made from it, valid for 365 days. +- The PEM certificate, Base64 encoded, sent as the encryption certificate when you update your participant record. + +The steps are in [generate and register a certificate](../flows/generate-and-register-certificate.md). The private key never leaves your system. + +### The recipient's certificate + +You fetch it with `/fetch/certs`, passing the recipient's participant code as `participantid`. The response carries the certificate in `encryption_cert`. The value is either a PEM X.509 certificate or a bare public key, so try X.509 first and fall back to the public key form. + +Cache each fetched certificate for 24 hours. Do not call `/fetch/certs` before every message. + +### Rotation + +Rotate your key pair once a year, and at once if the private key may be compromised. Upload the new certificate to your record. In production the certificate update needs no passcode. Senders that cached your old certificate keep using it until their cache expires, so keep the old private key able to open messages for a day after rotating. + +## How you know it worked + +You have understood this when you can answer both of these. + +1. You are about to send a claim to a payer. Whose certificate seals it, and where does your system get that certificate? +2. You rotated your key pair this morning and a payer's response fails to open. What is the likely cause, and how do you avoid it next time? + +## When it goes wrong + +**The recipient cannot open your message.** It reports [PAYR-1001](../errors/payr-1001.md). Fetch the recipient's certificate again from `/fetch/certs` and seal with that. See [the recipient cannot decrypt](../troubleshooting/recipient-cannot-decrypt.md). + +**The payer cannot seal its response to you.** It reports [PAYR-1002](../errors/payr-1002.md). Your certificate in the registry is missing, invalid or out of date. Update it. + +**Certificate not Base64 encoded.** The update is refused. Encode the whole PEM file, header and footer lines included. + +**Expired certificate.** A self-signed certificate made with `-days 365` expires after a year. Rotate before it does. diff --git a/catalogue/nhcx/concepts/error-code-spaces.md b/catalogue/nhcx/concepts/error-code-spaces.md new file mode 100644 index 000000000..b4a6b5db1 --- /dev/null +++ b/catalogue/nhcx/concepts/error-code-spaces.md @@ -0,0 +1,197 @@ +--- +id: nhcx.concept.error-code-spaces +type: concept +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Error code spaces: NHCX codes, standard payer codes and reference payer + codes' +summary: >- + Errors on the exchange come from three sources, the exchange itself, a standard + payer, and the government scheme's payer, and eighteen payer codes mean different + things depending on which payer sent them. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheets NHCX Error Codes, Payer Error Codes, Bridge Error, Coverage, Preauth, Claim, Insurance Plan. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Error Handling section. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1 error scenario and page 2 ProtocolResponse. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Page 26 response forms. +verified: + status: unverified +related: + concepts: + - nhcx.concept.retries-and-expiry + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.pmjay-on-nhcx + callbacks: + - nhcx.callback.error + flows: + - nhcx.flow.report-a-processing-error + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1001 + - nhcx.error.nhcx-1002 + - nhcx.error.nhcx-1003 + - nhcx.error.nhcx-1004 + - nhcx.error.nhcx-1005 + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1007 + - nhcx.error.nhcx-1008 + - nhcx.error.nhcx-1009 + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1012 + - nhcx.error.nhcx-1013 + - nhcx.error.nhcx-1014 + - nhcx.error.nhcx-1015 + - nhcx.error.nhcx-1016 + - nhcx.error.nhcx-1017 + - nhcx.error.nhcx-1018 + - nhcx.error.payr-1001 + - nhcx.error.payr-1002 + - nhcx.error.payr-1003 + - nhcx.error.payr-1004 + - nhcx.error.payr-1005 + - nhcx.error.payr-1006 + - nhcx.error.payr-1007 + - nhcx.error.payr-1008 + - nhcx.error.payr-1009 + - nhcx.error.payr-1010 + - nhcx.error.payr-1011 + - nhcx.error.payr-1012 + - nhcx.error.payr-1013 + - nhcx.error.payr-1014 + - nhcx.error.payr-1015 + - nhcx.error.payr-1016 + - nhcx.error.payr-1017 + - nhcx.error.payr-1018 + - nhcx.error.payr-1019 + - nhcx.error.payr-1020 + - nhcx.error.payr-1101 + - nhcx.error.payr-1201 + - nhcx.error.payr-1301 + - nhcx.error.payr-1401 + - nhcx.error.payr-1501 + - nhcx.error.err-pyr-clm-007 +--- + +# Error code spaces: NHCX codes, standard payer codes and reference payer codes + +## In plain words + +An error on NHCX can come from three places. The exchange refuses a bad envelope. A payer refuses a request it cannot accept. And the PMJAY payer has its own, much longer catalogue. + +Each source has its own codes. The catch: some payer codes are shared between the standard list and the PMJAY catalogue with different meanings. So a code alone does not always tell you what went wrong. + +## Before you start + +Read [the JWE envelope](./jwe-envelope.md) and [retries and expiry](./retries-and-expiry.md). Your system needs a `/v1/error` endpoint. + +## What happens + +### The three spaces + +| Space | Codes | Sent by | Arrives | +|---|---|---|---| +| Gateway | `NHCX-401`, `NHCX-1001` to `NHCX-1018` | NHCX itself | In the HTTP response to your call, or later on your callback or `/v1/error` | +| Standard payer | `PAYR-1001` to `PAYR-1020` | Any payer following the published standard | In `x-hcx-error_details` of a `ProtocolResponse`, or inside the sealed response | +| PMJAY reference payer | `PAYR-1001` to `PAYR-1520` | The PMJAY payer | The same way | + +```mermaid +graph LR + Y["Your request"] --> X["NHCX"] + X -->|envelope, registry, delivery problem| G["NHCX- code"] + X --> P["Payer"] + P -->|cannot open or validate| PR["ProtocolResponse
x-hcx-error_details"] + P -->|clinical or business problem| SR["Sealed response
error inside the bundle"] +``` + +A payer that cannot decrypt or validate your request answers with a `ProtocolResponse` in the clear, `x-hcx-status` `response.error`, and the code, message and trace in `x-hcx-error_details`. Clinical and business errors go inside the sealed response instead, so NHCX never sees them. + +### Gateway codes + +`NHCX-` codes are about the envelope, the registry and delivery: unregistered sender or receiver, bad headers, duplicate correlation id, unknown status, unreachable receiver. `NHCX-1001` is a transport error. The rest are business errors. + +### Standard payer codes + +| Codes | Meaning | +|---|---| +| `PAYR-1001` to `PAYR-1003` | Transport: cannot decrypt, cannot encrypt, cannot reach NHCX | +| `PAYR-1004` to `PAYR-1020` | Business: provider not registered, beneficiary not covered, policy missing or expired, amounts, preauthorisation, time limits, bank details | + +### PMJAY reference payer bands + +| Band | Where it arises | What it usually means | +|---|---|---| +| `PAYR-10xx` and `PAYR-15xx` | Envelope and bundle structure | An element, id, sequence, type or attachment is missing or malformed | +| `PAYR-11xx` | Coverage eligibility | The policy, the beneficiary or the hospital configuration | +| `PAYR-12xx` | Preauthorisation | Codes, amounts, dates, sequencing and scheme rules | +| `PAYR-13xx` | Claim | The same, checked against the approved preauthorisation | +| `PAYR-14xx` | Insurance plan | Empanelment, policy association, plan configuration | + +The PMJAY catalogue also has messages with no code, and marks `PAYR-1003`, `PAYR-1006` and `PAYR-1007` as deprecated in the structure band. + +### Eighteen codes with two readings + +`PAYR-1001` and `PAYR-1002` mean decryption and encryption failure in both spaces. From `PAYR-1003` to `PAYR-1020`, every code has one meaning from a standard payer and another from the PMJAY payer. + +| Code | Standard payer | PMJAY reference payer | +|---|---|---| +| `PAYR-1003` | Error connecting to NHCX; it will resend | Invalid workflow requested | +| `PAYR-1004` | Provider not registered with the payer for the policy | Received FHIR bundle is malformed | +| `PAYR-1005` | Beneficiary not covered by the policy | Maximum time limit exceeded in receiving the request | +| `PAYR-1006` | Policy does not exist | Invalid name in request | +| `PAYR-1007` | Policy expired | Invalid gender in request | +| `PAYR-1008` | Coverage amount insufficient | Invalid FHIR bundle received | +| `PAYR-1009` | Items not valid or not covered | No identifier for the patient | +| `PAYR-1010` | Preauthorisation required but not obtained | No type for the patient identifier | +| `PAYR-1011` | Package does not support enhancement | No identifier for the claim | +| `PAYR-1012` | Claim above the approved preauthorisation | No type for the claim identifier | +| `PAYR-1013` | No prior approval for the packages | No identifier for the provider organisation | +| `PAYR-1014` | Date of birth after date of service | No type for the provider organisation identifier | +| `PAYR-1015` | Date of service after date of death | No identifier for the payer organisation | +| `PAYR-1016` | Duplicate claim | No type for the payer organisation identifier | +| `PAYR-1017` | Amount calculations wrong | No task code received | +| `PAYR-1018` | Time limit for submission expired | No task reason code received | +| `PAYR-1019` | Additional information not received in time | Invalid sequence in supporting info | +| `PAYR-1020` | No valid bank details for the provider | Invalid category in supporting info | + +### The rule + +Handle a `PAYR` code together with its message text, never by the code alone. Log the code, the message and the trace. Keep a note of which payer sent it: the sender code on the response tells you. + +## How you know it worked + +You have understood this when you can answer both of these. + +1. A response arrives with `PAYR-1004` and the message "Received FHIR bundle is malformed". Which reading applies, and what do you fix? +2. Your claim submission gets `NHCX-1003` in the HTTP response. Did the payer ever see the claim? + +## When it goes wrong + +**Switching on the code alone.** A handler that maps `PAYR-1005` to "beneficiary not covered" misleads staff when the PMJAY payer means a stale timestamp. Read the message. + +**Treating a gateway error as a payer decision.** An `NHCX-` code means the exchange stopped the message. Fix the envelope or registration and send again. + +**No `/v1/error` endpoint.** Requests that NHCX drops after its retries are reported there. Without it, a failed claim looks like a slow one. See [report a processing error](../flows/report-a-processing-error.md). + +**Hard coding one list.** New PMJAY codes appear over time. Fall back to showing the payer's message for any code your system does not know. diff --git a/catalogue/nhcx/concepts/fhir-in-nhcx.md b/catalogue/nhcx/concepts/fhir-in-nhcx.md new file mode 100644 index 000000000..c1db0921e --- /dev/null +++ b/catalogue/nhcx/concepts/fhir-in-nhcx.md @@ -0,0 +1,147 @@ +--- +id: nhcx.concept.fhir-in-nhcx +type: concept +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: FHIR collection bundles and the NHCX claim profiles +summary: >- + Every claim message carries a collection bundle of health data records built to + the national claim profiles, with clinical records attached inside it, and it + must validate before it is sealed. +sources: +- url: https://hcxsbx.abdm.gov.in/#/domain-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications.md + hash: sha256:56234dd8a55fe4eb9dd852779b22b522b04760c9bec5c263d5e9bc3ac2c6f167 + fetched: '2026-09-14' + note: Site page /domain-specifications, text as shown on the site. Data Structure and Bundle types sections. +- url: https://hcxsbx.abdm.gov.in/images/2c3fbb4e6b09f0834f69.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Implementation Guide for Adoption of FHIR in ABDM and NHCX.pdf + hash: sha256:549377c9c26b1bd23decac3a1b9e5ebedfdc8e0fe99e53ef733859b188f51366 + fetched: '2026-09-14' + note: Implementation Guide for Adoption of FHIR in ABDM and NHCX, row 14 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Bundle structure section and validation steps. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 1.3 Key Principles; identifier types table. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 8.5.0 Structured Data Exchange; page 31 file limits. +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error, attachment and HFR rows. +verified: + status: unverified +related: + fhir: + - nhcx.fhir.collection-bundle + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.coverage-eligibility-response + - nhcx.fhir.insurance-plan-bundle + - nhcx.fhir.preauth-request + - nhcx.fhir.preauth-response + - nhcx.fhir.preauth-enhancement + - nhcx.fhir.preauth-cancel + - nhcx.fhir.query-update + - nhcx.fhir.claim-request + - nhcx.fhir.claim-response + - nhcx.fhir.payment-notice + - nhcx.fhir.task + - nhcx.fhir.terminologies + - nhcx.fhir.validation + - shared.fhir.hl7-validator-recipe + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.claim-cycle + - nhcx.concept.insurance-plan + - nhcx.concept.pmjay-on-nhcx + glossary: + - shared.glossary.fhir + - shared.glossary.nrces + - shared.glossary.hi-type + - shared.glossary.snomed-ct + errors: + - nhcx.error.payr-1004 + - nhcx.error.payr-1008 + - nhcx.error.payr-1043 + - nhcx.error.payr-1044 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# FHIR collection bundles and the NHCX claim profiles + +## In plain words + +The payload inside every sealed NHCX message is a [FHIR](../../shared/glossary/fhir.md) bundle: a set of related records packed together. A claim bundle holds the claim itself, the patient, the hospital, the payer, the policy, the diagnoses and procedures, and the supporting documents. + +The [NRCeS](../../shared/glossary/nrces.md) publishes the profiles these bundles must follow. A bundle that does not follow them is refused by the payer. + +## Before you start + +Read [the claim cycle](./claim-cycle.md), so you know which bundle each stage needs. + +## What happens + +### Collection, not document + +ABDM health records are FHIR bundles of type `document`, headed by a `Composition`. NHCX claim messages are bundles of type `collection`. A collection groups the records one workflow needs, with the main resource first and no bundle-level `Composition`. + +```mermaid +graph TD + B["Bundle, type collection"] --> C["Claim
use preauthorization or claim"] + B --> P["Patient"] + B --> O1["Organization: hospital, HFR ID as NPI"] + B --> O2["Organization: payer"] + B --> CV["Coverage: the policy"] + B --> PR["Practitioner, Procedure, Condition"] + C -->|supportingInfo| DR["DocumentReference
an ABDM health record inside"] +``` + +### The six claim bundles + +| Bundle | Main resource | Used for | +|---|---|---| +| Coverage eligibility request | `CoverageEligibilityRequest` | Eligibility checks | +| Coverage eligibility response | `CoverageEligibilityResponse` | Eligibility answers | +| Claim | `Claim`, with `use` of `predetermination`, `preauthorization` or `claim` | Predetermination, preauthorisation, claim | +| Claim response | `ClaimResponse` | Every decision on a claim bundle | +| Task | `Task` | Communication, payment notice, search, reprocess, insurance plan request | +| Insurance plan | `InsurancePlan` | The payer's plan | + +### Rules every bundle follows + +- Reference resources inside the bundle with `urn:uuid:` references. +- Declare the NRCeS profile of each resource in `meta.profile`. +- Send the hospital's HFR ID in the hospital `Organization` identifier, with type code `NPI`. +- Attach files as Base64. Allowed content types are `application/pdf`, `application/jpg`, `application/jpeg`, `application/png` and `application/fhir+json`. + +### Clinical records inside a claim + +Under PMJAY, clinical records travel as structured ABDM [health information types](../../shared/glossary/hi-type.md). Each record is a FHIR bundle, Base64 encoded into a `DocumentReference`, and referenced from `Claim.supportingInfo` with category `DIA`, `HDS`, `CD` or `INF`. Each document may be up to 2 MB and the whole bundle up to 20 MB. + +### Validate before you seal + +Validate every bundle against the NRCeS profile package, `https://nrces.in/ndhm/fhir/r4/package.tgz`, before encryption. A payer can only report a bad bundle after decrypting it, which costs you a full round trip. The validator command is in [the validator recipe](../../shared/fhir/hl7-validator-recipe.md). + +## How you know it worked + +You have understood this when you can answer both of these. + +1. You copied an ABDM discharge summary bundle and set its type to `collection` to use as a claim. What is still wrong with it? +2. Where in a preauthorisation bundle does a lab report go, and in what form? + +## When it goes wrong + +**Malformed bundle.** The PMJAY payer answers "Received FHIR bundle is malformed" with the validator's details. On the standard payer list the same code, [PAYR-1004](../errors/payr-1004.md), means something else, so read the message. Validate and fix. + +**Unparseable bundle.** The PMJAY payer answers [PAYR-1008](../errors/payr-1008.md) from its structure checks: invalid FHIR bundle received. + +**Dates in the wrong format.** The PMJAY payer refuses dates that do not follow the NRCeS date and date-time formats with [PAYR-1043](../errors/payr-1043.md) and [PAYR-1044](../errors/payr-1044.md). + +**Attachment rejected.** A missing name, a non Base64 value or a content type outside the list above is refused. See [the bundle is rejected](../troubleshooting/bundle-rejected.md). diff --git a/catalogue/nhcx/concepts/four-message-legs.md b/catalogue/nhcx/concepts/four-message-legs.md new file mode 100644 index 000000000..b3c5e3c73 --- /dev/null +++ b/catalogue/nhcx/concepts/four-message-legs.md @@ -0,0 +1,111 @@ +--- +id: nhcx.concept.four-message-legs +type: concept +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'The four legs of every exchange: request, acknowledgement, callback, acknowledgement' +summary: >- + Every use case completes in four legs, sender to exchange, exchange to receiver, + receiver to exchange and exchange to sender, and each leg is acknowledged at once. +sources: +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/healthclaims-exchange-protocol + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__healthclaims-exchange-protocol.md + hash: sha256:ff4b3aa02f2aa61e2b29e50699fe16bee82c3684908bc2be0815c07b97a83371 + fetched: '2026-09-14' + note: Site page /technical-specifications/open-protocol/healthclaims-exchange-protocol, text as shown on the site. Exchange Protocol, Legs 1-4 and Relays. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Message Flow and API Structure table. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 8.5 claim table, APIs to be called and implemented. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1 Acceptance scenario. +verified: + status: unverified +related: + concepts: + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.what-nhcx-is + - nhcx.concept.status-lifecycle + - nhcx.concept.retries-and-expiry + - nhcx.concept.message-identifiers + flows: + - nhcx.flow.send-a-sealed-request + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.payer-process-a-request + endpoints: + - nhcx.endpoint.claim-submit + - nhcx.endpoint.claim-on-submit + callbacks: + - nhcx.callback.claim-submit + - nhcx.callback.claim-on-submit + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback +--- + +# The four legs of every exchange: request, acknowledgement, callback, acknowledgement + +## In plain words + +NHCX works like email. You hand a message to the exchange and walk away. The answer comes back later as a new message, on a separate call. + +So every use case takes four legs. Your request goes to NHCX, NHCX delivers it, the recipient's answer goes to NHCX, and NHCX delivers the answer to you. Each leg is acknowledged at once, before any real work happens. + +## Before you start + +You need a registered endpoint URL that NHCX can reach. See [the participant registry](./participant-registry.md). + +## What happens + +```mermaid +graph LR + S["Sender"] -->|"Leg 1: POST /v1/claim/submit"| X["NHCX"] + X -->|"Leg 2: POST /v1/claim/submit"| R["Receiver"] + R -->|"Leg 3: POST /v1/claim/on_submit"| X + X -->|"Leg 4: POST /v1/claim/on_submit"| S +``` + +| Leg | Who calls | NHCX checks | Acknowledged by | +|---|---|---|---| +| 1. Sender to NHCX | The sender | Sender and recipient status, headers | NHCX, HTTP 202 | +| 2. NHCX to receiver | NHCX, to the receiver's registered endpoint | Recipient status | The receiver, HTTP 202 | +| 3. Receiver to NHCX | The receiver, on the `on_` path | Both statuses, headers | NHCX, HTTP 202 | +| 4. NHCX to sender | NHCX, to the sender's registered endpoint | Sender status | The sender, HTTP 202 | + +### The same path in both roles + +NHCX forwards a message on the same path it received it on. So `/v1/claim/submit` is a call a provider makes to NHCX, and also a call NHCX makes to the payer. `/v1/claim/on_submit` is a call the payer makes to NHCX, and also a call NHCX makes to the provider. + +Your system therefore implements the paths you receive. A provider implements the `on_` paths for its requests. A payer implements the request paths. + +### Who is the sender + +For eligibility, insurance plan, preauthorisation, claim and task requests, the provider is the sender. For payment notices and communication requests, the payer is the sender and the provider answers. + +### Between exchange instances + +The protocol allows relays between NHCX instances at the routing steps. Your system always talks to the one instance it is registered with. + +## How you know it worked + +You have understood this when you can answer both of these. + +1. You are a payer. Which path do you implement to receive a claim, and which path do you call to answer it? +2. Leg 1 returned HTTP 202 an hour ago and leg 4 has not arrived. Which legs could have failed, and which acknowledgement would have told NHCX to retry? + +## When it goes wrong + +**Waiting on the leg 1 response for the answer.** The 202 only closes leg 1. The answer is leg 4. See [the 202 acknowledgement](./synchronous-acknowledgement.md). + +**Leg 4 never arrives.** Your endpoint may be unreachable or slow to acknowledge. See [accepted, then no callback](../troubleshooting/accepted-then-no-callback.md). + +**Leg 2 fails at the receiver.** NHCX retries, then gives up and reports to your `/v1/error` endpoint. See [retries and expiry](./retries-and-expiry.md). diff --git a/catalogue/nhcx/concepts/grievance-redressal.md b/catalogue/nhcx/concepts/grievance-redressal.md new file mode 100644 index 000000000..d9c0431ee --- /dev/null +++ b/catalogue/nhcx/concepts/grievance-redressal.md @@ -0,0 +1,122 @@ +--- +id: nhcx.concept.grievance-redressal +type: concept +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Grievance redressal on the exchange +summary: >- + Any participant can raise a grievance against another under the exchange operator's + published policy, with named contacts, time limits, reopening and escalation, + and grievance messages carry their own workflow ids. +sources: +- url: https://hcxsbx.abdm.gov.in/#/domain-specifications/healthcare-operation-policy/guidelines-for-grienvance-redressal + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__healthcare-operation-policy__guidelines-for-grienvance-redressal.md + hash: sha256:c223f711b5158dbc2c3d10870c3a9610c4af32681306f53593babb64ee382230 + fetched: '2026-09-14' + note: Site page /domain-specifications/healthcare-operation-policy/guidelines-for-grienvance-redressal, text as shown on the site. Key Policy Design Guidelines. +- url: https://hcxsbx.abdm.gov.in/images/c42ad170f37c987ed173.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx + hash: sha256:f56dd156c232192296082f23b1561d0ff11fd40992e6675de41c5c991d579e6d + fetched: '2026-09-14' + note: Workflow Status Sheets(with Codes), row 12 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet1, G11 to G13 rows. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Communication reason code table; POST /communication/on_request row. +- url: https://hcxsbx.abdm.gov.in/#/introduction-NHCX/guidlines-for-participant-onboarding + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/introduction-NHCX__guidlines-for-participant-onboarding.md + hash: sha256:58aaa762f2a04565e2060658b0eda95e3cac4cbb0819b6d865f04cf53066680d + fetched: '2026-09-14' + note: Site page /introduction-NHCX/guidlines-for-participant-onboarding, text as shown on the site. Deboarding scenarios, last paragraph. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Section 23 Claim Reprocess, Q15. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. Integrator's Journey, FHIR Bundle Validation. +verified: + status: unverified +related: + concepts: + - nhcx.concept.access-control + - nhcx.concept.reprocess-and-cancel + - nhcx.concept.queries-and-communication + - nhcx.concept.audit-and-non-repudiation + - nhcx.concept.workflow-codes + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - nhcx.glossary.irdai + - nhcx.glossary.crc +--- + +# Grievance redressal on the exchange + +## In plain words + +Disputes happen between hospitals, payers, TPAs and patients. A payer ignores a case for weeks. A hospital bills a patient wrongly. A participant is removed from the exchange and disagrees. + +Each NHCX operator publishes a grievance policy that says how such disputes are raised, tracked and resolved, and how they escalate. The policy follows the insurance regulator's grievance guidelines, extended to disputes between any two participants. + +## Before you start + +Record a nodal contact for grievances, digital and physical, when your participant is onboarded. Other participants read it from the registry. + +## What happens + +### What the policy must provide + +| Guarantee | What it means for you | +|---|---| +| Digital grievances | You raise, route and track a grievance online | +| A stated scope | The policy lists which grievances it covers and where others go | +| Nodal bodies | Every participant, and the operator, publishes a contact in the registry | +| Types, priorities and time limits | Published per grievance type, including those set by regulation | +| A versioned policy | You sign it at onboarding, and you are told of every change | +| Due diligence | Grievances are investigated and reviewed before a reply | +| Reopening | You can reopen a grievance you are not satisfied with | +| Escalation | You can escalate to the operator, on faster time limits | +| Status updates | You are kept informed while it is open | + +### Grievance messages on the wire + +```mermaid +graph LR + G11["G11 grievance intimation
request.initiated"] --> G12["G12 acknowledgement
response.complete"] + G11 --> G13["G13 intimation failure
response.error"] +``` + +Workflow ids `G11`, `G12` and `G13` identify grievance intimation, acknowledgement and failure. The path a participant uses to raise a `G11` grievance is not yet published. + +A PMJAY payer also tells a hospital about a grievance that needs its action through a communication request with `Task.reasonCode` `grievance`. Acknowledge it like any communication request. See [queries and communication](./queries-and-communication.md). + +### A grievance is not a claim dispute + +To dispute a claim decision, raise a reprocess or erroneous claim through the task path. Under PMJAY those go to the [Claim Review Committee](../glossary/crc.md). See [reprocess and cancel](./reprocess-and-cancel.md). + +### Appealing removal + +A participant removed from the exchange against its will can appeal through the grievance process. + +For help with an integration, write to hcx.integration@nha.gov.in. + +## How you know it worked + +You have understood this when you can answer both of these. + +1. A payer has not answered your hospital's preauthorisation within the policy's time limit. Is that a reprocess, a query, or a grievance? What guarantees does the policy give you? +2. Your participant was blocked for repeated rate limit breaches. What route does the policy give you to challenge it? + +## When it goes wrong + +**Using a grievance to dispute a claim decision.** A rejected or short-paid claim goes through reprocess on the task path, not through grievance. + +**No nodal contact in the registry.** Other participants cannot reach you, and grievances against you escalate to the operator. + +**Ignoring a grievance communication.** Acknowledge a communication request with reason `grievance` like any other, within 30 seconds, and act on it. diff --git a/catalogue/nhcx/concepts/hmis-integration-architecture.md b/catalogue/nhcx/concepts/hmis-integration-architecture.md new file mode 100644 index 000000000..a80962daf --- /dev/null +++ b/catalogue/nhcx/concepts/hmis-integration-architecture.md @@ -0,0 +1,115 @@ +--- +id: nhcx.concept.hmis-integration-architecture +type: concept +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Hospital HMIS integration for PMJAY through NHCX +summary: >- + A hospital on the government health assurance scheme can move claims out of the + scheme's provider portal and into its own hospital system, after a six step migration + that ends in a manual mapping. +sources: +- url: https://hcxsbx.abdm.gov.in/images/be2e25fede3bf711f783.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/PMJAY Hospital Migration to HMIS via NHCX.docx + hash: sha256:cf5c9bf1c402b214f65bbb7bd0822f3a76d8ccda9b69c7bf77ba131befef3bc6 + fetched: '2026-09-14' + note: PMJAY Hospital Migration to HMIS via NHCX, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments, not named in the NHCX document sheet. Sections 2 to 3.6. +- url: https://hcxsbx.abdm.gov.in/images/b6bd99dab49a5e928ea3.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Overview.pdf + hash: sha256:c95469758a25cb8aca8c47757d8b18b4dedb8b4d42669663cff7343205f77fda + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Overview, row 27 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Pages 2-8. +verified: + status: unverified +related: + flows: + - nhcx.flow.pmjay-hospital-migration + - nhcx.flow.production-onboarding + - nhcx.flow.pmjay-patient-to-cashless + concepts: + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.participant-registry + - nhcx.concept.insurance-plan + - nhcx.concept.biometric-authentication + - nhcx.concept.encryption-certificate + endpoints: + - nhcx.endpoint.v2-participant-create + - nhcx.endpoint.validate + - nhcx.endpoint.participant-update + - nhcx.endpoint.update-validate + glossary: + - shared.glossary.hmis + - nhcx.glossary.tms + - nhcx.glossary.pmjay + - shared.glossary.dsc + - shared.glossary.hfr +--- + +# Hospital HMIS integration for PMJAY through NHCX + +## In plain words + +Today a PMJAY hospital records a patient in its own [HMIS](../../shared/glossary/hmis.md), then types the same details again into the scheme's [TMS](../glossary/tms.md) provider portal. Two systems, two rounds of data entry. + +With NHCX, the HMIS sends preauthorisations and claims itself, system to system, to the payer's TMS. The portal drops out of the hospital's workflow. + +## Before you start + +The hospital needs an [HFR](../../shared/glossary/hfr.md) facility ID with a registered mobile number, its PMJAY hospital ID, and an ABDM Milestone 1 compliant HMIS. + +## What happens + +### Before and after + +```mermaid +graph LR + subgraph "Today" + H1["HMIS"] -->|re-keyed by staff| TP["TMS 2.0 provider portal"] + TP --> TY1["TMS 2.0 payer system"] + end + subgraph "Through NHCX" + H2["NHCX-integrated HMIS"] -->|sealed FHIR messages| X["NHCX"] + X --> TY2["TMS 2.0 payer system"] + end +``` + +### What the HMIS must hold + +| Capability | Why | +|---|---| +| Session tokens and a certificate pair | To call NHCX and to seal and open messages | +| A public HTTPS endpoint | NHCX delivers payer responses there | +| An insurance plan store | Packages, rates, forms and required documents per policy | +| Biometric capture | Patient presence at registration, preauthorisation and discharge | +| A FHIR bundle builder and validator | Structured claims and clinical records | + +### The migration, in six steps + +1. **Create the participant** with registry type `10001` (HFR), role `10001` (provider), the HFR ID and the HFR-registered mobile number. +2. **Confirm it** with the transaction ID and the passcode sent to that mobile. +3. **Update it** with the HMIS endpoint URL and the Base64 encoded certificate. +4. **Confirm the update** with a second passcode, valid for 24 hours. +5. **Map it.** The hospital raises a ticket with the NHA NHCX operations team, giving the PMJAY hospital ID and the new participant ID. This step is manual. +6. **Go live.** The mapping is the switch. + +### Dual processing + +Cases submitted before the mapping finish in the TMS provider portal. Cases started after it go only through the HMIS. TMS stops accepting new preauthorisations from that hospital. + +## How you know it worked + +You have understood this when you can answer both of these. + +1. A patient's preauthorisation was raised in the TMS portal the day before your mapping. Where does its claim go? +2. Steps 1 to 4 are complete but claims still show only in TMS. Which step is missing, and who performs it? + +## When it goes wrong + +**Mobile number mismatch.** Participant creation fails unless the mobile matches the HFR record exactly. Update HFR first. + +**Wrong registry type or role.** A PMJAY hospital must use HFR (`10001`) and provider (`10001`). Anything else is rejected. + +**Mapping not raised or not complete.** Until the NHA operations team maps the hospital ID to the participant ID, new cases do not route through the HMIS. + +**Endpoint not reachable.** The mapping needs a live HTTPS endpoint that NHCX can reach. diff --git a/catalogue/nhcx/concepts/insurance-plan.md b/catalogue/nhcx/concepts/insurance-plan.md new file mode 100644 index 000000000..bc665b4fd --- /dev/null +++ b/catalogue/nhcx/concepts/insurance-plan.md @@ -0,0 +1,138 @@ +--- +id: nhcx.concept.insurance-plan +type: concept +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: The insurance plan and what a provider learns from it +summary: >- + The insurance plan is the payer's policy published as structured data, listing + the packages, rates, conditions and documents a hospital may claim, and the hospital + fetches and caches it before treating. +sources: +- url: https://hcxsbx.abdm.gov.in/images/13093b5f9b88fe826123.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Insurance Plan IG.docx + hash: sha256:e9c6c82b6d67fd8476d6d19a5961419beb04e3c0613533453ed1e16e2a569cc1 + fetched: '2026-09-14' + note: Insurance Plan IG, row 25 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Task request tables; InsurancePlan structure tables. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. InsurancePlan section, claim condition table. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Page 16 Insurance Plan technical guidelines. +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Insurance Plan Error, PAYR-1406. +verified: + status: unverified +related: + flows: + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.insuranceplan-request + - nhcx.endpoint.insuranceplan-on-request + callbacks: + - nhcx.callback.insuranceplan-request + - nhcx.callback.insuranceplan-on-request + fhir: + - nhcx.fhir.insurance-plan-bundle + - nhcx.fhir.pmjay-insurance-plan + errors: + - nhcx.error.payr-1401 + - nhcx.error.payr-1402 + - nhcx.error.payr-1403 + - nhcx.error.payr-1404 + - nhcx.error.payr-1405 + - nhcx.error.payr-1406 + concepts: + - nhcx.concept.coverage-eligibility-purposes + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.claim-cycle + - nhcx.concept.fhir-in-nhcx + glossary: + - nhcx.glossary.insurance-plan + - nhcx.glossary.hbp + - nhcx.glossary.pmjay + - shared.glossary.hfr + tests: + - nhcx.test.provider-uc-06 + - nhcx.test.payer-uc-08 +--- + +# The insurance plan and what a provider learns from it + +## In plain words + +An [insurance plan](../glossary/insurance-plan.md) is the payer's policy published as data rather than as a PDF. It tells a hospital what it may treat under the policy, at what rate, under which conditions, and with which documents. + +The hospital fetches it through NHCX, stores it, and uses it to fill in preauthorisations and claims. Under [PMJAY](../glossary/pmjay.md) nearly every later step depends on it. + +## Before you start + +You need the policy code, your [HFR](../../shared/glossary/hfr.md) facility ID, and the payer's participant code. + +## What happens + +### Asking for the plan + +You send a FHIR `Task` to `/v1/insuranceplan/request`: + +| Element | Value | +|---|---| +| `Task.status` | `requested` | +| `Task.intent` | `order` | +| `Task.code` | `poll`, system `https://nhcx.abdm.gov.in/api` | +| `Task.input` | `policyNumber` and `providerId`; at least one is required | + +The plan arrives later on `/v1/insuranceplan/on_request` as a `collection` bundle of `InsurancePlan`, `Organization` and `Questionnaire` resources. + +### What the plan holds + +```mermaid +graph TD + P["InsurancePlan.plan"] --> G["generalCost
overall sum insured"] + P --> SC["specificCost"] + SC --> CAT["category
speciality, such as GM"] + CAT --> BEN["benefit
package, such as SE012A"] + BEN --> COST["cost
package rate"] + COST --> QUAL["qualifiers
implant, stratification"] + P --> EXT["extensions
claim conditions, exclusions,
required documents"] +``` + +- **Specialities and packages.** Only those your hospital is empanelled for. The plan is specific to the payer, the policy and your hospital. +- **Package rates and qualifiers.** ICU or HDU stratification and implants carry their own amounts. +- **Claim conditions.** Per package flags such as `ApprovalNotRequired`, `EnhancementAllowed`, `ImplantApplicable`, `CyclicProcedure`, `Standalone` and `Unspecified`. +- **Required documents.** At policy level and per package, for preauthorisation and for claim. +- **Questionnaires.** Standard treatment guideline forms. You return the questionnaire URL in the `QuestionnaireResponse` of your preauthorisation or claim. + +### Keeping it current + +- The bundle can exceed 20 MB. Store it in a queryable form, linked to the policy. +- Refresh it weekly, and at once when the payer renews or amends the policy. +- Keep versions of rates and packages, and record which version each preauthorisation and claim used. + +## How you know it worked + +You have understood this when you can answer both of these. + +1. A package you want to add during an enhancement shows `EnhancementAllowed` as `N`. What should your system do? +2. Your weekly refresh fails for a policy while an earlier request is still running. What does the payer tell you, and how long do you wait? + +## When it goes wrong + +**A second request while one is running.** The PMJAY payer refuses it with [PAYR-1406](../errors/payr-1406.md). Wait 15 to 60 minutes. If no plan arrives after 60 minutes, contact support. + +**Policy not allowed for your hospital.** [PAYR-1401](../errors/payr-1401.md). + +**Policy or renewal unknown to the payer.** [PAYR-1402](../errors/payr-1402.md) and [PAYR-1403](../errors/payr-1403.md). Check the values in your `Task`. + +**No speciality configured, or hospital not found.** [PAYR-1404](../errors/payr-1404.md) and [PAYR-1405](../errors/payr-1405.md). Check the HFR ID you sent. + +**Stale rates.** A claim priced from an outdated plan version is rejected. Refresh before you price. diff --git a/catalogue/nhcx/concepts/jwe-envelope.md b/catalogue/nhcx/concepts/jwe-envelope.md new file mode 100644 index 000000000..4b97163fa --- /dev/null +++ b/catalogue/nhcx/concepts/jwe-envelope.md @@ -0,0 +1,134 @@ +--- +id: nhcx.concept.jwe-envelope +type: concept +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: The JWE envelope that seals every payload +summary: >- + Every use case message is a sealed encryption envelope: routing headers the exchange + can read, wrapped around a claim bundle only the recipient can open. +sources: +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy__message-security-and-integrity.md + hash: sha256:3768fd89932e4081c9e03a8695619bcaf70c641e28bb55a77eec090bb926eeb3 + fetched: '2026-09-14' + note: Site page /technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity, text as shown on the site. Message Security and Integrity, encryption steps. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/healthclaims-exchange-protocol + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__healthclaims-exchange-protocol.md + hash: sha256:ff4b3aa02f2aa61e2b29e50699fe16bee82c3684908bc2be0815c07b97a83371 + fetched: '2026-09-14' + note: Site page /technical-specifications/open-protocol/healthclaims-exchange-protocol, text as shown on the site. Message Structure, Registered JOSE and Signatures. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 4, Q13. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 1.3 Key Principles; Section 2.3 HTTP Request Format. +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use case 7 API logic. +verified: + status: unverified +related: + decisions: + - nhcx.decision.key-encryption-algorithm + - nhcx.decision.jwe-serialisation + concepts: + - nhcx.concept.protocol-headers + - nhcx.concept.encryption-certificate + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.error-code-spaces + flows: + - nhcx.flow.send-a-sealed-request + - nhcx.flow.receive-a-sealed-callback + errors: + - nhcx.error.payr-1001 + - nhcx.error.payr-1517 + glossary: + - nhcx.glossary.jwe + - nhcx.glossary.protected-header + - shared.glossary.fhir + troubleshooting: + - nhcx.troubleshooting.recipient-cannot-decrypt +--- + +# The JWE envelope that seals every payload + +## In plain words + +Every use case message on NHCX is a [JSON Web Encryption (JWE)](../glossary/jwe.md) envelope. Think of a sealed envelope with the address printed on the outside. + +The outside is the [protected header](../glossary/protected-header.md). It carries who sent the message, who must receive it and where it sits in the claim. NHCX reads it to route. The inside is the [FHIR](../../shared/glossary/fhir.md) bundle, encrypted so that only the recipient can read it. + +## Before you start + +You need the recipient's public certificate and your own private key. See [encryption certificates](./encryption-certificate.md). + +## What happens + +### The five parts + +A sealed message is five Base64URL parts joined by dots. + +```mermaid +graph LR + H["1. Protected header
alg, enc, x-hcx-*"] --- K["2. Encrypted key
content key, sealed with
recipient's RSA key"] + K --- I["3. Initialisation vector"] + I --- C["4. Ciphertext
the FHIR bundle"] + C --- T["5. Authentication tag"] +``` + +1. **Protected header.** The JOSE fields `alg` and `enc`, plus the [protocol headers](./protocol-headers.md) and any domain headers. +2. **Encrypted key.** A random content key, wrapped with the recipient's RSA public key using RSA-OAEP. Which RSA-OAEP variant to set in `alg` is covered in [the key encryption algorithm](../decisions/key-encryption-algorithm.md). +3. **Initialisation vector.** Random, fresh for every message. +4. **Ciphertext.** The FHIR bundle, encrypted with AES-256-GCM, so `enc` is `A256GCM`. +5. **Authentication tag.** Proves nothing changed. + +### Why there is no separate signature + +AES-GCM authenticates the protected header as well as the ciphertext. If anyone changes a header or a byte of the payload, the tag no longer matches and the recipient must reject the message. So the envelope needs no second signature. + +The protocol allows no unprotected headers and no multiple recipients. One envelope, one recipient. + +### What goes on the wire + +The request body carries the sealed string in a `payload` field: + +```json +{ "payload": "" } +``` + +How the five parts are serialised is covered in [JWE serialisation](../decisions/jwe-serialisation.md). + +### What comes back + +A response from a payer takes one of two forms, named by its `type`: + +| `type` | When | Readable by NHCX | +|---|---|---| +| `JWEPayloadResponse` | The payer processed the request | No, sealed for you | +| `ProtocolResponse` | The payer could not open or validate the request | Yes, headers and error in the clear | + +## How you know it worked + +You have understood this when you can answer both of these. + +1. A proxy between your system and NHCX rewrites `x-hcx-timestamp` inside the protected header. What happens when the payer tries to open the message, and why? +2. A payer cannot decrypt your request. In which of the two response forms does it tell you, and why can that form not be sealed? + +## When it goes wrong + +**The recipient cannot decrypt.** It reports [PAYR-1001](../errors/payr-1001.md). The usual cause is a stale or wrong certificate. Fetch it again. + +**Error sent sealed.** An error reply must be a `ProtocolResponse` in the clear. A sealed reply where an error structure is expected is refused with [PAYR-1517](../errors/payr-1517.md). + +**Header edited after sealing.** Any change to the protected header after encryption breaks the tag. Build the full header first, then seal. + +**Plaintext bundle in the body.** Every use case request must be sealed. No FHIR content travels in the clear. diff --git a/catalogue/nhcx/concepts/message-identifiers.md b/catalogue/nhcx/concepts/message-identifiers.md new file mode 100644 index 000000000..5d933a144 --- /dev/null +++ b/catalogue/nhcx/concepts/message-identifiers.md @@ -0,0 +1,116 @@ +--- +id: nhcx.concept.message-identifiers +type: concept +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Correlation id, API call id and workflow id +summary: >- + Four identifiers track every message: one per network call, one per request, one + per conversation and one for the stage of the case. +sources: +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Protected Header table. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 3, Q4. +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use case 7 Validations. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 2, item 8. +verified: + status: unverified +related: + glossary: + - nhcx.glossary.correlation-id + - nhcx.glossary.api-call-id + - nhcx.glossary.workflow-id + concepts: + - nhcx.concept.protocol-headers + - nhcx.concept.workflow-codes + - nhcx.concept.retries-and-expiry + - nhcx.concept.four-message-legs + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1012 + - nhcx.error.nhcx-1016 + - nhcx.error.payr-1516 + troubleshooting: + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + endpoints: + - nhcx.endpoint.status +--- + +# Correlation id, API call id and workflow id + +## In plain words + +Many messages fly back and forth for one patient's claim. Four identifiers in the protocol headers keep them apart and tie them together. + +The [API call id](../glossary/api-call-id.md) names one network call. The request id names one request. The [correlation id](../glossary/correlation-id.md) names one conversation, a request and everything that answers it. The [workflow id](../glossary/workflow-id.md) names the stage the case has reached. + +## Before you start + +Read [the protocol headers](./protocol-headers.md) first. + +## What happens + +| Identifier | Header | Scope | Who sets it | +|---|---|---|---| +| API call id | `x-hcx-api_call_id` | One HTTP call | The caller, new on every call | +| Request id | `x-hcx-request_id` | One originating request | The sender | +| Correlation id | `x-hcx-correlation_id` | One conversation | The initiator; responders copy it | +| Workflow id | `x-hcx-workflow_id` | The stage of the case | Whoever sends the message | + +API call id, request id and correlation id are random 36 character UUIDs. The API call id and the correlation id on a message are always different values. + +### How they relate in one exchange + +```mermaid +graph TD + R["Provider request
correlation C, call id A1"] --> ACK1["NHCX 202"] + R --> F["Delivered to payer
correlation C"] + F --> RS["Payer response
correlation C, call id A2"] + RS --> D["Delivered to provider
correlation C"] +``` + +The payer's response carries the same correlation id as the request, and a new API call id of its own. Your system matches the response to its request by the correlation id. + +### Rules + +- **New call, new API call id.** Never reuse one, even on a retry you send yourself. +- **New request, new correlation id.** NHCX refuses an initiating request whose correlation id it already holds. +- **A response copies the correlation id.** Every message that answers a request carries that request's correlation id. +- **After a failure, start again.** When a request fails, NHCX makes its correlation id inactive. Send a fresh request with a new correlation id. +- **The workflow id changes with the stage.** It says what this message is: a new preauthorisation, a query response, a payment acknowledgement. + +## How you know it worked + +You have understood this when you can answer both of these. + +1. Your preauthorisation failed on the payer's side and you fixed the bundle. Which identifiers must be new on the resubmission, and why? +2. Two responses arrive for two different claims from the same payer. Which header tells you which claim each one belongs to? + +## When it goes wrong + +**Duplicate correlation id.** NHCX refuses the request with [NHCX-1006](../errors/nhcx-1006.md). Generate a fresh correlation id. + +**Response with an unknown correlation id.** NHCX refuses a callback whose correlation id it does not hold with [NHCX-1010](../errors/nhcx-1010.md). + +**Unknown API call id.** A lookup by an API call id NHCX has no record of returns [NHCX-1012](../errors/nhcx-1012.md). + +**Wrong action for the conversation.** [NHCX-1016](../errors/nhcx-1016.md) means the action does not fit the correlation id you sent. + +**The payer has no matching event.** The PMJAY payer reports [PAYR-1516](../errors/payr-1516.md) when it cannot find the API call id and correlation id pair. See [mismatched correlation](../troubleshooting/duplicate-or-mismatched-correlation.md). diff --git a/catalogue/nhcx/concepts/notifications.md b/catalogue/nhcx/concepts/notifications.md new file mode 100644 index 000000000..c74c61220 --- /dev/null +++ b/catalogue/nhcx/concepts/notifications.md @@ -0,0 +1,117 @@ +--- +id: nhcx.concept.notifications +type: concept +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Notifications to patient apps +summary: >- + A patient's health record app subscribes on login to claim events for that person, + and the exchange then pushes short readable updates to the app, with only the + most recently linked app receiving them. +sources: +- url: https://hcxsbx.abdm.gov.in/images/01db86335b7c226eb745.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Notification Integration.docx + hash: sha256:05908862c103522fac0dbb482f8eb6a0f8536fc12b1ae3bdb0e98615f30812aa + fetched: '2026-09-14' + note: NHCX Notification Integration, listed on https://hcxsbx.abdm.gov.in/#/documents, not named in the NHCX document sheet. Whole document, sections 1 to 7. +verified: + status: unverified +related: + flows: + - nhcx.flow.notification-subscribe + endpoints: + - nhcx.endpoint.notification-subscribe + callbacks: + - nhcx.callback.notification-delivery + concepts: + - nhcx.concept.beneficiary-consent + - nhcx.concept.session-token + - nhcx.concept.jwe-envelope + - nhcx.concept.participant-roles + glossary: + - shared.glossary.phr + - shared.glossary.eua + - shared.glossary.abha-address + - nhcx.glossary.payment-notice +--- + +# Notifications to patient apps + +## In plain words + +A patient wants to know when their preauthorisation is approved or their claim is paid. NHCX can tell their [personal health record (PHR)](../../shared/glossary/phr.md) app directly. + +The app subscribes for the patient when the patient logs in. From then on, NHCX pushes each claim event to the app as a short message the app can show as it is. + +## Before you start + +The app must have completed ABDM Milestone 1, be registered on NHCX as a beneficiary service provider, and host an HTTPS endpoint on TLS 1.2 or later. It needs a [session token](./session-token.md) and must be able to seal a [JWE](./jwe-envelope.md). It must also have the patient's explicit consent to receive claim updates. + +## What happens + +```mermaid +graph LR + U["Patient logs in
with ABHA"] --> APP["PHR app"] + APP -->|"/v1/notification/subscribe
subscriber.id = ABHA"| X["NHCX"] + H["Hospital and payer
exchange claim messages"] --> X + X -->|"event pushed to
on_notification_url"| APP + APP --> U2["Patient sees the message"] +``` + +### Last linked wins + +A subscription is for one ABHA. When the patient logs into another app and that app subscribes, the new subscription replaces the old one. At any moment exactly one app receives the patient's notifications, so no app needs to handle duplicates. + +### The subscription + +| Field | Holds | +|---|---| +| `subscription_id` | Your ID for this subscription | +| `topic_code` | A list of topics | +| `recipient_code` | Your participant code | +| `subscriber.id` | The patient's ABHA address or number | +| `on_notification_url` | Your HTTPS endpoint for pushed events | +| `expiry` | Optional end time | + +| Topic | Carries | +|---|---| +| `workflow_events` | Preauthorisation, claim, payment and communication events for the patient | +| `network_events` | Platform updates and maintenance | +| `participant_events` | Changes to payer and provider registrations | + +Most patient apps need only `workflow_events`. + +### A pushed event + +Each event carries `notification_id`, `topic_code`, `timestamp`, `subscriber.id` and `message`. The `message` is written for the patient, for example "Preauthorization approved for Rs. 50,000". An optional `domain_values` map repeats `x-hcx-*` headers for apps that want detail. + +| Event type | Status values | +|---|---| +| `preauth_request`, `claim_request` | `queued`, `processing` | +| `preauth_response`, `claim_response` | `approved`, `rejected` | +| `payment_notice` | `paid`, `pending` | +| `communication` | `information_required` | + +### Not the same as a payment notice + +A [payment notice](../glossary/payment-notice.md) is a payer telling a hospital about money, as a FHIR bundle. A patient notification is NHCX telling an app about an event, as a short message. + +## How you know it worked + +You have understood this when you can answer both of these. + +1. A patient uses app A, then logs into app B, which subscribes. Which app receives the next claim event, and does app A need to do anything? +2. Your app wants only to show updates to the patient. Which field of the pushed event do you display? + +## When it goes wrong + +**401 Unauthorized.** The session token expired. Fetch a new one and subscribe again. + +**403 Forbidden.** Your participant is not authorised. Check your registration on NHCX. + +**No events arrive.** Another app subscribed for the same patient later, or your endpoint is not reachable over HTTPS with TLS 1.2 or later. + +**500 Server Error.** Retry the subscription with backoff. + +**Trusting any caller.** Validate the token NHCX sends with each push, check that the sender code is NHCX's, and rate limit the endpoint. diff --git a/catalogue/nhcx/concepts/participant-code.md b/catalogue/nhcx/concepts/participant-code.md new file mode 100644 index 000000000..bdf422848 --- /dev/null +++ b/catalogue/nhcx/concepts/participant-code.md @@ -0,0 +1,133 @@ +--- +id: nhcx.concept.participant-code +type: concept +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Participant codes and how every message is addressed +summary: >- + A participant code is the address the exchange issues to each registered organisation, + and every message carries two of them: the sender's and the recipient's. +sources: +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/registries + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__registries.md + hash: sha256:04bf78739fa0c3807a8a5a49d8c3e004f8aba664f524d0344d7fc44c3b2baf42 + fetched: '2026-09-14' + note: Site page /technical-specifications/open-protocol/registries, text as shown on the site. Registry table, participant_code row. +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use case 7 Validations. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 2, item 7. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 4, Q11. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. Integrator's Journey page 6, step 3c. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1 Acceptance scenario body. +- url: https://hcxsbx.abdm.gov.in/images/539853c50347b32b9a5e.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Policy Linking and De-Linking Process.pdf + hash: sha256:420115b9a54e15fa625312a56362164d92d23dd0d6ebf9195135bb00055d1911 + fetched: '2026-09-14' + note: Policy Linking and De-Linking Process, row 8 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1, Policy Linking Process. +verified: + status: unverified +related: + concepts: + - nhcx.concept.participant-registry + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.policy-linking + glossary: + - nhcx.glossary.participant-code + - shared.glossary.hfr + endpoints: + - nhcx.endpoint.fetch-participants-list + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.participant-get-policies + errors: + - nhcx.error.nhcx-1003 + - nhcx.error.payr-1001 + sandbox: + - nhcx.sandbox.test-participants + - nhcx.sandbox.dummy-payer +--- + +# Participant codes and how every message is addressed + +## In plain words + +A [participant code](../glossary/participant-code.md) is your address on the exchange. NHCX issues it when you register. It looks like a number followed by `@` and an instance code, for example `100001@sbx`. + +Every message carries two codes: who sent it and who must receive it. NHCX routes on those two codes alone. + +## Before you start + +You need a confirmed participant record. See [the participant registry](./participant-registry.md). + +## What happens + +### Where the codes appear + +| Place | Field | Holds | +|---|---|---| +| Protected header | `x-hcx-sender_code` | Your code | +| Protected header | `x-hcx-recipient_code` | The code of the participant that must act | +| Certificate lookup | `participantid` in `/fetch/certs` | The code whose certificate you need | +| Your 202 acknowledgement | `result.sender_code`, `result.recipient_code` | The codes from the message you received | +| Policy link | `payerid`, `processingid` | The insurer's code and the TPA's code | + +### Codes swap on the way back + +```mermaid +graph LR + subgraph Request + A1["sender: hospital code"] --> B1["recipient: payer code"] + end + subgraph Response + A2["sender: payer code"] --> B2["recipient: hospital code"] + end +``` + +A response reverses the pair. The responder puts its own code in `x-hcx-sender_code`. It puts the original sender's code in `x-hcx-recipient_code`. + +### One code per facility + +An organisation can hold several participant codes, one for each HFR facility ID. It uses the same ABDM credentials to create all of them. + +### Rules for handling a code + +- Store the code exactly as NHCX issued it, suffix included. +- Do not build codes or read meaning into the suffix. Sandbox and production codes are both opaque strings. +- Take a payer's code from the participant list or from the policy, never from memory. + +## How you know it worked + +You have understood this when you can answer both of these. + +1. A payer answers your claim. What must it put in `x-hcx-sender_code` and in `x-hcx-recipient_code`? +2. Your hospital group has three facilities with three HFR IDs. How many participant codes do you need, and how many sets of credentials? + +## When it goes wrong + +**Addressing the wrong party.** A provider must put the policy's `processingID` in `x-hcx-recipient_code`, not the `PayerID`. + +**Codes not swapped on a response.** A payer's response must name the original sender as recipient. Otherwise NHCX cannot deliver it to the right system. + +**Recipient not registered.** NHCX refuses the message with [NHCX-1003](../errors/nhcx-1003.md). + +**Certificate fetched for the wrong code.** The recipient cannot open a message sealed with someone else's key and reports [PAYR-1001](../errors/payr-1001.md). diff --git a/catalogue/nhcx/concepts/participant-registry.md b/catalogue/nhcx/concepts/participant-registry.md new file mode 100644 index 000000000..74edd433c --- /dev/null +++ b/catalogue/nhcx/concepts/participant-registry.md @@ -0,0 +1,136 @@ +--- +id: nhcx.concept.participant-registry +type: concept +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: The participant registry and what a participant record holds +summary: >- + The participant registry is the exchange's address book: each record holds a participant's + code, role, callback address and public certificate, and nothing routes until + the record is confirmed. +sources: +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/registries + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__registries.md + hash: sha256:04bf78739fa0c3807a8a5a49d8c3e004f8aba664f524d0344d7fc44c3b2baf42 + fetched: '2026-09-14' + note: Site page /technical-specifications/open-protocol/registries, text as shown on the site. Participating Organisations/Systems Registry table. +- url: https://hcxsbx.abdm.gov.in/images/260d0dec19a681e80262.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Production.pdf + hash: sha256:c38476fb90101f13fdfea447861292718d561e1dc088ae20950b193606500d2e + fetched: '2026-09-14' + note: Onboarding providers and payers in Production, row 5 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Steps 1-4 and Participant Certificate Updation. +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths /fetch/participants/list and /fetch/certs.' +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error, HFR mismatch row. +verified: + status: unverified +related: + concepts: + - nhcx.concept.participant-code + - nhcx.concept.participant-roles + - nhcx.concept.encryption-certificate + - nhcx.concept.session-token + endpoints: + - nhcx.endpoint.participant-create + - nhcx.endpoint.v2-participant-create + - nhcx.endpoint.validate + - nhcx.endpoint.participant-update + - nhcx.endpoint.v2-participant-update + - nhcx.endpoint.update-validate + - nhcx.endpoint.participant-search + - nhcx.endpoint.participant-details + - nhcx.endpoint.fetch-participants-list + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.v2-update-cert + flows: + - nhcx.flow.sandbox-onboarding + - nhcx.flow.production-onboarding + - nhcx.flow.generate-and-register-certificate + errors: + - nhcx.error.nhcx-1002 + - nhcx.error.nhcx-1003 + - nhcx.error.nhcx-1004 + glossary: + - nhcx.glossary.participant-code + - shared.glossary.hfr +--- + +# The participant registry and what a participant record holds + +## In plain words + +The participant registry is the exchange's address book. It holds one record for every organisation that can send or receive through NHCX. + +When a message arrives, NHCX looks up the sender and the recipient here. It finds where to deliver the message. Other participants find your public certificate here, so they can seal messages for you. + +## Before you start + +You need a session token from your ABDM credentials. See [the session token](./session-token.md). A provider also needs an [HFR](../../shared/glossary/hfr.md) facility ID whose registered mobile number you can receive a passcode on. + +## What happens + +### What a record holds + +| Attribute | Required | What it is for | +|---|---|---| +| `participant_code` | Yes | Your address on the exchange, issued by NHCX. See [participant codes](./participant-code.md) | +| `participant_name` | Yes | Your organisation's name | +| `roles` | Yes | What you may send and receive. See [participant roles](./participant-roles.md) | +| `registry_code` | No | Your ID in the external registry, such as your HFR ID | +| `mobile` | Yes | One to three numbers; passcodes go here | +| `email`, `phone` | No | Up to three each | +| `status` | Yes | Where the record is in its life | +| `endpoint_url` | Yes | Where NHCX delivers your incoming messages | +| `encryption_cert` | Yes | Your public certificate, so others can seal messages for you | +| `signing_cert_path`, `address`, `payment_details` | No | Signing certificate, address, bank or UPI details | + +### How a record comes to life + +```mermaid +graph LR + C["Create
role, registry ID, mobile"] -->|passcode to registered mobile| V["Confirm
transaction ID + passcode"] + V --> A["Active"] + A --> U["Update
endpoint URL + certificate"] + U -->|passcode| UV["Confirm update"] + UV --> R["Ready to exchange"] +``` + +1. **Create.** You send the registry type, registry ID, role, mobile and email. NHCX checks the mobile number against the HFR record for a provider, or the payer record for a payer. It returns your participant code. +2. **Confirm.** When the create response carries a `transactionid`, NHCX sends a passcode to the registered mobile. You confirm with both. Until then the record cannot be used. +3. **Update.** You add your endpoint URL and your Base64 encoded certificate. +4. **Confirm the update.** A second passcode confirms it. The endpoint and certificate then become live. + +In production the transaction ID and passcode are valid for 24 hours. A certificate alone can later be replaced without a passcode. + +### The four states + +The registry model defines four states: created and not yet verified, active, inactive, and blocked. Only an active participant can exchange messages. + +### How others read the registry + +A sender lists participants by role with `/fetch/participants/list`. It fetches a recipient's certificate with `/fetch/certs`, passing the recipient's participant code. + +## How you know it worked + +You have understood this when you can answer both of these. + +1. Your participant is created and confirmed, but no endpoint URL is recorded. What happens to a claim response a payer sends you? +2. You changed your key pair. Which attribute must change in your record, and why do other participants care? + +## When it goes wrong + +**The mobile number does not match.** For a provider, the mobile you send must match the HFR record exactly. Correct it in HFR or send the registered number. + +**Lost transaction ID or expired passcode.** Start the create or update call again. Each call issues a new transaction ID and passcode. + +**Sender or receiver not registered.** NHCX refuses the message with [NHCX-1002](../errors/nhcx-1002.md) or [NHCX-1003](../errors/nhcx-1003.md). [NHCX-1004](../errors/nhcx-1004.md) means no receiver is registered for the scheme you addressed. + +**HFR ID in the bundle differs from the registry.** The PMJAY payer checks the hospital HFR ID in the bundle. It refuses the bundle when that ID differs from the sender's registry ID. diff --git a/catalogue/nhcx/concepts/participant-roles.md b/catalogue/nhcx/concepts/participant-roles.md new file mode 100644 index 000000000..cb43ea682 --- /dev/null +++ b/catalogue/nhcx/concepts/participant-roles.md @@ -0,0 +1,145 @@ +--- +id: nhcx.concept.participant-roles +type: concept +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Participant roles: provider, payer, TPA and the exchange' +summary: >- + Every system on the claims exchange registers with one role, and the role decides + which messages it sends, which it receives and how it is addressed. +sources: +- url: https://hcxsbx.abdm.gov.in/images/260d0dec19a681e80262.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Production.pdf + hash: sha256:c38476fb90101f13fdfea447861292718d561e1dc088ae20950b193606500d2e + fetched: '2026-09-14' + note: Onboarding providers and payers in Production, row 5 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 4, Valid Role Enums and Registry Enums. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 3, Q6 to Q9. +- url: https://hcxsbx.abdm.gov.in/#/domain-specifications/healthcare-operation-policy/access-control + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__healthcare-operation-policy__access-control.md + hash: sha256:7c3d7b2cf396a9daaca76ade1c059a8d358d0686b7b7e041e96c5f7f239dae57 + fetched: '2026-09-14' + note: Site page /domain-specifications/healthcare-operation-policy/access-control, text as shown on the site. Access Controls role list. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. API Structure table. +- url: https://hcxsbx.abdm.gov.in/images/539853c50347b32b9a5e.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Policy Linking and De-Linking Process.pdf + hash: sha256:420115b9a54e15fa625312a56362164d92d23dd0d6ebf9195135bb00055d1911 + fetched: '2026-09-14' + note: Policy Linking and De-Linking Process, row 8 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1, Policy Linking Process. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1 item 5; page 2 item 7. +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error, 'No user role found' row. +verified: + status: unverified +related: + concepts: + - nhcx.concept.participant-registry + - nhcx.concept.participant-code + - nhcx.concept.access-control + - nhcx.concept.policy-linking + - nhcx.concept.what-nhcx-is + glossary: + - nhcx.glossary.provider + - nhcx.glossary.payer + - nhcx.glossary.tpa + - nhcx.glossary.irdai + - shared.glossary.eua + - shared.glossary.hfr + endpoints: + - nhcx.endpoint.participant-create + - nhcx.endpoint.v2-participant-create + - nhcx.endpoint.participant-get-policies + flows: + - nhcx.flow.sandbox-onboarding + - nhcx.flow.production-onboarding + - nhcx.flow.payer-process-a-request +--- + +# Participant roles: provider, payer, TPA and the exchange + +## In plain words + +Every system that talks through NHCX registers with a role. A hospital registers as a [provider](../glossary/provider.md). An insurer registers as a [payer](../glossary/payer.md). A [third party administrator (TPA)](../glossary/tpa.md) processes claims on an insurer's behalf. + +The role decides which messages your system sends and which it must receive. NHCX itself has no role in a claim. It routes messages between the participants. + +## Before you start + +Know which kind of organisation you are building for. A hospital system registers as a provider. An insurer or TPA system registers as a payer or TPA. + +## What happens + +### The role codes + +You pass one of these codes in `role` when you create a participant. + +| Role | Code | Who | +|---|---|---| +| `PROVIDER` | `10001` | Hospitals, clinics, diagnostic centres | +| `PAYER` | `10002` | Insurers and State Health Agencies | +| `AGENCY_TPA` | `10003` | Third party administrators acting for a payer | +| `AGENCY_REGULATOR` | `10004` | Regulators such as the [IRDAI](../glossary/irdai.md) | +| `RESEARCH` | `10005` | Research bodies | +| `MEMBER_ISNP` | `10006` | Insurance self network platforms | +| `AGENCY_SPONSOR` | `10007` | Scheme owners | +| `HIE_HIO_HCX` | `10008` | Other exchange instances | +| `EUA` | `10009` | [End user applications](../../shared/glossary/eua.md), such as patient apps | + +### Who starts which exchange + +```mermaid +graph LR + PR["Provider"] -->|eligibility, insurance plan,
preauth, claim, reprocess| X["NHCX"] + X --> PY["Payer or TPA"] + PY -->|payment notice,
communication request| X + X --> PR + RG["Regulator"] -->|claim search| X +``` + +A provider starts coverage eligibility, insurance plan, preauthorisation, claim and reprocess requests. A payer answers them. A payer starts payment notices and communication requests, and the provider answers those. + +In version 1 of the exchange a TPA behaves like a payer. It receives the same requests and sends the same responses. + +### The registry you prove yourself against + +| Role | Registry ID you send | Registry type code | +|---|---|---| +| Provider | Your [HFR](../../shared/glossary/hfr.md) facility ID | `10001` (HFR) | +| Payer or TPA | Your IRDAI registration ID, without leading zeros | `10004` (PAYER) | +| End user application | Your client ID | `10001` | + +The other registry type codes are `10002` (NIN) and `10003` (ROHINI). + +### Payer and TPA together + +Every insurer has its own participant code, even when a TPA processes its claims. When a policy is linked, `payerid` carries the insurer's code and `processingid` carries the TPA's code. A provider addresses claims on that policy to the `processingid`, because the TPA does the processing. + +## How you know it worked + +You have understood this when you can answer both of these. + +1. An insurer uses a TPA. Which participant code does your hospital system put in `x-hcx-recipient_code` for a claim on that insurer's policy? +2. Which role sends a payment notice, and which role must answer it? + +## When it goes wrong + +**Addressing the insurer instead of the TPA.** A provider that uses the `PayerID` from the get policies response sends the claim to the wrong participant. Use the `processingID`. See [policy linking](./policy-linking.md). + +**Wrong role or registry type at creation.** A code outside the lists above fails participant creation. A mismatch between role and registry type causes access problems and wrong routing later. + +**No role on the sender.** A payer refuses a sender that has no role in NHCX with the message "No user role found/associated for sender code". diff --git a/catalogue/nhcx/concepts/pmjay-on-nhcx.md b/catalogue/nhcx/concepts/pmjay-on-nhcx.md new file mode 100644 index 000000000..540b3af88 --- /dev/null +++ b/catalogue/nhcx/concepts/pmjay-on-nhcx.md @@ -0,0 +1,125 @@ +--- +id: nhcx.concept.pmjay-on-nhcx +type: concept +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PMJAY on NHCX and how it differs from the standard exchange +summary: >- + Claims under the government health assurance scheme use the same exchange calls + as any insurer, but the scheme adds four duties: use the insurance plan, authenticate + the patient biometrically, send structured records, and handle queries inside + responses. +sources: +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sections 1.2, 1.7, 8.1, 8.4 and 8.5 functional points. +- url: https://hcxsbx.abdm.gov.in/images/b6bd99dab49a5e928ea3.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Overview.pdf + hash: sha256:c95469758a25cb8aca8c47757d8b18b4dedb8b4d42669663cff7343205f77fda + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Overview, row 27 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Pages 7-8, NHCX normal flow vs PMJAY flow. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Section 24 Q9; Section 22 Q11; Section 23 Q4. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 8 partial approval table. +verified: + status: unverified +related: + concepts: + - nhcx.concept.hmis-integration-architecture + - nhcx.concept.biometric-authentication + - nhcx.concept.insurance-plan + - nhcx.concept.queries-and-communication + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.claim-cycle + - nhcx.concept.reprocess-and-cancel + flows: + - nhcx.flow.pmjay-patient-to-cashless + - nhcx.flow.pmjay-hospital-migration + - nhcx.flow.biometric-fingerprint-iris + - nhcx.flow.biometric-face + decisions: + - nhcx.decision.payer-implementation + glossary: + - nhcx.glossary.pmjay + - nhcx.glossary.sha + - nhcx.glossary.hbp + - nhcx.glossary.tms + - nhcx.glossary.bis + - shared.glossary.hmis + - shared.glossary.ayushman-card + errors: + - nhcx.error.payr-1256 + - nhcx.error.payr-1271 + - nhcx.error.payr-1254 + - nhcx.error.payr-1365 +--- + +# PMJAY on NHCX and how it differs from the standard exchange + +## In plain words + +[PMJAY](../glossary/pmjay.md) is the government health assurance scheme. Its claims travel on NHCX like any other insurer's. A hospital system that works with private insurers on NHCX uses the same calls for PMJAY. + +The scheme adds rules on top. Treatments are fixed packages at fixed rates. The patient must prove they are present with a fingerprint, iris or face scan. Clinical records go as structured data. And the payer asks its questions inside its responses. + +## Before you start + +Build and test the standard NHCX calls first. See [the claim cycle](./claim-cycle.md). To start PMJAY work in the sandbox, share your participant ID, client ID and registry ID with the NHCX team. The team adds your participant to the PMJAY staging environment. + +## What happens + +### Same calls, four added duties + +| Call | Standard exchange | PMJAY | +|---|---|---| +| Insurance plan | Useful | The backbone: packages, rates, conditions, forms and documents come from it | +| Get policy, eligibility | Same | Same | +| Preauthorisation | Same | Same, after biometric authentication of the patient | +| Payer queries | Communication request | Query inside the ClaimResponse, answered with a query workflow id | +| Claim | Same | Same, with discharge details inside the claim | +| Payment notice, status | Same | Same | + +### The four duties + +1. **Use the [insurance plan](./insurance-plan.md).** Fetch it per hospital and policy, cache it, refresh it weekly, and build preauthorisations and claims from it. +2. **Authenticate the patient.** At registration, before preauthorisation, at every cycle of a cyclic treatment, and at discharge. See [biometric authentication](./biometric-authentication.md). +3. **Send structured records.** Supporting clinical records go as ABDM health information bundles inside the claim, not as scanned files. See [FHIR in NHCX](./fhir-in-nhcx.md). +4. **Handle queries inside responses.** See [queries and communication](./queries-and-communication.md). + +### Scheme rules that change your system + +- Treatment is package based. Rates come from the plan, not from your bill. +- PMJAY is fully cashless. No co-payment is allowed on any package. +- A preauthorisation cannot be raised more than one day before admission. +- There is no separate discharge workflow. Discharge details go inside the claim. +- A claim cannot be cancelled. A reprocess can be raised once per claim. +- Standard treatment guideline questionnaires from the plan must be answered in the preauthorisation and the claim. + +Once PMJAY integration is complete, the production keys you receive also work for private insurers. + +## How you know it worked + +You have understood this when you can answer both of these. + +1. A PMJAY payer needs a missing report on your preauthorisation. How does the request reach you, and how do you answer it? +2. Your system submits a PMJAY preauthorisation with no biometric token and no consent questionnaire. What happens? + +## When it goes wrong + +**No biometric authentication and no consent questionnaire.** The PMJAY payer refuses a new preauthorisation with [PAYR-1256](../errors/payr-1256.md) or [PAYR-1271](../errors/payr-1271.md). + +**Treatment guideline questionnaire missing.** The payer refuses the preauthorisation with [PAYR-1254](../errors/payr-1254.md), and the claim with [PAYR-1365](../errors/payr-1365.md). + +**Waiting for a communication request that never comes.** PMJAY queries arrive inside the `ClaimResponse`. Handle `outcome` `partial` with a queried reason. + +**Rates taken from your own tariff.** Amounts above the package rate are cut back to it or refused. Price from the plan. diff --git a/catalogue/nhcx/concepts/policy-linking.md b/catalogue/nhcx/concepts/policy-linking.md new file mode 100644 index 000000000..f9e67b484 --- /dev/null +++ b/catalogue/nhcx/concepts/policy-linking.md @@ -0,0 +1,125 @@ +--- +id: nhcx.concept.policy-linking +type: concept +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Linking an ABHA to an insurance policy +summary: >- + A payer links a person's national health account number to the policies they hold, + so a hospital can look up the patient's cover from that number alone and address + its claims to the right processor. +sources: +- url: https://hcxsbx.abdm.gov.in/images/539853c50347b32b9a5e.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Policy Linking and De-Linking Process.pdf + hash: sha256:420115b9a54e15fa625312a56362164d92d23dd0d6ebf9195135bb00055d1911 + fetched: '2026-09-14' + note: Policy Linking and De-Linking Process, row 8 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Pages 1-2. +- url: https://hcxsbx.abdm.gov.in/images/b885e59891fedc7e725c.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-PARTICIPANT SERVICE_APIs Postman Collection.zip + hash: sha256:2d082f244ee41d137a62af82380dcd2d5db9ebbab66824fd54a23c506d4d9a7f + fetched: '2026-09-14' + note: AWS(Sandbox)-PARTICIPANT SERVICE_APIs Postman Collection, row 16 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Get Policies request body. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 2, item 7. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 7.4 Usage Guidelines, Discovery. +verified: + status: unverified +related: + flows: + - nhcx.flow.policy-link-and-delink + endpoints: + - nhcx.endpoint.participant-link-abha-policy + - nhcx.endpoint.v2-participant-link-abha-policy + - nhcx.endpoint.participant-delink-abha-policy + - nhcx.endpoint.v2-participant-delink-abha-policy + - nhcx.endpoint.participant-get-policies + - nhcx.endpoint.v2-participant-get-policies + tests: + - nhcx.test.payer-uc-01 + - nhcx.test.payer-uc-02 + - nhcx.test.payer-uc-03 + - nhcx.test.provider-uc-02 + concepts: + - nhcx.concept.participant-roles + - nhcx.concept.participant-code + - nhcx.concept.coverage-eligibility-purposes + - nhcx.concept.access-control + glossary: + - shared.glossary.abha-number + - shared.glossary.abha + - nhcx.glossary.tpa + - nhcx.glossary.payer +--- + +# Linking an ABHA to an insurance policy + +## In plain words + +When a person buys a health policy, the insurer can link it to the person's [ABHA number](../../shared/glossary/abha-number.md). After that, any hospital on NHCX can ask "which policies does this ABHA hold?" and get an answer. + +The answer also says who processes claims on each policy: the insurer itself, or a [TPA](../glossary/tpa.md) acting for it. That is the participant a hospital must address. + +## Before you start + +A payer needs its own participant code. Every insurer has one, even when a TPA handles its claims. See [participant roles](./participant-roles.md). + +## What happens + +```mermaid +graph LR + PY["Payer or TPA"] -->|link: ABHA, member ID,
payerid, processingid, policies| REG[("Policy links
in the participant service")] + H["Hospital"] -->|get policies: ABHA or mobile| REG + REG -->|policies with payerid, processingid| H + H -->|claims addressed to processingid| X["NHCX"] +``` + +### Linking + +The payer calls `/participant/link/abha/policy` on the participant service. The request carries: + +| Field | Holds | +|---|---| +| `requestid` | A UUID for this request | +| `abhanumber` | The person's ABHA number | +| `mobilenumber` | The person's mobile number | +| `memberid` | The payer's member ID for the person | +| `payerid` | The insurer's participant code | +| `processingid` | The participant code of whoever processes claims: the TPA, or the insurer itself | +| `policies` | A list of `productid` and `productname` pairs | + +### Looking up + +A hospital calls `/participant/get/policies` with the ABHA number or mobile number. Each policy comes back with its payer and processor. The hospital puts the `processingid` in `x-hcx-recipient_code` for eligibility, preauthorisation and claim messages on that policy. + +If the lookup returns nothing, the hospital can ask the payer directly with a coverage eligibility check using the `discovery` purpose. See [coverage eligibility purposes](./coverage-eligibility-purposes.md). + +### De-linking + +`/participant/delink/abha/policy` removes policies from the link. Only the participant named as `payerid` or `processingid` when the link was made may de-link it. NHCX reads the client ID from the session token and compares it with the one that registered that participant. + +When an insurer moves to a new TPA, it de-links its existing policies and links them again with the new TPA's participant code as `processingid`. + +## How you know it worked + +You have understood this when you can answer both of these. + +1. The get policies response shows `payerid` A and `processingid` B. To which participant does your hospital send the claim, and why? +2. A TPA stops handling an insurer's policies. What must happen to the existing links, and who is allowed to do it? + +## When it goes wrong + +**Claims addressed to the insurer.** A provider that uses the `PayerID` instead of the `processingID` sends claims to a participant that does not process them. + +**De-link refused.** The session token belongs to a client other than the one registered for `payerid` or `processingid`. Generate the token with the credentials used when that participant was created. + +**Policy not in the link.** De-linking a policy the link does not hold fails with "There is no policies with requested details". + +**Nothing found for the patient.** Fall back to a `discovery` eligibility check. diff --git a/catalogue/nhcx/concepts/protocol-headers.md b/catalogue/nhcx/concepts/protocol-headers.md new file mode 100644 index 000000000..b7ae4c2d9 --- /dev/null +++ b/catalogue/nhcx/concepts/protocol-headers.md @@ -0,0 +1,130 @@ +--- +id: nhcx.concept.protocol-headers +type: concept +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: The x-hcx protocol headers +summary: >- + The x-hcx headers inside the sealed envelope tell the exchange who is sending, + who must receive, which conversation the message belongs to and what state it + is in. +sources: +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Protected Header table and Status Description. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 2 ProtocolResponse. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 3, Q4. +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error, PAYR-1005 description. +verified: + status: unverified +related: + concepts: + - nhcx.concept.message-identifiers + - nhcx.concept.status-lifecycle + - nhcx.concept.workflow-codes + - nhcx.concept.jwe-envelope + - nhcx.concept.participant-code + - nhcx.concept.retries-and-expiry + glossary: + - nhcx.glossary.protected-header + - nhcx.glossary.correlation-id + - nhcx.glossary.api-call-id + - nhcx.glossary.workflow-id + - shared.glossary.abha-number + errors: + - nhcx.error.nhcx-1005 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1018 + - nhcx.error.nhcx-1006 + flows: + - nhcx.flow.send-a-sealed-request +--- + +# The x-hcx protocol headers + +## In plain words + +The protocol headers are the address and tracking label on every sealed message. They live inside the [protected header](../glossary/protected-header.md), and every name starts with `x-hcx-`. + +NHCX reads them to route and audit the message. It never reads the bundle underneath. + +## Before you start + +Read [the JWE envelope](./jwe-envelope.md) first. You need your own and the recipient's [participant codes](./participant-code.md). + +## What happens + +### The headers to send on every request + +Send all of these. Together they satisfy every published header list. + +| Header | Holds | +|---|---| +| `x-hcx-sender_code` | Your participant code | +| `x-hcx-recipient_code` | The participant that must act on the message | +| `x-hcx-api_call_id` | A new UUID for this one call. See [message identifiers](./message-identifiers.md) | +| `x-hcx-request_id` | A UUID for the originating request | +| `x-hcx-correlation_id` | The UUID of the conversation | +| `x-hcx-workflow_id` | The stage of the case. See [workflow codes](./workflow-codes.md) | +| `x-hcx-timestamp` | When you sent it, from a synchronised clock | +| `x-hcx-status` | The message state. See below | +| `x-hcx-ben-abha-id` | The beneficiary's [ABHA number](../../shared/glossary/abha-number.md) | + +Each UUID is a random 36 character universally unique identifier. + +### Status values + +| Who sends | `x-hcx-status` | +|---|---| +| The party starting a request | `request.initiated` | +| The party answering, final answer | `response.complete` | +| The party answering, partial answer or acknowledgement | `response.partial` | +| The party answering, rejection or error | `response.error` | + +[The status lifecycle](./status-lifecycle.md) covers the states NHCX adds itself. + +### Optional headers + +| Header | Holds | +|---|---| +| `x-hcx-debug_flag` | `Error`, `Info` or `Debug`: asks for debug detail. Servers may ignore it | +| `x-hcx-error_details` | An object with `code`, `message` and `trace` | +| `x-hcx-debug_details` | The same shape, for debugging | + +### Extra fields on an error response + +A `ProtocolResponse` repeats the protocol headers in the clear and adds `x-hcx-redirect_to`, `x-hcx-domain-header` (with `use_case_name` and `amt_processed`) and `x-hcx-entity-type`. The entity type is one of `coverageeligibility`, `preauth`, `claim`, `task`, `payment` and `insuranceplan`. + +## How you know it worked + +You have understood this when you can answer both of these. + +1. You answer a payer's communication request. What goes in `x-hcx-status`, and which header tells NHCX which conversation your answer belongs to? +2. Which three headers must hold fresh random UUIDs when you start a new preauthorisation? + +## When it goes wrong + +**Missing or malformed header.** NHCX refuses the envelope with [NHCX-1005](../errors/nhcx-1005.md). + +**Wrong status value.** NHCX refuses a status it does not recognise with [NHCX-1011](../errors/nhcx-1011.md). Use the four values above exactly, in lower case. + +**ABHA number in the wrong format.** NHCX refuses it with [NHCX-1018](../errors/nhcx-1018.md). The error message names the expected format, `XX-XXXX-XXXX-XXXX`. + +**Reused correlation ID.** A new request with a correlation ID NHCX has already seen is refused with [NHCX-1006](../errors/nhcx-1006.md). + +**Stale timestamp.** A payer refuses a request whose timestamp is 24 hours or more away from its own clock. See [retries and expiry](./retries-and-expiry.md). diff --git a/catalogue/nhcx/concepts/queries-and-communication.md b/catalogue/nhcx/concepts/queries-and-communication.md new file mode 100644 index 000000000..b52ba1051 --- /dev/null +++ b/catalogue/nhcx/concepts/queries-and-communication.md @@ -0,0 +1,124 @@ +--- +id: nhcx.concept.queries-and-communication +type: concept +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Payer queries and the communication cycle +summary: >- + A payer asks a hospital for more information in one of two ways, a query inside + its response or a separate communication request, and each needs a different answer. +sources: +- url: https://hcxsbx.abdm.gov.in/images/c42ad170f37c987ed173.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx + hash: sha256:f56dd156c232192296082f23b1561d0ff11fd40992e6675de41c5c991d579e6d + fetched: '2026-09-14' + note: Workflow Status Sheets(with Codes), row 12 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet1 query and query response rows. +- url: https://hcxsbx.abdm.gov.in/images/b6bd99dab49a5e928ea3.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Overview.pdf + hash: sha256:c95469758a25cb8aca8c47757d8b18b4dedb8b4d42669663cff7343205f77fda + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Overview, row 27 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Pages 7-8 Query flow. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 8.4.2 Resubmission. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Communication use case reason code tables. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Communication. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.communication-request + - nhcx.endpoint.communication-on-request + callbacks: + - nhcx.callback.communication-request + - nhcx.callback.communication-on-request + concepts: + - nhcx.concept.claim-cycle + - nhcx.concept.workflow-codes + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.message-identifiers + glossary: + - nhcx.glossary.communication-request + errors: + - nhcx.error.payr-1019 + - nhcx.error.payr-1218 + - nhcx.error.payr-1219 + - nhcx.error.payr-1303 + - nhcx.error.payr-1304 + fhir: + - nhcx.fhir.query-update + tests: + - nhcx.test.provider-uc-08 + - nhcx.test.payer-uc-10 +--- + +# Payer queries and the communication cycle + +## In plain words + +Payers often need more before they decide. A missing report, an unclear diagnosis, a bill that does not add up. + +There are two ways a payer asks. It can answer your preauthorisation or claim with a query instead of a decision. Or it can send a separate [communication request](../glossary/communication-request.md). Your system must recognise both and answer each the right way. + +## Before you start + +Read [the claim cycle](./claim-cycle.md) and [workflow codes](./workflow-codes.md). + +## What happens + +```mermaid +graph TD + subgraph "Channel 1: query inside the response" + R1["Provider: preauth or claim"] --> Q1["Payer: ClaimResponse
outcome partial, queried
workflow 24 or 27"] + Q1 --> A1["Provider: same bundle, updated
workflow 19 or 151"] + A1 --> D1["Payer: decision"] + end + subgraph "Channel 2: communication request" + Q2["Payer: /v1/communication/request
Task with CommunicationRequest"] --> A2["Provider: /v1/communication/on_request
Task with Communication"] + end +``` + +### Channel 1: a query inside the response + +The payer answers your preauthorisation or claim with a `ClaimResponse` whose `outcome` is `partial` and whose adjudication reason is `queried`. The workflow id says which stage: `24` for a preauthorisation, `241` for an enhancement, `27` for a claim. + +You answer by sending the same kind of bundle again, updated with what was asked, to the same path. Use the query response workflow id: `19` for a preauthorisation, `131` for an enhancement, `151` for a claim. Do not use a resubmission code. A resubmission replaces all earlier instances of the request. + +Under PMJAY, this is how every query on a preauthorisation or claim arrives. The PMJAY payer does not use the communication request for queries. + +### Channel 2: a communication request + +The payer calls `/v1/communication/request` with a `Task` bundle that carries a `CommunicationRequest`. Your system answers on `/v1/communication/on_request` with a `Task` bundle whose input is a `Communication`, carrying the documents or information asked for. The request and your answer share one correlation id. + +A standard payer uses this channel to ask for additional documents during a claim cycle. The PMJAY payer uses it for other notices, named in `Task.reasonCode`: `tatquery`, `grievance`, `walletupdate`, `policychange`, `additionalinfo` and `claimArbitration`. + +## How you know it worked + +You have understood this when you can answer both of these. + +1. A PMJAY `ClaimResponse` arrives with workflow id `27`. Which path do you answer on, with which workflow id, and with what bundle? +2. A communication request arrives from a standard payer during a claim. Which path carries your answer, and what must stay the same as in the request? + +## When it goes wrong + +**Answering too late.** A standard payer closes the query with [PAYR-1019](../errors/payr-1019.md), information not received in time. + +**Answering a case that is not queried.** The PMJAY payer refuses a query update with [PAYR-1219](../errors/payr-1219.md), case not queried, or [PAYR-1218](../errors/payr-1218.md) for a preauthorisation. For a claim the codes are [PAYR-1304](../errors/payr-1304.md) and [PAYR-1303](../errors/payr-1303.md). + +**Using the resubmission code for a query answer.** Workflow id `121` replaces the preauthorisation instead of answering the query. Use `19`. + +**Treating a communication request as a decision.** A communication request never approves or rejects. The decision still arrives on the preauthorisation or claim path. diff --git a/catalogue/nhcx/concepts/reprocess-and-cancel.md b/catalogue/nhcx/concepts/reprocess-and-cancel.md new file mode 100644 index 000000000..46801a0fe --- /dev/null +++ b/catalogue/nhcx/concepts/reprocess-and-cancel.md @@ -0,0 +1,132 @@ +--- +id: nhcx.concept.reprocess-and-cancel +type: concept +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Reprocess, cancel and the task resource +summary: >- + After a decision, a hospital sends a task request to dispute a rejection, claim + a shortfall or cancel a preauthorisation, and the payer answers with a task that + points at a new decision. +sources: +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sections 22 and 23 Erroneous and Reprocess. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Preauth cancel and reprocess Task tables. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 8.4.5 Cancellation; 8.5 functional points. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Value sets, Task codes and input types. +verified: + status: unverified +related: + flows: + - nhcx.flow.claim-reprocess + - nhcx.flow.preauth-cancel + endpoints: + - nhcx.endpoint.task-submit + - nhcx.endpoint.task-on-submit + callbacks: + - nhcx.callback.task-submit + - nhcx.callback.task-on-submit + fhir: + - nhcx.fhir.task + - nhcx.fhir.preauth-cancel + glossary: + - nhcx.glossary.reprocess + - nhcx.glossary.crc + errors: + - nhcx.error.payr-1017 + - nhcx.error.payr-1018 + - nhcx.error.payr-1252 + - nhcx.error.payr-1253 + - nhcx.error.payr-1257 + - nhcx.error.payr-1258 + concepts: + - nhcx.concept.claim-cycle + - nhcx.concept.workflow-codes + - nhcx.concept.grievance-redressal + tests: + - nhcx.test.provider-uc-12 + - nhcx.test.payer-uc-14 +--- + +# Reprocess, cancel and the task resource + +## In plain words + +Sometimes a hospital needs to act on a decision already made. The claim was rejected and the hospital disagrees. The claim was paid, but less than it should have been. Or the planned treatment is not going ahead, so the preauthorisation should be cancelled. + +All three are requests to the payer to do something, so they travel as a FHIR `Task` on `/v1/task/submit`. The payer answers on `/v1/task/on_submit`. + +## Before you start + +You need the earlier decision: the claim or preauthorisation number and the payer's response. Read [the claim cycle](./claim-cycle.md). + +## What happens + +### The three requests + +| Request | When | `Task.code` | Reason | Workflow id | +|---|---|---|---|---| +| [Reprocess](../glossary/reprocess.md) | A claim was fully rejected | `reprocess` | Why the rejection is disputed | `36` | +| Erroneous claim | A claim was paid, but short | `reprocess` | `partialpayment` | `36` | +| Cancel | A preauthorisation should not proceed | `cancel` | Why, for example `treatmentplanchanged` | `PC01` | + +`Task.code` comes from `http://terminology.hl7.org/CodeSystem/financialtaskcode`, which also holds `release` and `nullify`. Reason codes come from `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-reason-code`. + +### What the task carries + +- `Task.status` `requested` and `Task.intent` `order`. +- An input `claimNumber` with the case number, and for a preauthorisation an input `initimationNumber`, spelt that way. +- A supporting document. It is mandatory for a reprocess and for an erroneous claim. +- For an erroneous claim only, the amount: never more than the gap between claimed and paid. + +### The answer + +```mermaid +graph LR + T["Provider Task
/v1/task/submit"] --> P["Payer re-adjudicates"] + P --> TR["Payer Task, status completed
/v1/task/on_submit"] + TR -->|output valueReference| CR["ClaimResponse
the new decision"] +``` + +The answer is a `Task` with `status` `completed`. Its `output` points at a `ClaimResponse`, which you read exactly like any other decision. + +### Rules under PMJAY + +- A reprocess or erroneous claim can be raised once per claim. +- Reprocess needs no payment notice and can follow the rejection at once. +- An erroneous claim waits for payment settled, workflow id `33`, and your acknowledgement of it. +- The [Claim Review Committee (CRC)](../glossary/crc.md) decides reprocess cases, and its decision is final. No erroneous claim can follow a CRC decision. +- A preauthorisation can be cancelled only while it is submitted or approved. A claim cannot be cancelled. + +## How you know it worked + +You have understood this when you can answer both of these. + +1. A claim for 10,000 was paid at 6,000. Which request do you raise, with which reason, and what is the largest amount you may ask for? +2. The answer to your reprocess arrives on `/v1/task/on_submit`. Where in the bundle is the new decision? + +## When it goes wrong + +**Wrong combination of code, reason and input.** The PMJAY payer refuses the task with "Invalid input, code and reason code received". Its structure checks use [PAYR-1017](../errors/payr-1017.md) for "No task code received" and [PAYR-1018](../errors/payr-1018.md) for "No task reason code received". + +**Missing case number.** The payer refuses a task without a valid `claimNumber` or `initimationNumber`. + +**Cancelling too late.** The PMJAY payer refuses to cancel a case that is not active ([PAYR-1252](../errors/payr-1252.md)), already cancelled ([PAYR-1253](../errors/payr-1253.md)), or in payment ([PAYR-1257](../errors/payr-1257.md), [PAYR-1258](../errors/payr-1258.md)). + +**Raising an erroneous claim before settlement.** Wait for workflow id `33`, acknowledge it, then raise it. diff --git a/catalogue/nhcx/concepts/retries-and-expiry.md b/catalogue/nhcx/concepts/retries-and-expiry.md new file mode 100644 index 000000000..b4894bef1 --- /dev/null +++ b/catalogue/nhcx/concepts/retries-and-expiry.md @@ -0,0 +1,112 @@ +--- +id: nhcx.concept.retries-and-expiry +type: concept +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Gateway retries and the 24 hour expiry window +summary: >- + The exchange retries a delivery up to five times and then drops the request and + tells the sender, and a payer refuses any request whose timestamp is 24 hours + or more out. +sources: +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1 Error scenario. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 4, Q14. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 2, item 8. +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error, PAYR-1005. +verified: + status: unverified +related: + concepts: + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.message-identifiers + - nhcx.concept.protocol-headers + - nhcx.concept.status-lifecycle + - nhcx.concept.error-code-spaces + callbacks: + - nhcx.callback.error + flows: + - nhcx.flow.report-a-processing-error + errors: + - nhcx.error.payr-1005 + - nhcx.error.nhcx-1001 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback +--- + +# Gateway retries and the 24 hour expiry window + +## In plain words + +NHCX does not give up on the first failed delivery. If the recipient does not accept a message, NHCX sends it again, up to five times. After that it drops the request and tells the sender through the sender's `/v1/error` endpoint. + +Messages also go stale. A payer refuses a request whose timestamp is 24 hours or more away from the payer's own clock. + +## Before you start + +Read [the 202 acknowledgement](./synchronous-acknowledgement.md). Your system needs a `/v1/error` endpoint to hear about requests that were dropped. + +## What happens + +### The retry loop + +```mermaid +graph TD + D["NHCX delivers the message"] --> A{"202 with the acceptance body
within 30 seconds?"} + A -->|yes| OK["Delivered"] + A -->|no, or rejected| R{"Fewer than 5 attempts?"} + R -->|yes| D + R -->|no| T["Request terminated
and deleted"] + T --> E["Rejection sent to the sender's /v1/error"] +``` + +NHCX counts a delivery as failed when the recipient rejects it, answers with the wrong format, or does not answer with 202 within 30 seconds. The interval between attempts is not published. + +After the fifth failure, NHCX deletes the request for that correlation id and marks the correlation id inactive. The sender learns about it on `/v1/error`. + +### What this means for each side + +| You are | Your duty | +|---|---| +| The recipient | Accept within 30 seconds with the right body, or the same message arrives again | +| The recipient | Treat a repeat of a message you already accepted as the same message. Key your inbox on `x-hcx-api_call_id` and `x-hcx-correlation_id` | +| The sender | Implement `/v1/error`, record the rejection and alert your users | +| The sender | Resend a dropped request with a new correlation id | + +### The 24 hour window + +`x-hcx-timestamp` must be the time you actually send the message. The PMJAY payer refuses a request whose timestamp is 24 hours or more away from its current time. Keep your server clock synchronised, and never reuse a stored timestamp on a resend. + +## How you know it worked + +You have understood this when you can answer both of these. + +1. Your endpoint was down for an hour. A payer's claim response was delivered during that time. What did NHCX do, and how does the payer find out? +2. You resend a request that was dropped yesterday, with the same headers. Name two things that make it fail. + +## When it goes wrong + +**The same message processed twice.** Your acknowledgement arrived late, so NHCX retried. Deduplicate on the identifiers above before you act. + +**Resending with the old correlation id.** NHCX refuses it with [NHCX-1006](../errors/nhcx-1006.md). A dropped request's correlation id is inactive. Use a new one. + +**Stale timestamp.** The PMJAY payer refuses it with the message "Maximum time limit exceeded in receiving the request". On the standard payer list [PAYR-1005](../errors/payr-1005.md) means something else, so read the message text. + +**Receiver unreachable.** The sender sees [NHCX-1001](../errors/nhcx-1001.md). See [accepted, then no callback](../troubleshooting/accepted-then-no-callback.md). diff --git a/catalogue/nhcx/concepts/session-token.md b/catalogue/nhcx/concepts/session-token.md new file mode 100644 index 000000000..073089b76 --- /dev/null +++ b/catalogue/nhcx/concepts/session-token.md @@ -0,0 +1,114 @@ +--- +id: nhcx.concept.session-token +type: concept +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: The session token every NHCX call carries +summary: >- + Your system trades its client credentials for a short-lived bearer token and sends + it on every call, while the exchange proves itself to you with a token of its + own. +sources: +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/data-security-and-privacy/api-security + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy__api-security.md + hash: sha256:9fe2d5a643356558131e5de801b5f325b76f80aa48e931ee6b77e088dd90a65c + fetched: '2026-09-14' + note: Site page /technical-specifications/open-protocol/data-security-and-privacy/api-security, text as shown on the site. API Security. +- url: https://hcxsbx.abdm.gov.in/images/54d18468412741b759f3.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Authenticating with NHCX.pdf + hash: sha256:0ea90b635634844aaf8981e917cbf8b765ddd83a340f3c934883912599a62d8b + fetched: '2026-09-14' + note: Authenticating with NHCX, row 3 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 5, Q20. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 2, items 6 and 9. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.get-session + - nhcx.endpoint.session-token + decisions: + - nhcx.decision.session-endpoint + errors: + - nhcx.error.nhcx-401 + troubleshooting: + - nhcx.troubleshooting.everything-returns-401 + tests: + - nhcx.test.provider-uc-04 + - nhcx.test.payer-uc-06 + concepts: + - nhcx.concept.participant-registry + - nhcx.concept.jwe-envelope + glossary: + - shared.glossary.sandbox + - shared.glossary.m1 +--- + +# The session token every NHCX call carries + +## In plain words + +Every call your system makes to NHCX carries a session token. The token tells NHCX which participant is calling. + +You get the token by sending your client ID and client secret to a session endpoint. The token expires after a short time, so your system fetches a new one before it lapses. + +## Before you start + +You need a client ID and client secret from the ABDM [sandbox](../../shared/glossary/sandbox.md) registration. If your system already has credentials for ABDM [Milestone 1](../../shared/glossary/m1.md), the same credentials work for NHCX. + +## What happens + +Two tokens are in play, one in each direction. + +| Direction | Who issues it | How it is checked | +|---|---|---| +| Your system to NHCX | NHCX, from your client ID and secret | NHCX checks it on every call | +| NHCX to your endpoint | NHCX signs its own token with RS256 | You check it with the NHCX instance's public key | + +```mermaid +graph LR + C["Client ID + secret"] -->|session endpoint| T["Bearer token
short lifetime"] + T -->|header on every call| X["NHCX"] + X -->|its own signed token
on every delivery| E["Your endpoint"] +``` + +### Getting and keeping a token + +- Call the session endpoint with your credentials. Which endpoint to call is covered in [choosing the session endpoint](../decisions/session-endpoint.md). +- Read the lifetime from the response, `expiresIn` or `expires_in` depending on the endpoint. +- Renew the token before it lapses, from a background task, so no request goes out with an expired token. +- Send it as `Bearer `. Each endpoint atom names the request header that carries it. + +### Revocation + +NHCX revokes access by issuing you a new client secret. Your old tokens stop working, and you must fetch a new token with the new secret. + +### The token NHCX sends you + +When NHCX delivers a message to your endpoint, it presents a token it signed itself with `alg` `RS256`. The claims are `jti`, `iss`, `sub`, `iat` and `exp`, with `iss` and `sub` both naming the NHCX instance. Validate the signature before you trust the delivery. + +## How you know it worked + +You have understood this when you can answer both of these. + +1. Your token was issued at 10:00 and a call at 10:25 returns HTTP 401. What happened, and what does your system do before retrying? +2. Which token does your callback endpoint check when NHCX delivers a message, and whose key verifies it? + +## When it goes wrong + +**Expired token.** HTTP 401 with the message "Sender is not authorized to execute the operation" means the session token has expired. Fetch a new one and retry. See [NHCX-401](../errors/nhcx-401.md). + +**Missing `Bearer` prefix.** The header value must start with `Bearer ` followed by the token. A bare token is refused with 401. + +**Old secret.** After NHCX issues a new client secret, calls with tokens from the old secret fail. Update the secret in your configuration. + +**Every call fails.** Work through [every call returns 401](../troubleshooting/everything-returns-401.md). diff --git a/catalogue/nhcx/concepts/status-lifecycle.md b/catalogue/nhcx/concepts/status-lifecycle.md new file mode 100644 index 000000000..ac5f42026 --- /dev/null +++ b/catalogue/nhcx/concepts/status-lifecycle.md @@ -0,0 +1,114 @@ +--- +id: nhcx.concept.status-lifecycle +type: concept +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Status values and how a request moves through them +summary: >- + A message moves through states set by the sender, by the exchange and by the responder, + and each state is visible in the status header or the acknowledgement. +sources: +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Status Description (Protected Header). +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Status. +- url: https://hcxsbx.abdm.gov.in/images/c42ad170f37c987ed173.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx + hash: sha256:f56dd156c232192296082f23b1561d0ff11fd40992e6675de41c5c991d579e6d + fetched: '2026-09-14' + note: Workflow Status Sheets(with Codes), row 12 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet1. +verified: + status: unverified +related: + concepts: + - nhcx.concept.protocol-headers + - nhcx.concept.workflow-codes + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.four-message-legs + - nhcx.concept.retries-and-expiry + endpoints: + - nhcx.endpoint.status + - nhcx.endpoint.on-status + callbacks: + - nhcx.callback.status + - nhcx.callback.on-status + flows: + - nhcx.flow.status-check + decisions: + - nhcx.decision.status-poll-or-wait + errors: + - nhcx.error.nhcx-1011 + tests: + - nhcx.test.provider-uc-13 +--- + +# Status values and how a request moves through them + +## In plain words + +Every message carries a status. The status says where the message is in its life: newly sent, waiting at the exchange, delivered, or answered. + +Three parties set statuses. The sender marks a new request. NHCX tracks delivery. The responder marks its answer as final, partial or an error. + +## Before you start + +Read [the protocol headers](./protocol-headers.md) and [the four message legs](./four-message-legs.md). + +## What happens + +```mermaid +stateDiagram-v2 + [*] --> initiated: sender sets request.initiated + initiated --> queued: NHCX accepts the envelope + queued --> dispatched: the recipient's system received it + queued --> stopped: delivery failed after retries + dispatched --> partial: responder sets response.partial + dispatched --> complete: responder sets response.complete + dispatched --> error: responder sets response.error + partial --> complete + complete --> [*] + error --> [*] + stopped --> [*] +``` + +| Status | Set by | Meaning | +|---|---|---| +| `request.initiated` | The sender, in `x-hcx-status` | Starts a request cycle | +| `request.queued` | NHCX | Accepted and waiting for delivery | +| `request.dispatched` | NHCX | Reached the recipient's system | +| `request.stopped` | NHCX | Stopped after failed delivery attempts | +| `response.partial` | The responder, in `x-hcx-status` | A partial answer or an acknowledgement | +| `response.complete` | The responder, in `x-hcx-status` | The final answer, closing the cycle | +| `response.error` | The responder, in `x-hcx-status` | The request was rejected or failed | + +You only ever put `request.initiated`, `response.partial`, `response.complete` or `response.error` in `x-hcx-status`. The `request.queued`, `request.dispatched` and `request.stopped` states belong to NHCX. You see them in acknowledgements and status answers. + +### Message status is not claim status + +`x-hcx-status` tracks the message. The claim's own progress lives in the [workflow id](./workflow-codes.md) and in the FHIR response, for example `ClaimResponse.outcome`. A `response.complete` message can carry a rejection. + +### Asking for a status + +Send `/v1/status` with the sealed request whose status you want. NHCX answers on your `/v1/on_status` endpoint with the protocol headers of that request. Whether to poll or wait is covered in [poll or wait](../decisions/status-poll-or-wait.md). + +## How you know it worked + +You have understood this when you can answer both of these. + +1. You sent a claim an hour ago and a status check shows it `request.dispatched`. Has the payer decided? Where would the decision show? +2. A payer's answer arrives with `response.complete` and a rejected claim inside. Is that a protocol error? Which fields tell you it was rejected? + +## When it goes wrong + +**Invented status values.** NHCX refuses an `x-hcx-status` it does not recognise with [NHCX-1011](../errors/nhcx-1011.md). Use the exact lower case values above. + +**Treating `response.partial` as final.** A partial answer means more is coming, or the payer wants something from you. Keep the case open until a `response.complete` or `response.error` arrives. + +**Reading claim outcome from the message status.** Read the workflow id and the FHIR outcome for the business decision. diff --git a/catalogue/nhcx/concepts/synchronous-acknowledgement.md b/catalogue/nhcx/concepts/synchronous-acknowledgement.md new file mode 100644 index 000000000..a600addde --- /dev/null +++ b/catalogue/nhcx/concepts/synchronous-acknowledgement.md @@ -0,0 +1,119 @@ +--- +id: nhcx.concept.synchronous-acknowledgement +type: concept +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: The 202 acknowledgement and the 30 second rule +summary: >- + Every delivery on the exchange is answered at once with a short accepted reply, + within 30 seconds, and the real answer follows later as a separate message. +sources: +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Pages 1-2. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 4, Q12 and Q14. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Message Flow and Error Handling. +verified: + status: unverified +related: + concepts: + - nhcx.concept.four-message-legs + - nhcx.concept.retries-and-expiry + - nhcx.concept.status-lifecycle + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.payer-process-a-request + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback + - nhcx.troubleshooting.callback-url-rejected + sandbox: + - nhcx.sandbox.callback-url-requirements + errors: + - nhcx.error.nhcx-1001 + - nhcx.error.nhcx-1015 + - nhcx.error.nhcx-1017 +--- + +# The 202 acknowledgement and the 30 second rule + +## In plain words + +On NHCX, whoever receives a message answers it at once with HTTP 202 Accepted. The 202 says "I have it". It does not say "I have done it". + +This applies in both directions. NHCX answers your call with 202. Your system answers NHCX with 202 when NHCX delivers a message to you, and it must do so within 30 seconds. + +## Before you start + +Read [the four message legs](./four-message-legs.md). Your endpoint must be reachable from NHCX. See [the callback URL requirements](../sandbox/callback-url-requirements.md). + +## What happens + +### Two acknowledgements + +| When | Who sends the 202 | What it means | +|---|---|---| +| You call NHCX | NHCX | Your envelope passed validation and is queued for delivery | +| NHCX delivers a message to your endpoint | Your system | You received it and will process it | + +If NHCX finds a problem with your envelope, it answers with an error instead of 202. + +### Your acknowledgement body + +When NHCX delivers a message to you, return HTTP 202 with this body: + +```json +{ + "timestamp": "DD/MM/YYYY hh:mm:ss:sss", + "api_call_id": "UUID", + "correlation_id": "UUID", + "result": { + "sender_code": "PYRXX@hcx", + "recipient_code": "INXXXXX@hcx", + "entity_type": "coverageeligibility/preauth/claim/task/payment/insuranceplan", + "protocol_status": "request.queued/request.dispatched/request.error" + }, + "error": { "code": "", "message": "" } +} +``` + +`entity_type` takes one of `coverageeligibility`, `preauth`, `claim`, `task`, `payment` or `insuranceplan`. `protocol_status` takes one of `request.queued`, `request.dispatched` or `request.error`. The `error` fields stay empty when you accept. + +### Acknowledge first, work later + +```mermaid +graph LR + D["Delivery arrives"] --> C["Check it is a well formed envelope"] + C --> A["Return 202 with the body
within 30 seconds"] + A --> Q["Queue it"] + Q --> W["Decrypt, validate, process"] + W --> R["Send your answer later
on the on_ path"] +``` + +Decrypting, validating FHIR and adjudicating can take longer than 30 seconds. So accept first, then do the work from a queue. If the work fails, send your answer as a `ProtocolResponse` with `x-hcx-status` set to `response.error`. + +## How you know it worked + +You have understood this when you can answer both of these. + +1. Your callback handler decrypts and stores the bundle before it replies, and sometimes that takes 40 seconds. What does NHCX conclude, and what will it do next? +2. NHCX returns 202 to your claim submission. Which of the four legs does that close? + +## When it goes wrong + +**Replying late.** If NHCX gets no 202 within 30 seconds, it treats the delivery as failed and retries. See [retries and expiry](./retries-and-expiry.md). + +**Replying with the wrong body or status.** A reply that does not follow the acceptance format counts as an error, and NHCX retries the same request. [NHCX-1015](../errors/nhcx-1015.md) and [NHCX-1017](../errors/nhcx-1017.md) report an invalid response from the receiver. + +**Endpoint unreachable.** NHCX reports [NHCX-1001](../errors/nhcx-1001.md) to the sender. See [accepted, then no callback](../troubleshooting/accepted-then-no-callback.md). diff --git a/catalogue/nhcx/concepts/what-nhcx-is.md b/catalogue/nhcx/concepts/what-nhcx-is.md new file mode 100644 index 000000000..3308da68e --- /dev/null +++ b/catalogue/nhcx/concepts/what-nhcx-is.md @@ -0,0 +1,140 @@ +--- +id: nhcx.concept.what-nhcx-is +type: concept +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: What the National Health Claims Exchange is and what it does not do +summary: >- + The claims exchange is a switch that carries sealed claim messages between hospitals + and insurers; it routes and checks envelopes but never reads or decides a claim. +sources: +- url: https://hcxsbx.abdm.gov.in/#/introduction-NHCX + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/introduction-NHCX.md + hash: sha256:39f92cfaa00639c278575132b12064ff6bfd557f16f324f13d8c2ccccf6153bb + fetched: '2026-09-14' + note: Site page /introduction-NHCX, text as shown on the site. Introduction to NHCX. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. NHCX Protocols and Message Flow. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy__message-security-and-integrity.md + hash: sha256:3768fd89932e4081c9e03a8695619bcaf70c641e28bb55a77eec090bb926eeb3 + fetched: '2026-09-14' + note: Site page /technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity, text as shown on the site. Message Security and Integrity. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/data-security-and-privacy/audit-and-reporting + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy__audit-and-reporting.md + hash: sha256:3805b33513ec0863294014053849d921b6fc4093d1cd0356a5e10b9eb54ef6c6 + fetched: '2026-09-14' + note: Site page /technical-specifications/open-protocol/data-security-and-privacy/audit-and-reporting, text as shown on the site. Audit and Reporting. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 4, Q12. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 8.2, page 18. +- url: https://hcxsbx.abdm.gov.in/#/domain-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications.md + hash: sha256:56234dd8a55fe4eb9dd852779b22b522b04760c9bec5c263d5e9bc3ac2c6f167 + fetched: '2026-09-14' + note: Site page /domain-specifications, text as shown on the site. ABDM sandbox onboarding section. +verified: + status: unverified +related: + concepts: + - nhcx.concept.participant-roles + - nhcx.concept.four-message-legs + - nhcx.concept.claim-cycle + - nhcx.concept.jwe-envelope + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.audit-and-non-repudiation + glossary: + - shared.glossary.nhcx + - shared.glossary.abdm + - shared.glossary.fhir + - shared.glossary.uhi + - shared.glossary.hie-cm + - shared.glossary.hmis + - nhcx.glossary.payer + - nhcx.glossary.provider + - nhcx.glossary.tpa + - nhcx.glossary.adjudication + flows: + - nhcx.flow.sandbox-onboarding + - nhcx.flow.send-a-sealed-request + - nhcx.flow.receive-a-sealed-callback + errors: + - nhcx.error.nhcx-1002 + - nhcx.error.nhcx-1003 +--- + +# What the National Health Claims Exchange is and what it does not do + +## In plain words + +The [National Health Claims Exchange (NHCX)](../../shared/glossary/nhcx.md) is the claims switch of [ABDM](../../shared/glossary/abdm.md). A hospital sends a claim message to NHCX. NHCX routes it to the insurer or [third party administrator](../glossary/tpa.md) that must answer, and carries the answer back. + +It works like an email exchange. NHCX reads the address on the envelope and delivers the message. It cannot read the letter inside, because the sender seals it for the recipient. + +NHCX is one of three ABDM gateways. The other two are the [Unified Health Interface](../../shared/glossary/uhi.md) and the [Health Information Exchange and Consent Manager](../../shared/glossary/hie-cm.md). + +## Before you start + +Nothing. Read this first. Then read [participant roles](./participant-roles.md) and [the four message legs](./four-message-legs.md). + +## What happens + +Every exchange has the same shape. A sender builds a [FHIR](../../shared/glossary/fhir.md) bundle, seals it for the recipient, and posts it to NHCX. NHCX checks the envelope and forwards the sealed message. + +```mermaid +graph LR + H["Provider system
(hospital HMIS)"] -->|sealed request| X["NHCX"] + X -->|same sealed request| P["Payer or TPA system"] + P -->|sealed response| X + X -->|same sealed response| H + X -.->|looks up sender, recipient, endpoint| R[("Participant registry")] +``` + +### What NHCX does + +- Checks that the sender and the recipient are registered and allowed to exchange. +- Validates the protocol headers on the envelope. +- Accepts the call, then forwards the message to the recipient's registered endpoint. +- Retries delivery when the recipient does not acknowledge. +- Records each call it receives, using only the unencrypted envelope details. + +### What NHCX does not do + +| NHCX does not | Because | Who does it instead | +|---|---|---| +| Read the claim | The payload is sealed with the recipient's public key | The recipient, with its private key | +| Decide a claim | The gateway never returns an adjudication on your call | The payer, in a later callback | +| Authenticate the patient | Biometric authentication is a separate API, used for PMJAY | Your system, before preauthorisation | +| Create an ABHA | ABHA creation is ABDM Milestone 1 work | Your system, through the ABDM APIs | +| Hold your private key | You generate your own key pair | You | + +### The use cases it carries + +Coverage eligibility, insurance plan, preauthorisation, predetermination, claim, communication requests, payment notices, reprocess and cancel tasks, status checks and claim search. [The claim cycle](./claim-cycle.md) shows how they fit together. + +## How you know it worked + +You have understood this when you can answer both of these. + +1. Your system submits a preauthorisation and receives HTTP 202 from NHCX. Has the payer approved anything yet? Where will the decision arrive? +2. Someone proposes that NHCX log the decrypted claim to help debugging. Why is that impossible, and where can the claim be read? + +## When it goes wrong + +**Treating the 202 as the answer.** The 202 means NHCX accepted the envelope. The payer's decision arrives later on your callback endpoint. See [the 202 acknowledgement](./synchronous-acknowledgement.md). + +**Sending before you are registered.** NHCX refuses a sender it does not know with [NHCX-1002](../errors/nhcx-1002.md), and an unknown recipient with [NHCX-1003](../errors/nhcx-1003.md). + +**Expecting NHCX to fix the payload.** NHCX cannot see the payload, so it cannot correct a bad bundle. The payer reports bundle problems back to you. See [error code spaces](./error-code-spaces.md). diff --git a/catalogue/nhcx/concepts/workflow-codes.md b/catalogue/nhcx/concepts/workflow-codes.md new file mode 100644 index 000000000..b7c08f3e9 --- /dev/null +++ b/catalogue/nhcx/concepts/workflow-codes.md @@ -0,0 +1,124 @@ +--- +id: nhcx.concept.workflow-codes +type: concept +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Workflow codes and the stage each one names +summary: >- + The workflow id header names the business stage a message belongs to, such as + a new preauthorisation or a payment settled, and pairs with the status header + to say exactly what the message is. +sources: +- url: https://hcxsbx.abdm.gov.in/images/c42ad170f37c987ed173.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx + hash: sha256:f56dd156c232192296082f23b1561d0ff11fd40992e6675de41c5c991d579e6d + fetched: '2026-09-14' + note: Workflow Status Sheets(with Codes), row 12 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet1. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Section 22 Q5 and Section 23 Q5. +verified: + status: unverified +related: + concepts: + - nhcx.concept.protocol-headers + - nhcx.concept.status-lifecycle + - nhcx.concept.claim-cycle + - nhcx.concept.reprocess-and-cancel + - nhcx.concept.queries-and-communication + - nhcx.concept.message-identifiers + glossary: + - nhcx.glossary.workflow-id + - nhcx.glossary.preauthorisation + - nhcx.glossary.enhancement + errors: + - nhcx.error.payr-1321 + - nhcx.error.payr-1003 + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + - nhcx.flow.payment-notice +--- + +# Workflow codes and the stage each one names + +## In plain words + +The [workflow id](../glossary/workflow-id.md) says which stage of a case a message belongs to. `12` is a new preauthorisation. `15` is a claim. `33` is a payment settled. + +It travels in `x-hcx-workflow_id`, next to `x-hcx-status`. The pair tells the receiver exactly what the message is, without opening the bundle. + +## Before you start + +Read [the protocol headers](./protocol-headers.md) and [the claim cycle](./claim-cycle.md). + +## What happens + +### The codes a provider sends + +| Code | Stage | `x-hcx-status` | +|---|---|---| +| `10` | Patient registered | `request.initiated` | +| `11` | Patient admitted | `request.initiated` | +| `12` | Preauthorisation request initiated | `request.initiated` | +| `121` | Preauthorisation resubmission | `request.initiated` | +| `13` | Enhancement request initiated | `request.initiated` | +| `19` | Preauthorisation query response submitted | `response.complete` | +| `131` | Enhancement query response submitted | `response.complete` | +| `14` | Discharge submitted | `request.initiated` | +| `15` | Claim request initiated | `request.initiated` | +| `151` | Claim query response submitted | `response.complete` | +| `17` | Payment notice received | `response.complete` | +| `36` | Claim arbitration intimation (reprocess or erroneous claim) | `request.initiated` | +| `PC01` | Preauthorisation cancellation | `request.initiated` | + +### The codes a payer sends + +| Code | Stage | `x-hcx-status` | +|---|---|---| +| `20` | Preauthorisation acknowledged | `response.partial` | +| `21` | Preauthorisation approved | `response.complete` | +| `22` | Enhancement approved | `response.complete` | +| `23` | Preauthorisation rejected | `response.complete` | +| `24` | Preauthorisation queried | `request.initiated` | +| `241` | Enhancement queried | `request.initiated` | +| `25` | Claim documents acknowledged | `response.partial` | +| `26` | Claim approved | `response.complete` | +| `27` | Claim queried | `request.initiated` | +| `28` | Claim in process | `response.partial` | +| `29` | Claim forwarded | `response.partial` | +| `252`, `253`, `254` | Reprocess approved, rejected, queried | `response.complete`, `response.complete`, `request.initiated` | +| `30` | Payment notice initiated | `request.initiated` | +| `31` | Payment processed | `request.initiated` | +| `33` | Payment settled | `request.initiated` | +| `PC02` | Preauthorisation cancellation accomplished | `response.complete` | + +### Other families + +`R` codes cover reimbursement claims, for example `R15` for a reimbursement claim submitted. `G11` to `G13` cover grievances, `RP1` to `RP3` return payments, `N01` to `N04` notifications and `DC01` to `DC02` discharge corrections. + +### One code, several stages + +Some codes appear more than once and the status tells them apart. Code `20` with `response.partial` is an acknowledgement that succeeded. The same code with `response.error` is an acknowledgement that failed, and you handle it as a protocol error. + +### Rule + +Keep workflow ids in configuration, not in code. A payer may ask for a corrected code, and a configuration change needs no release. + +## How you know it worked + +You have understood this when you can answer both of these. + +1. A payer's message arrives with `x-hcx-workflow_id` `24`. What happened to your preauthorisation, and which code does your answer carry? +2. Code `20` arrives with `response.error`. Is the preauthorisation rejected? How do you treat it? + +## When it goes wrong + +**Invalid workflow id.** The PMJAY payer refuses a claim with an unknown workflow id with [PAYR-1321](../errors/payr-1321.md). Its structure checks use [PAYR-1003](../errors/payr-1003.md) for "Invalid workflow requested". + +**Query answered as a resubmission.** Answer a query with the query response code (`19` or `151`). A resubmission code (`121`) replaces the earlier request instead. + +**Acknowledgement failures read as rejections.** An "Ack Failed" code with `response.error` is a delivery or protocol problem, not a business decision. diff --git a/catalogue/nhcx/decisions/biometric-modality.md b/catalogue/nhcx/decisions/biometric-modality.md new file mode 100644 index 000000000..2b162ec83 --- /dev/null +++ b/catalogue/nhcx/decisions/biometric-modality.md @@ -0,0 +1,104 @@ +--- +id: nhcx.decision.biometric-modality +type: decision +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Fingerprint, iris or face authentication +summary: >- + Build all three ways of proving the patient is present, and let the desk use whichever + one the patient can complete. +sources: +- url: https://hcxsbx.abdm.gov.in/images/9f1e6b545a693d38a704.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Biometric Authentication Implementation Steps.docx + hash: sha256:fac8b14bfe8d518c0e651740537b9441c501d3cf2ab0f0482a07ab9f417e43a9 + fetched: '2026-09-14' + note: Biometric Authentication Implementation Steps, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments, not named in the NHCX document sheet. Fingerprint/IRIS APIs and Face-Auth API curl. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Section 26 Q9-Q13; Section 27 Q1-Q4; Q10 K-547. +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error, PAYR-1256. +verified: + status: unverified +related: + concepts: + - nhcx.concept.biometric-authentication + flows: + - nhcx.flow.biometric-fingerprint-iris + - nhcx.flow.biometric-face + endpoints: + - nhcx.endpoint.abha-biometric-auth-init + - nhcx.endpoint.abha-biometric-auth-verify + - nhcx.endpoint.abha-biometric-auth-refresh-token + - nhcx.endpoint.abha-biometric-faceauth-init + - nhcx.endpoint.abha-biometric-capture-pid + - nhcx.endpoint.abha-biometric-v2-auth-verify + errors: + - nhcx.error.payr-1256 + - nhcx.error.payr-1272 + - nhcx.error.payr-1363 + - nhcx.error.payr-1366 + - nhcx.error.payr-1367 + - nhcx.error.payr-1369 + glossary: + - nhcx.glossary.rd-service + - nhcx.glossary.pid-block + - nhcx.glossary.pmjay + - shared.glossary.abha + - shared.glossary.kyc +--- + +# Fingerprint, iris or face authentication + +## In plain words + +[PMJAY](../glossary/pmjay.md) requires proof that the beneficiary is at the hospital. You capture it by fingerprint, iris or face at registration, preauthorisation and discharge. + +Build all three modalities: PMJAY integration requires it. At the desk, use fingerprint or iris where you have a scanner, and face on a phone where you do not. + +## Before you start + +- The beneficiary's [ABHA](../../shared/glossary/abha.md) is linked to their PMJAY card. Others follow the scheme's alternate [KYC](../../shared/glossary/kyc.md) process. +- You hold a session token. See [the session token every NHCX call carries](../concepts/session-token.md). +- You have read [biometric authentication of the beneficiary](../concepts/biometric-authentication.md). + +## What happens + +| | Fingerprint | Iris | Face | +|---|---|---|---| +| Hardware | Fingerprint scanner at the desk | Iris scanner at the desk | A phone with the ABHA app and the Aadhaar [RD Service](../glossary/rd-service.md) app | +| Calls | [`auth/init`](../endpoints/abha-biometric-auth-init.md), then [`auth/verify`](../endpoints/abha-biometric-auth-verify.md) | The same two calls | [`faceauth/init`](../endpoints/abha-biometric-faceauth-init.md), [`capture/pid`](../endpoints/abha-biometric-capture-pid.md) until `COMPLETE`, then [`v2/auth/verify`](../endpoints/abha-biometric-v2-auth-verify.md) | +| `authMode` | `FINGERPRINT` | `IRIS` | `FACE_AUTH` | +| Captured value you send | [`fingerPrintAuthPid`](../glossary/pid-block.md) | `irisAuthPid` | None. You send the Aadhaar number, RSA encrypted, and the mobile number | +| Result | A user token valid 1800 seconds and a refresh token valid 1296000 seconds | The same | The same | + +Rules that hold for every modality: + +- Preauthorisation and claim may use different modalities. +- Set the `process` header to `Preauth` or `Discharge`. Every cycle of a cyclic procedure uses `Discharge`. +- A refresh token keeps a session alive without a new capture, except for cyclic procedures. Every cycle needs a live capture, in any modality. +- Where no capture is possible, send the Authentication Consent Questionnaire response instead. This fallback is not allowed for cyclic procedures. + +The default is all three built, with the operator choosing per patient. A scanner capture needs no phone. Face needs no scanner. When one modality fails on a patient, the next is a new init call away. + +## How you know it worked + +- Fingerprint or iris: `auth/verify` returns `authResult` `success` with `token` and `refreshToken`. +- Face: `capture/pid` moves from `PENDING` to `COMPLETE`, and `v2/auth/verify` returns tokens. +- The preauthorisation or claim that carries the token is not refused with `PAYR-1272` or `PAYR-1366`. +- Your desk completes all three modalities in the sandbox. + +## When it goes wrong + +Switching modality is per capture: start a new init with the other `authMode`. Nothing is registered, so you can add a modality after go-live. PMJAY integration still needs all three. + +- `PAYR-1272` or `PAYR-1366`: the user token is invalid or has expired. Capture again. See [PAYR-1272](../errors/payr-1272.md) and [PAYR-1366](../errors/payr-1366.md). +- `PAYR-1256` or `PAYR-1363`: no biometric and no consent questionnaire at preauthorisation or discharge. See [PAYR-1256](../errors/payr-1256.md) and [PAYR-1363](../errors/payr-1363.md). +- `PAYR-1367` or `PAYR-1369`: a cycle has no capture for its date, or two captures share one date. See [PAYR-1367](../errors/payr-1367.md) and [PAYR-1369](../errors/payr-1369.md). +- Fingerprint capture fails with `K-547`: build the `wadh` value with `lr` set to `Y`. See [authenticate a beneficiary by fingerprint or iris](../flows/biometric-fingerprint-iris.md). diff --git a/catalogue/nhcx/decisions/eligibility-purpose.md b/catalogue/nhcx/decisions/eligibility-purpose.md new file mode 100644 index 000000000..8e28d6a28 --- /dev/null +++ b/catalogue/nhcx/decisions/eligibility-purpose.md @@ -0,0 +1,95 @@ +--- +id: nhcx.decision.eligibility-purpose +type: decision +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Which coverage eligibility purpose to send +summary: >- + Confirm the policy when the patient arrives, then ask what each planned treatment + needs before you request approval for it. +sources: +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 7.3 and 7.4. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 8.3; page 32 functional points. +- url: https://hcxsbx.abdm.gov.in/images/13093b5f9b88fe826123.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Insurance Plan IG.docx + hash: sha256:e9c6c82b6d67fd8476d6d19a5961419beb04e3c0613533453ed1e16e2a569cc1 + fetched: '2026-09-14' + note: Insurance Plan IG, row 25 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. CoverageEligibility tables. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Section 24 Unspecified Procedure, Q5. +verified: + status: unverified +related: + concepts: + - nhcx.concept.coverage-eligibility-purposes + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.preauth-query-response + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.participant-get-policies + fhir: + - nhcx.fhir.coverage-eligibility-request + errors: + - nhcx.error.payr-1032 + - nhcx.error.payr-1033 + - nhcx.error.payr-1101 + glossary: + - nhcx.glossary.coverage-eligibility +--- + +# Which coverage eligibility purpose to send + +## In plain words + +A [coverage eligibility](../glossary/coverage-eligibility.md) check asks the payer about a patient's policy over [NHCX](../../shared/glossary/nhcx.md). The `purpose` element of the `CoverageEligibilityRequest` says what you are asking. Four values exist: `discovery`, `validation`, `benefits` and `auth-requirements`. + +Send `validation` at registration or admission. Send `auth-requirements` before every preauthorisation and whenever a treatment is added. + +## Before you start + +- You know the patient's payer and policy. Get them from [`POST /participant/get/policies`](../endpoints/participant-get-policies.md). +- You can send a sealed eligibility request. See [check coverage eligibility](../flows/coverage-eligibility-check.md). +- You have read [the coverage eligibility purposes](../concepts/coverage-eligibility-purposes.md). + +## What happens + +Every purpose needs the beneficiary ID, the coverage or plan code, the payer ID and the provider ID. + +| Purpose | Send it when | Extra input | What comes back | +|---|---|---|---| +| `discovery` | `/participant/get/policies` finds no policy for the patient | None | The active policy code. Use it in a `validation` check next | +| `validation` | At registration or admission | None | `insurance[*].inforce`, the wallet amount used and the amount still available | +| `benefits` | You need benefit detail for procedures | Procedure or package codes | Benefit details for the listed items | +| `auth-requirements` | Before each preauthorisation, and when a treatment is added | Procedure or package codes in `item[*]`, mandatory | Whether each item is covered, the covered amount, `authorizationRequired`, required questionnaires and `authorizationSupporting` document codes | + +The default is `validation` first, then `auth-requirements` before each preauthorisation. `validation` tells you the policy is in force and how much wallet remains. `auth-requirements` tells you which documents and questionnaires the preauthorisation must carry, so you send it complete. Use `discovery` only as a fallback. An unspecified procedure also needs an `auth-requirements` check. + +`purpose` is a list. One request may carry more than one value, for example `validation` and `auth-requirements` together. + +## How you know it worked + +- The answer on `/v1/coverageeligibility/on_check` has `outcome` `complete`. +- For `validation`, `insurance[*].inforce` is `true` and the wallet amounts are present. +- For `auth-requirements`, every item you sent comes back with `authorizationRequired` and any `authorizationSupporting` codes. +- The preauthorisation you then send carries every document and questionnaire those codes named. + +## When it goes wrong + +The purpose is chosen per request and nothing is registered, so switching is immediate. + +- `PAYR-1033`: you sent a purpose that needs items without any `item[*]`. Add the procedure or package codes. See [PAYR-1033](../errors/payr-1033.md). +- `PAYR-1032` or `PAYR-1101`: the purpose is not one of the four values. Send it exactly as written above, lower case, no spaces. See [PAYR-1032](../errors/payr-1032.md) and [PAYR-1101](../errors/payr-1101.md). +- You skipped `auth-requirements` and the preauthorisation comes back queried for missing documents. Run the check, attach what it names, and answer the query. See [answer a payer query on a preauthorisation](../flows/preauth-query-response.md). diff --git a/catalogue/nhcx/decisions/jwe-serialisation.md b/catalogue/nhcx/decisions/jwe-serialisation.md new file mode 100644 index 000000000..f53c917fc --- /dev/null +++ b/catalogue/nhcx/decisions/jwe-serialisation.md @@ -0,0 +1,99 @@ +--- +id: nhcx.decision.jwe-serialisation +type: decision +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Compact or flattened JWE serialisation +summary: >- + Send the sealed payload as one compact string inside the payload field, and parse + either written form when you receive one. +sources: +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 4, Q13. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 2.3 to 2.5. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy__message-security-and-integrity.md + hash: sha256:3768fd89932e4081c9e03a8695619bcaf70c641e28bb55a77eec090bb926eeb3 + fetched: '2026-09-14' + note: Site page /technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity, text as shown on the site. Message Encryption, final representation. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Response rows, all use case sheets. +- url: https://hcxsbx.abdm.gov.in/images/2b7fde4358fd0a4b2086.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Code Snippets references for payload preparation.pdf + hash: sha256:cea0cfbf5897e9642eaf9a515a941b0a1de39474ea39444c9e05abe21cd9ec73 + fetched: '2026-09-14' + note: NHCX Code Snippets references for payload preparation, row 13 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sections 3 and 4. +verified: + status: unverified +related: + concepts: + - nhcx.concept.jwe-envelope + decisions: + - nhcx.decision.key-encryption-algorithm + flows: + - nhcx.flow.send-a-sealed-request + - nhcx.flow.receive-a-sealed-callback + errors: + - nhcx.error.payr-1001 + troubleshooting: + - nhcx.troubleshooting.recipient-cannot-decrypt + glossary: + - nhcx.glossary.jwe + - nhcx.glossary.protected-header +--- + +# Compact or flattened JWE serialisation + +## In plain words + +A [JWE](../glossary/jwe.md) can be written two ways. Compact serialisation is one string of five Base64url parts joined by dots. Flattened JSON serialisation is an object with one member per part. + +Send compact, inside the `payload` field of the request body. Parse either form when you receive. + +## Before you start + +- You seal payloads with `alg` `RSA-OAEP-256` and `enc` `A256GCM`. See [RSA-OAEP or RSA-OAEP-256 for the content key](../decisions/key-encryption-algorithm.md). +- You have read [the JWE envelope that seals every payload](../concepts/jwe-envelope.md). + +## What happens + +| | Compact | Flattened JSON | +|---|---|---| +| Shape | `....`, one string | An object with `protected`, `encrypted_key`, `aad`, `iv`, `ciphertext` and `tag` | +| Where it travels | Inside the `payload` field of the body | As the body itself | +| Nimbus JOSE | `jweObject.serialize()` returns it | Built from the parts | +| Your system | Sends it on every request and callback | Parses it if one arrives | + +The default is compact. Every outgoing request to NHCX uses JWE Compact Serialization. The request body is exactly: + +```json +{"payload": ""} +``` + +Sealed answers arrive with a `type` member beside `payload`, for example `{"type": "JWEPayload", "payload": ""}`. A recipient that cannot process your message answers with `"type": "ProtocolResponse"` and clear-text headers instead. Read `type` first. `ProtocolResponse` is clear text; any other value means `payload` holds a sealed string. + +The five compact parts carry the same five values as the flattened members `protected`, `encrypted_key`, `iv`, `ciphertext` and `tag`. Split the compact string on its dots and pass the parts to one decrypt routine. The published decrypt sample takes exactly those five named parts, so it serves both forms. + +## How you know it worked + +- The body you send is one JSON object with one key, `payload`, whose value contains exactly four dots. +- Your receiver opens a sealed callback by splitting that string into five parts. +- Your receiver handles a `ProtocolResponse` without trying to decrypt it. + +## When it goes wrong + +Switching from flattened to compact changes one call: use your library's compact serializer and wrap the result in `payload`. Keys, headers and certificates stay the same, so you can switch after go-live. + +- Your callback handler tries to decrypt every body: a `ProtocolResponse` breaks it and you lose the error it carries. Branch on `type` first. See [receive, open and acknowledge a sealed message](../flows/receive-a-sealed-callback.md). +- The recipient answers `PAYR-1001`: check the serialisation along with the other causes in [the recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). See [PAYR-1001](../errors/payr-1001.md). diff --git a/catalogue/nhcx/decisions/key-encryption-algorithm.md b/catalogue/nhcx/decisions/key-encryption-algorithm.md new file mode 100644 index 000000000..41693b237 --- /dev/null +++ b/catalogue/nhcx/decisions/key-encryption-algorithm.md @@ -0,0 +1,94 @@ +--- +id: nhcx.decision.key-encryption-algorithm +type: decision +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: RSA-OAEP or RSA-OAEP-256 for the content key +summary: >- + Seal what you send with the stronger key wrapping value, and open messages sealed + with either value. +sources: +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Protected Header rows, all use case sheets. +- url: https://hcxsbx.abdm.gov.in/images/2b7fde4358fd0a4b2086.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Code Snippets references for payload preparation.pdf + hash: sha256:cea0cfbf5897e9642eaf9a515a941b0a1de39474ea39444c9e05abe21cd9ec73 + fetched: '2026-09-14' + note: NHCX Code Snippets references for payload preparation, row 13 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Section 3 constants. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy__message-security-and-integrity.md + hash: sha256:3768fd89932e4081c9e03a8695619bcaf70c641e28bb55a77eec090bb926eeb3 + fetched: '2026-09-14' + note: Site page /technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity, text as shown on the site. Message Encryption and Decryption steps. +- url: https://hcxsbx.abdm.gov.in/images/ec361a6c3e90e766d227.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Steps to generate encryption Certificate.pdf + hash: sha256:94605e935f05ebb49e24dee50787cb4f3f1c401983a9616a5aaabdbc302f664b + fetched: '2026-09-14' + note: Steps to generate encryption Certificate, row 20 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1, Step 1. +verified: + status: unverified +related: + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.encryption-certificate + decisions: + - nhcx.decision.jwe-serialisation + flows: + - nhcx.flow.send-a-sealed-request + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.generate-and-register-certificate + endpoints: + - nhcx.endpoint.fetch-certs + errors: + - nhcx.error.payr-1001 + troubleshooting: + - nhcx.troubleshooting.recipient-cannot-decrypt + glossary: + - nhcx.glossary.jwe + - nhcx.glossary.protected-header + - nhcx.glossary.x509-certificate +--- + +# RSA-OAEP or RSA-OAEP-256 for the content key + +## In plain words + +Every payload you send through [NHCX](../../shared/glossary/nhcx.md) is sealed as a [JWE](../glossary/jwe.md). A random content key encrypts the payload, and that key is wrapped with the recipient's RSA public key. The `alg` value in the [protected header](../glossary/protected-header.md) names how the key is wrapped. Two values are published: `RSA-OAEP`, which uses SHA-1, and `RSA-OAEP-256`, which uses SHA-256. + +Send `RSA-OAEP-256`. Accept both values when you decrypt. + +## Before you start + +- You have a 2048-bit RSA key pair and an [X.509 certificate](../glossary/x509-certificate.md) registered for it. See [generate an encryption certificate and register it](../flows/generate-and-register-certificate.md). +- You can fetch a recipient's certificate with [`POST /fetch/certs`](../endpoints/fetch-certs.md). +- You have read [the JWE envelope that seals every payload](../concepts/jwe-envelope.md). + +## What happens + +| | `RSA-OAEP-256` | `RSA-OAEP` | +|---|---|---| +| Digest used to wrap the content key | SHA-256 | SHA-1 | +| Content encryption, `enc` | `A256GCM` | `A256GCM` | +| Key pair | Your 2048-bit RSA pair | The same pair | +| Your system | Sends it on every message | Accepts it when decrypting | + +The default is `RSA-OAEP-256` on everything you send. It is the mandatory `alg` on every use case request and response. The reference Java code sets `KEY_MANAGEMENT_ALGORITHM = JWEAlgorithm.RSA_OAEP_256` with `EncryptionMethod.A256GCM`. Your outgoing protected header carries `"alg":"RSA-OAEP-256"` and `"enc":"A256GCM"` alongside the x-hcx protocol headers. + +Accepting both on receipt costs nothing. A recipient reads `alg` from the protected header of each message and chooses the key management mode from it. A decrypter that allows both values opens either, with the same private key. + +## How you know it worked + +- Base64url-decode the first segment of a JWE you sent. It shows `alg` `RSA-OAEP-256` and `enc` `A256GCM`. +- Seal a test payload to your own certificate twice, once with each `alg`. Your decrypter opens both. +- The recipient's answer arrives on your callback as a sealed payload, not as a `ProtocolResponse` carrying `PAYR-1001`. + +## When it goes wrong + +Switching the sending side is a one-line change to the algorithm constant. Switching the receiving side means adding the other value to your decrypter's allowed list. Neither touches your certificate or your registry entry, so both are safe after go-live. + +- A recipient answers `PAYR-1001` and you sent `RSA-OAEP`: change to `RSA-OAEP-256` first, then work through [the recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). See [PAYR-1001](../errors/payr-1001.md). +- Your decrypter rejects an incoming message on `alg`: you allowed only one value. Allow both. diff --git a/catalogue/nhcx/decisions/payer-implementation.md b/catalogue/nhcx/decisions/payer-implementation.md new file mode 100644 index 000000000..911e43e7c --- /dev/null +++ b/catalogue/nhcx/decisions/payer-implementation.md @@ -0,0 +1,106 @@ +--- +id: nhcx.decision.payer-implementation +type: decision +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Answer as your own payer system or through the PMJAY payer service +summary: >- + An insurer answers requests from its own system, while a government scheme case + is decided role by role in the scheme's system. +sources: +- file: catalogue/openapi/.raw/nhcx-site-2026-09-14/not-on-site/External_NHCX_Payer_Service_API_Workflow_Guide.docx + hash: sha256:1028d480d2fabe3204301f1c1b192a0077ddfa64f7f9084b01f73e004253fdd7 + fetched: '2026-09-05' + note: NHCX Payer Service API Workflow Guide for External Integrators, not listed on hcxsbx.abdm.gov.in and not named in the NHCX document sheet, received separately. Whole document. +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use cases 7 to 14 Validations and API logic. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 4 Existing PMJAY workflow. +- url: https://hcxsbx.abdm.gov.in/images/819467ec15aff13cc2a8.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Dummy Payer Implementation.pdf + hash: sha256:97335ebc4cd32c86e0c34328b2f4c526420b32a7a009208364043d6334e9e757 + fetched: '2026-09-14' + note: NHCX Dummy Payer Implementation, row 19 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Pages 1-3. +verified: + status: unverified +related: + concepts: + - nhcx.concept.participant-roles + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.payer-process-a-request + endpoints: + - nhcx.endpoint.payer-service-get-user-role + - nhcx.endpoint.payer-service-process-case + - nhcx.endpoint.dummy-payer-process-request + sandbox: + - nhcx.sandbox.dummy-payer + troubleshooting: + - nhcx.troubleshooting.callback-url-rejected + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + glossary: + - nhcx.glossary.adjudication + - nhcx.glossary.pmjay + - nhcx.glossary.tms + - nhcx.glossary.sha + - nhcx.glossary.tpa + - nhcx.glossary.payer +--- + +# Answer as your own payer system or through the PMJAY payer service + +## In plain words + +A request addressed to a payer needs an adjudicated answer on its `on_` callback. That answer comes from one of two places. Your own payer system decides it and answers over [NHCX](../../shared/glossary/nhcx.md). For a [PMJAY](../glossary/pmjay.md) case, named roles in the [SHA](../glossary/sha.md)'s [TMS](../glossary/tms.md) decide it, and integrators act on the case through the PMJAY payer service. + +If you are an insurer or a [TPA](../glossary/tpa.md), answer from your own payer system. Use the PMJAY payer service only for PMJAY cases. + +## Before you start + +- You are registered as a payer (`10002`) or TPA (`10003`), with a certificate and a callback endpoint. See [participant roles](../concepts/participant-roles.md). +- You know who processes each policy. A policy under a TPA names the insurer as `payerid` and the TPA as `processingid`. +- You have read [receive, adjudicate and answer a request as a payer](../flows/payer-process-a-request.md). + +## What happens + +| | Your own payer system | PMJAY payer service | +|---|---|---| +| Who decides | Your adjudication | The role holding the case in the SHA's TMS | +| What you build | A receiver for every request path, sealing, every `on_` call, and `/v1/error` | Two calls: [`get/user-role`](../endpoints/payer-service-get-user-role.md), then [`wrapper/process/case`](../endpoints/payer-service-process-case.md) | +| How the answer leaves | You send `/v1/preauth/on_submit`, `/v1/claim/on_submit` and the other `on_` calls, sealed to the provider | A role's action moves the case, and the verdict returns to the provider over NHCX | +| Preauthorisation roles | Yours | `PPD-Trust`: `Approve`, `Reject`, `Query` | +| Claim roles | Yours | `CEX-Trust`, `CPD-Trust`, Medical Audit Committee, `ACO-Trust`, `SHA-Trust`, Claim Review Committee, in that order | + +The default is your own payer system for any insurer or TPA. It is the only way requests addressed to your participant code are answered. The payer sandbox exit checks it one callback at a time. The PMJAY payer service exists because a PMJAY case is decided in the scheme's own system, by role, on that system's schedule. + +If you answer from your own system, each answer passes four checks: + +1. The payload validates against the [NRCeS](../../shared/glossary/nrces.md) profiles. +2. The api call id of your answer differs from its correlation id. +3. The correlation id is the api call id of the request you are answering. +4. The receiver code is the sender code of that request. + +If you act through the payer service, read the role before every action. Send the action name exactly as that role takes it: `cpdApprove`, `cpdReject` and `iQuery` are case sensitive. + +## How you know it worked + +Own payer system: every request addressed to your code reaches your endpoint, and each gets its `on_` call. The provider receives it with the correlation id it expects. + +PMJAY payer service: `get/user-role` names a role for the case. An action from that role's list is accepted, and the provider receives `/v1/preauth/on_submit` or `/v1/claim/on_submit`. + +## When it goes wrong + +Nothing built for one branch serves the other. Choose by who owns the decision, not by effort. + +- An action fails on the payer service: read the role again with `get/user-role`. The service moves cases on its own schedule, so the role you read earlier may have changed. +- A provider's request never reaches your own system: check that the provider addressed your processing code and that your endpoint is reachable. See [your callback URL is rejected or never called](../troubleshooting/callback-url-rejected.md). +- Your answer is refused or lands on the wrong case: check the four answer rules above. See [responses arrive against the wrong request](../troubleshooting/duplicate-or-mismatched-correlation.md). + +Provider teams testing in the sandbox use the [dummy payer](../sandbox/dummy-payer.md) instead. [`POST /process/request`](../endpoints/dummy-payer-process-request.md) triggers an approve, reject or query answer for a preauthorisation or claim. diff --git a/catalogue/nhcx/decisions/preauth-or-predetermination.md b/catalogue/nhcx/decisions/preauth-or-predetermination.md new file mode 100644 index 000000000..c138f9e8e --- /dev/null +++ b/catalogue/nhcx/decisions/preauth-or-predetermination.md @@ -0,0 +1,97 @@ +--- +id: nhcx.decision.preauth-or-predetermination +type: decision +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Preauthorisation or predetermination +summary: >- + Ask the payer to approve planned treatment with a preauthorisation, and use a + predetermination only as an optional preview. +sources: +- url: https://hcxsbx.abdm.gov.in/images/af8d243edcc2139a515d.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Usecases.pdf + hash: sha256:8709b2907a0d5a0dbb36f5e63ed8deae269e0c75372b05d71ce7380c8a0929e7 + fetched: '2026-09-14' + note: NHCX Usecases, row 1 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use case table, Preauth and Predetermination rows. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. API Structure table. +- url: https://hcxsbx.abdm.gov.in/images/2c3fbb4e6b09f0834f69.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Implementation Guide for Adoption of FHIR in ABDM and NHCX.pdf + hash: sha256:549377c9c26b1bd23decac3a1b9e5ebedfdc8e0fe99e53ef733859b188f51366 + fetched: '2026-09-14' + note: Implementation Guide for Adoption of FHIR in ABDM and NHCX, row 14 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. API table rows 5-6. +- url: https://hcxsbx.abdm.gov.in/images/819467ec15aff13cc2a8.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Dummy Payer Implementation.pdf + hash: sha256:97335ebc4cd32c86e0c34328b2f4c526420b32a7a009208364043d6334e9e757 + fetched: '2026-09-14' + note: NHCX Dummy Payer Implementation, row 19 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1 use case list. +- url: https://hcxsbx.abdm.gov.in/images/b6bd99dab49a5e928ea3.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Overview.pdf + hash: sha256:c95469758a25cb8aca8c47757d8b18b4dedb8b4d42669663cff7343205f77fda + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Overview, row 27 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Page 8 flow table. +verified: + status: unverified +related: + concepts: + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.predetermination + - nhcx.flow.preauth-query-response + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.predetermination-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.payr-1010 + decisions: + - nhcx.decision.eligibility-purpose + glossary: + - nhcx.glossary.preauthorisation + - nhcx.glossary.predetermination +--- + +# Preauthorisation or predetermination + +## In plain words + +Before planned treatment, a provider can ask a payer about it over [NHCX](../../shared/glossary/nhcx.md) in two ways. A [preauthorisation](../glossary/preauthorisation.md) asks the payer to approve the treatment. A [predetermination](../glossary/predetermination.md) asks the payer to adjudicate the planned claim in advance, against the policy and the beneficiary's past history. + +Send a preauthorisation. Send a predetermination only to a payer that answers them, when you want that preview first. + +## Before you start + +- You have run coverage eligibility with `auth-requirements`. See [which coverage eligibility purpose to send](../decisions/eligibility-purpose.md). +- You have read [the claim cycle from eligibility to payment](../concepts/claim-cycle.md). + +## What happens + +| | Preauthorisation | Predetermination | +|---|---|---| +| Request | [`POST /v1/preauth/submit`](../endpoints/preauth-submit.md) | [`POST /v1/predetermination/submit`](../endpoints/predetermination-submit.md) | +| Answer arrives on | `/v1/preauth/on_submit` | `/v1/predetermination/on_submit` | +| Payload | Claim bundle whose `use` marks a preauthorisation | Claim bundle whose `use` marks a predetermination | +| Payer's answer | A ClaimResponse approving, rejecting or querying the request | A ClaimResponse with auto adjudication details against the policy and past history | +| Sandbox dummy payer | Answers it | Not among its use cases | +| [PMJAY](../glossary/pmjay.md) | Part of the flow, after biometric authentication | Not part of the flow | + +The default is preauthorisation. It is the request a payer approves before treatment. It is in the PMJAY flow, and the sandbox dummy payer answers it, so you can test it end to end. Use predetermination when a payer offers it and you want an adjudication preview before you commit to a preauthorisation. + +## How you know it worked + +- The payer answers your preauthorisation on `/v1/preauth/on_submit` with a ClaimResponse. +- Where you use predetermination, the payer answers on `/v1/predetermination/on_submit`, and you still send the preauthorisation afterwards. + +## When it goes wrong + +The two share the Claim bundle, so switching is a change of path and `use`. Start the new request with a new correlation id; nothing carries over between the two cycles. + +- A predetermination gets no answer: confirm that the payer handles predeterminations. Then see [the request was accepted with 202 and no callback arrives](../troubleshooting/accepted-then-no-callback.md). +- The preauthorisation comes back queried: send a query response, not a resubmission. See [answer a payer query on a preauthorisation](../flows/preauth-query-response.md). +- The claim is refused with `PAYR-1010`, preauthorisation required but not obtained. See [PAYR-1010](../errors/payr-1010.md). diff --git a/catalogue/nhcx/decisions/session-endpoint.md b/catalogue/nhcx/decisions/session-endpoint.md new file mode 100644 index 000000000..742cb1408 --- /dev/null +++ b/catalogue/nhcx/decisions/session-endpoint.md @@ -0,0 +1,118 @@ +--- +id: nhcx.decision.session-endpoint +type: decision +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Which session token endpoint to call +summary: >- + Get the token that every exchange call carries from one place in your code, and + set the address it calls per environment. +sources: +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 2, Q2 base URLs; Page 5, Q20. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 3.1 Token Request. +- url: https://hcxsbx.abdm.gov.in/images/54d18468412741b759f3.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Authenticating with NHCX.pdf + hash: sha256:0ea90b635634844aaf8981e917cbf8b765ddd83a340f3c934883912599a62d8b + fetched: '2026-09-14' + note: Authenticating with NHCX, row 3 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1. +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use case 4 Get the auth token. +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use case 6 Get the auth token. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 2, items 6 and 9. +verified: + status: unverified +related: + concepts: + - nhcx.concept.session-token + endpoints: + - nhcx.endpoint.session-token + - nhcx.endpoint.get-session + errors: + - nhcx.error.nhcx-401 + tests: + - nhcx.test.provider-uc-04 + - nhcx.test.payer-uc-06 + troubleshooting: + - nhcx.troubleshooting.everything-returns-401 + sandbox: + - nhcx.sandbox.environments-and-base-urls + glossary: + - shared.glossary.request-id + - shared.glossary.timestamp-header + - shared.glossary.x-cm-id +--- + +# Which session token endpoint to call + +## In plain words + +Every call you make to [NHCX](../../shared/glossary/nhcx.md) carries a bearer token. You mint it from the client ID and secret issued at onboarding. Two token calls are published: the [ABDM](../../shared/glossary/abdm.md) gateway sessions call and the participant service `/get/session` call. Both take the same client credentials and return a token with its lifetime. + +Put token acquisition behind one client in your code. Make its address, body format and response field names configuration. Set it to the gateway sessions call at `/api/hiecm/gateway/v3/sessions` by default. + +## Before you start + +- You hold a client ID and secret. The [Milestone 1](../../shared/glossary/m1.md) credentials work here; no separate credentials are issued. See [onboard as a participant in the NHCX sandbox](../flows/sandbox-onboarding.md). +- You know which environment you are calling. See [environments and base URLs](../sandbox/environments-and-base-urls.md). +- You have read [the session token every NHCX call carries](../concepts/session-token.md). + +## What happens + +| | ABDM gateway sessions | Participant service `/get/session` | +|---|---|---| +| Sandbox address | `POST https://dev.abdm.gov.in/api/hiecm/gateway/v3/sessions` | `POST /get/session` on `apisbx.abdm.gov.in` | +| Request headers | `Content-Type: application/json`, [`REQUEST-ID`](../../shared/glossary/request-id.md), [`TIMESTAMP`](../../shared/glossary/timestamp-header.md), [`X-CM-ID`](../../shared/glossary/x-cm-id.md) `sbx` | `Content-Type: application/x-www-form-urlencoded` | +| Body | `clientId`, `clientSecret`, `grantType` `client_credentials` | `client_id`, `client_secret`, `grant_type=client_credentials` | +| Token field in the response | `accessToken` | `access_token` | +| Lifetime field in the response | `expiresIn`, in seconds | `expires_in`, in seconds | + +The same gateway call is also published at `/gateway/v0.5/sessions`, taking `clientId` and `clientSecret`. Point new builds at the v3 address, which requires `grantType`. + +The default is the gateway sessions call at the v3 address. It is the session address in the sandbox base URL list. It takes the credentials you already hold from Milestone 1. One token from it serves every NHCX call. + +Whichever address you configure, these rules hold: + +1. Read the token from `accessToken` or `access_token`, whichever is present. +2. Read the lifetime from `expiresIn` or `expires_in` on every response. Never hard-code a lifetime. +3. Store the token with the time you received it. Fetch a new one before it expires. +4. On a `401`, fetch a new token and retry that call once. A second `401` means the credentials are wrong or revoked: stop and alert. +5. Send the token as `Bearer ` in both the `bearer_auth` and `Authorization` headers. +6. Never log the token or the client secret. + +## How you know it worked + +You chose correctly when all of these hold: + +- A token call returns a token and a lifetime, and your client stores both. +- A call made with that token, such as `POST /fetch/participants/list`, returns its normal response, not `401`. +- Pointing the configuration at the other address needs no code change. + +Sandbox exit use case 4 for providers and use case 6 for payers name `/get/session` as the auth token call. Point the configuration there when you demonstrate those cases. See [provider use case 4](../tests/provider-uc-04.md) and [payer use case 6](../tests/payer-uc-06.md). + +## When it goes wrong + +Switching is a configuration change: the address, the body encoding and the two response field names. Nothing is registered against either call, so you can switch at any time, including after go-live. Production addresses come with production access; see [going live](../sandbox/going-live.md). + +If you hard-coded a lifetime or a field name, calls fail at a fixed interval after each new token. You see `401` with `Sender is not authorized to execute the operation`. See [every NHCX call returns 401](../troubleshooting/everything-returns-401.md) and [NHCX-401](../errors/nhcx-401.md). + +If the token call itself answers `400`, the body does not match the address. The gateway call takes JSON; `/get/session` takes form encoding with `grant_type=client_credentials`. diff --git a/catalogue/nhcx/decisions/status-poll-or-wait.md b/catalogue/nhcx/decisions/status-poll-or-wait.md new file mode 100644 index 000000000..97af3590d --- /dev/null +++ b/catalogue/nhcx/decisions/status-poll-or-wait.md @@ -0,0 +1,99 @@ +--- +id: nhcx.decision.status-poll-or-wait +type: decision +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Poll with /v1/status or wait for the callback +summary: >- + Wait for the answer to come to you, and ask where a request stands only when its + answer is overdue. +sources: +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Status. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 4, Q12. +verified: + status: unverified +related: + concepts: + - nhcx.concept.four-message-legs + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.retries-and-expiry + - nhcx.concept.status-lifecycle + flows: + - nhcx.flow.status-check + endpoints: + - nhcx.endpoint.status + callbacks: + - nhcx.callback.on-status + - nhcx.callback.error + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1012 + tests: + - nhcx.test.provider-uc-13 + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback + glossary: + - nhcx.glossary.correlation-id + - nhcx.glossary.api-call-id +--- + +# Poll with /v1/status or wait for the callback + +## In plain words + +When [NHCX](../../shared/glossary/nhcx.md) accepts your request with `202`, the answer comes later on the `on_` callback. `POST /v1/status` tells you where a request stands in the meantime. + +Wait for the callback. Call `/v1/status` only when the callback is overdue, then act on what it says. Never resubmit to find out. + +## Before you start + +- Your callback endpoint answers `202` within 30 seconds. See [the 202 acknowledgement and the 30 second rule](../concepts/synchronous-acknowledgement.md). +- You implement `/v1/error`. See [receiving POST /v1/error](../callbacks/error.md). +- You store each request's api call id and correlation id against the case before you send it. + +## What happens + +| | Wait for the callback | Call `/v1/status` | +|---|---|---| +| What you learn | The decision itself, sealed in the `on_` callback | Where the request is: `request.queued` or `request.dispatched` | +| Cost | Nothing beyond your callback endpoint | One sealed call per check | +| What follows | Nothing: the callback ends the cycle | `request.queued`: nothing yet; the request is still inside NHCX. `request.dispatched`: the recipient holds it, and a `/v1/on_status` callback follows | + +The default is to wait. Every decision, acknowledgement and error reaches you through a callback. `/v1/status` reports transport position only. + +When a callback is overdue by your own tolerance, send one [status check](../endpoints/status.md): + +- Set `x-hcx-correlation_id` to the api call id of the request you are checking. +- Set `x-hcx-status` to `request.initiated`. +- Use a fresh `x-hcx-api_call_id`. + +Set each initiating request's correlation id equal to its api call id. The status call then carries that one value. See [correlation id](../glossary/correlation-id.md). + +## How you know it worked + +- Callbacks arrive for requests you never checked. +- Each status call you make returns `202` with `protocol_status` `request.queued` or `request.dispatched`. +- Your logs show no `NHCX-1006` from a resubmitted request. + +## When it goes wrong + +Moving from polling to waiting means deleting scheduled status calls and keeping one check for overdue requests. Nothing is registered, so you can switch at any time. + +- `NHCX-1006`: you resubmitted a request with its original correlation id. See [NHCX-1006](../errors/nhcx-1006.md). +- `NHCX-1012`: the status call's correlation id matches no api call id you sent. Use the original request's api call id. See [NHCX-1012](../errors/nhcx-1012.md). +- Status finds nothing for a request you did send: after five failed deliveries, NHCX deletes the request and the failure goes to your `/v1/error`. Start a new cycle. See [gateway retries and the 24 hour expiry window](../concepts/retries-and-expiry.md). +- The callback never comes at all: see [the request was accepted with 202 and no callback arrives](../troubleshooting/accepted-then-no-callback.md). diff --git a/catalogue/nhcx/endpoints/abha-biometric-auth-init.md b/catalogue/nhcx/endpoints/abha-biometric-auth-init.md new file mode 100644 index 000000000..4af097841 --- /dev/null +++ b/catalogue/nhcx/endpoints/abha-biometric-auth-init.md @@ -0,0 +1,117 @@ +--- +id: nhcx.endpoint.abha-biometric-auth-init +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /hcx/abha/biometric/auth/init +summary: >- + Start a fingerprint or iris check that proves a scheme patient is at the hospital, + and get the transaction id the next step needs. +sources: +- url: https://hcxsbx.abdm.gov.in/images/9f1e6b545a693d38a704.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Biometric Authentication Implementation Steps.docx + hash: sha256:fac8b14bfe8d518c0e651740537b9441c501d3cf2ab0f0482a07ab9f417e43a9 + fetched: '2026-09-14' + note: Biometric Authentication Implementation Steps, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments, not named in the NHCX document sheet. Biometric Authentication - Fingerprint/IRIS, Auth INIT; applicability table. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. page 18-20, section 8.2 Biometric Authentication. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 15, Q26.9 process type. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.abha-biometric-auth-init + - nhcx.endpoint.abha-biometric-auth-verify + - nhcx.endpoint.abha-biometric-auth-refresh-token + - nhcx.endpoint.abha-biometric-faceauth-init + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + - nhcx.endpoint.session-token + errors: + - nhcx.error.payr-1256 + - nhcx.error.payr-1363 + concepts: + - nhcx.concept.biometric-authentication + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.biometric-fingerprint-iris + decisions: + - nhcx.decision.biometric-modality + glossary: + - nhcx.glossary.rd-service + - nhcx.glossary.pid-block +--- + +# POST /hcx/abha/biometric/auth/init + +## In plain words + +[PMJAY](../glossary/pmjay.md) requires proof that the beneficiary is physically present at the hospital. The hospital proves it by authenticating the beneficiary against their [ABHA](../../shared/glossary/abha.md), by fingerprint, iris or face. Init starts a fingerprint or iris authentication and returns a `txnId`. You then capture the biometric on a device and complete it with [auth verify](abha-biometric-auth-verify.md). + +These are plain JSON calls: no JWE envelope and no callback. + +## Before you start + +- The beneficiary's ABHA is linked to their PMJAY card. Where it is not, follow the scheme's approved [KYC](../../shared/glossary/kyc.md) protocols instead. +- A session token for the `Authorization` header, not `bearer_auth`. See [the session token](../concepts/session-token.md). +- The participant code of the scheme payer the authentication is for. It goes in the `payerid` header. +- The beneficiary's ABHA number, with hyphens, as `91-XXXX-XXXX-XXXX`. +- A fingerprint or iris capture device with its [RD service](../glossary/rd-service.md) app. For iris or face instead, see [which modality to use](../decisions/biometric-modality.md). + +## What happens + +Your system calls the ABHA biometric service directly. Choose the modality: + +| Modality | `scope` | `authMode` | +|---|---|---| +| Fingerprint | `["abha-login", "aadhaar-bio-verify"]` | `FINGERPRINT` | +| Iris | `["abha-login", "aadhaar-iris-verify"]` | `IRIS` | + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/hcx/abha/biometric/auth/init' \ + --header 'accept: */*' \ + --header 'Content-Type: application/json' \ + --header 'Authorization: Bearer ' \ + --header 'process: Preauth' \ + --header 'payerid: ' \ + --data-raw '{ + "scope": ["abha-login", "aadhaar-bio-verify"], + "loginHint": "abha-number", + "loginId": "", + "otpSystem": "aadhaar", + "authMode": "FINGERPRINT" + }' +``` + +`process` is `Preauth` at registration or pre-authorisation, and `Discharge` at discharge. + +**Retrying.** Each init starts a new transaction. If a call fails, call init again and use the `txnId` it returns. + +## How you know it worked + +You receive a JSON body with a `txnId`: + +```json +{ + "txnId": "", + "authMode": null, + "message": "FingerPrint authentication request successfully sent.", + "status": null +} +``` + +The step is done when you hold a `txnId`. Capture the biometric and send it with that `txnId` to auth verify. + +## When it goes wrong + +- `401` although the token is fresh: the token went on `bearer_auth`. These calls read `Authorization`. +- The request goes to the face host. Fingerprint and iris sit under `/hcx/abha/biometric/`, face under `/pmjay/sbxhcx/abdmproxy/abha/biometric/`. +- `loginId` has its hyphens stripped. Send the ABHA number as `91-XXXX-XXXX-XXXX`. diff --git a/catalogue/nhcx/endpoints/abha-biometric-auth-refresh-token.md b/catalogue/nhcx/endpoints/abha-biometric-auth-refresh-token.md new file mode 100644 index 000000000..cd765e71e --- /dev/null +++ b/catalogue/nhcx/endpoints/abha-biometric-auth-refresh-token.md @@ -0,0 +1,94 @@ +--- +id: nhcx.endpoint.abha-biometric-auth-refresh-token +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: GET /hcx/abha/biometric/auth/refresh/token +summary: >- + Swap a scheme patient's refresh token for a new short-lived presence token without + capturing their biometric again. +sources: +- url: https://hcxsbx.abdm.gov.in/images/9f1e6b545a693d38a704.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Biometric Authentication Implementation Steps.docx + hash: sha256:fac8b14bfe8d518c0e651740537b9441c501d3cf2ab0f0482a07ab9f417e43a9 + fetched: '2026-09-14' + note: Biometric Authentication Implementation Steps, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments, not named in the NHCX document sheet. 3. Auth Refresh Token. +- url: https://hcxsbx.abdm.gov.in/images/8a3940fb518ea05d34e9.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Biometric Authentication APIs Postman Collection.zip + hash: sha256:725dc838b39beb3e3ddd2c008314323e6d5cd1c237d98875280da5218da458a4 + fetched: '2026-09-14' + note: Biometric Authentication APIs Postman Collection, row 30 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. item auth/refresh/token Copy. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 15, Q26.9 process type. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.abha-biometric-auth-init + - nhcx.endpoint.abha-biometric-auth-verify + - nhcx.endpoint.abha-biometric-auth-refresh-token + - nhcx.endpoint.abha-biometric-faceauth-init + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + - nhcx.endpoint.session-token + errors: + - nhcx.error.payr-1256 + - nhcx.error.payr-1363 + concepts: + - nhcx.concept.biometric-authentication + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.biometric-fingerprint-iris + - nhcx.flow.biometric-face + decisions: + - nhcx.decision.biometric-modality + glossary: + - nhcx.glossary.rd-service + - nhcx.glossary.pid-block +--- + +# GET /hcx/abha/biometric/auth/refresh/token + +## In plain words + +[PMJAY](../glossary/pmjay.md) requires proof that the beneficiary is physically present at the hospital. The hospital proves it by authenticating the beneficiary against their [ABHA](../../shared/glossary/abha.md), by fingerprint, iris or face. The user token from a biometric verify lasts 30 minutes, but a case lasts longer. This call exchanges the refresh token for a new user token and a new refresh token, so the case stays authenticated. + +These are plain JSON calls: no JWE envelope and no callback. + +## Before you start + +- A session token for the `Authorization` header, not `bearer_auth`. See [the session token](../concepts/session-token.md). +- The participant code of the scheme payer the authentication is for. It goes in the `payerid` header. +- A refresh token less than 15 days old, from [auth verify](abha-biometric-auth-verify.md), [face verify](abha-biometric-v2-auth-verify.md) or an earlier refresh. + +## What happens + +Your system calls the ABHA biometric service with the refresh token on the `R-token` header. The request has no body. + +```bash +curl --location --request GET 'https://apisbx.abdm.gov.in/hcx/abha/biometric/auth/refresh/token' \ + --header 'R-token: Bearer ' \ + --header 'Authorization: Bearer ' \ + --header 'payerid: ' \ + --header 'process: Preauth' +``` + +`process` is `Preauth` at registration or pre-authorisation, and `Discharge` at discharge. + +Each refresh returns a new refresh token whose 15 days run from that moment. Refresh at least once every 10 days and store the new token to keep the chain alive. + +## How you know it worked + +You receive a new token pair in the same shape as auth verify: `token` with `expiresIn` 1800 and `refreshToken` with `refreshExpiresIn` 1296000. + +The step is done when the new user token and the new refresh token are stored against the case, replacing the old ones. + +## When it goes wrong + +- The refresh token went on `Authorization`. It belongs on `R-token`, and the session token on `Authorization`. +- The old refresh token was kept after a refresh. Store the new one every time. +- The refresh token is more than 15 days old. Start a fresh biometric authentication. diff --git a/catalogue/nhcx/endpoints/abha-biometric-auth-verify.md b/catalogue/nhcx/endpoints/abha-biometric-auth-verify.md new file mode 100644 index 000000000..6934fb8cc --- /dev/null +++ b/catalogue/nhcx/endpoints/abha-biometric-auth-verify.md @@ -0,0 +1,129 @@ +--- +id: nhcx.endpoint.abha-biometric-auth-verify +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /hcx/abha/biometric/auth/verify +summary: >- + Complete a fingerprint or iris check of a scheme patient and receive the short-lived + token that proves they were present. +sources: +- url: https://hcxsbx.abdm.gov.in/images/9f1e6b545a693d38a704.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Biometric Authentication Implementation Steps.docx + hash: sha256:fac8b14bfe8d518c0e651740537b9441c501d3cf2ab0f0482a07ab9f417e43a9 + fetched: '2026-09-14' + note: Biometric Authentication Implementation Steps, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments, not named in the NHCX document sheet. Auth Verify; Token Validity and Refresh Mechanism table. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 3-4, Q10 K-547; page 15, Q26.9 process type. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.abha-biometric-auth-init + - nhcx.endpoint.abha-biometric-auth-verify + - nhcx.endpoint.abha-biometric-auth-refresh-token + - nhcx.endpoint.abha-biometric-faceauth-init + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + - nhcx.endpoint.session-token + errors: + - nhcx.error.payr-1256 + - nhcx.error.payr-1363 + concepts: + - nhcx.concept.biometric-authentication + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.biometric-fingerprint-iris + decisions: + - nhcx.decision.biometric-modality + glossary: + - nhcx.glossary.rd-service + - nhcx.glossary.pid-block +--- + +# POST /hcx/abha/biometric/auth/verify + +## In plain words + +[PMJAY](../glossary/pmjay.md) requires proof that the beneficiary is physically present at the hospital. The hospital proves it by authenticating the beneficiary against their [ABHA](../../shared/glossary/abha.md), by fingerprint, iris or face. Verify completes a fingerprint or iris authentication started by [auth init](abha-biometric-auth-init.md). It sends the captured biometric and returns the beneficiary's user token, valid 30 minutes, and a refresh token, valid 15 days. + +These are plain JSON calls: no JWE envelope and no callback. + +## Before you start + +- The beneficiary's ABHA is linked to their PMJAY card. Where it is not, follow the scheme's approved [KYC](../../shared/glossary/kyc.md) protocols instead. +- A session token for the `Authorization` header, not `bearer_auth`. See [the session token](../concepts/session-token.md). +- The participant code of the scheme payer the authentication is for. It goes in the `payerid` header. +- A `txnId` from [auth init](abha-biometric-auth-init.md) for the same modality. +- The [PID block](../glossary/pid-block.md) from the capture device. Build the device's wrapped Aadhaar data hash with `lr` set to `Y`. + +## What happens + +Your system calls the ABHA biometric service directly with the capture. + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/hcx/abha/biometric/auth/verify' \ + --header 'accept: */*' \ + --header 'Content-Type: application/json' \ + --header 'Authorization: Bearer ' \ + --header 'process: Preauth' \ + --header 'payerid: ' \ + --data-raw '{ + "scope": ["abha-login", "aadhaar-bio-verify"], + "authData": { + "authMethods": ["bio"], + "bio": { + "txnId": "", + "fingerPrintAuthPid": "" + } + }, + "authMode": "FINGERPRINT" + }' +``` + +For iris, send `scope` `["abha-login", "aadhaar-iris-verify"]`, `authMethods` `["iris"]`, an `iris` object with `txnId` and `irisAuthPid`, and `authMode` `IRIS`. + +`process` is `Preauth` at registration or pre-authorisation, and `Discharge` at discharge. + +**Retrying.** A capture belongs to its `txnId`. After a failure, start again with a new init and a new capture. + +## How you know it worked + +You receive a JSON body with `authResult` `success`: + +```json +{ + "txnId": "", + "authResult": "success", + "message": "", + "token": "", + "refreshToken": "", + "expiresIn": 1800, + "refreshExpiresIn": 1296000, + "accounts": [ + { + "ABHANumber": "", + "preferredAbhaAddress": "", + "name": "", + "status": "ACTIVE" + } + ] +} +``` + +- `token` is the user token. It expires after `expiresIn` seconds, 1800. +- `refreshToken` lasts `refreshExpiresIn` seconds, 1296000, which is 15 days. +- `accounts[0].ABHANumber` is the beneficiary you authenticated. + +The step is done when both tokens are stored against the case. Keep the user token live with [the refresh call](abha-biometric-auth-refresh-token.md) until the transaction cycle ends. + +## When it goes wrong + +- The biometric APIs answer `K-547`: the wrapped Aadhaar data hash was built with `lr` `N`. Build it with `lr` `Y`, keeping `rc` `Y`, `de` `N` and `pfr` `N`. +- The PID block sits under the wrong key. Fingerprint uses `bio.fingerPrintAuthPid`, iris uses `iris.irisAuthPid`. +- The token lapsed and cannot be refreshed. Start a fresh authentication. Without one, a pre-authorisation is refused with [`PAYR-1256`](../errors/payr-1256.md) and a claim with [`PAYR-1363`](../errors/payr-1363.md), unless it carries the consent questionnaire response. +- `401`: the token went on `bearer_auth` instead of `Authorization`. diff --git a/catalogue/nhcx/endpoints/abha-biometric-capture-pid.md b/catalogue/nhcx/endpoints/abha-biometric-capture-pid.md new file mode 100644 index 000000000..35d5ccc46 --- /dev/null +++ b/catalogue/nhcx/endpoints/abha-biometric-capture-pid.md @@ -0,0 +1,99 @@ +--- +id: nhcx.endpoint.abha-biometric-capture-pid +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /pmjay/sbxhcx/abdmproxy/abha/biometric/capture/pid +summary: >- + Check whether a scheme patient has finished the face scan on their phone, so the + hospital can complete the face check. +sources: +- url: https://hcxsbx.abdm.gov.in/images/9f1e6b545a693d38a704.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Biometric Authentication Implementation Steps.docx + hash: sha256:fac8b14bfe8d518c0e651740537b9441c501d3cf2ab0f0482a07ab9f417e43a9 + fetched: '2026-09-14' + note: Biometric Authentication Implementation Steps, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments, not named in the NHCX document sheet. NHCX Face-Auth API Curl, FACE AUTH Capture PID. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.abha-biometric-faceauth-init + - nhcx.endpoint.abha-biometric-capture-pid + - nhcx.endpoint.abha-biometric-v2-auth-verify + - nhcx.endpoint.abha-biometric-auth-refresh-token + - nhcx.endpoint.abha-biometric-auth-init + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.session-token + errors: + - nhcx.error.payr-1256 + - nhcx.error.payr-1363 + concepts: + - nhcx.concept.biometric-authentication + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.biometric-face + decisions: + - nhcx.decision.biometric-modality +--- + +# POST /pmjay/sbxhcx/abdmproxy/abha/biometric/capture/pid + +## In plain words + +[PMJAY](../glossary/pmjay.md) requires proof that the beneficiary is physically present at the hospital. The hospital proves it by authenticating the beneficiary against their [ABHA](../../shared/glossary/abha.md), by fingerprint, iris or face. In face authentication the capture happens on the patient's phone, out of your system's sight. This call tells you whether it has finished. You poll it between showing the QR code and calling face verify. + +These are plain JSON calls: no JWE envelope and no callback. + +## Before you start + +- A session token for the `Authorization` header, not `bearer_auth`. See [the session token](../concepts/session-token.md). +- A `txnId` from [face auth init](abha-biometric-faceauth-init.md), shown to the patient as a QR code. + +## What happens + +Your system calls the ABDM proxy host with the `txnId`, repeatedly, until the capture is complete. + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/abdmproxy/abha/biometric/capture/pid' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'Authorization: Bearer ' \ + --header 'REQUEST-ID: ' \ + --header 'TIMESTAMP: ' \ + --data-raw '{ + "txnId": "" + }' +``` + +`REQUEST-ID` is a new UUID for every call ([REQUEST-ID](../../shared/glossary/request-id.md)). `TIMESTAMP` is the current time in UTC, ISO 8601 with milliseconds and a trailing `Z` ([TIMESTAMP](../../shared/glossary/timestamp-header.md)). + +**Retrying.** The call only reads the capture state, so repeat it freely. Give each attempt a new `REQUEST-ID`. + +## How you know it worked + +Before the patient finishes, you receive: + +```json +{ + "status": "PENDING", + "message": "Awaiting PID capture" +} +``` + +After the face scan, you receive: + +```json +{ + "status": "COMPLETE", + "message": "PID capture successful" +} +``` + +The step is done when `status` is `COMPLETE`. Call [face verify](abha-biometric-v2-auth-verify.md) next. + +## When it goes wrong + +- The status stays `PENDING`: the patient has not scanned the code or not finished the scan. Ask them to complete it in the ABHA app. +- Face verify is called before `COMPLETE`. Wait for `COMPLETE` first. +- The call goes to the fingerprint host. Use the ABDM proxy host. diff --git a/catalogue/nhcx/endpoints/abha-biometric-faceauth-init.md b/catalogue/nhcx/endpoints/abha-biometric-faceauth-init.md new file mode 100644 index 000000000..98cd1a664 --- /dev/null +++ b/catalogue/nhcx/endpoints/abha-biometric-faceauth-init.md @@ -0,0 +1,103 @@ +--- +id: nhcx.endpoint.abha-biometric-faceauth-init +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /pmjay/sbxhcx/abdmproxy/abha/biometric/faceauth/init +summary: >- + Start a face check that proves a scheme patient is at the hospital, and get the + transaction id for the code the patient scans. +sources: +- url: https://hcxsbx.abdm.gov.in/images/9f1e6b545a693d38a704.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Biometric Authentication Implementation Steps.docx + hash: sha256:fac8b14bfe8d518c0e651740537b9441c501d3cf2ab0f0482a07ab9f417e43a9 + fetched: '2026-09-14' + note: Biometric Authentication Implementation Steps, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments, not named in the NHCX document sheet. NHCX Face-Auth API Curl, Face Auth Init API and step 1.1. +- url: https://hcxsbx.abdm.gov.in/images/a2f07ff8158e86e9e92a.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/FaceAuth Postman Collection.zip + hash: sha256:f2db63f7fe272178ee57acfcfd32dbc40680d69527dc35c6724f0da2a32fcaab + fetched: '2026-09-14' + note: FaceAuth Postman Collection, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments, not named in the NHCX document sheet. item FaceAuth init. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.abha-biometric-faceauth-init + - nhcx.endpoint.abha-biometric-capture-pid + - nhcx.endpoint.abha-biometric-v2-auth-verify + - nhcx.endpoint.abha-biometric-auth-refresh-token + - nhcx.endpoint.abha-biometric-auth-init + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.session-token + errors: + - nhcx.error.payr-1256 + - nhcx.error.payr-1363 + concepts: + - nhcx.concept.biometric-authentication + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.biometric-face + decisions: + - nhcx.decision.biometric-modality +--- + +# POST /pmjay/sbxhcx/abdmproxy/abha/biometric/faceauth/init + +## In plain words + +[PMJAY](../glossary/pmjay.md) requires proof that the beneficiary is physically present at the hospital. The hospital proves it by authenticating the beneficiary against their [ABHA](../../shared/glossary/abha.md), by fingerprint, iris or face. Face authentication works when fingerprint and iris do not. The patient completes the capture on their own phone in the ABHA app. Init returns a `txnId` that you show to the patient as a QR code. + +These are plain JSON calls: no JWE envelope and no callback. + +## Before you start + +- The beneficiary's ABHA is linked to their PMJAY card. Where it is not, follow the scheme's approved [KYC](../../shared/glossary/kyc.md) protocols instead. +- A session token for the `Authorization` header, not `bearer_auth`. See [the session token](../concepts/session-token.md). +- The patient has the ABHA app on a phone. In the sandbox, use the sandbox ABHA app. +- The patient can complete a face scan with the Aadhaar [RD service](../glossary/rd-service.md) app. + +## What happens + +Your system calls the ABDM proxy host, not the fingerprint host. + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/abdmproxy/abha/biometric/faceauth/init' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'Authorization: Bearer ' \ + --header 'REQUEST-ID: ' \ + --header 'TIMESTAMP: ' \ + --data-raw '{ + "scope": ["abha-enrol", "face-auth"] + }' +``` + +`REQUEST-ID` is a new UUID for every call ([REQUEST-ID](../../shared/glossary/request-id.md)). `TIMESTAMP` is the current time in UTC, ISO 8601 with milliseconds and a trailing `Z` ([TIMESTAMP](../../shared/glossary/timestamp-header.md)). + +Then: + +1. Render `https://phrsbx.abdm.gov.in/face-auth?txnId=` as a QR code. +2. The patient taps the QR icon in the ABHA app, scans the code, presses **Continue** and completes the face scan. +3. Poll [capture PID](abha-biometric-capture-pid.md) until it answers `COMPLETE`. + +**Retrying.** Each init returns its own `txnId`. If the patient cannot finish, call init again and show the new code. + +## How you know it worked + +You receive a JSON body with a `txnId`: + +```json +{ + "txnId": "", + "message": "Transaction Id generated Successfully" +} +``` + +The step is done when the QR code built from that `txnId` is on screen for the patient. + +## When it goes wrong + +- The call goes to the fingerprint host. Face sits under `/pmjay/sbxhcx/abdmproxy/abha/biometric/`. +- You wait for a callback. None comes. Poll capture PID. +- The same `REQUEST-ID` is sent twice. Generate a new one for every call. diff --git a/catalogue/nhcx/endpoints/abha-biometric-v2-auth-verify.md b/catalogue/nhcx/endpoints/abha-biometric-v2-auth-verify.md new file mode 100644 index 000000000..8945ddc07 --- /dev/null +++ b/catalogue/nhcx/endpoints/abha-biometric-v2-auth-verify.md @@ -0,0 +1,128 @@ +--- +id: nhcx.endpoint.abha-biometric-v2-auth-verify +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /pmjay/sbxhcx/abdmproxy/abha/biometric/v2/auth/verify +summary: >- + Complete a face check of a scheme patient and receive the short-lived token that + proves they were present. +sources: +- url: https://hcxsbx.abdm.gov.in/images/9f1e6b545a693d38a704.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Biometric Authentication Implementation Steps.docx + hash: sha256:fac8b14bfe8d518c0e651740537b9441c501d3cf2ab0f0482a07ab9f417e43a9 + fetched: '2026-09-14' + note: Biometric Authentication Implementation Steps, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments, not named in the NHCX document sheet. NHCX Face-Auth API Curl, FACE AUTH Aadhar Verify. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 15, Q26.9 process type. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.abha-biometric-faceauth-init + - nhcx.endpoint.abha-biometric-capture-pid + - nhcx.endpoint.abha-biometric-v2-auth-verify + - nhcx.endpoint.abha-biometric-auth-refresh-token + - nhcx.endpoint.abha-biometric-auth-init + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.session-token + errors: + - nhcx.error.payr-1256 + - nhcx.error.payr-1363 + concepts: + - nhcx.concept.biometric-authentication + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.biometric-face + decisions: + - nhcx.decision.biometric-modality +--- + +# POST /pmjay/sbxhcx/abdmproxy/abha/biometric/v2/auth/verify + +## In plain words + +[PMJAY](../glossary/pmjay.md) requires proof that the beneficiary is physically present at the hospital. The hospital proves it by authenticating the beneficiary against their [ABHA](../../shared/glossary/abha.md), by fingerprint, iris or face. Face verify completes a face authentication once the capture is `COMPLETE`. It sends the encrypted Aadhaar number and the Aadhaar-linked mobile, and returns the same token pair as fingerprint and iris, with the ABHA profile. + +These are plain JSON calls: no JWE envelope and no callback. + +## Before you start + +- A session token for the `Authorization` header, not `bearer_auth`. See [the session token](../concepts/session-token.md). +- The participant code of the scheme payer the authentication is for. It goes in the `payerid` header. +- A `txnId` from [face auth init](abha-biometric-faceauth-init.md) that [capture PID](abha-biometric-capture-pid.md) reports `COMPLETE`. +- The patient's Aadhaar number, encrypted with the public key below using the transformation `RSA/ECB/OAEPWithSHA-1AndMGF1Padding`, base64 encoded. +- The patient's Aadhaar-linked mobile number. + +## What happens + +Encrypt the Aadhaar number with this X.509 public key: + +```text +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAstWB95C5pHLXiYW59qyO4Xb+59KYVm9Hywbo77qETZVAyc6VIsxU+UWhd/k/YtjZibCznB+HaXWX9TVTFs9Nwgv7LRGq5uLczpZQDrU7dnGkl/urRA8p0Jv/f8T0MZdFWQgks91uFffeBmJOb58u68ZRxSYGMPe4hb9XXKDVsgoSJaRNYviH7RgAI2QhTCwLEiMqIaUX3p1SAc178ZlN8qHXSSGXvhDR1GKM+y2DIyJqlzfik7lD14mDY/I4lcbftib8cv7llkybtjX1AayfZp4XpmIXKWv8nRM488/jOAF81Bi13paKgpjQUUuwq9tb5Qd/DChytYgBTBTJFe7irDFCmTIcqPr8+IMB7tXA3YXPp3z605Z6cGoYxezUm2Nz2o6oUmarDUntDhq/PnkNergmSeSvS8gD9DHBuJkJWZweG3xOPXiKQAUBr92mdFhJGm6fitO5jsBxgpmulxpG0oKDy9lAOLWSqK92JMcbMNHn4wRikdI9HSiXrrI7fLhJYTbyU3I4v5ESdEsayHXuiwO/1C8y56egzKSw44GAtEpbAkTNEEfK5H5R0QnVBIXOvfeF4tzGvmkfOO6nNXU3o/WAdOyV3xSQ9dqLY5MEL4sJCGY1iJBIAQ452s8v0ynJG5Yq+8hNhsCVnklCzAlsIzQpnSVDUVEzv17grVAw078CAwEAAQ== +``` + +Then call the ABDM proxy host: + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/abdmproxy/abha/biometric/v2/auth/verify' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'Authorization: Bearer ' \ + --header 'REQUEST-ID: ' \ + --header 'TIMESTAMP: ' \ + --header 'payerid: ' \ + --header 'process: Preauth' \ + --data-raw '{ + "authData": { + "authMethods": ["face_auth"], + "face": { + "txnId": "", + "aadhaar": "", + "mobile": "" + } + }, + "authMode": "FACE_AUTH" + }' +``` + +`REQUEST-ID` is a new UUID for every call ([REQUEST-ID](../../shared/glossary/request-id.md)). `TIMESTAMP` is the current time in UTC, ISO 8601 with milliseconds and a trailing `Z` ([TIMESTAMP](../../shared/glossary/timestamp-header.md)). `process` is `Preauth` at registration or pre-authorisation, and `Discharge` at discharge. + +**Retrying.** A face capture belongs to its `txnId`. After a failure, start again with a new init. + +## How you know it worked + +You receive a JSON body with a `tokens` object and an `ABHAProfile`: + +```json +{ + "txnId": "", + "message": "", + "tokens": { + "token": "", + "expiresIn": "1800", + "refreshExpiresIn": "1296000", + "refreshToken": "" + }, + "ABHAProfile": { + "ABHANumber": "", + "preferredAddress": "", + "abhaStatus": "ACTIVE" + } +} +``` + +`expiresIn` and `refreshExpiresIn` arrive as strings here. The profile also carries name, date of birth, gender, photo, mobile and address. + +The step is done when both tokens are stored against the case. Keep only the profile fields the record needs. + +## When it goes wrong + +- The Aadhaar number is sent in the clear, or validated as twelve digits after encryption. Send the base64 ciphertext. +- The call is made before capture PID answers `COMPLETE`. +- The call goes to the fingerprint host. Use the ABDM proxy host. +- No token is obtained before the pre-authorisation or claim. The request is refused with [`PAYR-1256`](../errors/payr-1256.md) or [`PAYR-1363`](../errors/payr-1363.md) unless it carries the consent questionnaire response. diff --git a/catalogue/nhcx/endpoints/claim-on-submit.md b/catalogue/nhcx/endpoints/claim-on-submit.md new file mode 100644 index 000000000..e90f1f165 --- /dev/null +++ b/catalogue/nhcx/endpoints/claim-on-submit.md @@ -0,0 +1,192 @@ +--- +id: nhcx.endpoint.claim-on-submit +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /v1/claim/on_submit +summary: >- + Send an insurer's decision on a hospital's claim back to that hospital through + the claims exchange. +sources: +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: 'NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet: Claim, /v1/claim/on_submit rows.' +- url: https://hcxsbx.abdm.gov.in/claimhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/claimhcxservice.json + hash: sha256:488eea449c6ee45dc324f4f7c095a862c7d50d0e238075846122b51b2bab4878 + fetched: '2026-09-14' + note: 'API specification: claimhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/claim/on_submit.post.' +- url: https://hcxsbx.abdm.gov.in/images/bc1e7d077857fc0fa071.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-NHCX USECASE Postman Collection.zip + hash: sha256:9d15daafa813d6d57e688fe800baa5a73d2540b8d0d12c6a1315f86a424817e4 + fetched: '2026-09-14' + note: AWS(Sandbox)-NHCX USECASE Postman Collection, row 17 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item /v1/claim/on_submit. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1 Acceptance and Error scenario; page 2. +- url: https://hcxsbx.abdm.gov.in/images/c42ad170f37c987ed173.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx + hash: sha256:f56dd156c232192296082f23b1561d0ff11fd40992e6675de41c5c991d579e6d + fetched: '2026-09-14' + note: Workflow Status Sheets(with Codes), row 12 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet1, workflow ids 25, 26, 27, 28 and 29. +- url: https://hcxsbx.abdm.gov.in/images/064cf2e059987011e53a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Claim.pdf + hash: sha256:66290de20d57d69e681946a0101518092ca43b3775bb38997c43beb17fb38076 + fetched: '2026-09-14' + note: Claim, listed on https://hcxsbx.abdm.gov.in/#/documents, not named in the NHCX document sheet. page 2, items 4 to 6. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Message Structure, Status Description. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 4, Q14. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.claim-submit + - nhcx.endpoint.paymentnotice-request + - nhcx.endpoint.session-token + - nhcx.endpoint.fetch-certs + callbacks: + - nhcx.callback.claim-submit + - nhcx.callback.claim-on-submit + - nhcx.callback.error + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1012 + - nhcx.error.payr-1517 + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.four-message-legs + - nhcx.concept.retries-and-expiry + - nhcx.concept.claim-cycle + - nhcx.concept.workflow-codes + flows: + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + fhir: + - nhcx.fhir.claim-response + tests: + - nhcx.test.payer-uc-11 + troubleshooting: + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.everything-returns-401 +--- + +# POST /v1/claim/on_submit + +## In plain words + +This carries the payer's decision on a claim, often in stages. As a payer, you send a sealed ClaimResponse bundle to [NHCX](../../shared/glossary/nhcx.md), which delivers it to the provider. Interim answers keep the claim open. A final answer closes it. + +You call it after you have received a [`/v1/claim/submit`](claim-submit.md). An approved claim is followed by [payment notices](paymentnotice-request.md). + +## Before you start + +- A session token that has not expired. See [the session token](../concepts/session-token.md). +- The `/v1/claim/submit` you are answering, received on [your registered address](../callbacks/claim-submit.md), decrypted, and acknowledged with 202 within 30 seconds. +- That request's `x-hcx-correlation_id` and `x-hcx-sender_code`, stored. You echo the first and address the answer to the second. +- The encryption certificate of the provider, fetched with [`/fetch/certs`](fetch-certs.md). +- A ClaimResponse bundle in [FHIR](../../shared/glossary/fhir.md), built as in [the claim response bundle](../fhir/claim-response.md). +- A handler for [`/v1/error`](../callbacks/error.md), where NHCX reports an answer it could not deliver. + +## What happens + +Your system, as the payer or a TPA acting for it, answers a request it received ([receiving the request](../callbacks/claim-submit.md)) by calling NHCX on `/v1/claim/on_submit`. NHCX answers 202 at once and delivers the same path to the registered address of the provider ([receiving `/v1/claim/on_submit`](../callbacks/claim-on-submit.md)). + +### 1. Seal the answer + +Swap the sender and recipient codes of the request. Echo its correlation id. Put these values in the [JWE](../glossary/jwe.md) [protected header](../glossary/protected-header.md): + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-request_id": "", + "x-hcx-correlation_id": "", + "x-hcx-workflow_id": "26", + "x-hcx-timestamp": "", + "x-hcx-status": "response.complete", + "x-hcx-ben-abha-id": "" +} +``` + +Interim answers carry `response.partial`: `25` received, `28` in process, `29` forwarded. `27` raises a query. `26` approves with `response.complete`. After a `response.complete`, send nothing more on that claim. The `x-hcx-*` values ride inside the JWE [protected header](../glossary/protected-header.md), not as HTTP headers. [The protocol headers](../concepts/protocol-headers.md) explains each one, including the timestamp format. + +### 2. Send it + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/hcx/v1/claim/on_submit' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --header 'Authorization: Bearer ' \ + --data-raw '{ + "type": "JWEPayload", + "payload": "" + }' +``` + +Send the token on both `bearer_auth` and `Authorization`, with the same value and the word `Bearer` in front. `` is your sealed message: five base64url parts joined by dots. See [the JWE envelope](../concepts/jwe-envelope.md). + +### 3. Refusing a request + +To refuse the request at protocol level instead, send `"type": "ProtocolResponse"` on this path with `x-hcx-status` `response.error` and `x-hcx-error_details` holding `code`, `message` and `trace`. Keep clinical and business reasons inside the sealed payload. Only protocol errors go in the header. + +### 4. Retrying + +**Idempotency.** Echo the `x-hcx-correlation_id` of the request you are answering. A correlation id NHCX does not hold, or one it has already deleted, is refused with [`NHCX-1010`](../errors/nhcx-1010.md). Generate a new `x-hcx-api_call_id` for every call. `/v1/status` looks a message up by that value ([`NHCX-1012`](../errors/nhcx-1012.md) when it cannot), so never reuse one. + +## How you know it worked + +You receive HTTP `202 Accepted` with this body: + +```json +{ + "timestamp": "
", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "claim", + "protocol_status": "request.dispatched" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `correlation_id` matches the request you answered, and `api_call_id` matches the value you sealed. +- `result.entity_type` is `claim`. +- `error.code` and `error.message` are empty. + +NHCX then delivers your answer to the provider. The recipient must answer each delivery with 202 and the acknowledgement body within 30 seconds. Otherwise NHCX retries up to five times, then deletes the request and reports it on the sender's [`/v1/error`](../callbacks/error.md). The step is done when you hold the 202 and no report for this correlation id arrives on your `/v1/error`. + +## When it goes wrong + +- [`NHCX-1010`](../errors/nhcx-1010.md): NHCX holds no request with that correlation id. You minted a new one instead of echoing it, or the request was deleted after failed deliveries. +- [`NHCX-1011`](../errors/nhcx-1011.md): `x-hcx-status` is not `response.complete`, `response.partial` or `response.error`. +- [`PAYR-1517`](../errors/payr-1517.md): a refusal arrived as a `JWEPayload`. Protocol refusals travel as `ProtocolResponse`. +- `401 Unauthorized`, or [`NHCX-401`](../errors/nhcx-401.md): get a new session token and send again. +- A report arrives on your [`/v1/error`](../callbacks/error.md): the requester's address did not acknowledge five deliveries. The request is dead on that correlation id. diff --git a/catalogue/nhcx/endpoints/claim-submit.md b/catalogue/nhcx/endpoints/claim-submit.md new file mode 100644 index 000000000..b087be667 --- /dev/null +++ b/catalogue/nhcx/endpoints/claim-submit.md @@ -0,0 +1,207 @@ +--- +id: nhcx.endpoint.claim-submit +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /v1/claim/submit +summary: >- + Send the final bill for a treated patient to the insurer through the claims exchange, + and get a receipt while the decision follows later. +sources: +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: 'NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet: Claim, /v1/claim/submit rows.' +- url: https://hcxsbx.abdm.gov.in/claimhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/claimhcxservice.json + hash: sha256:488eea449c6ee45dc324f4f7c095a862c7d50d0e238075846122b51b2bab4878 + fetched: '2026-09-14' + note: 'API specification: claimhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/claim/submit.post.' +- url: https://hcxsbx.abdm.gov.in/images/bc1e7d077857fc0fa071.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-NHCX USECASE Postman Collection.zip + hash: sha256:9d15daafa813d6d57e688fe800baa5a73d2540b8d0d12c6a1315f86a424817e4 + fetched: '2026-09-14' + note: AWS(Sandbox)-NHCX USECASE Postman Collection, row 17 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item /v1/claim/submit. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Acceptance scenario. +- url: https://hcxsbx.abdm.gov.in/images/c42ad170f37c987ed173.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx + hash: sha256:f56dd156c232192296082f23b1561d0ff11fd40992e6675de41c5c991d579e6d + fetched: '2026-09-14' + note: Workflow Status Sheets(with Codes), row 12 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet1, workflow ids 15, 151 and 27. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2 Q3; page 4 Q12 and Q14. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. items 6, 7 and 8. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. page 5 table 5.1; page 12 Discharge details. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.claim-on-submit + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.participant-get-policies + - nhcx.endpoint.dummy-payer-process-request + - nhcx.endpoint.task-submit + - nhcx.endpoint.session-token + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.status + callbacks: + - nhcx.callback.claim-submit + - nhcx.callback.claim-on-submit + - nhcx.callback.communication-request + - nhcx.callback.error + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1003 + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1012 + - nhcx.error.payr-1001 + - nhcx.error.payr-1302 + - nhcx.error.payr-1363 + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.four-message-legs + - nhcx.concept.claim-cycle + - nhcx.concept.workflow-codes + flows: + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + fhir: + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + tests: + - nhcx.test.provider-uc-09 + - nhcx.test.tc-cl-01 + - nhcx.test.tc-cl-02 + sandbox: + - nhcx.sandbox.dummy-payer + - nhcx.sandbox.environments-and-base-urls + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback + - nhcx.troubleshooting.everything-returns-401 +--- + +# POST /v1/claim/submit + +## In plain words + +A claim is the hospital's request to be paid for treatment already given. After discharge, your system, as the provider, sends a Claim bundle with `use` `claim` to [NHCX](../../shared/glossary/nhcx.md), sealed for the payer. NHCX gives you a receipt at once. The payer's decision arrives later on your `/v1/claim/on_submit`, possibly in several stages. + +The same path carries the first claim, a resubmission and your answer to a payer's query. + +## Before you start + +- A session token that has not expired. See [the session token](../concepts/session-token.md) and [how to get one](session-token.md). +- Your own [participant code](../glossary/participant-code.md), with your callback address registered, reachable from NHCX and answering 202 within 30 seconds. See [callback URL rules](../sandbox/callback-url-requirements.md). +- The payer's participant code. Take it from `processingID` in the [`/participant/get/policies`](participant-get-policies.md) response, not from `PayerID`. +- The recipient's encryption certificate, fetched with [`/fetch/certs`](fetch-certs.md). You seal the message with its public key. +- A Claim bundle in [FHIR](../../shared/glossary/fhir.md) with `use` `claim`, built as in [the claim request bundle](../fhir/claim-request.md), referencing the approved pre-authorisation. +- A handler for [`/v1/error`](../callbacks/error.md), so a request NHCX cannot deliver does not look like one still under review. +- An approved pre-authorisation for the case, from [`/v1/preauth/submit`](preauth-submit.md). +- For a [PMJAY](../glossary/pmjay.md) case: discharge biometric authentication, or the Authentication Consent questionnaire response. +- A handler for [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- In the sandbox you can address the [dummy payer](../sandbox/dummy-payer.md), participant `1000003538@hcx`, which answers without a real insurer. + +## What happens + +Your system, as the provider, calls NHCX on `/v1/claim/submit`. NHCX checks the envelope, answers 202 at once, and forwards the same path to the payer's registered address ([receiving `/v1/claim/submit`](../callbacks/claim-submit.md)). The payer answers later on [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md), which NHCX delivers to you. + +### 1. Seal the message + +Put these values in the [JWE](../glossary/jwe.md) [protected header](../glossary/protected-header.md) and encrypt the bundle with the recipient's public key. + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-request_id": "", + "x-hcx-correlation_id": "", + "x-hcx-workflow_id": "15", + "x-hcx-use_case": "New", + "x-hcx-timestamp": "", + "x-hcx-status": "request.initiated", + "x-hcx-ben-abha-id": "" +} +``` + +The `x-hcx-*` values ride inside the JWE [protected header](../glossary/protected-header.md), not as HTTP headers. [The protocol headers](../concepts/protocol-headers.md) explains each one, including the timestamp format. Workflow `15` is a new claim. Answer a payer's claim query (workflow `27`) with `151`, not a fresh `15`. `x-hcx-use_case` takes `New` or `Resubmit`. + +### 2. Send it + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/hcx/v1/claim/submit' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --header 'Authorization: Bearer ' \ + --data-raw '{ + "payload": "" + }' +``` + +Send the token on both `bearer_auth` and `Authorization`, with the same value and the word `Bearer` in front. `` is your sealed message: five base64url parts joined by dots. See [the JWE envelope](../concepts/jwe-envelope.md). + +### 3. Retrying + +**Idempotency.** NHCX keys every conversation on `x-hcx-correlation_id`. An initiating request that reuses a correlation id NHCX already holds is refused with [`NHCX-1006`](../errors/nhcx-1006.md). So a blind retry is not safe. If your call timed out, ask [`/v1/status`](status.md) before you resend. `/v1/status` finds a message by its `x-hcx-api_call_id` ([`NHCX-1012`](../errors/nhcx-1012.md) when it cannot), so generate a new one for every call, a retry included. After a request fails for good, NHCX makes its correlation id inactive. Start a new cycle with a new correlation id. + +## How you know it worked + +You receive HTTP `202 Accepted` with this body: + +```json +{ + "timestamp": "
", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "claim", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `correlation_id` and `api_call_id` match the values you sealed. +- `result.entity_type` is `claim`. +- `result.protocol_status` is `request.queued` or `request.dispatched`. +- `error.code` and `error.message` are empty. + +The 202 is a receipt, not a decision. NHCX never returns a decision synchronously. The step is done when [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md) reaches your callback address with the same `x-hcx-correlation_id`, and your handler has answered it 202 within 30 seconds. Interim answers carry `response.partial`. The claim is decided when an answer carries `response.complete`. + +## When it goes wrong + +- [`PAYR-1302`](../errors/payr-1302.md): no approved pre-authorisation exists for the case number. +- [`PAYR-1363`](../errors/payr-1363.md): a [PMJAY](../glossary/pmjay.md) claim carries neither discharge biometric authentication nor the consent questionnaire response. +- `401 Unauthorized`, or [`NHCX-401`](../errors/nhcx-401.md): the session token expired or lacks the `Bearer ` prefix. Get a new token and send again. See [every call returns 401](../troubleshooting/everything-returns-401.md). +- [`NHCX-1003`](../errors/nhcx-1003.md): the recipient code is not registered. A provider used `PayerID` instead of `processingID`. +- [`NHCX-1006`](../errors/nhcx-1006.md): the correlation id was used before. Start the cycle with a new one. +- [`NHCX-1011`](../errors/nhcx-1011.md): `x-hcx-status` is not `request.initiated`. diff --git a/catalogue/nhcx/endpoints/communication-on-request.md b/catalogue/nhcx/endpoints/communication-on-request.md new file mode 100644 index 000000000..2805d4272 --- /dev/null +++ b/catalogue/nhcx/endpoints/communication-on-request.md @@ -0,0 +1,184 @@ +--- +id: nhcx.endpoint.communication-on-request +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /v1/communication/on_request +summary: >- + Answer an insurer's message about a case, for example with the documents it asked + for, through the claims exchange. +sources: +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: 'NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet: Communication (additional docs), /v1/communication/on_request rows.' +- url: https://hcxsbx.abdm.gov.in/communicationhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/communicationhcxservice.json + hash: sha256:0ad58a98851158057d38d42a8327349548644c1b2f1a33b4f94acb4c1840a8a4 + fetched: '2026-09-14' + note: 'API specification: communicationhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/communication/on_request.post.' +- url: https://hcxsbx.abdm.gov.in/images/bc1e7d077857fc0fa071.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-NHCX USECASE Postman Collection.zip + hash: sha256:9d15daafa813d6d57e688fe800baa5a73d2540b8d0d12c6a1315f86a424817e4 + fetched: '2026-09-14' + note: AWS(Sandbox)-NHCX USECASE Postman Collection, row 17 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item /v1/communication/on_request. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1 Acceptance and Error scenario; page 2. +- url: https://hcxsbx.abdm.gov.in/images/819467ec15aff13cc2a8.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Dummy Payer Implementation.pdf + hash: sha256:97335ebc4cd32c86e0c34328b2f4c526420b32a7a009208364043d6334e9e757 + fetched: '2026-09-14' + note: NHCX Dummy Payer Implementation, row 19 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1 Preauth step 5; page 2 Communication steps 3 and 4. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 4, Q14. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.communication-request + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + - nhcx.endpoint.dummy-payer-process-request + - nhcx.endpoint.session-token + - nhcx.endpoint.fetch-certs + callbacks: + - nhcx.callback.communication-request + - nhcx.callback.communication-on-request + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + - nhcx.callback.error + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1012 + - nhcx.error.payr-1517 + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.four-message-legs + - nhcx.concept.retries-and-expiry + - nhcx.concept.queries-and-communication + flows: + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-query-response + tests: + - nhcx.test.provider-uc-08 + sandbox: + - nhcx.sandbox.dummy-payer + troubleshooting: + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.everything-returns-401 +--- + +# POST /v1/communication/on_request + +## In plain words + +When a payer sends you a communication request, you answer it here. Your system, as the provider, sends a sealed Task bundle with a Communication to [NHCX](../../shared/glossary/nhcx.md), carrying the documents or information the payer asked for. NHCX delivers it to the payer. + +After a query, the payer's final decision arrives later on `/v1/preauth/on_submit` or `/v1/claim/on_submit`. + +## Before you start + +- A session token that has not expired. See [the session token](../concepts/session-token.md). +- The `/v1/communication/request` you are answering, received on [your registered address](../callbacks/communication-request.md), decrypted, and acknowledged with 202 within 30 seconds. +- That request's `x-hcx-correlation_id` and `x-hcx-sender_code`, stored. You echo the first and address the answer to the second. +- The encryption certificate of the payer, fetched with [`/fetch/certs`](fetch-certs.md). +- A Task bundle in [FHIR](../../shared/glossary/fhir.md) with a Communication whose `payload.contentAttachment` carries what the payer asked for. +- A handler for [`/v1/error`](../callbacks/error.md), where NHCX reports an answer it could not deliver. + +## What happens + +Your system, as the provider, answers a request it received ([receiving the request](../callbacks/communication-request.md)) by calling NHCX on `/v1/communication/on_request`. NHCX answers 202 at once and delivers the same path to the registered address of the payer ([receiving `/v1/communication/on_request`](../callbacks/communication-on-request.md)). + +### 1. Seal the answer + +Swap the sender and recipient codes of the request. Echo its correlation id. Put these values in the [JWE](../glossary/jwe.md) [protected header](../glossary/protected-header.md): + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-request_id": "", + "x-hcx-correlation_id": "", + "x-hcx-timestamp": "", + "x-hcx-status": "response.complete", + "x-hcx-ben-abha-id": "" +} +``` + +Send `response.complete`. The `x-hcx-*` values ride inside the JWE [protected header](../glossary/protected-header.md), not as HTTP headers. [The protocol headers](../concepts/protocol-headers.md) explains each one, including the timestamp format. + +### 2. Send it + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/hcx/v1/communication/on_request' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --header 'Authorization: Bearer ' \ + --data-raw '{ + "type": "JWEPayload", + "payload": "" + }' +``` + +Send the token on both `bearer_auth` and `Authorization`, with the same value and the word `Bearer` in front. `` is your sealed message: five base64url parts joined by dots. See [the JWE envelope](../concepts/jwe-envelope.md). + +### 3. Refusing a request + +To refuse the request at protocol level instead, send `"type": "ProtocolResponse"` on this path with `x-hcx-status` `response.error` and `x-hcx-error_details` holding `code`, `message` and `trace`. Keep clinical and business reasons inside the sealed payload. Only protocol errors go in the header. + +### 4. Retrying + +**Idempotency.** Echo the `x-hcx-correlation_id` of the request you are answering. A correlation id NHCX does not hold, or one it has already deleted, is refused with [`NHCX-1010`](../errors/nhcx-1010.md). Generate a new `x-hcx-api_call_id` for every call. `/v1/status` looks a message up by that value ([`NHCX-1012`](../errors/nhcx-1012.md) when it cannot), so never reuse one. + +## How you know it worked + +You receive HTTP `202 Accepted` with this body: + +```json +{ + "timestamp": "
", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "task", + "protocol_status": "request.dispatched" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `correlation_id` matches the request you answered, and `api_call_id` matches the value you sealed. +- `result.entity_type` is `task`. +- `error.code` and `error.message` are empty. + +NHCX then delivers your answer to the payer. The recipient must answer each delivery with 202 and the acknowledgement body within 30 seconds. Otherwise NHCX retries up to five times, then deletes the request and reports it on the sender's [`/v1/error`](../callbacks/error.md). The step is done when you hold the 202 and no report for this correlation id arrives on your `/v1/error`. The payer's decision then arrives on [`/v1/preauth/on_submit`](../callbacks/preauth-on-submit.md) or [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). + +## When it goes wrong + +- [`NHCX-1010`](../errors/nhcx-1010.md): NHCX holds no request with that correlation id. You minted a new one instead of echoing it, or the request was deleted after failed deliveries. +- [`NHCX-1011`](../errors/nhcx-1011.md): `x-hcx-status` is not `response.complete`, `response.partial` or `response.error`. +- [`PAYR-1517`](../errors/payr-1517.md): a refusal arrived as a `JWEPayload`. Protocol refusals travel as `ProtocolResponse`. +- `401 Unauthorized`, or [`NHCX-401`](../errors/nhcx-401.md): get a new session token and send again. +- A report arrives on your [`/v1/error`](../callbacks/error.md): the requester's address did not acknowledge five deliveries. The request is dead on that correlation id. diff --git a/catalogue/nhcx/endpoints/communication-request.md b/catalogue/nhcx/endpoints/communication-request.md new file mode 100644 index 000000000..aa2e53475 --- /dev/null +++ b/catalogue/nhcx/endpoints/communication-request.md @@ -0,0 +1,189 @@ +--- +id: nhcx.endpoint.communication-request +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /v1/communication/request +summary: >- + Send a hospital a message about a case in progress, such as a request for more + documents, through the claims exchange. +sources: +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: 'NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet: Communication (additional docs), /v1/communication/request rows.' +- url: https://hcxsbx.abdm.gov.in/communicationhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/communicationhcxservice.json + hash: sha256:0ad58a98851158057d38d42a8327349548644c1b2f1a33b4f94acb4c1840a8a4 + fetched: '2026-09-14' + note: 'API specification: communicationhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/communication/request.post.' +- url: https://hcxsbx.abdm.gov.in/images/bc1e7d077857fc0fa071.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-NHCX USECASE Postman Collection.zip + hash: sha256:9d15daafa813d6d57e688fe800baa5a73d2540b8d0d12c6a1315f86a424817e4 + fetched: '2026-09-14' + note: AWS(Sandbox)-NHCX USECASE Postman Collection, row 17 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item /v1/communication/request. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Acceptance scenario. +- url: https://hcxsbx.abdm.gov.in/images/819467ec15aff13cc2a8.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Dummy Payer Implementation.pdf + hash: sha256:97335ebc4cd32c86e0c34328b2f4c526420b32a7a009208364043d6334e9e757 + fetched: '2026-09-14' + note: NHCX Dummy Payer Implementation, row 19 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1 Preauth steps 3 to 5. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 12.1 Business context; 12.1 API and workflow codes. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2 Q3; page 4 Q12 and Q14. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. items 6 and 8. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.communication-on-request + - nhcx.endpoint.preauth-on-submit + - nhcx.endpoint.claim-on-submit + - nhcx.endpoint.session-token + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.status + callbacks: + - nhcx.callback.communication-request + - nhcx.callback.communication-on-request + - nhcx.callback.error + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1003 + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1012 + - nhcx.error.payr-1003 + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.four-message-legs + - nhcx.concept.queries-and-communication + - nhcx.concept.workflow-codes + flows: + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-query-response + tests: + - nhcx.test.payer-uc-10 + sandbox: + - nhcx.sandbox.dummy-payer +--- + +# POST /v1/communication/request + +## In plain words + +A communication request is the payer's way to speak first. As a payer, you send the hospital a sealed message about a case already in progress, for example a request for additional documents. [NHCX](../../shared/glossary/nhcx.md) delivers it to the provider, which answers on `/v1/communication/on_request`. + +The claim or pre-authorisation stays with you while you wait. Your decision still goes out later on its own `on_submit` path. + +## Before you start + +- A session token that has not expired. See [the session token](../concepts/session-token.md) and [how to get one](session-token.md). +- Your own [participant code](../glossary/participant-code.md), with your callback address registered, reachable from NHCX and answering 202 within 30 seconds. See [callback URL rules](../sandbox/callback-url-requirements.md). +- The provider's participant code: the sender code of the claim or pre-authorisation this message concerns. +- The recipient's encryption certificate, fetched with [`/fetch/certs`](fetch-certs.md). You seal the message with its public key. +- A Task bundle in [FHIR](../../shared/glossary/fhir.md) that references a CommunicationRequest saying what you need. See [queries and communication](../concepts/queries-and-communication.md). +- A handler for [`/v1/error`](../callbacks/error.md), so a request NHCX cannot deliver does not look like one still under review. +- A handler for [`/v1/communication/on_request`](../callbacks/communication-on-request.md), where the provider's answer arrives. + +## What happens + +Your system, as the payer, calls NHCX on `/v1/communication/request`. NHCX checks the envelope, answers 202 at once, and forwards the same path to the provider's registered address ([receiving `/v1/communication/request`](../callbacks/communication-request.md)). The provider answers later on [`/v1/communication/on_request`](../callbacks/communication-on-request.md), which NHCX delivers to you. + +### 1. Seal the message + +Put these values in the [JWE](../glossary/jwe.md) [protected header](../glossary/protected-header.md) and encrypt the bundle with the recipient's public key. + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-request_id": "", + "x-hcx-correlation_id": "", + "x-hcx-workflow_id": "", + "x-hcx-timestamp": "", + "x-hcx-status": "request.initiated", + "x-hcx-ben-abha-id": "" +} +``` + +The `x-hcx-*` values ride inside the JWE [protected header](../glossary/protected-header.md), not as HTTP headers. [The protocol headers](../concepts/protocol-headers.md) explains each one, including the timestamp format. `x-hcx-workflow_id` is the workflow of the claim or pre-authorisation the message concerns. NHCX checks it. + +### 2. Send it + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/hcx/v1/communication/request' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --header 'Authorization: Bearer ' \ + --data-raw '{ + "payload": "" + }' +``` + +Send the token on both `bearer_auth` and `Authorization`, with the same value and the word `Bearer` in front. `` is your sealed message: five base64url parts joined by dots. See [the JWE envelope](../concepts/jwe-envelope.md). + +### 3. Retrying + +**Idempotency.** NHCX keys every conversation on `x-hcx-correlation_id`. An initiating request that reuses a correlation id NHCX already holds is refused with [`NHCX-1006`](../errors/nhcx-1006.md). So a blind retry is not safe. If your call timed out, ask [`/v1/status`](status.md) before you resend. `/v1/status` finds a message by its `x-hcx-api_call_id` ([`NHCX-1012`](../errors/nhcx-1012.md) when it cannot), so generate a new one for every call, a retry included. After a request fails for good, NHCX makes its correlation id inactive. Start a new cycle with a new correlation id. + +## How you know it worked + +You receive HTTP `202 Accepted` with this body: + +```json +{ + "timestamp": "
", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "task", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `correlation_id` and `api_call_id` match the values you sealed. +- `result.entity_type` is `task`. +- `result.protocol_status` is `request.queued` or `request.dispatched`. +- `error.code` and `error.message` are empty. + +The 202 is a receipt, not a decision. NHCX never returns a decision synchronously. The step is done when [`/v1/communication/on_request`](../callbacks/communication-on-request.md) reaches your callback address with the same `x-hcx-correlation_id`, and your handler has answered it 202 within 30 seconds. + +## When it goes wrong + +- [`PAYR-1003`](../errors/payr-1003.md), invalid workflow requested: the workflow id does not match the claim or pre-authorisation. +- `401 Unauthorized`, or [`NHCX-401`](../errors/nhcx-401.md): get a new session token and send again. +- [`NHCX-1003`](../errors/nhcx-1003.md): the provider code is not registered in NHCX. +- [`NHCX-1006`](../errors/nhcx-1006.md): the correlation id was used before. Open the cycle with a new one. +- [`NHCX-1011`](../errors/nhcx-1011.md): `x-hcx-status` is not `request.initiated`. +- You got 202 and nothing more arrives. The provider's address may be unreachable. Check your [`/v1/error`](../callbacks/error.md) and ask [`/v1/status`](status.md). diff --git a/catalogue/nhcx/endpoints/coverageeligibility-check.md b/catalogue/nhcx/endpoints/coverageeligibility-check.md new file mode 100644 index 000000000..16e3460fc --- /dev/null +++ b/catalogue/nhcx/endpoints/coverageeligibility-check.md @@ -0,0 +1,194 @@ +--- +id: nhcx.endpoint.coverageeligibility-check +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /v1/coverageeligibility/check +summary: >- + Ask an insurer, through the claims exchange, whether a patient's policy is active + and what it covers, and get a receipt while the answer follows later. +sources: +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: 'NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet: CoverageEligibility, /v1/coverageeligibility/check rows.' +- url: https://hcxsbx.abdm.gov.in/coverageeligibilityhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/coverageeligibilityhcxservice.json + hash: sha256:1723a4020b1b33d0bc1d7175609f0d05e6a6a78e8b4c52041222396639ceb52c + fetched: '2026-09-14' + note: 'API specification: coverageeligibilityhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/coverageeligibility/check.post.' +- url: https://hcxsbx.abdm.gov.in/images/bc1e7d077857fc0fa071.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-NHCX USECASE Postman Collection.zip + hash: sha256:9d15daafa813d6d57e688fe800baa5a73d2540b8d0d12c6a1315f86a424817e4 + fetched: '2026-09-14' + note: AWS(Sandbox)-NHCX USECASE Postman Collection, row 17 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item /v1/coverageeligibility/check. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Acceptance scenario. +- url: https://hcxsbx.abdm.gov.in/images/53347f5988b0ce5396f1.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_APIs to be called based on scenario.xlsx + hash: sha256:f92a30673d65dd2cc3cf09e2087c624f23f781dc4ca6b5cd8ec1825e224ac108 + fetched: '2026-09-14' + note: 'NHCX_APIs to be called based on scenario, row 26 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sheet: Scenarios, rows 3 to 5.' +- url: https://hcxsbx.abdm.gov.in/images/cfcbe62e8378d4f48ee6.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Coverage Eligibility.pdf + hash: sha256:69dd680ddac44231a97276a1d735e45777d8e43b5563b7248fd367a838d9744f + fetched: '2026-09-14' + note: Coverage Eligibility, listed on https://hcxsbx.abdm.gov.in/#/documents, not named in the NHCX document sheet. page 1, items 6 to 8. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2 Q3; page 4 Q12 and Q14. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. items 6, 7 and 8. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.coverageeligibility-on-check + - nhcx.endpoint.participant-get-policies + - nhcx.endpoint.session-token + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.status + callbacks: + - nhcx.callback.coverageeligibility-check + - nhcx.callback.coverageeligibility-on-check + - nhcx.callback.error + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1003 + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1012 + - nhcx.error.payr-1001 + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.four-message-legs + - nhcx.concept.coverage-eligibility-purposes + flows: + - nhcx.flow.coverage-eligibility-check + fhir: + - nhcx.fhir.coverage-eligibility-request + decisions: + - nhcx.decision.eligibility-purpose + tests: + - nhcx.test.provider-uc-05 + - nhcx.test.tc-ce-01 + sandbox: + - nhcx.sandbox.dummy-payer + - nhcx.sandbox.environments-and-base-urls + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback + - nhcx.troubleshooting.everything-returns-401 +--- + +# POST /v1/coverageeligibility/check + +## In plain words + +A hospital asks the patient's insurer whether the policy is in force, what it covers, and whether a treatment needs pre-authorisation. Your system, as the provider, sends the question to [NHCX](../../shared/glossary/nhcx.md), the National Health Claims Exchange, sealed so only the payer can read it. NHCX gives you a receipt at once. The payer's answer arrives later on your `/v1/coverageeligibility/on_check`. + +Call it at registration or admission, before [`/v1/preauth/submit`](preauth-submit.md). + +## Before you start + +- A session token that has not expired. See [the session token](../concepts/session-token.md) and [how to get one](session-token.md). +- Your own [participant code](../glossary/participant-code.md), with your callback address registered, reachable from NHCX and answering 202 within 30 seconds. See [callback URL rules](../sandbox/callback-url-requirements.md). +- The payer's participant code. Take it from `processingID` in the [`/participant/get/policies`](participant-get-policies.md) response, not from `PayerID`. +- The recipient's encryption certificate, fetched with [`/fetch/certs`](fetch-certs.md). You seal the message with its public key. +- A CoverageEligibilityRequest bundle in [FHIR](../../shared/glossary/fhir.md), built as in [the coverage eligibility request bundle](../fhir/coverage-eligibility-request.md). Its `purpose` decides what the payer computes. See [which purpose to send](../decisions/eligibility-purpose.md). +- A handler for [`/v1/error`](../callbacks/error.md), so a request NHCX cannot deliver does not look like one still under review. +- A handler for [`/v1/coverageeligibility/on_check`](../callbacks/coverageeligibility-on-check.md). +- In the sandbox you can address the [dummy payer](../sandbox/dummy-payer.md), participant `1000003538@hcx`, which answers without a real insurer. + +## What happens + +Your system, as the provider, calls NHCX on `/v1/coverageeligibility/check`. NHCX checks the envelope, answers 202 at once, and forwards the same path to the payer's registered address ([receiving `/v1/coverageeligibility/check`](../callbacks/coverageeligibility-check.md)). The payer answers later on [`/v1/coverageeligibility/on_check`](../callbacks/coverageeligibility-on-check.md), which NHCX delivers to you. + +### 1. Seal the message + +Put these values in the [JWE](../glossary/jwe.md) [protected header](../glossary/protected-header.md) and encrypt the bundle with the recipient's public key. + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-request_id": "", + "x-hcx-correlation_id": "", + "x-hcx-timestamp": "", + "x-hcx-status": "request.initiated", + "x-hcx-ben-abha-id": "" +} +``` + +The `x-hcx-*` values ride inside the JWE [protected header](../glossary/protected-header.md), not as HTTP headers. [The protocol headers](../concepts/protocol-headers.md) explains each one, including the timestamp format. `x-hcx-workflow_id` is optional on this call. `x-hcx-ben-abha-id` carries the beneficiary's [ABHA](../../shared/glossary/abha.md) number. + +### 2. Send it + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/hcx/v1/coverageeligibility/check' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --header 'Authorization: Bearer ' \ + --data-raw '{ + "payload": "" + }' +``` + +Send the token on both `bearer_auth` and `Authorization`, with the same value and the word `Bearer` in front. `` is your sealed message: five base64url parts joined by dots. See [the JWE envelope](../concepts/jwe-envelope.md). + +### 3. Retrying + +**Idempotency.** NHCX keys every conversation on `x-hcx-correlation_id`. An initiating request that reuses a correlation id NHCX already holds is refused with [`NHCX-1006`](../errors/nhcx-1006.md). So a blind retry is not safe. If your call timed out, ask [`/v1/status`](status.md) before you resend. `/v1/status` finds a message by its `x-hcx-api_call_id` ([`NHCX-1012`](../errors/nhcx-1012.md) when it cannot), so generate a new one for every call, a retry included. After a request fails for good, NHCX makes its correlation id inactive. Start a new cycle with a new correlation id. + +## How you know it worked + +You receive HTTP `202 Accepted` with this body: + +```json +{ + "timestamp": "
", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "coverageeligibility", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `correlation_id` and `api_call_id` match the values you sealed. +- `result.entity_type` is `coverageeligibility`. +- `result.protocol_status` is `request.queued` or `request.dispatched`. +- `error.code` and `error.message` are empty. + +The 202 is a receipt, not a decision. NHCX never returns a decision synchronously. The step is done when [`/v1/coverageeligibility/on_check`](../callbacks/coverageeligibility-on-check.md) reaches your callback address with the same `x-hcx-correlation_id`, and your handler has answered it 202 within 30 seconds. The answer is a CoverageEligibilityResponse, a `ProtocolResponse` with an error, or an instruction to try another payer. + +## When it goes wrong + +- `401 Unauthorized`, or [`NHCX-401`](../errors/nhcx-401.md): the session token expired or lacks the `Bearer ` prefix. Get a new token and send again. See [every call returns 401](../troubleshooting/everything-returns-401.md). +- [`NHCX-1003`](../errors/nhcx-1003.md): the recipient code is not registered. A provider used `PayerID` instead of `processingID`. +- [`NHCX-1006`](../errors/nhcx-1006.md): the correlation id was used before. Start the cycle with a new one. +- [`NHCX-1011`](../errors/nhcx-1011.md): `x-hcx-status` is not `request.initiated`. +- You got 202 and nothing more arrives. The recipient may have failed to decrypt ([`PAYR-1001`](../errors/payr-1001.md)) or your callback is unreachable. See [accepted, then no callback](../troubleshooting/accepted-then-no-callback.md). diff --git a/catalogue/nhcx/endpoints/coverageeligibility-on-check.md b/catalogue/nhcx/endpoints/coverageeligibility-on-check.md new file mode 100644 index 000000000..f5e52de4d --- /dev/null +++ b/catalogue/nhcx/endpoints/coverageeligibility-on-check.md @@ -0,0 +1,183 @@ +--- +id: nhcx.endpoint.coverageeligibility-on-check +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /v1/coverageeligibility/on_check +summary: >- + Send an insurer's answer to an eligibility question back to the hospital through + the claims exchange. +sources: +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: 'NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet: CoverageEligibility, /v1/coverageeligibility/on_check rows.' +- url: https://hcxsbx.abdm.gov.in/coverageeligibilityhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/coverageeligibilityhcxservice.json + hash: sha256:1723a4020b1b33d0bc1d7175609f0d05e6a6a78e8b4c52041222396639ceb52c + fetched: '2026-09-14' + note: 'API specification: coverageeligibilityhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/coverageeligibility/on_check.post.' +- url: https://hcxsbx.abdm.gov.in/images/bc1e7d077857fc0fa071.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-NHCX USECASE Postman Collection.zip + hash: sha256:9d15daafa813d6d57e688fe800baa5a73d2540b8d0d12c6a1315f86a424817e4 + fetched: '2026-09-14' + note: AWS(Sandbox)-NHCX USECASE Postman Collection, row 17 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item /v1/coverageeligibility/on_check. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1 Acceptance and Error scenario; page 2. +- url: https://hcxsbx.abdm.gov.in/images/cfcbe62e8378d4f48ee6.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Coverage Eligibility.pdf + hash: sha256:69dd680ddac44231a97276a1d735e45777d8e43b5563b7248fd367a838d9744f + fetched: '2026-09-14' + note: Coverage Eligibility, listed on https://hcxsbx.abdm.gov.in/#/documents, not named in the NHCX document sheet. page 2, items 4 to 7. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Message Structure, Status Description. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 4, Q14. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.session-token + - nhcx.endpoint.fetch-certs + callbacks: + - nhcx.callback.coverageeligibility-check + - nhcx.callback.coverageeligibility-on-check + - nhcx.callback.error + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1012 + - nhcx.error.payr-1517 + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.four-message-legs + - nhcx.concept.retries-and-expiry + - nhcx.concept.coverage-eligibility-purposes + flows: + - nhcx.flow.coverage-eligibility-check + fhir: + - nhcx.fhir.coverage-eligibility-response + tests: + - nhcx.test.payer-uc-07 + troubleshooting: + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.everything-returns-401 +--- + +# POST /v1/coverageeligibility/on_check + +## In plain words + +This is the answer leg of an eligibility check. As a payer, you tell the hospital whether the policy is in force, what it covers, and whether a treatment needs pre-authorisation. You send a sealed CoverageEligibilityResponse to [NHCX](../../shared/glossary/nhcx.md), which delivers it to the provider. + +You call it after you have received and processed a [`/v1/coverageeligibility/check`](coverageeligibility-check.md). + +## Before you start + +- A session token that has not expired. See [the session token](../concepts/session-token.md). +- The `/v1/coverageeligibility/check` you are answering, received on [your registered address](../callbacks/coverageeligibility-check.md), decrypted, and acknowledged with 202 within 30 seconds. +- That request's `x-hcx-correlation_id` and `x-hcx-sender_code`, stored. You echo the first and address the answer to the second. +- The encryption certificate of the provider, fetched with [`/fetch/certs`](fetch-certs.md). +- A CoverageEligibilityResponse bundle in [FHIR](../../shared/glossary/fhir.md), built as in [the coverage eligibility response bundle](../fhir/coverage-eligibility-response.md). +- A handler for [`/v1/error`](../callbacks/error.md), where NHCX reports an answer it could not deliver. + +## What happens + +Your system, as the payer or a TPA acting for it, answers a request it received ([receiving the request](../callbacks/coverageeligibility-check.md)) by calling NHCX on `/v1/coverageeligibility/on_check`. NHCX answers 202 at once and delivers the same path to the registered address of the provider ([receiving `/v1/coverageeligibility/on_check`](../callbacks/coverageeligibility-on-check.md)). + +### 1. Seal the answer + +Swap the sender and recipient codes of the request. Echo its correlation id. Put these values in the [JWE](../glossary/jwe.md) [protected header](../glossary/protected-header.md): + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-request_id": "", + "x-hcx-correlation_id": "", + "x-hcx-timestamp": "", + "x-hcx-status": "response.complete", + "x-hcx-ben-abha-id": "" +} +``` + +Send `response.complete` for a final answer and `response.partial` for a partial one. The `x-hcx-*` values ride inside the JWE [protected header](../glossary/protected-header.md), not as HTTP headers. [The protocol headers](../concepts/protocol-headers.md) explains each one, including the timestamp format. + +### 2. Send it + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/hcx/v1/coverageeligibility/on_check' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --header 'Authorization: Bearer ' \ + --data-raw '{ + "type": "JWEPayload", + "payload": "" + }' +``` + +Send the token on both `bearer_auth` and `Authorization`, with the same value and the word `Bearer` in front. `` is your sealed message: five base64url parts joined by dots. See [the JWE envelope](../concepts/jwe-envelope.md). + +### 3. Refusing a request + +To refuse the request at protocol level instead, send `"type": "ProtocolResponse"` on this path with `x-hcx-status` `response.error` and `x-hcx-error_details` holding `code`, `message` and `trace`. Keep clinical and business reasons inside the sealed payload. Only protocol errors go in the header. + +### 4. Retrying + +**Idempotency.** Echo the `x-hcx-correlation_id` of the request you are answering. A correlation id NHCX does not hold, or one it has already deleted, is refused with [`NHCX-1010`](../errors/nhcx-1010.md). Generate a new `x-hcx-api_call_id` for every call. `/v1/status` looks a message up by that value ([`NHCX-1012`](../errors/nhcx-1012.md) when it cannot), so never reuse one. + +## How you know it worked + +You receive HTTP `202 Accepted` with this body: + +```json +{ + "timestamp": "
", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "coverageeligibility", + "protocol_status": "request.dispatched" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `correlation_id` matches the request you answered, and `api_call_id` matches the value you sealed. +- `result.entity_type` is `coverageeligibility`. +- `error.code` and `error.message` are empty. + +NHCX then delivers your answer to the provider. The recipient must answer each delivery with 202 and the acknowledgement body within 30 seconds. Otherwise NHCX retries up to five times, then deletes the request and reports it on the sender's [`/v1/error`](../callbacks/error.md). The step is done when you hold the 202 and no report for this correlation id arrives on your `/v1/error`. + +## When it goes wrong + +- [`NHCX-1010`](../errors/nhcx-1010.md): NHCX holds no request with that correlation id. You minted a new one instead of echoing it, or the request was deleted after failed deliveries. +- [`NHCX-1011`](../errors/nhcx-1011.md): `x-hcx-status` is not `response.complete`, `response.partial` or `response.error`. +- [`PAYR-1517`](../errors/payr-1517.md): a refusal arrived as a `JWEPayload`. Protocol refusals travel as `ProtocolResponse`. +- `401 Unauthorized`, or [`NHCX-401`](../errors/nhcx-401.md): get a new session token and send again. +- A report arrives on your [`/v1/error`](../callbacks/error.md): the requester's address did not acknowledge five deliveries. The request is dead on that correlation id. diff --git a/catalogue/nhcx/endpoints/dummy-payer-paymentnotice-init.md b/catalogue/nhcx/endpoints/dummy-payer-paymentnotice-init.md new file mode 100644 index 000000000..a068c37cc --- /dev/null +++ b/catalogue/nhcx/endpoints/dummy-payer-paymentnotice-init.md @@ -0,0 +1,89 @@ +--- +id: nhcx.endpoint.dummy-payer-paymentnotice-init +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /paymentNotice/init +summary: >- + Make the sandbox's test insurer send your hospital a payment notice on demand, + so you can test receiving and acknowledging it. +sources: +- url: https://hcxsbx.abdm.gov.in/images/819467ec15aff13cc2a8.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Dummy Payer Implementation.pdf + hash: sha256:97335ebc4cd32c86e0c34328b2f4c526420b32a7a009208364043d6334e9e757 + fetched: '2026-09-14' + note: NHCX Dummy Payer Implementation, row 19 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2-3, Payment Notice and CURL for Payment Notice Trigger API. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 4, Q14 and Q16. +- url: https://hcxsbx.abdm.gov.in/images/53347f5988b0ce5396f1.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_APIs to be called based on scenario.xlsx + hash: sha256:f92a30673d65dd2cc3cf09e2087c624f23f781dc4ca6b5cd8ec1825e224ac108 + fetched: '2026-09-14' + note: NHCX_APIs to be called based on scenario, row 26 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. sheet Scenarios, row 13. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + - nhcx.endpoint.communication-on-request + - nhcx.endpoint.paymentnotice-on-request + - nhcx.endpoint.session-token + sandbox: + - nhcx.sandbox.dummy-payer + - nhcx.sandbox.test-participants + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + - nhcx.flow.payment-notice + callbacks: + - nhcx.callback.paymentnotice-request +--- + +# POST /paymentNotice/init + +## In plain words + +A payment notice normally follows a settled claim, which is slow to reach in a test. This test hook makes the [NHCX](../../shared/glossary/nhcx.md) sandbox's [dummy payer](../sandbox/dummy-payer.md), `1000003538@hcx`, send one to you now. + +You call it as a provider integration testing its payment notice handling in the sandbox. It exists only in the sandbox. + +## Before you start + +- A handler for [`/v1/paymentnotice/request`](../callbacks/paymentnotice-request.md) on your registered callback address, answering 202 within 30 seconds. +- Your own participant code. +- A session token, sent on `bearer_auth`. See [the session token](../concepts/session-token.md). + +## What happens + +Your system calls the dummy payer's test hook directly. + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/dummyhcxpayer/paymentNotice/init' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --data-raw '{ + "providerId": "", + "claimNumber": "" + }' +``` + +Note the camel case in `paymentNotice`. Send `claimNumber` as an empty string. + +**Idempotency.** Each call triggers a notice. Call it again only when you want another one. + +## How you know it worked + +A payment notice from `1000003538@hcx` arrives on your [`/v1/paymentnotice/request`](../callbacks/paymentnotice-request.md). + +The step is done when your handler has answered it 202 within 30 seconds and you have sent the acknowledgement on [`/v1/paymentnotice/on_request`](paymentnotice-on-request.md). + +## When it goes wrong + +- Nothing arrives: `providerId` is not your participant code, or your callback address is unreachable. +- The notice arrives but the test is incomplete: you did not send the acknowledgement on `/v1/paymentnotice/on_request`. diff --git a/catalogue/nhcx/endpoints/dummy-payer-process-request.md b/catalogue/nhcx/endpoints/dummy-payer-process-request.md new file mode 100644 index 000000000..57ebe9e8e --- /dev/null +++ b/catalogue/nhcx/endpoints/dummy-payer-process-request.md @@ -0,0 +1,97 @@ +--- +id: nhcx.endpoint.dummy-payer-process-request +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /process/request +summary: >- + Make the sandbox's test insurer approve, reject or query a request you sent it, + so you can test your handling of each answer. +sources: +- url: https://hcxsbx.abdm.gov.in/images/819467ec15aff13cc2a8.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Dummy Payer Implementation.pdf + hash: sha256:97335ebc4cd32c86e0c34328b2f4c526420b32a7a009208364043d6334e9e757 + fetched: '2026-09-14' + note: NHCX Dummy Payer Implementation, row 19 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1-3, Preauth, Claim, Communication steps and CURL for Test Usecase Action API. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 4, Q14 and Q16. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheets Preauth and Claim, on_submit rows. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + - nhcx.endpoint.communication-on-request + - nhcx.endpoint.paymentnotice-on-request + - nhcx.endpoint.session-token + sandbox: + - nhcx.sandbox.dummy-payer + - nhcx.sandbox.test-participants + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + - nhcx.flow.payment-notice + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + - nhcx.callback.communication-request +--- + +# POST /process/request + +## In plain words + +The [NHCX](../../shared/glossary/nhcx.md) sandbox hosts a [dummy payer](../sandbox/dummy-payer.md), participant `1000003538@hcx`, that answers back. This test hook decides what it answers: approve, reject or query. + +You call it as a provider integration testing in the sandbox, after you have sent a pre-authorisation or claim to the dummy payer. It exists only in the sandbox. + +## Before you start + +- A pre-authorisation or claim sent to `1000003538@hcx` on [`/v1/preauth/submit`](preauth-submit.md) or [`/v1/claim/submit`](claim-submit.md), answered 202, with its correlation id kept. +- Your callback address registered, reachable from NHCX, and answering 202 within 30 seconds. +- A session token, sent on `bearer_auth`. See [the session token](../concepts/session-token.md). + +## What happens + +Your system calls the dummy payer's test hook directly. There is no JWE envelope on this call. + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/dummyhcxpayer/process/request' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --data-raw '{ + "action": "Approve", + "method": "Preauth", + "correlationId": "" + }' +``` + +`action` is `Approve`, `Reject` or `Query`. `method` is `Preauth` or `Claim`. + +After a `Query`, the dummy payer sends a communication request first. Answer it on [`/v1/communication/on_request`](communication-on-request.md) with the supporting documents. The final answer follows. + +**Idempotency.** Trigger one answer per request. To test another outcome, send a new request with its own correlation id. + +## How you know it worked + +The dummy payer's answer reaches your callback address on the correlation id you named: [`/v1/preauth/on_submit`](../callbacks/preauth-on-submit.md) for `Preauth`, [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md) for `Claim`. It is a sealed `ClaimResponse`, or a `ProtocolResponse` refusing the request. + +After a `Query`, a [`/v1/communication/request`](../callbacks/communication-request.md) arrives first. + +The step is done when your handler has answered that callback 202 within 30 seconds and recorded the outcome. + +## When it goes wrong + +- Nothing arrives: the correlation id belongs to a request that was not addressed to `1000003538@hcx`. +- After a `Query` the decision never comes: you did not answer the communication request on `/v1/communication/on_request`. +- A `ProtocolResponse` refuses an empty test bundle: there is no `Claim` inside. For a smoke test this refusal is the expected answer. diff --git a/catalogue/nhcx/endpoints/fetch-certs.md b/catalogue/nhcx/endpoints/fetch-certs.md new file mode 100644 index 000000000..e5154f7f4 --- /dev/null +++ b/catalogue/nhcx/endpoints/fetch-certs.md @@ -0,0 +1,126 @@ +--- +id: nhcx.endpoint.fetch-certs +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /fetch/certs +summary: >- + Fetch a recipient's public encryption certificate so you can seal a message only + they can open. +sources: +- url: https://hcxsbx.abdm.gov.in/images/b885e59891fedc7e725c.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-PARTICIPANT SERVICE_APIs Postman Collection.zip + hash: sha256:2d082f244ee41d137a62af82380dcd2d5db9ebbab66824fd54a23c506d4d9a7f + fetched: '2026-09-14' + note: AWS(Sandbox)-PARTICIPANT SERVICE_APIs Postman Collection, row 16 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Postman SANDBOX-Participant_APIs item Fetch Certs. +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./fetch/certs.post.' +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 3.3 Certificate Fetch; Section 2.4. +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1, Use case 3 Get public Key. +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1, Use case 5 Get public Key. +- url: https://hcxsbx.abdm.gov.in/images/539853c50347b32b9a5e.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Policy Linking and De-Linking Process.pdf + hash: sha256:420115b9a54e15fa625312a56362164d92d23dd0d6ebf9195135bb00055d1911 + fetched: '2026-09-14' + note: Policy Linking and De-Linking Process, row 8 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1, For Sandbox / For Production envBaseUrl. +verified: + status: unverified +related: + concepts: + - nhcx.concept.encryption-certificate + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.send-a-sealed-request + decisions: + - nhcx.decision.key-encryption-algorithm + endpoints: + - nhcx.endpoint.fetch-participants-list + - nhcx.endpoint.participant-search + - nhcx.endpoint.session-token + errors: + - nhcx.error.nhcx-401 + troubleshooting: + - nhcx.troubleshooting.recipient-cannot-decrypt + tests: + - nhcx.test.provider-uc-03 + - nhcx.test.payer-uc-05 +--- + +# POST /fetch/certs + +## In plain words + +This call returns a participant's public encryption certificate. You seal every [NHCX](../../shared/glossary/nhcx.md) message with the recipient's certificate, so only the recipient can open it. See [encryption certificates](../concepts/encryption-certificate.md) and [the JWE envelope](../concepts/jwe-envelope.md). + +Get public Key is use case 3 of the provider [sandbox exit](../glossary/sandbox-exit.md) and use case 5 of the payer sandbox exit. + +## Before you start + +- A current access token from the [session call](session-token.md). It goes in the `bearer_auth` header as `Bearer `, with `Bearer` and a space in front. +- The recipient's [participant code](../glossary/participant-code.md). It is the same value you will put in `x-hcx-recipient_code`. + +## What happens + +Your system posts the recipient's participant code to the participant service. The registry answers on the same connection with the certificate. Nothing changes and no callback follows. + +| Environment | Participant service base URL | +|---|---| +| Sandbox | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice` | +| Production | `https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice` | + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/fetch/certs' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -d '{ + "participantid": "" + }' +``` + +Send all three headers on every participant service call: `Accept`, `Content-Type` and `bearer_auth`. The token header is `bearer_auth`, not `Authorization`. + +`participantid` is mandatory. + +The response body has this shape: + +```json +{ + "encryption_cert": "-----BEGIN CERTIFICATE-----\n\n-----END CERTIFICATE-----" +} +``` + +The value is PEM text. Some participants register a bare public key (SPKI) rather than a full [X.509 certificate](../glossary/x509-certificate.md). Import it as X.509 first, and fall back to SPKI if that fails. Short keys, under about 400 bytes, are usually SPKI. + +Cache each certificate for 24 hours, keyed by participant code. Do not fetch it before every message. + +**Idempotency.** The call only reads. Repeating it is safe. + +## How you know it worked + +You receive HTTP 200 with a PEM value in `encryption_cert`. Your code imports it as an X.509 certificate or an SPKI public key without error. + +A message you seal with that key reaches the recipient, and the recipient opens it. A decryption error from the recipient means the key is wrong or stale. + +## When it goes wrong + +- **400 or no certificate.** The body used `participant_code` or `participantcode`. This call takes `participantid`. +- **The recipient cannot decrypt your message.** You sealed it with your own certificate, or with a cached one the recipient has since replaced. Evict the cache entry, fetch again and resend. See [recipient cannot decrypt](../troubleshooting/recipient-cannot-decrypt.md). +- **Key import fails.** The participant registered a bare SPKI key. Fall back to SPKI import. +- **401 Unauthorized.** The token is missing, has expired, or went out without the `Bearer ` prefix. Mint a new token, then retry the call once. See [NHCX-401](../errors/nhcx-401.md) and [every call returns 401](../troubleshooting/everything-returns-401.md). diff --git a/catalogue/nhcx/endpoints/fetch-participants-list.md b/catalogue/nhcx/endpoints/fetch-participants-list.md new file mode 100644 index 000000000..a30a38fd6 --- /dev/null +++ b/catalogue/nhcx/endpoints/fetch-participants-list.md @@ -0,0 +1,138 @@ +--- +id: nhcx.endpoint.fetch-participants-list +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /fetch/participants/list +summary: >- + List the payers, providers or third party administrators registered in a date + window, to pick who to address. +sources: +- url: https://hcxsbx.abdm.gov.in/images/b885e59891fedc7e725c.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-PARTICIPANT SERVICE_APIs Postman Collection.zip + hash: sha256:2d082f244ee41d137a62af82380dcd2d5db9ebbab66824fd54a23c506d4d9a7f + fetched: '2026-09-14' + note: AWS(Sandbox)-PARTICIPANT SERVICE_APIs Postman Collection, row 16 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Postman SANDBOX-Participant_APIs item Participant List. +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./fetch/participants/list.post; schemas FetchParticipantRequest, ParticipantDetails.' +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 5.5 Payer Discovery API. +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1, Use case 1 Get Participant List. +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1, Use case 4 Get Participant List. +- url: https://hcxsbx.abdm.gov.in/images/539853c50347b32b9a5e.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Policy Linking and De-Linking Process.pdf + hash: sha256:420115b9a54e15fa625312a56362164d92d23dd0d6ebf9195135bb00055d1911 + fetched: '2026-09-14' + note: Policy Linking and De-Linking Process, row 8 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1, For Sandbox / For Production envBaseUrl. +verified: + status: unverified +related: + concepts: + - nhcx.concept.participant-registry + - nhcx.concept.participant-code + flows: + - nhcx.flow.pmjay-patient-to-cashless + endpoints: + - nhcx.endpoint.participant-search + - nhcx.endpoint.participant-get-policies + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.session-token + errors: + - nhcx.error.nhcx-401 + sandbox: + - nhcx.sandbox.dummy-payer + - nhcx.sandbox.environments-and-base-urls + tests: + - nhcx.test.provider-uc-01 + - nhcx.test.payer-uc-04 +--- + +# POST /fetch/participants/list + +## In plain words + +This call lists the participants of one role registered on [NHCX](../../shared/glossary/nhcx.md) within a date window. A hospital uses it to find the [payer](../glossary/payer.md) to deal with. That payer's [participant code](../glossary/participant-code.md) becomes the address of every claim message. + +Get Participant List is use case 1 of the provider [sandbox exit](../glossary/sandbox-exit.md) and use case 4 of the payer sandbox exit. + +## Before you start + +- A current access token from the [session call](session-token.md). It goes in the `bearer_auth` header as `Bearer `, with `Bearer` and a space in front. +- A date window wide enough to cover the registration dates of the participants you expect. + +## What happens + +Your system posts a role and a date window to the participant service. The registry answers on the same connection. Nothing changes and no callback follows. + +| Environment | Participant service base URL | +|---|---| +| Sandbox | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice` | +| Production | `https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice` | + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/fetch/participants/list' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -d '{ + "role": "", + "fromdate": "", + "todate": "" + }' +``` + +Send all three headers on every participant service call: `Accept`, `Content-Type` and `bearer_auth`. The token header is `bearer_auth`, not `Authorization`. + +| Field | What to send | +|---|---| +| `role` | `PAYER`, `PROVIDER` or `TPA`. These are names, not the numeric role codes used at registration. | +| `fromdate`, `todate` | Dates in `dd/MM/yyyy` format only, for example `01/04/2021`. | +| `entitytype` | Optional. `Gov` narrows the list to government schemes. | + +The response body has this shape: + +```json +{ + "participantdetails": [ + { + "participantcode": "", + "participantname": "", + "address": "
", + "state": "" + } + ] +} +``` + +The list can also arrive under `participants`, or as a bare array. Accept all three forms. There is no name filter, so filter by name in your own code. + +**Idempotency.** The call only reads. Repeating it is safe. Fetch once with a wide window, cache the list and refresh it on a schedule. + +## How you know it worked + +You receive HTTP 200 with a list of participants of the role you asked for. The code you intend to address appears in it. + +In the sandbox, a `PAYER` list includes the [dummy payer](../sandbox/dummy-payer.md), `1000003538@hcx`. Confirm a chosen code with [`/participant/search`](participant-search.md) before you address it. + +## When it goes wrong + +- **400 or no results.** A date is not in `dd/MM/yyyy` format. Send `01/04/2021`, not `2021-04-01`. +- **A payer you expect is missing.** The date window is too narrow. Widen it to cover the payer's registration date. +- **Your parser finds nothing.** The list arrived under `participants` or as a bare array. Accept all three forms. +- **`role` is refused.** A numeric code such as `10002` went in. Send `PAYER`, `PROVIDER` or `TPA`. +- **401 Unauthorized.** The token is missing, has expired, or went out without the `Bearer ` prefix. Mint a new token, then retry the call once. See [NHCX-401](../errors/nhcx-401.md) and [every call returns 401](../troubleshooting/everything-returns-401.md). diff --git a/catalogue/nhcx/endpoints/get-session.md b/catalogue/nhcx/endpoints/get-session.md new file mode 100644 index 000000000..830560083 --- /dev/null +++ b/catalogue/nhcx/endpoints/get-session.md @@ -0,0 +1,112 @@ +--- +id: nhcx.endpoint.get-session +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /get/session +summary: >- + Trade your client id and client secret, sent as a form, for an access token to + use on claims exchange calls. +sources: +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 3.1 Token Request and Token Response. +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Use case 4 Get the auth token. +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1-2, Use case 6 Get the auth token. +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./get/session.post.' +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, Q3; page 5, Q20. +verified: + status: unverified +related: + concepts: + - nhcx.concept.session-token + endpoints: + - nhcx.endpoint.session-token + - nhcx.endpoint.fetch-certs + decisions: + - nhcx.decision.session-endpoint + errors: + - nhcx.error.nhcx-401 + troubleshooting: + - nhcx.troubleshooting.everything-returns-401 + tests: + - nhcx.test.provider-uc-04 + - nhcx.test.payer-uc-06 +--- + +# POST /get/session + +## In plain words + +`/get/session` returns an access token for [NHCX](../../shared/glossary/nhcx.md) calls. You post your client id and client secret as a form. The response carries `access_token` and its lifetime in `expires_in`. + +Get the auth token is use case 4 of the provider [sandbox exit](../glossary/sandbox-exit.md) and use case 6 of the payer sandbox exit. Both use cases name this call. The ABDM [session call](session-token.md) also issues NHCX tokens. [Choosing a session endpoint](../decisions/session-endpoint.md) compares the two. Use one of them across your whole integration. + +## Before you start + +- Your client id and client secret for the environment you are calling. Sandbox credentials do not work in production. +- No token is needed for this call itself. + +## What happens + +Your system posts a form to the sandbox host. The service answers on the same connection with the token. No callback follows. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/get/session' \ + -H 'Content-Type: application/x-www-form-urlencoded' \ + --data-urlencode 'client_id=' \ + --data-urlencode 'client_secret=' \ + --data-urlencode 'grant_type=client_credentials' +``` + +`grant_type` is always `client_credentials`. The two credentials are the only values you change. The body is a form, not JSON. + +A production address for this call is not yet published. + +The response body has this shape: + +```json +{ + "access_token": "", + "expires_in": , + "token_type": "Bearer" +} +``` + +Send `access_token` on every NHCX call as `bearer_auth: Bearer `. Read `expires_in` from each response and renew the token before it runs out. + +**Idempotency.** Each call mints a new token. Repeating it is safe. Keep the newest token. + +## How you know it worked + +You receive HTTP 200 with a non-empty `access_token`, `token_type` set to `Bearer` and an integer `expires_in`. + +A participant service call such as [`/fetch/certs`](fetch-certs.md) then returns 200 when it carries the token in `bearer_auth`. + +The token is valid for `expires_in` seconds from the moment it arrived. + +## When it goes wrong + +- **400 on this call.** The body went as JSON, or `grant_type` is missing or misspelt. Send `Content-Type: application/x-www-form-urlencoded` with all three fields. +- **Calls start returning 401 after a while.** The token lapsed. Mint a new one and retry the failed call once. See [NHCX-401](../errors/nhcx-401.md). +- **401 with a fresh token.** The `Bearer ` prefix is missing from `bearer_auth`. See [every call returns 401](../troubleshooting/everything-returns-401.md). +- **401 again after a retry with a new token.** The credentials are wrong or were replaced. Stop retrying and check the client id and secret. diff --git a/catalogue/nhcx/endpoints/insuranceplan-on-request.md b/catalogue/nhcx/endpoints/insuranceplan-on-request.md new file mode 100644 index 000000000..82b17dd4f --- /dev/null +++ b/catalogue/nhcx/endpoints/insuranceplan-on-request.md @@ -0,0 +1,179 @@ +--- +id: nhcx.endpoint.insuranceplan-on-request +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /v1/insuranceplan/on_request +summary: >- + Send a policy's machine-readable terms for one hospital back to that hospital + through the claims exchange. +sources: +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: 'NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet: Insurance Plan, /v1/insuranceplan/on_request rows.' +- url: https://hcxsbx.abdm.gov.in/insuranceplanhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/insuranceplanhcxservice.json + hash: sha256:03665c6e6a5c8d86e3d621ab577dd683cf13c155d5b9529f5be6ca70fef13dee + fetched: '2026-09-14' + note: 'API specification: insuranceplanhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/insuranceplan/on_request.post.' +- url: https://hcxsbx.abdm.gov.in/images/bc1e7d077857fc0fa071.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-NHCX USECASE Postman Collection.zip + hash: sha256:9d15daafa813d6d57e688fe800baa5a73d2540b8d0d12c6a1315f86a424817e4 + fetched: '2026-09-14' + note: AWS(Sandbox)-NHCX USECASE Postman Collection, row 17 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item /v1/insuranceplan/on_request. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1 Acceptance and Error scenario; page 2. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 6.1 Key Characteristics; 6.3 Business Conditions. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 4, Q14. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.insuranceplan-request + - nhcx.endpoint.session-token + - nhcx.endpoint.fetch-certs + callbacks: + - nhcx.callback.insuranceplan-request + - nhcx.callback.insuranceplan-on-request + - nhcx.callback.error + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1012 + - nhcx.error.payr-1517 + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.four-message-legs + - nhcx.concept.retries-and-expiry + - nhcx.concept.insurance-plan + flows: + - nhcx.flow.insurance-plan-request + fhir: + - nhcx.fhir.insurance-plan-bundle + - nhcx.fhir.pmjay-insurance-plan + tests: + - nhcx.test.payer-uc-08 + troubleshooting: + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.everything-returns-401 +--- + +# POST /v1/insuranceplan/on_request + +## In plain words + +This is the answer to an insurance plan request. As a payer, you return an InsurancePlan collection bundle for the policy and hospital named in the request. It lists specialities, packages, rates, claim conditions, mandatory documents and questionnaires. [NHCX](../../shared/glossary/nhcx.md) delivers it to the provider. + +You call it after you have received a [`/v1/insuranceplan/request`](insuranceplan-request.md). An empty plan is a valid answer when no coverage matches. + +## Before you start + +- A session token that has not expired. See [the session token](../concepts/session-token.md). +- The `/v1/insuranceplan/request` you are answering, received on [your registered address](../callbacks/insuranceplan-request.md), decrypted, and acknowledged with 202 within 30 seconds. +- That request's `x-hcx-correlation_id` and `x-hcx-sender_code`, stored. You echo the first and address the answer to the second. +- The encryption certificate of the provider, fetched with [`/fetch/certs`](fetch-certs.md). +- An InsurancePlan collection bundle in [FHIR](../../shared/glossary/fhir.md), built as in [the InsurancePlan bundles](../fhir/insurance-plan-bundle.md), filtered to the requesting hospital and policy. +- A handler for [`/v1/error`](../callbacks/error.md), where NHCX reports an answer it could not deliver. + +## What happens + +Your system, as the payer or a TPA acting for it, answers a request it received ([receiving the request](../callbacks/insuranceplan-request.md)) by calling NHCX on `/v1/insuranceplan/on_request`. NHCX answers 202 at once and delivers the same path to the registered address of the provider ([receiving `/v1/insuranceplan/on_request`](../callbacks/insuranceplan-on-request.md)). + +### 1. Seal the answer + +Swap the sender and recipient codes of the request. Echo its correlation id. Put these values in the [JWE](../glossary/jwe.md) [protected header](../glossary/protected-header.md): + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-request_id": "", + "x-hcx-correlation_id": "", + "x-hcx-timestamp": "", + "x-hcx-status": "response.complete", + "x-hcx-ben-abha-id": "" +} +``` + +Send `response.complete` with the plan. When you cannot produce one, refuse as described below. The `x-hcx-*` values ride inside the JWE [protected header](../glossary/protected-header.md), not as HTTP headers. [The protocol headers](../concepts/protocol-headers.md) explains each one, including the timestamp format. + +### 2. Send it + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/hcx/v1/insuranceplan/on_request' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --header 'Authorization: Bearer ' \ + --data-raw '{ + "type": "JWEPayload", + "payload": "" + }' +``` + +Send the token on both `bearer_auth` and `Authorization`, with the same value and the word `Bearer` in front. `` is your sealed message: five base64url parts joined by dots. See [the JWE envelope](../concepts/jwe-envelope.md). + +### 3. Refusing a request + +To refuse the request at protocol level instead, send `"type": "ProtocolResponse"` on this path with `x-hcx-status` `response.error` and `x-hcx-error_details` holding `code`, `message` and `trace`. Keep clinical and business reasons inside the sealed payload. Only protocol errors go in the header. + +### 4. Retrying + +**Idempotency.** Echo the `x-hcx-correlation_id` of the request you are answering. A correlation id NHCX does not hold, or one it has already deleted, is refused with [`NHCX-1010`](../errors/nhcx-1010.md). Generate a new `x-hcx-api_call_id` for every call. `/v1/status` looks a message up by that value ([`NHCX-1012`](../errors/nhcx-1012.md) when it cannot), so never reuse one. + +## How you know it worked + +You receive HTTP `202 Accepted` with this body: + +```json +{ + "timestamp": "
", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "insuranceplan", + "protocol_status": "request.dispatched" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `correlation_id` matches the request you answered, and `api_call_id` matches the value you sealed. +- `result.entity_type` is `insuranceplan`. +- `error.code` and `error.message` are empty. + +NHCX then delivers your answer to the provider. The recipient must answer each delivery with 202 and the acknowledgement body within 30 seconds. Otherwise NHCX retries up to five times, then deletes the request and reports it on the sender's [`/v1/error`](../callbacks/error.md). The step is done when you hold the 202 and no report for this correlation id arrives on your `/v1/error`. + +## When it goes wrong + +- [`NHCX-1010`](../errors/nhcx-1010.md): NHCX holds no request with that correlation id. You minted a new one instead of echoing it, or the request was deleted after failed deliveries. +- [`NHCX-1011`](../errors/nhcx-1011.md): `x-hcx-status` is not `response.complete`, `response.partial` or `response.error`. +- [`PAYR-1517`](../errors/payr-1517.md): a refusal arrived as a `JWEPayload`. Protocol refusals travel as `ProtocolResponse`. +- `401 Unauthorized`, or [`NHCX-401`](../errors/nhcx-401.md): get a new session token and send again. +- A report arrives on your [`/v1/error`](../callbacks/error.md): the requester's address did not acknowledge five deliveries. The request is dead on that correlation id. diff --git a/catalogue/nhcx/endpoints/insuranceplan-request.md b/catalogue/nhcx/endpoints/insuranceplan-request.md new file mode 100644 index 000000000..5db17b530 --- /dev/null +++ b/catalogue/nhcx/endpoints/insuranceplan-request.md @@ -0,0 +1,195 @@ +--- +id: nhcx.endpoint.insuranceplan-request +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /v1/insuranceplan/request +summary: >- + Ask an insurer, through the claims exchange, for the machine-readable terms of + a policy at your hospital: packages, rates and required documents. +sources: +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: 'NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet: Insurance Plan, /v1/insuranceplan/request rows.' +- url: https://hcxsbx.abdm.gov.in/insuranceplanhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/insuranceplanhcxservice.json + hash: sha256:03665c6e6a5c8d86e3d621ab577dd683cf13c155d5b9529f5be6ca70fef13dee + fetched: '2026-09-14' + note: 'API specification: insuranceplanhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/insuranceplan/request.post.' +- url: https://hcxsbx.abdm.gov.in/images/bc1e7d077857fc0fa071.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-NHCX USECASE Postman Collection.zip + hash: sha256:9d15daafa813d6d57e688fe800baa5a73d2540b8d0d12c6a1315f86a424817e4 + fetched: '2026-09-14' + note: AWS(Sandbox)-NHCX USECASE Postman Collection, row 17 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item /v1/insuranceplan/request. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Acceptance scenario. +- url: https://hcxsbx.abdm.gov.in/images/819467ec15aff13cc2a8.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Dummy Payer Implementation.pdf + hash: sha256:97335ebc4cd32c86e0c34328b2f4c526420b32a7a009208364043d6334e9e757 + fetched: '2026-09-14' + note: NHCX Dummy Payer Implementation, row 19 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Insurance Plan. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 6.1 Recommended Integration Points; 6.3 Business Conditions. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2 Q3; page 4 Q12 and Q14. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. items 6, 7 and 8. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.insuranceplan-on-request + - nhcx.endpoint.participant-get-policies + - nhcx.endpoint.session-token + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.status + callbacks: + - nhcx.callback.insuranceplan-request + - nhcx.callback.insuranceplan-on-request + - nhcx.callback.error + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1003 + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1012 + - nhcx.error.payr-1001 + - nhcx.error.payr-1406 + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.four-message-legs + - nhcx.concept.insurance-plan + flows: + - nhcx.flow.insurance-plan-request + fhir: + - nhcx.fhir.insurance-plan-bundle + - nhcx.fhir.pmjay-insurance-plan + tests: + - nhcx.test.provider-uc-06 + - nhcx.test.tc-hbp-01 + sandbox: + - nhcx.sandbox.dummy-payer + - nhcx.sandbox.environments-and-base-urls + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback + - nhcx.troubleshooting.everything-returns-401 +--- + +# POST /v1/insuranceplan/request + +## In plain words + +A hospital asks the insurer for the policy's terms as data, not as a PDF. The answer, an InsurancePlan, lists the specialities, packages, rates, claim conditions and mandatory documents that apply at your hospital. Your system, as the provider, sends the request to [NHCX](../../shared/glossary/nhcx.md) sealed for the payer. The plan arrives later on your `/v1/insuranceplan/on_request`. + +Call it before cost estimation and before any pre-authorisation for that payer and policy. + +## Before you start + +- A session token that has not expired. See [the session token](../concepts/session-token.md) and [how to get one](session-token.md). +- Your own [participant code](../glossary/participant-code.md), with your callback address registered, reachable from NHCX and answering 202 within 30 seconds. See [callback URL rules](../sandbox/callback-url-requirements.md). +- The payer's participant code. Take it from `processingID` in the [`/participant/get/policies`](participant-get-policies.md) response, not from `PayerID`. +- The recipient's encryption certificate, fetched with [`/fetch/certs`](fetch-certs.md). You seal the message with its public key. +- A Task bundle in [FHIR](../../shared/glossary/fhir.md) with `code` `poll` and at least one input: the policy number, your provider id, or both. See [the InsurancePlan request bundle](../fhir/insurance-plan-bundle.md). +- A handler for [`/v1/error`](../callbacks/error.md), so a request NHCX cannot deliver does not look like one still under review. +- A handler for [`/v1/insuranceplan/on_request`](../callbacks/insuranceplan-on-request.md). +- In the sandbox you can address the [dummy payer](../sandbox/dummy-payer.md), participant `1000003538@hcx`, which answers without a real insurer. With the dummy payer, use provider id `32722` inside the bundle and policy number `100217`. + +## What happens + +Your system, as the provider, calls NHCX on `/v1/insuranceplan/request`. NHCX checks the envelope, answers 202 at once, and forwards the same path to the payer's registered address ([receiving `/v1/insuranceplan/request`](../callbacks/insuranceplan-request.md)). The payer answers later on [`/v1/insuranceplan/on_request`](../callbacks/insuranceplan-on-request.md), which NHCX delivers to you. + +### 1. Seal the message + +Put these values in the [JWE](../glossary/jwe.md) [protected header](../glossary/protected-header.md) and encrypt the bundle with the recipient's public key. + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-request_id": "", + "x-hcx-correlation_id": "", + "x-hcx-timestamp": "", + "x-hcx-status": "request.initiated", + "x-hcx-ben-abha-id": "" +} +``` + +The `x-hcx-*` values ride inside the JWE [protected header](../glossary/protected-header.md), not as HTTP headers. [The protocol headers](../concepts/protocol-headers.md) explains each one, including the timestamp format. `x-hcx-workflow_id` is optional on this call. + +### 2. Send it + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/hcx/v1/insuranceplan/request' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --header 'Authorization: Bearer ' \ + --data-raw '{ + "payload": "" + }' +``` + +Send the token on both `bearer_auth` and `Authorization`, with the same value and the word `Bearer` in front. `` is your sealed message: five base64url parts joined by dots. See [the JWE envelope](../concepts/jwe-envelope.md). + +### 3. Retrying + +**Idempotency.** NHCX keys every conversation on `x-hcx-correlation_id`. An initiating request that reuses a correlation id NHCX already holds is refused with [`NHCX-1006`](../errors/nhcx-1006.md). So a blind retry is not safe. If your call timed out, ask [`/v1/status`](status.md) before you resend. `/v1/status` finds a message by its `x-hcx-api_call_id` ([`NHCX-1012`](../errors/nhcx-1012.md) when it cannot), so generate a new one for every call, a retry included. After a request fails for good, NHCX makes its correlation id inactive. Start a new cycle with a new correlation id. + +## How you know it worked + +You receive HTTP `202 Accepted` with this body: + +```json +{ + "timestamp": "
", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "insuranceplan", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `correlation_id` and `api_call_id` match the values you sealed. +- `result.entity_type` is `insuranceplan`. +- `result.protocol_status` is `request.queued` or `request.dispatched`. +- `error.code` and `error.message` are empty. + +The 202 is a receipt, not a decision. NHCX never returns a decision synchronously. The step is done when [`/v1/insuranceplan/on_request`](../callbacks/insuranceplan-on-request.md) reaches your callback address with the same `x-hcx-correlation_id`, and your handler has answered it 202 within 30 seconds. An empty plan is a valid answer when no coverage matches the policy and hospital. + +## When it goes wrong + +- [`PAYR-1406`](../errors/payr-1406.md): an earlier request with the same payer is still in progress. Wait 15 to 60 minutes for it to finish, then send again. +- `401 Unauthorized`, or [`NHCX-401`](../errors/nhcx-401.md): the session token expired or lacks the `Bearer ` prefix. Get a new token and send again. See [every call returns 401](../troubleshooting/everything-returns-401.md). +- [`NHCX-1003`](../errors/nhcx-1003.md): the recipient code is not registered. A provider used `PayerID` instead of `processingID`. +- [`NHCX-1006`](../errors/nhcx-1006.md): the correlation id was used before. Start the cycle with a new one. +- [`NHCX-1011`](../errors/nhcx-1011.md): `x-hcx-status` is not `request.initiated`. +- You got 202 and nothing more arrives. The recipient may have failed to decrypt ([`PAYR-1001`](../errors/payr-1001.md)) or your callback is unreachable. See [accepted, then no callback](../troubleshooting/accepted-then-no-callback.md). diff --git a/catalogue/nhcx/endpoints/notification-subscribe.md b/catalogue/nhcx/endpoints/notification-subscribe.md new file mode 100644 index 000000000..c83589a6a --- /dev/null +++ b/catalogue/nhcx/endpoints/notification-subscribe.md @@ -0,0 +1,123 @@ +--- +id: nhcx.endpoint.notification-subscribe +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /v1/notification/subscribe +summary: >- + Let a patient's health record app receive plain-language updates about that patient's + insurance claims. +sources: +- url: https://hcxsbx.abdm.gov.in/images/01db86335b7c226eb745.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Notification Integration.docx + hash: sha256:05908862c103522fac0dbb482f8eb6a0f8536fc12b1ae3bdb0e98615f30812aa + fetched: '2026-09-14' + note: NHCX Notification Integration, listed on https://hcxsbx.abdm.gov.in/#/documents, not named in the NHCX document sheet. sections 2, 3, 4.2, 6.1, 6.3, 7.3. +- url: https://hcxsbx.abdm.gov.in/subscriptionhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/subscriptionhcxservice.json + hash: sha256:0d0d4781aa96017c06c8c2533e63dd1a6b36bb2342ebb51aeefca3349d892029 + fetched: '2026-09-14' + note: 'API specification: subscriptionhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/notification/subscribe.post; components.schemas.SubscribeResponse.' +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.session-token + callbacks: + - nhcx.callback.notification-delivery + errors: + - nhcx.error.nhcx-401 + concepts: + - nhcx.concept.notifications + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.beneficiary-consent + flows: + - nhcx.flow.notification-subscribe + decisions: + - nhcx.decision.session-endpoint +--- + +# POST /v1/notification/subscribe + +## In plain words + +A [PHR](../../shared/glossary/phr.md) app registered with [NHCX](../../shared/glossary/nhcx.md) as a Beneficiary Service Provider subscribes a beneficiary to claim notifications. Afterwards, when a hospital and payer exchange a pre-authorisation, claim, payment or communication for that beneficiary, NHCX pushes a readable message to the app. + +You call it every time the beneficiary logs in to your app with their ABHA address. Only the most recently subscribed app receives notifications for an ABHA. + +## Before you start + +- [Milestone 1](../../shared/glossary/m1.md) integration complete, and your app registered in NHCX as a Beneficiary Service Provider. +- A session token, sent on `Authorization`. See [which session endpoint to call](../decisions/session-endpoint.md). +- An HTTPS callback endpoint, TLS 1.2 or newer, for notifications. See [receiving a notification](../callbacks/notification-delivery.md). +- The beneficiary's explicit consent to subscribe, and their [ABHA address](../../shared/glossary/abha-address.md). + +## What happens + +Your app calls NHCX on the portal host, not on the exchange host the other `/v1` calls use. + +Seal the subscription as a [JWE](../glossary/jwe.md) with these protected headers: + +```json +{ + "alg": "RSA-OAEP", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-timestamp": "", + "x-hcx-correlation_id": "" +} +``` + +The sealed payload: + +```json +{ + "subscription_id": "", + "topic_code": ["workflow_events"], + "recipient_code": "", + "subscriber": { "id": "" }, + "on_notification_url": "" +} +``` + +`topic_code` also accepts `network_events` and `participant_events`. `expiry` is optional. + +```bash +curl --location --request POST 'https://hcxsbx.abdm.gov.in/v1/notification/subscribe' \ + --header 'Authorization: Bearer ' \ + --header 'Content-Type: application/json' \ + --data-raw '{ + "payload": "" + }' +``` + +**Idempotency.** A subscription for an ABHA replaces any earlier one, from your app or another. Subscribing again on every login is safe. Generate a new `x-hcx-correlation_id` for every attempt, a retry included. + +## How you know it worked + +You receive HTTP `200` with the subscription state: + +```json +{ + "timestamp": "", + "api_call_id": "", + "correlation_id": "", + "subscription_id": "", + "subscription_status": "active", + "expiry": "", + "message": "" +} +``` + +The step is done when `subscription_status` is `active` for your `subscription_id`. Store the `subscription_id`, and show the status in your app's settings. A later `replaced` means another app has taken the beneficiary's notifications. + +## When it goes wrong + +- `401 Unauthorized`: the token expired. Get a new one and subscribe again. +- `403 Forbidden`: your app is not authorised. Check your registry entry in NHCX. +- `409 Conflict`: this should not occur when every attempt carries a new `x-hcx-correlation_id`. +- `500`: a gateway fault. Retry with backoff and a new correlation id. +- The call goes to `https://apisbx.abdm.gov.in/hcx`, or carries the token on `bearer_auth` only. Use the portal host and `Authorization`. diff --git a/catalogue/nhcx/endpoints/on-status.md b/catalogue/nhcx/endpoints/on-status.md new file mode 100644 index 000000000..4ed1a23dd --- /dev/null +++ b/catalogue/nhcx/endpoints/on-status.md @@ -0,0 +1,146 @@ +--- +id: nhcx.endpoint.on-status +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /v1/on_status +summary: >- + Tell a participant who asked about one of its messages that the message has reached + you. +sources: +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: 'NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet: Status, /v1/on_status rows.' +- url: https://hcxsbx.abdm.gov.in/images/bc1e7d077857fc0fa071.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-NHCX USECASE Postman Collection.zip + hash: sha256:9d15daafa813d6d57e688fe800baa5a73d2540b8d0d12c6a1315f86a424817e4 + fetched: '2026-09-14' + note: AWS(Sandbox)-NHCX USECASE Postman Collection, row 17 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item /v1/on_status. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1 Acceptance and Error scenario; page 2. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 4, Q14. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.status + - nhcx.endpoint.session-token + callbacks: + - nhcx.callback.status + - nhcx.callback.on-status + - nhcx.callback.error + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1012 + - nhcx.error.payr-1517 + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.four-message-legs + - nhcx.concept.retries-and-expiry + - nhcx.concept.status-lifecycle + flows: + - nhcx.flow.status-check + tests: + - nhcx.test.payer-uc-15 + troubleshooting: + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.everything-returns-401 +--- + +# POST /v1/on_status + +## In plain words + +A participant that sent you a message can ask [NHCX](../../shared/glossary/nhcx.md) where it stands with [`/v1/status`](status.md). When the message has reached you, NHCX forwards the question to you. You answer on `/v1/on_status`, and NHCX delivers the answer to the participant that asked. + +The answer reports delivery, not a decision. The sealed payload is an empty string. + +## Before you start + +- A session token that has not expired. See [the session token](../concepts/session-token.md). +- The `/v1/status` you are answering, received on [your registered address](../callbacks/status.md), decrypted, and acknowledged with 202 within 30 seconds. +- That request's `x-hcx-correlation_id` and `x-hcx-sender_code`, stored. You echo the first and address the answer to the second. +- The encryption certificate of the participant that asked, fetched with [`/fetch/certs`](fetch-certs.md). +- Nothing to build. The sealed payload is an empty string. +- A handler for [`/v1/error`](../callbacks/error.md), where NHCX reports an answer it could not deliver. + +## What happens + +Your system, as the recipient of the original message, answers a request it received ([receiving the request](../callbacks/status.md)) by calling NHCX on `/v1/on_status`. NHCX answers 202 at once and delivers the same path to the registered address of the participant that asked ([receiving `/v1/on_status`](../callbacks/on-status.md)). + +### 1. Seal the answer + +Swap the sender and recipient codes of the request. Echo its correlation id. Put these values in the [JWE](../glossary/jwe.md) [protected header](../glossary/protected-header.md): + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-request_id": "", + "x-hcx-correlation_id": "", + "x-hcx-timestamp": "", + "x-hcx-status": "request.dispatched", + "x-hcx-ben-abha-id": "" +} +``` + +Send `request.dispatched`: the message the participant asked about has reached you. The correlation id is that of the status request, not of the original message. The `x-hcx-*` values ride inside the JWE [protected header](../glossary/protected-header.md), not as HTTP headers. [The protocol headers](../concepts/protocol-headers.md) explains each one, including the timestamp format. + +### 2. Send it + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/hcx/v1/on_status' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --header 'Authorization: Bearer ' \ + --data-raw '{ + "type": "JWEPayload", + "payload": "" + }' +``` + +Send the token on both `bearer_auth` and `Authorization`, with the same value and the word `Bearer` in front. `` is your sealed message: five base64url parts joined by dots. See [the JWE envelope](../concepts/jwe-envelope.md). + +### 3. Refusing a request + +To refuse the request at protocol level instead, send `"type": "ProtocolResponse"` on this path with `x-hcx-status` `response.error` and `x-hcx-error_details` holding `code`, `message` and `trace`. Keep clinical and business reasons inside the sealed payload. Only protocol errors go in the header. + +### 4. Retrying + +**Idempotency.** Echo the `x-hcx-correlation_id` of the request you are answering. A correlation id NHCX does not hold, or one it has already deleted, is refused with [`NHCX-1010`](../errors/nhcx-1010.md). Generate a new `x-hcx-api_call_id` for every call. `/v1/status` looks a message up by that value ([`NHCX-1012`](../errors/nhcx-1012.md) when it cannot), so never reuse one. + +## How you know it worked + +You receive HTTP `202 Accepted` with the acknowledgement body: `timestamp`, `api_call_id`, `correlation_id`, `result` and an empty `error`. + +- `correlation_id` matches the status request you answered. +- `error.code` and `error.message` are empty. + +NHCX then delivers your answer to the participant that asked. The recipient must answer each delivery with 202 and the acknowledgement body within 30 seconds. Otherwise NHCX retries up to five times, then deletes the request and reports it on the sender's [`/v1/error`](../callbacks/error.md). The step is done when you hold the 202 and no report for this correlation id arrives on your `/v1/error`. + +## When it goes wrong + +- [`NHCX-1010`](../errors/nhcx-1010.md): NHCX holds no request with that correlation id. You minted a new one instead of echoing it, or the request was deleted after failed deliveries. +- [`NHCX-1011`](../errors/nhcx-1011.md): `x-hcx-status` is not `response.complete`, `response.partial` or `response.error`. +- [`PAYR-1517`](../errors/payr-1517.md): a refusal arrived as a `JWEPayload`. Protocol refusals travel as `ProtocolResponse`. +- `401 Unauthorized`, or [`NHCX-401`](../errors/nhcx-401.md): get a new session token and send again. +- A report arrives on your [`/v1/error`](../callbacks/error.md): the requester's address did not acknowledge five deliveries. The request is dead on that correlation id. diff --git a/catalogue/nhcx/endpoints/participant-create.md b/catalogue/nhcx/endpoints/participant-create.md new file mode 100644 index 000000000..225fe2460 --- /dev/null +++ b/catalogue/nhcx/endpoints/participant-create.md @@ -0,0 +1,160 @@ +--- +id: nhcx.endpoint.participant-create +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /participant/create +summary: >- + Register your organisation in the sandbox participant registry and receive the + participant code that addresses all your messages. +sources: +- url: https://hcxsbx.abdm.gov.in/images/e683dda0a8cf953abbc7.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)NHCX-OnBoarding APIs Postman Collection.zip + hash: sha256:ca4348e8a373c54bdcabd07eff8e49a55d93cdfae65fa5008ae0d56526a769f2 + fetched: '2026-09-14' + note: AWS(Sandbox)NHCX-OnBoarding APIs Postman Collection, row 6 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Postman SANDBOX_NHCX-OnBoarding APIs item Participant Create. +- url: https://hcxsbx.abdm.gov.in/images/bc2efb078b98548f8e6b.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Sandbox.pdf + hash: sha256:cbd03baf428655f0305e2f60ca331f8b76700496b070c522cafcc95001710b3a + fetched: '2026-09-14' + note: Onboarding providers and payers in Sandbox, row 4 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1, API Definition - Create Participant. +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./participant/create.post; schemas ParticipantCreateBody, ParticipantCreateResponse.' +- url: https://hcxsbx.abdm.gov.in/images/260d0dec19a681e80262.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Production.pdf + hash: sha256:c38476fb90101f13fdfea447861292718d561e1dc088ae20950b193606500d2e + fetched: '2026-09-14' + note: Onboarding providers and payers in Production, row 5 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 4, Valid Role Enums and Valid Registry Enums. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 3 Q6-Q9; Page 4 Q11; Page 5 Q21. +- url: https://hcxsbx.abdm.gov.in/images/ec361a6c3e90e766d227.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Steps to generate encryption Certificate.pdf + hash: sha256:94605e935f05ebb49e24dee50787cb4f3f1c401983a9616a5aaabdbc302f664b + fetched: '2026-09-14' + note: Steps to generate encryption Certificate, row 20 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 3, Step 4 Base64 Encoding. +verified: + status: unverified +related: + concepts: + - nhcx.concept.participant-registry + - nhcx.concept.participant-code + - nhcx.concept.participant-roles + - nhcx.concept.encryption-certificate + flows: + - nhcx.flow.sandbox-onboarding + - nhcx.flow.generate-and-register-certificate + endpoints: + - nhcx.endpoint.v2-participant-create + - nhcx.endpoint.participant-update + - nhcx.endpoint.participant-search + - nhcx.endpoint.fetch-participants-list + - nhcx.endpoint.session-token + errors: + - nhcx.error.nhcx-401 + troubleshooting: + - nhcx.troubleshooting.callback-url-rejected + sandbox: + - nhcx.sandbox.prerequisites + - nhcx.sandbox.callback-url-requirements +--- + +# POST /participant/create + +## In plain words + +This call registers your organisation in the [NHCX](../../shared/glossary/nhcx.md) [participant registry](../concepts/participant-registry.md). The registry answers with your [participant code](../glossary/participant-code.md). Every message you send or receive on NHCX is addressed with that code. + +This is the sandbox create call. In production, call [`/v2/participant/create`](v2-participant-create.md) and confirm it with [`/validate`](validate.md). + +## Before you start + +- A current access token from the [session call](session-token.md). +- Your registry id. A [provider](../glossary/provider.md) uses its [HFR](../../shared/glossary/hfr.md) ID. A [payer](../glossary/payer.md) or [TPA](../glossary/tpa.md) uses its [IRDAI](../glossary/irdai.md) or other authority-issued ID. An [EUA](../../shared/glossary/eua.md) uses its client id. +- Your public encryption certificate, Base64 encoded. See [generate and register a certificate](../flows/generate-and-register-certificate.md). +- Your callback bridge URL, on a domain name, served from India. See [callback URL requirements](../sandbox/callback-url-requirements.md). + +## What happens + +Your system posts a JSON profile to the sandbox participant service. The registry validates the linked registry codes, creates the record and answers on the same connection. No callback follows. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/participant/create' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -d '{ + "linked_registry_codes": [""], + "registryid": "", + "participant_name": "", + "scheme_code": "", + "state": "", + "district": "", + "roles": [""], + "primaryEmail": "", + "phone": [""], + "primaryMobile": "", + "signing_cert_path": "", + "encryption_cert": "", + "endpoint_url": "" + }' +``` + +Send all three headers on every participant service call: `Accept`, `Content-Type` and `bearer_auth`. The token header is `bearer_auth`, not `Authorization`. + +Put a role code in `roles`: + +| Role | Code | +|---|---| +| PROVIDER | `10001` | +| PAYER | `10002` | +| AGENCY_TPA | `10003` | +| AGENCY_REGULATOR | `10004` | +| RESEARCH | `10005` | +| MEMBER_ISNP | `10006` | +| AGENCY_SPONSOR | `10007` | +| HIE_HIO_HCX | `10008` | +| EUA | `10009` | + +Put a registry code in `linked_registry_codes`: + +| Registry | Code | Who uses it | +|---|---|---| +| HFR | `10001` | Providers and EUAs | +| NIN | `10002` | | +| ROHINI | `10003` | | +| PAYER | `10004` | Payers and TPAs | + +Send every code as a five-digit string with no spaces, for example `"10003"`. `10001` means PROVIDER in `roles` and HFR in `linked_registry_codes`. They are different fields. + +`encryption_cert` is the Base64 encoding of the whole PEM certificate, including the `BEGIN` and `END` lines. `endpoint_url` is the bridge URL where NHCX delivers messages to you. + +The response body has this shape: + +```json +{ + "participant_code": "" +} +``` + +**Idempotency.** Do not repeat create to retry a timeout or to fix a field. If a create times out, look for your organisation in [`/fetch/participants/list`](fetch-participants-list.md) first. Change a field with [`/participant/update`](participant-update.md). An organisation holds more than one participant code only when each code is linked to a separate HFR ID. + +## How you know it worked + +You receive HTTP 200 with `participant_code` in the body. Store it as configuration. It becomes `x-hcx-sender_code` on every message you send. + +A [`/participant/search`](participant-search.md) with that code returns your record, with the `endpoint_url` and `encryption_cert` you sent. Your organisation exchanges claims only after the record reaches status `Active`. + +## When it goes wrong + +- **400 Client error.** A field is malformed or the `Accept` header is missing. Check the snake_case field names, the codes in `roles` and `linked_registry_codes`, and that `encryption_cert` is Base64 of the PEM, not the raw PEM. +- **Wrong role or registry code.** A wrong mapping leads to rejected requests or misrouted transactions later. Use the tables above. +- **401 Unauthorized.** The token is missing, has expired, or went out without the `Bearer ` prefix. Mint a new token, then retry the call once. See [NHCX-401](../errors/nhcx-401.md) and [every call returns 401](../troubleshooting/everything-returns-401.md). +- **Messages never reach you after onboarding.** The `endpoint_url` uses an IP address or a port, or the host is outside India. See [callback URL rejected](../troubleshooting/callback-url-rejected.md). +- **404 or 500.** 404 means a resource was not found, so check the registry codes you sent. 500 means a downstream system is down. Retry a 500 later. diff --git a/catalogue/nhcx/endpoints/participant-delink-abha-policy.md b/catalogue/nhcx/endpoints/participant-delink-abha-policy.md new file mode 100644 index 000000000..6241e78bc --- /dev/null +++ b/catalogue/nhcx/endpoints/participant-delink-abha-policy.md @@ -0,0 +1,116 @@ +--- +id: nhcx.endpoint.participant-delink-abha-policy +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /participant/delink/abha/policy +summary: >- + As a payer, remove products from a beneficiary's policy link so hospitals stop + finding coverage that has ended. +sources: +- url: https://hcxsbx.abdm.gov.in/images/539853c50347b32b9a5e.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Policy Linking and De-Linking Process.pdf + hash: sha256:420115b9a54e15fa625312a56362164d92d23dd0d6ebf9195135bb00055d1911 + fetched: '2026-09-14' + note: Policy Linking and De-Linking Process, row 8 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 2, Validation for De-Linking; Page 1 TPA change. +- url: https://hcxsbx.abdm.gov.in/images/b885e59891fedc7e725c.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-PARTICIPANT SERVICE_APIs Postman Collection.zip + hash: sha256:2d082f244ee41d137a62af82380dcd2d5db9ebbab66824fd54a23c506d4d9a7f + fetched: '2026-09-14' + note: AWS(Sandbox)-PARTICIPANT SERVICE_APIs Postman Collection, row 16 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Postman SANDBOX-Participant_APIs item Delink Abha. +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./participant/delink/abha/policy.post; schema ParticipantDeLinkAbhaRequest.' +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 2, item 10 Policy Linking/Delinking auth restriction. +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1, Use case 3 De-Link ABHA from Policy. +verified: + status: unverified +related: + concepts: + - nhcx.concept.policy-linking + flows: + - nhcx.flow.policy-link-and-delink + endpoints: + - nhcx.endpoint.v2-participant-delink-abha-policy + - nhcx.endpoint.participant-link-abha-policy + - nhcx.endpoint.participant-get-policies + - nhcx.endpoint.session-token + errors: + - nhcx.error.nhcx-401 + tests: + - nhcx.test.payer-uc-03 +--- + +# POST /participant/delink/abha/policy + +## In plain words + +A [payer](../glossary/payer.md) calls this to remove products from a beneficiary's policy link on [NHCX](../../shared/glossary/nhcx.md). Hospitals then stop finding that coverage through [`/participant/get/policies`](participant-get-policies.md). It reverses [`/participant/link/abha/policy`](participant-link-abha-policy.md). + +De-Link ABHA from Policy is use case 3 of the payer [sandbox exit](../glossary/sandbox-exit.md). Call this path. [`/V2/participant/delink/abha/policy`](v2-participant-delink-abha-policy.md) takes the same body. + +## Before you start + +- The products are linked for this `payerid` and `memberid`. +- You are the participant named as `payerid` or `processingid` when the products were linked. +- A current access token minted with the client id used when your participant was created. It goes in `bearer_auth` as `Bearer `. + +## What happens + +Your system posts the products to remove. NHCX reads the client id from your token and checks that it matches the insurer (`payerid`) or the TPA (`processingid`) that linked them. It then removes the products and answers on the same connection. No callback follows. + +| Environment | Participant service base URL | +|---|---| +| Sandbox | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice` | +| Production | `https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice` | + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/participant/delink/abha/policy' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -d '{ + "requestid": "", + "payerid": "", + "memberid": "", + "processingid": "", + "policies": [ + { + "productid": "", + "productname": "" + } + ] + }' +``` + +Send all three headers on every participant service call: `Accept`, `Content-Type` and `bearer_auth`. The token header is `bearer_auth`, not `Authorization`. + +The body has no `abhanumber` field. It is keyed on `payerid`, `memberid` and the products listed. Omit `processingid` if the products were linked without one. List only the products to remove. + +To move an insurer to a new TPA, de-link its policies here, then link them again with the new TPA's code in `processingid`. + +**Idempotency.** Send a new `requestid` on every call. Repeating a de-link that already succeeded returns `There is no policies with requested details`. Treat that message after a timeout as done, and confirm with [`/participant/get/policies`](participant-get-policies.md). + +## How you know it worked + +You receive HTTP 200. + +[`/participant/get/policies`](participant-get-policies.md) for the beneficiary no longer returns the removed products for that payer. + +## When it goes wrong + +- **The de-link is refused with an error message.** The client id in your token belongs to neither the `payerid` nor the `processingid` participant from the link. Mint the token with the client id used when that participant was created. +- **`There is no policies with requested details`.** A listed product is not linked for this `payerid` and `memberid`. Check the product id and name against the link. +- **A hospital still sees the policy.** Hospitals cache policy lookups. Ask them to refresh the lookup for this beneficiary. +- **401 Unauthorized.** The token is missing, has expired, or went out without the `Bearer ` prefix. Mint a new token, then retry the call once. See [NHCX-401](../errors/nhcx-401.md) and [every call returns 401](../troubleshooting/everything-returns-401.md). diff --git a/catalogue/nhcx/endpoints/participant-details.md b/catalogue/nhcx/endpoints/participant-details.md new file mode 100644 index 000000000..43057670c --- /dev/null +++ b/catalogue/nhcx/endpoints/participant-details.md @@ -0,0 +1,93 @@ +--- +id: nhcx.endpoint.participant-details +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /participant/details +summary: >- + Read one participant's full registry record by its participant code, through the + second lookup path. +sources: +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./participant/details.post; schemas ParticipantSearchReq, ParticipantSearchResponse.' +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/registries + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__registries.md + hash: sha256:04bf78739fa0c3807a8a5a49d8c3e004f8aba664f524d0344d7fc44c3b2baf42 + fetched: '2026-09-14' + note: Site page /technical-specifications/open-protocol/registries, text as shown on the site. Participating Organisations/Systems Registry table, status. +- url: https://hcxsbx.abdm.gov.in/images/539853c50347b32b9a5e.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Policy Linking and De-Linking Process.pdf + hash: sha256:420115b9a54e15fa625312a56362164d92d23dd0d6ebf9195135bb00055d1911 + fetched: '2026-09-14' + note: Policy Linking and De-Linking Process, row 8 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1, For Sandbox / For Production envBaseUrl. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 2, item 6 Missing the Accept parameter. +verified: + status: unverified +related: + concepts: + - nhcx.concept.participant-registry + endpoints: + - nhcx.endpoint.participant-search + - nhcx.endpoint.fetch-participants-list + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.session-token + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1003 +--- + +# POST /participant/details + +## In plain words + +This call reads one participant's record from the [NHCX](../../shared/glossary/nhcx.md) participant registry by [participant code](../glossary/participant-code.md). It takes the same body as [`/participant/search`](participant-search.md) and returns the same record. + +Either path works. Use one of the two consistently across your integration. + +## Before you start + +- A current access token from the [session call](session-token.md). It goes in the `bearer_auth` header as `Bearer `, with `Bearer` and a space in front. +- The participant code you want to read. + +## What happens + +Your system posts the code to the participant service. The registry answers on the same connection. Nothing changes and no callback follows. + +| Environment | Participant service base URL | +|---|---| +| Sandbox | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice` | +| Production | `https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice` | + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/participant/details' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -d '{ + "participant_code": "" + }' +``` + +Send all three headers on every participant service call: `Accept`, `Content-Type` and `bearer_auth`. The token header is `bearer_auth`, not `Authorization`. + +The response has the same shape as [`/participant/search`](participant-search.md): a `timestamp` and a `participants` array of records carrying `participant_code`, `roles`, `status`, `encryption_cert` and `endpoint_url`. + +**Idempotency.** The call only reads. Repeating it is safe. + +## How you know it worked + +You receive HTTP 200 with a `participants` array. One entry carries the `participant_code` you sent, with status `Active` when the participant can transact. + +## When it goes wrong + +- **400 or an empty result.** The body used `participantid` or `participantcode`. This call takes `participant_code`. +- **No entry for the code.** The code is wrong or not registered. Messages addressed to it fail with [NHCX-1003](../errors/nhcx-1003.md). +- **401 Unauthorized.** The token is missing, has expired, or went out without the `Bearer ` prefix. Mint a new token, then retry the call once. See [NHCX-401](../errors/nhcx-401.md) and [every call returns 401](../troubleshooting/everything-returns-401.md). diff --git a/catalogue/nhcx/endpoints/participant-get-policies.md b/catalogue/nhcx/endpoints/participant-get-policies.md new file mode 100644 index 000000000..92a9d9678 --- /dev/null +++ b/catalogue/nhcx/endpoints/participant-get-policies.md @@ -0,0 +1,133 @@ +--- +id: nhcx.endpoint.participant-get-policies +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /participant/get/policies +summary: >- + Look up the policies linked to a beneficiary by health account number, member + id or mobile number, to learn whom to address. +sources: +- url: https://hcxsbx.abdm.gov.in/images/b885e59891fedc7e725c.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-PARTICIPANT SERVICE_APIs Postman Collection.zip + hash: sha256:2d082f244ee41d137a62af82380dcd2d5db9ebbab66824fd54a23c506d4d9a7f + fetched: '2026-09-14' + note: AWS(Sandbox)-PARTICIPANT SERVICE_APIs Postman Collection, row 16 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Postman SANDBOX-Participant_APIs item Get Policies. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 2, item 7 Providers pointing to the PayerID. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 5.6.2 to 5.6.4 Policy Discovery API. +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./participant/get/policies.post; schema FetchParticipantPoliciesRequest.' +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1, Use case 2 Get Policy. +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1, Use case 2 Get Policy. +- url: https://hcxsbx.abdm.gov.in/images/539853c50347b32b9a5e.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Policy Linking and De-Linking Process.pdf + hash: sha256:420115b9a54e15fa625312a56362164d92d23dd0d6ebf9195135bb00055d1911 + fetched: '2026-09-14' + note: Policy Linking and De-Linking Process, row 8 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1, For Sandbox / For Production envBaseUrl. +verified: + status: unverified +related: + concepts: + - nhcx.concept.policy-linking + - nhcx.concept.participant-code + flows: + - nhcx.flow.pmjay-patient-to-cashless + - nhcx.flow.policy-link-and-delink + endpoints: + - nhcx.endpoint.v2-participant-get-policies + - nhcx.endpoint.participant-link-abha-policy + - nhcx.endpoint.fetch-participants-list + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.session-token + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1003 + - nhcx.error.payr-1331 + tests: + - nhcx.test.provider-uc-02 + - nhcx.test.payer-uc-02 + - nhcx.test.tc-abha-01 +--- + +# POST /participant/get/policies + +## In plain words + +This call returns the policies that payers have linked to a beneficiary. A hospital uses it to learn which [payer](../glossary/payer.md) or [TPA](../glossary/tpa.md) to address, and the member id and product to put in claim messages. Payers use it to confirm their own links. + +Get Policy is use case 2 of both the provider and the payer [sandbox exit](../glossary/sandbox-exit.md). Call this path. [`/V2/participant/get/policies`](v2-participant-get-policies.md) takes the same body. + +## Before you start + +- A current access token from the [session call](session-token.md). It goes in the `bearer_auth` header as `Bearer `, with `Bearer` and a space in front. +- A payer or TPA has linked the beneficiary with [`/participant/link/abha/policy`](participant-link-abha-policy.md). Without a link, the lookup returns nothing. +- At least one identifier for the beneficiary: an [ABHA number](../../shared/glossary/abha-number.md), a member id or a mobile number. + +## What happens + +Your system posts one identifier to the participant service. The registry answers on the same connection with the linked policies. Nothing changes and no callback follows. + +| Environment | Participant service base URL | +|---|---| +| Sandbox | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice` | +| Production | `https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice` | + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/participant/get/policies' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -d '{ + "identifiertype": "", + "identifiervalue": "" + }' +``` + +Send all three headers on every participant service call: `Accept`, `Content-Type` and `bearer_auth`. The token header is `bearer_auth`, not `Authorization`. + +| Field | What to send | +|---|---| +| `identifiertype` | `AbhaNumber`, `MemberId` or `MobileNo`. | +| `identifiervalue` | The value of that identifier. Send an ABHA number as 14 digits without hyphens. | + +Try the identifiers in this order until one returns a policy: `AbhaNumber` first, then `MemberId`, then `MobileNo`. + +For each returned policy, read the payer id, the processing id, the member id, and the product id and name. The processing id is the participant you address: it goes in `x-hcx-recipient_code`. Do not address the payer id. Field names in the response are not yet published, so map them from your first sandbox response. + +Cache the result per patient. Refresh it when a payer-side change is suspected. + +**Idempotency.** The call only reads. Repeating it is safe. + +## How you know it worked + +You receive HTTP 200 with at least one linked policy for the identifier. + +You hold a processing participant code, a member id and a product for the patient. A [`/participant/search`](participant-search.md) on the processing code shows status `Active`. + +## When it goes wrong + +- **Messages to the payer fail with a receiver error.** The payer id went into `x-hcx-recipient_code`. Use the processing id from this response. See [NHCX-1003](../errors/nhcx-1003.md) and [PAYR-1331](../errors/payr-1331.md). +- **Nothing is returned for an ABHA number.** The number went with hyphens. Send 14 digits without hyphens. If it is still empty, try `MemberId`, then `MobileNo`. +- **Nothing is returned for any identifier.** No payer has linked this beneficiary. The payer links with [`/participant/link/abha/policy`](participant-link-abha-policy.md). +- **A de-linked policy still appears.** Your cache is stale. Refresh the lookup for this patient. +- **401 Unauthorized.** The token is missing, has expired, or went out without the `Bearer ` prefix. Mint a new token, then retry the call once. See [NHCX-401](../errors/nhcx-401.md) and [every call returns 401](../troubleshooting/everything-returns-401.md). diff --git a/catalogue/nhcx/endpoints/participant-link-abha-policy.md b/catalogue/nhcx/endpoints/participant-link-abha-policy.md new file mode 100644 index 000000000..b1f2ec7e5 --- /dev/null +++ b/catalogue/nhcx/endpoints/participant-link-abha-policy.md @@ -0,0 +1,129 @@ +--- +id: nhcx.endpoint.participant-link-abha-policy +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /participant/link/abha/policy +summary: >- + As a payer, link a beneficiary's health account number and member id to the products + they hold, so hospitals can find the policy. +sources: +- url: https://hcxsbx.abdm.gov.in/images/539853c50347b32b9a5e.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Policy Linking and De-Linking Process.pdf + hash: sha256:420115b9a54e15fa625312a56362164d92d23dd0d6ebf9195135bb00055d1911 + fetched: '2026-09-14' + note: Policy Linking and De-Linking Process, row 8 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1 Policy Linking Process; Page 2 request. +- url: https://hcxsbx.abdm.gov.in/images/b885e59891fedc7e725c.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-PARTICIPANT SERVICE_APIs Postman Collection.zip + hash: sha256:2d082f244ee41d137a62af82380dcd2d5db9ebbab66824fd54a23c506d4d9a7f + fetched: '2026-09-14' + note: AWS(Sandbox)-PARTICIPANT SERVICE_APIs Postman Collection, row 16 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Postman SANDBOX-Participant_APIs item Link Abha. +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./participant/link/abha/policy.post; schemas ParticipantLinkAbhaRequest, ParticipantLinkAbhaResponse.' +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 2, item 10 Policy Linking/Delinking auth restriction. +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1, Use case 1 Link ABHA with Policy. +verified: + status: unverified +related: + concepts: + - nhcx.concept.policy-linking + flows: + - nhcx.flow.policy-link-and-delink + endpoints: + - nhcx.endpoint.v2-participant-link-abha-policy + - nhcx.endpoint.participant-get-policies + - nhcx.endpoint.participant-delink-abha-policy + - nhcx.endpoint.session-token + errors: + - nhcx.error.nhcx-401 + tests: + - nhcx.test.payer-uc-01 +--- + +# POST /participant/link/abha/policy + +## In plain words + +A [payer](../glossary/payer.md) calls this to link a beneficiary's [ABHA number](../../shared/glossary/abha-number.md) and member id to the products the beneficiary holds. Hospitals then find the policy with [`/participant/get/policies`](participant-get-policies.md). Without a link, a hospital's lookup returns nothing and the patient cannot be processed as cashless on [NHCX](../../shared/glossary/nhcx.md). + +Link ABHA with Policy is use case 1 of the payer [sandbox exit](../glossary/sandbox-exit.md). Call this path. [`/V2/participant/link/abha/policy`](v2-participant-link-abha-policy.md) takes the same body. See [policy linking](../concepts/policy-linking.md). + +## Before you start + +- Your insurance company is registered and holds its own [participant code](../glossary/participant-code.md). If a [TPA](../glossary/tpa.md) processes your claims, the TPA holds its own code too. +- A current access token minted with the client id that was used when the insurer or the TPA participant was created. It goes in `bearer_auth` as `Bearer `. +- The beneficiary's ABHA number, mobile number, member id and products. + +## What happens + +Your system posts the link to the participant service. The registry records it and answers on the same connection. No callback follows. + +| Environment | Participant service base URL | +|---|---| +| Sandbox | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice` | +| Production | `https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice` | + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/participant/link/abha/policy' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -d '{ + "requestid": "", + "abhanumber": "", + "mobilenumber": "", + "memberid": "", + "payerid": "", + "processingid": "", + "policies": [ + { + "productid": "", + "productname": "" + } + ] + }' +``` + +Send all three headers on every participant service call: `Accept`, `Content-Type` and `bearer_auth`. The token header is `bearer_auth`, not `Authorization`. + +| Field | What to send | +|---|---| +| `requestid` | A new UUID for every call. | +| `abhanumber` | The policy holder's 14-digit ABHA number, without hyphens. | +| `mobilenumber` | The policy holder's mobile number. | +| `memberid` | The policy holder id in your system. | +| `payerid` | The insurance company's own participant code. Every payer has one, even under a TPA. | +| `processingid` | The participant code of the TPA that processes this insurer's claims. | +| `policies` | One entry per product, each with `productid` and `productname`. | + +For an insurer without a TPA, `payerid` is the insurer's own participant code. When an insurer moves to a new TPA, de-link its policies with [`/participant/delink/abha/policy`](participant-delink-abha-policy.md), then link them again with the new TPA's code in `processingid`. + +The response is JSON with a `result` string. + +**Idempotency.** Send a new `requestid` on every call and log it with the response. Before you retry a link that timed out, look the beneficiary up with [`/participant/get/policies`](participant-get-policies.md). Link again only if the products are missing. + +## How you know it worked + +You receive HTTP 200 with a `result` string. + +[`/participant/get/policies`](participant-get-policies.md) with `identifiertype` `AbhaNumber` and the same ABHA number returns the products you linked. + +## When it goes wrong + +- **The link is refused although the token is valid.** Only the participants named as `payerid` or `processingid` may link. The token must come from the client id used when that participant was created. +- **`payerid` and `processingid` are swapped.** `payerid` is always the insurer. `processingid` is the TPA. +- **Moving to a new TPA by linking again.** De-link the existing policies first, then link with the new `processingid`. +- **400 Client error.** A required field is missing, or `requestid` is not a UUID. +- **401 Unauthorized.** The token is missing, has expired, or went out without the `Bearer ` prefix. Mint a new token, then retry the call once. See [NHCX-401](../errors/nhcx-401.md) and [every call returns 401](../troubleshooting/everything-returns-401.md). diff --git a/catalogue/nhcx/endpoints/participant-search.md b/catalogue/nhcx/endpoints/participant-search.md new file mode 100644 index 000000000..4de1bcec7 --- /dev/null +++ b/catalogue/nhcx/endpoints/participant-search.md @@ -0,0 +1,120 @@ +--- +id: nhcx.endpoint.participant-search +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /participant/search +summary: >- + Read one participant's full registry record by its participant code. +sources: +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./participant/search.post; schemas ParticipantSearchReq, ParticipantSearchResponse, ParticipantSearchRequest.' +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/registries + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__registries.md + hash: sha256:04bf78739fa0c3807a8a5a49d8c3e004f8aba664f524d0344d7fc44c3b2baf42 + fetched: '2026-09-14' + note: Site page /technical-specifications/open-protocol/registries, text as shown on the site. Participating Organisations/Systems Registry table. +- url: https://hcxsbx.abdm.gov.in/images/539853c50347b32b9a5e.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Policy Linking and De-Linking Process.pdf + hash: sha256:420115b9a54e15fa625312a56362164d92d23dd0d6ebf9195135bb00055d1911 + fetched: '2026-09-14' + note: Policy Linking and De-Linking Process, row 8 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1, For Sandbox / For Production envBaseUrl. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 2, item 6 Missing the Accept parameter. +verified: + status: unverified +related: + concepts: + - nhcx.concept.participant-registry + - nhcx.concept.participant-code + endpoints: + - nhcx.endpoint.participant-details + - nhcx.endpoint.fetch-participants-list + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.session-token + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1003 + sandbox: + - nhcx.sandbox.environments-and-base-urls +--- + +# POST /participant/search + +## In plain words + +This call reads one participant's record from the [NHCX](../../shared/glossary/nhcx.md) [participant registry](../concepts/participant-registry.md). You send a [participant code](../glossary/participant-code.md). You get back the roles, status, bridge URL and certificate reference held for that code. + +Use it before you address a new counterparty, and after every change to your own record. [`/participant/details`](participant-details.md) takes the same body and returns the same record. Use one of the two paths consistently. + +## Before you start + +- A current access token from the [session call](session-token.md). It goes in the `bearer_auth` header as `Bearer `, with `Bearer` and a space in front. +- The participant code you want to read, usually from [`/fetch/participants/list`](fetch-participants-list.md). + +## What happens + +Your system posts the code to the participant service. The registry answers on the same connection. Nothing changes and no callback follows. + +| Environment | Participant service base URL | +|---|---| +| Sandbox | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice` | +| Production | `https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice` | + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/participant/search' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -d '{ + "participant_code": "" + }' +``` + +Send all three headers on every participant service call: `Accept`, `Content-Type` and `bearer_auth`. The token header is `bearer_auth`, not `Authorization`. + +The response body has this shape: + +```json +{ + "timestamp": , + "participants": [ + { + "participant_code": "", + "participant_name": "", + "linked_registry_codes": [""], + "scheme_code": "", + "roles": [""], + "status": [""], + "primaryEmail": "", + "primaryMobile": "", + "encryption_cert": "", + "endpoint_url": "" + } + ] +} +``` + +`status` is one of `Created` (not yet verified), `Active`, `Inactive` or `Blocked`. `encryption_cert` is a reference to the certificate. To get the certificate itself, call [`/fetch/certs`](fetch-certs.md). + +**Idempotency.** The call only reads. Repeating it is safe. + +## How you know it worked + +You receive HTTP 200 with a `participants` array. One entry carries the `participant_code` you sent. + +A counterparty is ready to receive messages when its entry shows status `Active`, the role you expect, and a filled `endpoint_url` and `encryption_cert`. + +## When it goes wrong + +- **400 or an empty result.** The body used `participantid` or `participantcode`. This call takes `participant_code`. +- **No entry for the code.** The code is wrong or not registered. Messages addressed to it fail with [NHCX-1003](../errors/nhcx-1003.md). Pick the code again from [`/fetch/participants/list`](fetch-participants-list.md). +- **Status is not `Active`.** The participant cannot transact yet. Do not address it. +- **401 Unauthorized.** The token is missing, has expired, or went out without the `Bearer ` prefix. Mint a new token, then retry the call once. See [NHCX-401](../errors/nhcx-401.md) and [every call returns 401](../troubleshooting/everything-returns-401.md). diff --git a/catalogue/nhcx/endpoints/participant-update.md b/catalogue/nhcx/endpoints/participant-update.md new file mode 100644 index 000000000..89a6b2a6d --- /dev/null +++ b/catalogue/nhcx/endpoints/participant-update.md @@ -0,0 +1,120 @@ +--- +id: nhcx.endpoint.participant-update +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /participant/update +summary: >- + Change your sandbox registry record, such as your bridge address or encryption + certificate. +sources: +- url: https://hcxsbx.abdm.gov.in/images/e683dda0a8cf953abbc7.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)NHCX-OnBoarding APIs Postman Collection.zip + hash: sha256:ca4348e8a373c54bdcabd07eff8e49a55d93cdfae65fa5008ae0d56526a769f2 + fetched: '2026-09-14' + note: AWS(Sandbox)NHCX-OnBoarding APIs Postman Collection, row 6 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Postman SANDBOX_NHCX-OnBoarding APIs item Participant Update. +- url: https://hcxsbx.abdm.gov.in/images/bc2efb078b98548f8e6b.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Sandbox.pdf + hash: sha256:cbd03baf428655f0305e2f60ca331f8b76700496b070c522cafcc95001710b3a + fetched: '2026-09-14' + note: Onboarding providers and payers in Sandbox, row 4 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 2-3, API Definition - Update Participant. +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./participant/update.post; schema ParticipantUpdateBody.' +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 5, Q21 Not getting call back on my server. +verified: + status: unverified +related: + concepts: + - nhcx.concept.participant-registry + - nhcx.concept.encryption-certificate + flows: + - nhcx.flow.sandbox-onboarding + - nhcx.flow.rotate-certificate + endpoints: + - nhcx.endpoint.v2-participant-update + - nhcx.endpoint.v2-update-cert + - nhcx.endpoint.participant-create + - nhcx.endpoint.participant-search + - nhcx.endpoint.fetch-certs + errors: + - nhcx.error.nhcx-401 + troubleshooting: + - nhcx.troubleshooting.callback-url-rejected + - nhcx.troubleshooting.recipient-cannot-decrypt + sandbox: + - nhcx.sandbox.callback-url-requirements +--- + +# POST /participant/update + +## In plain words + +This call changes your record in the [NHCX](../../shared/glossary/nhcx.md) participant registry. Use it to move your bridge URL, replace your encryption certificate or change any other attribute. `participant_code` is mandatory in every request. + +This is the sandbox update call. In production, call [`/v2/participant/update`](v2-participant-update.md) and confirm it with [`/update/validate`](update-validate.md). For a production certificate change without a passcode, call [`/v2/update/cert`](v2-update-cert.md). + +## Before you start + +- Your [participant code](../glossary/participant-code.md) from [`/participant/create`](participant-create.md). +- A current access token from the [session call](session-token.md). It goes in the `bearer_auth` header as `Bearer `, with `Bearer` and a space in front. +- For a new certificate: the Base64 certificate, with its private key already deployed where you decrypt inbound messages. See [rotate a certificate](../flows/rotate-certificate.md). +- For a new bridge URL: the new host is live on a domain name in India. Your firewall lets the NHCX NAT addresses through. See [callback URL requirements](../sandbox/callback-url-requirements.md). + +## What happens + +Your system posts the record to the sandbox participant service. The registry validates the linked registry codes, applies the change and answers on the same connection. No callback follows. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/participant/update' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -d '{ + "participant_code": "", + "participant_name": "", + "scheme_code": "", + "roles": [""], + "primaryEmail": "", + "phone": [""], + "primaryMobile": "", + "signing_cert_path": "", + "encryption_cert": "", + "endpoint_url": "" + }' +``` + +Send all three headers on every participant service call: `Accept`, `Content-Type` and `bearer_auth`. The token header is `bearer_auth`, not `Authorization`. + +The field names are snake_case, as in [`/participant/create`](participant-create.md). Role codes are listed there. + +The response body has this shape: + +```json +{ + "participant_code": "" +} +``` + +**Idempotency.** Send the values you want the record to hold. Before you retry an update that timed out, read your record with [`/participant/search`](participant-search.md) and compare. + +## How you know it worked + +You receive HTTP 200 with your own `participant_code` in the body. + +[`/participant/search`](participant-search.md) with your code returns the new `endpoint_url` or `encryption_cert`. After a certificate change, [`/fetch/certs`](fetch-certs.md) with your code returns the new certificate. + +## When it goes wrong + +- **400 Client error.** A field name came from the v2 body, such as `participantcode`, `encryptioncert` or `endpointurl`. Use the snake_case names above. A missing `Accept` header also fails the call. +- **Inbound messages stop decrypting after a certificate change.** The new certificate went live before its private key did. Deploy the key first. See [recipient cannot decrypt](../troubleshooting/recipient-cannot-decrypt.md). +- **Messages stop arriving after a bridge change.** The new `endpoint_url` uses an IP address or a port, or the host is outside India. See [callback URL rejected](../troubleshooting/callback-url-rejected.md). +- **404 Resource not found.** The `participant_code` is wrong. Copy it from the create response. +- **401 Unauthorized.** The token is missing, has expired, or went out without the `Bearer ` prefix. Mint a new token, then retry the call once. See [NHCX-401](../errors/nhcx-401.md) and [every call returns 401](../troubleshooting/everything-returns-401.md). diff --git a/catalogue/nhcx/endpoints/payer-service-get-user-role.md b/catalogue/nhcx/endpoints/payer-service-get-user-role.md new file mode 100644 index 000000000..eb8b39605 --- /dev/null +++ b/catalogue/nhcx/endpoints/payer-service-get-user-role.md @@ -0,0 +1,112 @@ +--- +id: nhcx.endpoint.payer-service-get-user-role +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /pmjay/sbxhcx/nhcxpayerservice/v1/get/user-role +summary: >- + Find out which desk in the government scheme's case system currently holds a case, + and so which actions it can take next. +sources: +- file: catalogue/openapi/.raw/nhcx-site-2026-09-14/not-on-site/External_NHCX_Payer_Service_API_Workflow_Guide.docx + hash: sha256:1028d480d2fabe3204301f1c1b192a0077ddfa64f7f9084b01f73e004253fdd7 + fetched: '2026-09-05' + note: NHCX Payer Service API Workflow Guide for External Integrators, not listed on hcxsbx.abdm.gov.in and not named in the NHCX document sheet, received separately. Get User Role API (Mandatory for Claims); role table. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. page 9-10, sections 3 and 4.2. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.payer-service-get-user-role + - nhcx.endpoint.payer-service-process-case + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + - nhcx.endpoint.session-token + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + concepts: + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.payer-process-a-request + - nhcx.flow.pmjay-patient-to-cashless + decisions: + - nhcx.decision.payer-implementation + glossary: + - nhcx.glossary.sha + - nhcx.glossary.tms + - nhcx.glossary.pmjay + errors: + - nhcx.error.payr-1238 +--- + +# POST /pmjay/sbxhcx/nhcxpayerservice/v1/get/user-role + +## In plain words + +[PMJAY](../glossary/pmjay.md) cases are not decided over [NHCX](../../shared/glossary/nhcx.md). The PMJAY payer service holds each PMJAY case in the [State Health Agency](../glossary/sha.md)'s [Transaction Management System](../glossary/tms.md). A case moves when the role that holds it acts on it. This call tells you which role holds a case now. Only that role's actions are accepted next. + +You call it as an integrator working a PMJAY case through the PMJAY payer service. In the sandbox, it moves a case your hospital system submitted. It is specific to that service. Other payers do not expose it. Call it before every [act on a case](payer-service-process-case.md) call, and whenever a case has gone quiet. + +## Before you start + +- A session token, sent on `bearer_auth`. See [the session token](../concepts/session-token.md). +- The scheme's case ID for the case, not your hospital's claim number. It appears in the payer's acknowledgement and status answers once a request is accepted. +- The PMJAY payer's code, written without `@hcx`. + +## What happens + +Your system calls the PMJAY payer service directly, on the sandbox host. There is no JWE envelope and no callback. + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/nhcxpayerservice/v1/get/user-role' \ + --header 'accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --data-raw '{ + "caseid": "", + "payerid": "" + }' +``` + +The role in the answer is one of these: + +| Step | Role | Actions | `usecase` | +|---|---|---|---| +| Pre-authorisation | `PPD-Trust` | `Approve`, `Reject`, `Query` | `PREAUTH` | +| Claim 1 | `CEX-Trust` | `Forward` | `CLAIM` | +| Claim 2 | `CPD-Trust` | `cpdApprove`, `cpdReject`, `Pending` | `CLAIM` | +| Claim 3 | `Medical Audit Committee` | `Approve`, `Reject`, `iQuery` | `Medical Audit Committee` | +| Claim 4 | `ACO-Trust` | `Approve`, `Reject`, `Pending` | `CLAIM` | +| Claim 5 | `SHA-Trust` | `Approve`, `Reject`, `Pending` | `CLAIM` | +| Claim 6 | `Claim Review Committee` | `Approve`, `Reject`, `Pending` | `Claim Review Committee` | + +**Retrying.** The call only reads, so repeat it freely. Read the role again before every action and after it. + +## How you know it worked + +You receive a JSON body naming the role that holds the case: + +```json +{ + "currentuserrole": "PPD-Trust", + "errormessage": null +} +``` + +- `currentuserrole` is set and `errormessage` is empty. +- Once the case is decided, the answer carries no role. + +The step is done when you hold the current role. Act on the case only with that role's actions. + +## When it goes wrong + +- The answer reads `No Data found with the caseid . Please use the current active case id.`: you sent your hospital's claim number. Send the scheme's case ID. +- `PPD-Trust` comes back while you ask about a claim: the case has not left the pre-authorisation queue yet. +- A later request for the same beneficiary is refused with [`PAYR-1238`](../errors/payr-1238.md). The refusal names the active case; use that case ID here. diff --git a/catalogue/nhcx/endpoints/payer-service-process-case.md b/catalogue/nhcx/endpoints/payer-service-process-case.md new file mode 100644 index 000000000..030bc901b --- /dev/null +++ b/catalogue/nhcx/endpoints/payer-service-process-case.md @@ -0,0 +1,115 @@ +--- +id: nhcx.endpoint.payer-service-process-case +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /pmjay/hcx/nhcxpayerservice/wrapper/process/case +summary: >- + Approve, reject, query or forward a government scheme case as the desk that currently + holds it, so the decision flows back to the hospital. +sources: +- file: catalogue/openapi/.raw/nhcx-site-2026-09-14/not-on-site/External_NHCX_Payer_Service_API_Workflow_Guide.docx + hash: sha256:1028d480d2fabe3204301f1c1b192a0077ddfa64f7f9084b01f73e004253fdd7 + fetched: '2026-09-05' + note: NHCX Payer Service API Workflow Guide for External Integrators, not listed on hcxsbx.abdm.gov.in and not named in the NHCX document sheet, received separately. Common Processing Endpoint; Example CURLs PREAUTH and CLAIM Steps 1-6; Important Notes. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. page 9-10, sections 3 and 4.2. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.payer-service-get-user-role + - nhcx.endpoint.payer-service-process-case + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + - nhcx.endpoint.session-token + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + concepts: + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.payer-process-a-request + - nhcx.flow.pmjay-patient-to-cashless + decisions: + - nhcx.decision.payer-implementation + glossary: + - nhcx.glossary.sha + - nhcx.glossary.tms + - nhcx.glossary.pmjay +--- + +# POST /pmjay/hcx/nhcxpayerservice/wrapper/process/case + +## In plain words + +[PMJAY](../glossary/pmjay.md) cases are not decided over [NHCX](../../shared/glossary/nhcx.md). The PMJAY payer service holds each PMJAY case in the [State Health Agency](../glossary/sha.md)'s [Transaction Management System](../glossary/tms.md). A case moves when the role that holds it acts on it. This call takes that action: approve, reject, query, forward or hold, as the role that holds the case. + +You call it as an integrator working a PMJAY case through the PMJAY payer service. In the sandbox, it moves a case your hospital system submitted. It is specific to that service. Other payers do not expose it. + +## Before you start + +- A session token, sent on `bearer_auth`. See [the session token](../concepts/session-token.md). +- The current role for the case, read immediately before this call with [the role lookup](payer-service-get-user-role.md). +- The scheme's case ID, the beneficiary's member ID, the payer code and your provider participant code. Write both codes without `@hcx`. + +## What happens + +Your system calls the PMJAY payer service directly. The action call and the role lookup sit on different hosts. Use each exactly as shown. + +```bash +curl --location --request POST 'https://apisbeta.nha.gov.in/pmjay/hcx/nhcxpayerservice/wrapper/process/case' \ + --header 'Accept: application/json' \ + --header 'bearer_auth: Bearer ' \ + --header 'Content-Type: application/json' \ + --data-raw '{ + "casenumber": "", + "action": "Approve", + "receivercode": "", + "usecase": "PREAUTH", + "correlationid": "", + "sendercode": "", + "memberid": "", + "remarks": "" + }' +``` + +Spell `action` and `usecase` exactly as the holding role takes them. Both are case-sensitive: + +| Step | Role | Actions | `usecase` | +|---|---|---|---| +| Pre-authorisation | `PPD-Trust` | `Approve`, `Reject`, `Query` | `PREAUTH` | +| Claim 1 | `CEX-Trust` | `Forward` | `CLAIM` | +| Claim 2 | `CPD-Trust` | `cpdApprove`, `cpdReject`, `Pending` | `CLAIM` | +| Claim 3 | `Medical Audit Committee` | `Approve`, `Reject`, `iQuery` | `Medical Audit Committee` | +| Claim 4 | `ACO-Trust` | `Approve`, `Reject`, `Pending` | `CLAIM` | +| Claim 5 | `SHA-Trust` | `Approve`, `Reject`, `Pending` | `CLAIM` | +| Claim 6 | `Claim Review Committee` | `Approve`, `Reject`, `Pending` | `Claim Review Committee` | + +**Idempotency.** Use a new UUID in `correlationid` on every call. It is not the correlation id of the NHCX request. Read the role again before a repeat: if it has moved, the earlier call took effect. + +## How you know it worked + +The call answers synchronously, for example: + +```json +{ + "status": "success", + "message": "Case processed" +} +``` + +The step is done when the scheme's verdict reaches the provider over NHCX: a `ClaimResponse` on [`/v1/preauth/on_submit`](../callbacks/preauth-on-submit.md) or [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md), on the original request's correlation id. For a claim, repeat the lookup and the action for each role until the lookup returns no role. + +## When it goes wrong + +- `Approve` sent to `CPD-Trust`: that role takes `cpdApprove` and `cpdReject`. +- `usecase` `CLAIM` sent at a committee: each committee takes its full name, with spaces. +- The action is refused for the role: the case has moved. Read the role again. +- `Event Meta Log not found for correlationId`: NHCX has not finished delivering the request. Retry shortly. +- `Case not found for caseId`: the case is still being filed. Retry shortly. diff --git a/catalogue/nhcx/endpoints/paymentnotice-on-request.md b/catalogue/nhcx/endpoints/paymentnotice-on-request.md new file mode 100644 index 000000000..1683fcb3b --- /dev/null +++ b/catalogue/nhcx/endpoints/paymentnotice-on-request.md @@ -0,0 +1,192 @@ +--- +id: nhcx.endpoint.paymentnotice-on-request +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /v1/paymentnotice/on_request +summary: >- + Confirm to an insurer, through the claims exchange, that your hospital has received + and recorded a payment notice. +sources: +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 11.6 Payment Acknowledgement bundle; Implementation notes. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: 'NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet: PaymentNotice, /v1/paymentnotice/on_request rows.' +- url: https://hcxsbx.abdm.gov.in/servicehcxpayment/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/servicehcxpayment.json + hash: sha256:f5c9e3728efbbeaa5e0e8083334b0ae60a05930e5a1e096ca06d40abb235d658 + fetched: '2026-09-14' + note: 'API specification: servicehcxpayment, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/paymentnotice/on_request.post.' +- url: https://hcxsbx.abdm.gov.in/images/bc1e7d077857fc0fa071.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-NHCX USECASE Postman Collection.zip + hash: sha256:9d15daafa813d6d57e688fe800baa5a73d2540b8d0d12c6a1315f86a424817e4 + fetched: '2026-09-14' + note: AWS(Sandbox)-NHCX USECASE Postman Collection, row 17 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item /v1/paymentnotice/on_request. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1 Acceptance and Error scenario; page 2. +- url: https://hcxsbx.abdm.gov.in/images/c42ad170f37c987ed173.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx + hash: sha256:f56dd156c232192296082f23b1561d0ff11fd40992e6675de41c5c991d579e6d + fetched: '2026-09-14' + note: Workflow Status Sheets(with Codes), row 12 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet1, workflow id 17. +- url: https://hcxsbx.abdm.gov.in/images/b7260763ce8270b6baac.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Payment.pdf + hash: sha256:6d372cdeec0abaea66b4d267c5ee6137a01830c577360dba7699e0244e49615f + fetched: '2026-09-14' + note: Payment, listed on https://hcxsbx.abdm.gov.in/#/documents, not named in the NHCX document sheet. page 2, items 4 to 6. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 4, Q14. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.paymentnotice-request + - nhcx.endpoint.dummy-payer-paymentnotice-init + - nhcx.endpoint.session-token + - nhcx.endpoint.fetch-certs + callbacks: + - nhcx.callback.paymentnotice-request + - nhcx.callback.paymentnotice-on-request + - nhcx.callback.error + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1012 + - nhcx.error.payr-1517 + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.four-message-legs + - nhcx.concept.retries-and-expiry + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.payment-notice + fhir: + - nhcx.fhir.payment-notice + tests: + - nhcx.test.provider-uc-11 + sandbox: + - nhcx.sandbox.dummy-payer + troubleshooting: + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.everything-returns-401 +--- + +# POST /v1/paymentnotice/on_request + +## In plain words + +When a payer sends you a payment notice, you acknowledge it here. Your system, as the provider, sends a sealed Task bundle to [NHCX](../../shared/glossary/nhcx.md) saying the payment is acknowledged for that claim. NHCX delivers it to the payer. The acknowledgement closes the payment for the claim on both sides. + +Send it after you have stored the amount, deductions and bank reference against the claim. + +## Before you start + +- A session token that has not expired. See [the session token](../concepts/session-token.md). +- The `/v1/paymentnotice/request` you are answering, received on [your registered address](../callbacks/paymentnotice-request.md), decrypted, and acknowledged with 202 within 30 seconds. +- That request's `x-hcx-correlation_id` and `x-hcx-sender_code`, stored. You echo the first and address the answer to the second. +- The encryption certificate of the payer, fetched with [`/fetch/certs`](fetch-certs.md). +- A Task bundle with `status` `completed`, `output` `paymentack` and the claim number. See [the PaymentNotice bundle and its acknowledgement](../fhir/payment-notice.md). +- A handler for [`/v1/error`](../callbacks/error.md), where NHCX reports an answer it could not deliver. + +## What happens + +Your system, as the provider, answers a request it received ([receiving the request](../callbacks/paymentnotice-request.md)) by calling NHCX on `/v1/paymentnotice/on_request`. NHCX answers 202 at once and delivers the same path to the registered address of the payer ([receiving `/v1/paymentnotice/on_request`](../callbacks/paymentnotice-on-request.md)). + +### 1. Seal the answer + +Swap the sender and recipient codes of the request. Echo its correlation id. Put these values in the [JWE](../glossary/jwe.md) [protected header](../glossary/protected-header.md): + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-request_id": "", + "x-hcx-correlation_id": "", + "x-hcx-workflow_id": "17", + "x-hcx-timestamp": "", + "x-hcx-status": "response.complete", + "x-hcx-ben-abha-id": "" +} +``` + +Workflow `17` is payment received. Send `response.complete`. The `x-hcx-*` values ride inside the JWE [protected header](../glossary/protected-header.md), not as HTTP headers. [The protocol headers](../concepts/protocol-headers.md) explains each one, including the timestamp format. + +### 2. Send it + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/hcx/v1/paymentnotice/on_request' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --header 'Authorization: Bearer ' \ + --data-raw '{ + "type": "JWEPayload", + "payload": "" + }' +``` + +Send the token on both `bearer_auth` and `Authorization`, with the same value and the word `Bearer` in front. `` is your sealed message: five base64url parts joined by dots. See [the JWE envelope](../concepts/jwe-envelope.md). + +### 3. Refusing a request + +To refuse the request at protocol level instead, send `"type": "ProtocolResponse"` on this path with `x-hcx-status` `response.error` and `x-hcx-error_details` holding `code`, `message` and `trace`. Keep clinical and business reasons inside the sealed payload. Only protocol errors go in the header. + +### 4. Retrying + +**Idempotency.** Echo the `x-hcx-correlation_id` of the request you are answering. A correlation id NHCX does not hold, or one it has already deleted, is refused with [`NHCX-1010`](../errors/nhcx-1010.md). Generate a new `x-hcx-api_call_id` for every call. `/v1/status` looks a message up by that value ([`NHCX-1012`](../errors/nhcx-1012.md) when it cannot), so never reuse one. + +## How you know it worked + +You receive HTTP `202 Accepted` with this body: + +```json +{ + "timestamp": "
", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "payment", + "protocol_status": "request.dispatched" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `correlation_id` matches the request you answered, and `api_call_id` matches the value you sealed. +- `result.entity_type` is `payment`. +- `error.code` and `error.message` are empty. + +NHCX then delivers your answer to the payer. The recipient must answer each delivery with 202 and the acknowledgement body within 30 seconds. Otherwise NHCX retries up to five times, then deletes the request and reports it on the sender's [`/v1/error`](../callbacks/error.md). The step is done when you hold the 202 and no report for this correlation id arrives on your `/v1/error`. + +## When it goes wrong + +- [`NHCX-1010`](../errors/nhcx-1010.md): NHCX holds no request with that correlation id. You minted a new one instead of echoing it, or the request was deleted after failed deliveries. +- [`NHCX-1011`](../errors/nhcx-1011.md): `x-hcx-status` is not `response.complete`, `response.partial` or `response.error`. +- [`PAYR-1517`](../errors/payr-1517.md): a refusal arrived as a `JWEPayload`. Protocol refusals travel as `ProtocolResponse`. +- `401 Unauthorized`, or [`NHCX-401`](../errors/nhcx-401.md): get a new session token and send again. +- A report arrives on your [`/v1/error`](../callbacks/error.md): the requester's address did not acknowledge five deliveries. The request is dead on that correlation id. diff --git a/catalogue/nhcx/endpoints/paymentnotice-request.md b/catalogue/nhcx/endpoints/paymentnotice-request.md new file mode 100644 index 000000000..4bbae6697 --- /dev/null +++ b/catalogue/nhcx/endpoints/paymentnotice-request.md @@ -0,0 +1,189 @@ +--- +id: nhcx.endpoint.paymentnotice-request +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /v1/paymentnotice/request +summary: >- + Tell a hospital, through the claims exchange, that payment for an approved claim + has been started, processed or settled. +sources: +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: 'NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet: PaymentNotice, /v1/paymentnotice/request rows.' +- url: https://hcxsbx.abdm.gov.in/servicehcxpayment/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/servicehcxpayment.json + hash: sha256:f5c9e3728efbbeaa5e0e8083334b0ae60a05930e5a1e096ca06d40abb235d658 + fetched: '2026-09-14' + note: 'API specification: servicehcxpayment, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/paymentnotice/request.post.' +- url: https://hcxsbx.abdm.gov.in/images/bc1e7d077857fc0fa071.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-NHCX USECASE Postman Collection.zip + hash: sha256:9d15daafa813d6d57e688fe800baa5a73d2540b8d0d12c6a1315f86a424817e4 + fetched: '2026-09-14' + note: AWS(Sandbox)-NHCX USECASE Postman Collection, row 17 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item /v1/paymentnotice/request. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Acceptance scenario. +- url: https://hcxsbx.abdm.gov.in/images/c42ad170f37c987ed173.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx + hash: sha256:f56dd156c232192296082f23b1561d0ff11fd40992e6675de41c5c991d579e6d + fetched: '2026-09-14' + note: Workflow Status Sheets(with Codes), row 12 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet1, workflow ids 30, 31 and 33. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 11.4 API and workflow codes; Implementation notes. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2 Q3; page 4 Q12 and Q14. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. items 6 and 8. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.paymentnotice-on-request + - nhcx.endpoint.claim-on-submit + - nhcx.endpoint.dummy-payer-paymentnotice-init + - nhcx.endpoint.session-token + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.status + callbacks: + - nhcx.callback.paymentnotice-request + - nhcx.callback.paymentnotice-on-request + - nhcx.callback.error + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1003 + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1012 + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.four-message-legs + - nhcx.concept.claim-cycle + - nhcx.concept.workflow-codes + flows: + - nhcx.flow.payment-notice + fhir: + - nhcx.fhir.payment-notice + tests: + - nhcx.test.payer-uc-13 + sandbox: + - nhcx.sandbox.dummy-payer +--- + +# POST /v1/paymentnotice/request + +## In plain words + +A payment notice tells the hospital whether the money for an approved claim has moved. As a payer, you send a sealed Task bundle to [NHCX](../../shared/glossary/nhcx.md) with a PaymentNotice and a PaymentReconciliation. They carry the amount, the deductions and the bank reference, including the UTR once settled. The provider acknowledges on `/v1/paymentnotice/on_request`. + +Send one notice at each stage of the transfer. + +## Before you start + +- A session token that has not expired. See [the session token](../concepts/session-token.md) and [how to get one](session-token.md). +- Your own [participant code](../glossary/participant-code.md), with your callback address registered, reachable from NHCX and answering 202 within 30 seconds. See [callback URL rules](../sandbox/callback-url-requirements.md). +- The provider's participant code: the sender code of the claim or pre-authorisation this message concerns. +- The recipient's encryption certificate, fetched with [`/fetch/certs`](fetch-certs.md). You seal the message with its public key. +- A Task bundle in [FHIR](../../shared/glossary/fhir.md) with `code` `deliver`, a PaymentNotice and a PaymentReconciliation carrying status, payment date, amount and payment identifier. See [the PaymentNotice bundle](../fhir/payment-notice.md). +- A handler for [`/v1/error`](../callbacks/error.md), so a request NHCX cannot deliver does not look like one still under review. +- A claim you approved on [`/v1/claim/on_submit`](claim-on-submit.md) with `response.complete`. +- A handler for [`/v1/paymentnotice/on_request`](../callbacks/paymentnotice-on-request.md). + +## What happens + +Your system, as the payer, calls NHCX on `/v1/paymentnotice/request`. NHCX checks the envelope, answers 202 at once, and forwards the same path to the provider's registered address ([receiving `/v1/paymentnotice/request`](../callbacks/paymentnotice-request.md)). The provider answers later on [`/v1/paymentnotice/on_request`](../callbacks/paymentnotice-on-request.md), which NHCX delivers to you. + +### 1. Seal the message + +Put these values in the [JWE](../glossary/jwe.md) [protected header](../glossary/protected-header.md) and encrypt the bundle with the recipient's public key. + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-request_id": "", + "x-hcx-correlation_id": "", + "x-hcx-workflow_id": "30", + "x-hcx-timestamp": "", + "x-hcx-status": "request.initiated", + "x-hcx-ben-abha-id": "" +} +``` + +The `x-hcx-*` values ride inside the JWE [protected header](../glossary/protected-header.md), not as HTTP headers. [The protocol headers](../concepts/protocol-headers.md) explains each one, including the timestamp format. `x-hcx-workflow_id` is the stage: `30` payment initiated, `31` processed, `33` settled. The UTR goes in the `33` notice. + +### 2. Send it + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/hcx/v1/paymentnotice/request' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --header 'Authorization: Bearer ' \ + --data-raw '{ + "payload": "" + }' +``` + +Send the token on both `bearer_auth` and `Authorization`, with the same value and the word `Bearer` in front. `` is your sealed message: five base64url parts joined by dots. See [the JWE envelope](../concepts/jwe-envelope.md). + +### 3. Retrying + +**Idempotency.** NHCX keys every conversation on `x-hcx-correlation_id`. An initiating request that reuses a correlation id NHCX already holds is refused with [`NHCX-1006`](../errors/nhcx-1006.md). So a blind retry is not safe. If your call timed out, ask [`/v1/status`](status.md) before you resend. `/v1/status` finds a message by its `x-hcx-api_call_id` ([`NHCX-1012`](../errors/nhcx-1012.md) when it cannot), so generate a new one for every call, a retry included. After a request fails for good, NHCX makes its correlation id inactive. Start a new cycle with a new correlation id. + +## How you know it worked + +You receive HTTP `202 Accepted` with this body: + +```json +{ + "timestamp": "
", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "payment", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `correlation_id` and `api_call_id` match the values you sealed. +- `result.entity_type` is `payment`. +- `result.protocol_status` is `request.queued` or `request.dispatched`. +- `error.code` and `error.message` are empty. + +The 202 is a receipt, not a decision. NHCX never returns a decision synchronously. The step is done when [`/v1/paymentnotice/on_request`](../callbacks/paymentnotice-on-request.md) reaches your callback address with the same `x-hcx-correlation_id`, and your handler has answered it 202 within 30 seconds. + +## When it goes wrong + +- `401 Unauthorized`, or [`NHCX-401`](../errors/nhcx-401.md): get a new session token and send again. +- [`NHCX-1003`](../errors/nhcx-1003.md): the provider code is not registered in NHCX. +- [`NHCX-1006`](../errors/nhcx-1006.md): the correlation id was used before. Open the cycle with a new one. +- [`NHCX-1011`](../errors/nhcx-1011.md): `x-hcx-status` is not `request.initiated`. +- You got 202 and nothing more arrives. The provider's address may be unreachable. Check your [`/v1/error`](../callbacks/error.md) and ask [`/v1/status`](status.md). diff --git a/catalogue/nhcx/endpoints/preauth-on-submit.md b/catalogue/nhcx/endpoints/preauth-on-submit.md new file mode 100644 index 000000000..d05fb6e9a --- /dev/null +++ b/catalogue/nhcx/endpoints/preauth-on-submit.md @@ -0,0 +1,194 @@ +--- +id: nhcx.endpoint.preauth-on-submit +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /v1/preauth/on_submit +summary: >- + Send an insurer's decision on a pre-approval request back to the hospital through + the claims exchange. +sources: +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: 'NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet: Preauth, /v1/preauth/on_submit rows.' +- url: https://hcxsbx.abdm.gov.in/preauthhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/preauthhcxservice.json + hash: sha256:2e8c594c51d9640ae4a576be34a5d190614918d1e7697d6718bc91c31fa66948 + fetched: '2026-09-14' + note: 'API specification: preauthhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/preauth/on_submit.post.' +- url: https://hcxsbx.abdm.gov.in/images/bc1e7d077857fc0fa071.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-NHCX USECASE Postman Collection.zip + hash: sha256:9d15daafa813d6d57e688fe800baa5a73d2540b8d0d12c6a1315f86a424817e4 + fetched: '2026-09-14' + note: AWS(Sandbox)-NHCX USECASE Postman Collection, row 17 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item /v1/preauth/on_submit. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1 Acceptance and Error scenario; page 2. +- url: https://hcxsbx.abdm.gov.in/images/c42ad170f37c987ed173.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx + hash: sha256:f56dd156c232192296082f23b1561d0ff11fd40992e6675de41c5c991d579e6d + fetched: '2026-09-14' + note: Workflow Status Sheets(with Codes), row 12 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet1, workflow ids 20, 21, 22, 23, 24 and 241. +- url: https://hcxsbx.abdm.gov.in/images/3799f26f2a0b2c9a80c5.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Preauthorization.pdf + hash: sha256:75d5628e7dd8a8e1a55c4ab3836c0591088ba378a8cd498e8277d83911129439 + fetched: '2026-09-14' + note: Preauthorization, listed on https://hcxsbx.abdm.gov.in/#/documents, not named in the NHCX document sheet. page 2, items 5 and 6. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 8.2 Preauth Lifecycle; 8.5 Response ClaimResponse Bundle. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 4, Q14. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.communication-request + - nhcx.endpoint.session-token + - nhcx.endpoint.fetch-certs + callbacks: + - nhcx.callback.preauth-submit + - nhcx.callback.preauth-on-submit + - nhcx.callback.error + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1012 + - nhcx.error.payr-1517 + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.four-message-legs + - nhcx.concept.retries-and-expiry + - nhcx.concept.claim-cycle + - nhcx.concept.workflow-codes + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + fhir: + - nhcx.fhir.preauth-response + - nhcx.fhir.preauth-enhancement + tests: + - nhcx.test.payer-uc-09 + troubleshooting: + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.everything-returns-401 +--- + +# POST /v1/preauth/on_submit + +## In plain words + +This carries the payer's decision on a pre-authorisation: approved, partly approved, queried or rejected. As a payer, you send a sealed ClaimResponse bundle to [NHCX](../../shared/glossary/nhcx.md), which delivers it to the provider. An approval carries the `preAuthRef` the hospital needs for its claim. + +You call it after you have received a [`/v1/preauth/submit`](preauth-submit.md). You may call it more than once for one request, for example an acknowledgement first and the decision later. + +## Before you start + +- A session token that has not expired. See [the session token](../concepts/session-token.md). +- The `/v1/preauth/submit` you are answering, received on [your registered address](../callbacks/preauth-submit.md), decrypted, and acknowledged with 202 within 30 seconds. +- That request's `x-hcx-correlation_id` and `x-hcx-sender_code`, stored. You echo the first and address the answer to the second. +- The encryption certificate of the provider, fetched with [`/fetch/certs`](fetch-certs.md). +- A ClaimResponse bundle in [FHIR](../../shared/glossary/fhir.md), built as in [the preauthorisation response bundle](../fhir/preauth-response.md), with `preAuthRef` on an approval and `processNote` explaining any reduction. +- A handler for [`/v1/error`](../callbacks/error.md), where NHCX reports an answer it could not deliver. + +## What happens + +Your system, as the payer or a TPA acting for it, answers a request it received ([receiving the request](../callbacks/preauth-submit.md)) by calling NHCX on `/v1/preauth/on_submit`. NHCX answers 202 at once and delivers the same path to the registered address of the provider ([receiving `/v1/preauth/on_submit`](../callbacks/preauth-on-submit.md)). + +### 1. Seal the answer + +Swap the sender and recipient codes of the request. Echo its correlation id. Put these values in the [JWE](../glossary/jwe.md) [protected header](../glossary/protected-header.md): + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-request_id": "", + "x-hcx-correlation_id": "", + "x-hcx-workflow_id": "21", + "x-hcx-timestamp": "", + "x-hcx-status": "response.complete", + "x-hcx-ben-abha-id": "" +} +``` + +`x-hcx-workflow_id` names the outcome: `20` received, `21` approved, `23` rejected, `24` queried. For an enhancement, `22` approved and `241` queried. [Workflow codes](../concepts/workflow-codes.md) gives the status that goes with each. The `x-hcx-*` values ride inside the JWE [protected header](../glossary/protected-header.md), not as HTTP headers. [The protocol headers](../concepts/protocol-headers.md) explains each one, including the timestamp format. + +### 2. Send it + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/hcx/v1/preauth/on_submit' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --header 'Authorization: Bearer ' \ + --data-raw '{ + "type": "JWEPayload", + "payload": "" + }' +``` + +Send the token on both `bearer_auth` and `Authorization`, with the same value and the word `Bearer` in front. `` is your sealed message: five base64url parts joined by dots. See [the JWE envelope](../concepts/jwe-envelope.md). + +### 3. Refusing a request + +To refuse the request at protocol level instead, send `"type": "ProtocolResponse"` on this path with `x-hcx-status` `response.error` and `x-hcx-error_details` holding `code`, `message` and `trace`. Keep clinical and business reasons inside the sealed payload. Only protocol errors go in the header. + +### 4. Retrying + +**Idempotency.** Echo the `x-hcx-correlation_id` of the request you are answering. A correlation id NHCX does not hold, or one it has already deleted, is refused with [`NHCX-1010`](../errors/nhcx-1010.md). Generate a new `x-hcx-api_call_id` for every call. `/v1/status` looks a message up by that value ([`NHCX-1012`](../errors/nhcx-1012.md) when it cannot), so never reuse one. + +## How you know it worked + +You receive HTTP `202 Accepted` with this body: + +```json +{ + "timestamp": "
", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "preauth", + "protocol_status": "request.dispatched" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `correlation_id` matches the request you answered, and `api_call_id` matches the value you sealed. +- `result.entity_type` is `preauth`. +- `error.code` and `error.message` are empty. + +NHCX then delivers your answer to the provider. The recipient must answer each delivery with 202 and the acknowledgement body within 30 seconds. Otherwise NHCX retries up to five times, then deletes the request and reports it on the sender's [`/v1/error`](../callbacks/error.md). The step is done when you hold the 202 and no report for this correlation id arrives on your `/v1/error`. + +## When it goes wrong + +- [`NHCX-1010`](../errors/nhcx-1010.md): NHCX holds no request with that correlation id. You minted a new one instead of echoing it, or the request was deleted after failed deliveries. +- [`NHCX-1011`](../errors/nhcx-1011.md): `x-hcx-status` is not `response.complete`, `response.partial` or `response.error`. +- [`PAYR-1517`](../errors/payr-1517.md): a refusal arrived as a `JWEPayload`. Protocol refusals travel as `ProtocolResponse`. +- `401 Unauthorized`, or [`NHCX-401`](../errors/nhcx-401.md): get a new session token and send again. +- A report arrives on your [`/v1/error`](../callbacks/error.md): the requester's address did not acknowledge five deliveries. The request is dead on that correlation id. diff --git a/catalogue/nhcx/endpoints/preauth-submit.md b/catalogue/nhcx/endpoints/preauth-submit.md new file mode 100644 index 000000000..c41dd4fdf --- /dev/null +++ b/catalogue/nhcx/endpoints/preauth-submit.md @@ -0,0 +1,211 @@ +--- +id: nhcx.endpoint.preauth-submit +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /v1/preauth/submit +summary: >- + Ask an insurer, through the claims exchange, to approve a treatment before it + happens, and get a receipt while the decision follows later. +sources: +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: 'NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet: Preauth, /v1/preauth/submit rows.' +- url: https://hcxsbx.abdm.gov.in/preauthhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/preauthhcxservice.json + hash: sha256:2e8c594c51d9640ae4a576be34a5d190614918d1e7697d6718bc91c31fa66948 + fetched: '2026-09-14' + note: 'API specification: preauthhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/preauth/submit.post.' +- url: https://hcxsbx.abdm.gov.in/images/bc1e7d077857fc0fa071.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-NHCX USECASE Postman Collection.zip + hash: sha256:9d15daafa813d6d57e688fe800baa5a73d2540b8d0d12c6a1315f86a424817e4 + fetched: '2026-09-14' + note: AWS(Sandbox)-NHCX USECASE Postman Collection, row 17 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item /v1/preauth/submit. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Acceptance scenario. +- url: https://hcxsbx.abdm.gov.in/images/c42ad170f37c987ed173.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx + hash: sha256:f56dd156c232192296082f23b1561d0ff11fd40992e6675de41c5c991d579e6d + fetched: '2026-09-14' + note: Workflow Status Sheets(with Codes), row 12 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet1, workflow ids 12, 13 and 131. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2 Q3; page 4 Q12 and Q14. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. items 6, 7 and 8. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. page 5 table 5.1; page 6 API Flows. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.preauth-on-submit + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.participant-get-policies + - nhcx.endpoint.dummy-payer-process-request + - nhcx.endpoint.abha-biometric-auth-verify + - nhcx.endpoint.session-token + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.status + callbacks: + - nhcx.callback.preauth-submit + - nhcx.callback.preauth-on-submit + - nhcx.callback.communication-request + - nhcx.callback.error + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1003 + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1012 + - nhcx.error.payr-1001 + - nhcx.error.payr-1256 + - nhcx.error.payr-1238 + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.four-message-legs + - nhcx.concept.claim-cycle + - nhcx.concept.workflow-codes + - nhcx.concept.biometric-authentication + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.preauth-enhancement + - nhcx.fhir.query-update + tests: + - nhcx.test.provider-uc-07 + - nhcx.test.tc-pa-01 + - nhcx.test.tc-pa-02 + decisions: + - nhcx.decision.preauth-or-predetermination + sandbox: + - nhcx.sandbox.dummy-payer + - nhcx.sandbox.environments-and-base-urls + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback + - nhcx.troubleshooting.everything-returns-401 +--- + +# POST /v1/preauth/submit + +## In plain words + +Pre-authorisation is the hospital's request for the insurer's approval of a specific treatment before it is given. Your system, as the provider, sends a Claim bundle with `use` `preauthorization` to [NHCX](../../shared/glossary/nhcx.md), sealed for the payer. NHCX gives you a receipt at once. The decision arrives later on your `/v1/preauth/on_submit`. + +The same path carries a new request, a resubmission, an enhancement and your answer to a payer's query. `x-hcx-workflow_id` and `x-hcx-use_case` tell the payer which one it is. + +## Before you start + +- A session token that has not expired. See [the session token](../concepts/session-token.md) and [how to get one](session-token.md). +- Your own [participant code](../glossary/participant-code.md), with your callback address registered, reachable from NHCX and answering 202 within 30 seconds. See [callback URL rules](../sandbox/callback-url-requirements.md). +- The payer's participant code. Take it from `processingID` in the [`/participant/get/policies`](participant-get-policies.md) response, not from `PayerID`. +- The recipient's encryption certificate, fetched with [`/fetch/certs`](fetch-certs.md). You seal the message with its public key. +- A Claim bundle in [FHIR](../../shared/glossary/fhir.md) with `use` `preauthorization`, built as in [the preauthorisation request bundle](../fhir/preauth-request.md). Attach every document the eligibility answer or insurance plan asked for. +- A handler for [`/v1/error`](../callbacks/error.md), so a request NHCX cannot deliver does not look like one still under review. +- For a [PMJAY](../glossary/pmjay.md) case: a beneficiary token from [biometric authentication](abha-biometric-auth-verify.md), or the Authentication Consent questionnaire response. +- A handler for [`/v1/preauth/on_submit`](../callbacks/preauth-on-submit.md) and for [`/v1/communication/request`](../callbacks/communication-request.md), where payer queries can arrive. +- In the sandbox you can address the [dummy payer](../sandbox/dummy-payer.md), participant `1000003538@hcx`, which answers without a real insurer. + +## What happens + +Your system, as the provider, calls NHCX on `/v1/preauth/submit`. NHCX checks the envelope, answers 202 at once, and forwards the same path to the payer's registered address ([receiving `/v1/preauth/submit`](../callbacks/preauth-submit.md)). The payer answers later on [`/v1/preauth/on_submit`](../callbacks/preauth-on-submit.md), which NHCX delivers to you. + +### 1. Seal the message + +Put these values in the [JWE](../glossary/jwe.md) [protected header](../glossary/protected-header.md) and encrypt the bundle with the recipient's public key. + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-request_id": "", + "x-hcx-correlation_id": "", + "x-hcx-workflow_id": "12", + "x-hcx-use_case": "New", + "x-hcx-timestamp": "", + "x-hcx-status": "request.initiated", + "x-hcx-ben-abha-id": "" +} +``` + +The `x-hcx-*` values ride inside the JWE [protected header](../glossary/protected-header.md), not as HTTP headers. [The protocol headers](../concepts/protocol-headers.md) explains each one, including the timestamp format. Workflow `12` with use case `New` opens a new pre-authorisation. An enhancement is workflow `13` with use case `Enhancement`, and its query answer is `131`. Take the code for any other step from [workflow codes](../concepts/workflow-codes.md). Always send both headers, even though the envelope marks them optional. + +### 2. Send it + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/hcx/v1/preauth/submit' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --header 'Authorization: Bearer ' \ + --data-raw '{ + "payload": "" + }' +``` + +Send the token on both `bearer_auth` and `Authorization`, with the same value and the word `Bearer` in front. `` is your sealed message: five base64url parts joined by dots. See [the JWE envelope](../concepts/jwe-envelope.md). + +### 3. Retrying + +**Idempotency.** NHCX keys every conversation on `x-hcx-correlation_id`. An initiating request that reuses a correlation id NHCX already holds is refused with [`NHCX-1006`](../errors/nhcx-1006.md). So a blind retry is not safe. If your call timed out, ask [`/v1/status`](status.md) before you resend. `/v1/status` finds a message by its `x-hcx-api_call_id` ([`NHCX-1012`](../errors/nhcx-1012.md) when it cannot), so generate a new one for every call, a retry included. After a request fails for good, NHCX makes its correlation id inactive. Start a new cycle with a new correlation id. + +## How you know it worked + +You receive HTTP `202 Accepted` with this body: + +```json +{ + "timestamp": "
", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "preauth", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `correlation_id` and `api_call_id` match the values you sealed. +- `result.entity_type` is `preauth`. +- `result.protocol_status` is `request.queued` or `request.dispatched`. +- `error.code` and `error.message` are empty. + +The 202 is a receipt, not a decision. NHCX never returns a decision synchronously. The step is done when [`/v1/preauth/on_submit`](../callbacks/preauth-on-submit.md) reaches your callback address with the same `x-hcx-correlation_id`, and your handler has answered it 202 within 30 seconds. The payer may send an acknowledgement first and the decision later, each on the same correlation id. + +## When it goes wrong + +- [`PAYR-1256`](../errors/payr-1256.md): a new [PMJAY](../glossary/pmjay.md) pre-authorisation carries neither biometric authentication nor the consent questionnaire response. +- [`PAYR-1238`](../errors/payr-1238.md): the beneficiary already has an active pre-authorisation at this hospital. Cancel it or raise its claim first. +- `401 Unauthorized`, or [`NHCX-401`](../errors/nhcx-401.md): the session token expired or lacks the `Bearer ` prefix. Get a new token and send again. See [every call returns 401](../troubleshooting/everything-returns-401.md). +- [`NHCX-1003`](../errors/nhcx-1003.md): the recipient code is not registered. A provider used `PayerID` instead of `processingID`. +- [`NHCX-1006`](../errors/nhcx-1006.md): the correlation id was used before. Start the cycle with a new one. +- [`NHCX-1011`](../errors/nhcx-1011.md): `x-hcx-status` is not `request.initiated`. diff --git a/catalogue/nhcx/endpoints/predetermination-on-submit.md b/catalogue/nhcx/endpoints/predetermination-on-submit.md new file mode 100644 index 000000000..3ca9fad13 --- /dev/null +++ b/catalogue/nhcx/endpoints/predetermination-on-submit.md @@ -0,0 +1,153 @@ +--- +id: nhcx.endpoint.predetermination-on-submit +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /v1/predetermination/on_submit +summary: >- + Send an insurer's estimate for a planned treatment back to the hospital through + the claims exchange. +sources: +- url: https://hcxsbx.abdm.gov.in/images/bc1e7d077857fc0fa071.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-NHCX USECASE Postman Collection.zip + hash: sha256:9d15daafa813d6d57e688fe800baa5a73d2540b8d0d12c6a1315f86a424817e4 + fetched: '2026-09-14' + note: AWS(Sandbox)-NHCX USECASE Postman Collection, row 17 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item /v1/predetermination/on_submit. +- url: https://hcxsbx.abdm.gov.in/images/2c3fbb4e6b09f0834f69.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Implementation Guide for Adoption of FHIR in ABDM and NHCX.pdf + hash: sha256:549377c9c26b1bd23decac3a1b9e5ebedfdc8e0fe99e53ef733859b188f51366 + fetched: '2026-09-14' + note: Implementation Guide for Adoption of FHIR in ABDM and NHCX, row 14 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. API table, row 6. +- url: https://hcxsbx.abdm.gov.in/images/af8d243edcc2139a515d.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Usecases.pdf + hash: sha256:8709b2907a0d5a0dbb36f5e63ed8deae269e0c75372b05d71ce7380c8a0929e7 + fetched: '2026-09-14' + note: NHCX Usecases, row 1 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1 to 2, Predetermination Request Submission. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1 Acceptance and Error scenario; page 2. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 4, Q14. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.predetermination-submit + - nhcx.endpoint.session-token + - nhcx.endpoint.fetch-certs + callbacks: + - nhcx.callback.predetermination-submit + - nhcx.callback.predetermination-on-submit + - nhcx.callback.error + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1012 + - nhcx.error.payr-1517 + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.four-message-legs + - nhcx.concept.retries-and-expiry + flows: + - nhcx.flow.predetermination + fhir: + - nhcx.fhir.preauth-response + decisions: + - nhcx.decision.preauth-or-predetermination + troubleshooting: + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.everything-returns-401 +--- + +# POST /v1/predetermination/on_submit + +## In plain words + +This carries the payer's estimate for a proposed treatment. As a payer that supports predetermination, you send a sealed ClaimResponse with `use` `predetermination` to [NHCX](../../shared/glossary/nhcx.md), which delivers it to the provider. The estimate reserves nothing against the policy. + +You call it after you have received a [`/v1/predetermination/submit`](predetermination-submit.md). + +## Before you start + +- A session token that has not expired. See [the session token](../concepts/session-token.md). +- The `/v1/predetermination/submit` you are answering, received on [your registered address](../callbacks/predetermination-submit.md), decrypted, and acknowledged with 202 within 30 seconds. +- That request's `x-hcx-correlation_id` and `x-hcx-sender_code`, stored. You echo the first and address the answer to the second. +- The encryption certificate of the provider, fetched with [`/fetch/certs`](fetch-certs.md). +- A bundle with `ClaimResponse`, `Patient`, both `Organization` entries and `Coverage`. `ClaimResponse.use` is `predetermination` and the estimated benefit sits in `ClaimResponse.total` under category `benefit`. +- A handler for [`/v1/error`](../callbacks/error.md), where NHCX reports an answer it could not deliver. + +## What happens + +Your system, as the payer or a TPA acting for it, answers a request it received ([receiving the request](../callbacks/predetermination-submit.md)) by calling NHCX on `/v1/predetermination/on_submit`. NHCX answers 202 at once and delivers the same path to the registered address of the provider ([receiving `/v1/predetermination/on_submit`](../callbacks/predetermination-on-submit.md)). + +### 1. Seal the answer + +Swap the sender and recipient codes of the request. Echo its correlation id. Put these values in the [JWE](../glossary/jwe.md) [protected header](../glossary/protected-header.md): + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-request_id": "", + "x-hcx-correlation_id": "", + "x-hcx-timestamp": "", + "x-hcx-status": "response.complete", + "x-hcx-ben-abha-id": "" +} +``` + +Send `response.complete`. No workflow code applies. The `x-hcx-*` values ride inside the JWE [protected header](../glossary/protected-header.md), not as HTTP headers. [The protocol headers](../concepts/protocol-headers.md) explains each one, including the timestamp format. + +### 2. Send it + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/hcx/v1/predetermination/on_submit' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --header 'Authorization: Bearer ' \ + --data-raw '{ + "type": "JWEPayload", + "payload": "" + }' +``` + +Send the token on both `bearer_auth` and `Authorization`, with the same value and the word `Bearer` in front. `` is your sealed message: five base64url parts joined by dots. See [the JWE envelope](../concepts/jwe-envelope.md). + +### 3. Refusing a request + +To refuse the request at protocol level instead, send `"type": "ProtocolResponse"` on this path with `x-hcx-status` `response.error` and `x-hcx-error_details` holding `code`, `message` and `trace`. Keep clinical and business reasons inside the sealed payload. Only protocol errors go in the header. + +### 4. Retrying + +**Idempotency.** Echo the `x-hcx-correlation_id` of the request you are answering. A correlation id NHCX does not hold, or one it has already deleted, is refused with [`NHCX-1010`](../errors/nhcx-1010.md). Generate a new `x-hcx-api_call_id` for every call. `/v1/status` looks a message up by that value ([`NHCX-1012`](../errors/nhcx-1012.md) when it cannot), so never reuse one. + +## How you know it worked + +You receive HTTP `202 Accepted` with the acknowledgement body: `timestamp`, `api_call_id`, `correlation_id`, `result` and an empty `error`. + +- `correlation_id` matches the request you answered. +- `error.code` and `error.message` are empty. + +NHCX then delivers your answer to the provider. The recipient must answer each delivery with 202 and the acknowledgement body within 30 seconds. Otherwise NHCX retries up to five times, then deletes the request and reports it on the sender's [`/v1/error`](../callbacks/error.md). The step is done when you hold the 202 and no report for this correlation id arrives on your `/v1/error`. + +## When it goes wrong + +- [`NHCX-1010`](../errors/nhcx-1010.md): NHCX holds no request with that correlation id. You minted a new one instead of echoing it, or the request was deleted after failed deliveries. +- [`NHCX-1011`](../errors/nhcx-1011.md): `x-hcx-status` is not `response.complete`, `response.partial` or `response.error`. +- [`PAYR-1517`](../errors/payr-1517.md): a refusal arrived as a `JWEPayload`. Protocol refusals travel as `ProtocolResponse`. +- `401 Unauthorized`, or [`NHCX-401`](../errors/nhcx-401.md): get a new session token and send again. +- A report arrives on your [`/v1/error`](../callbacks/error.md): the requester's address did not acknowledge five deliveries. The request is dead on that correlation id. diff --git a/catalogue/nhcx/endpoints/predetermination-submit.md b/catalogue/nhcx/endpoints/predetermination-submit.md new file mode 100644 index 000000000..006a1f07f --- /dev/null +++ b/catalogue/nhcx/endpoints/predetermination-submit.md @@ -0,0 +1,158 @@ +--- +id: nhcx.endpoint.predetermination-submit +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /v1/predetermination/submit +summary: >- + Ask an insurer, through the claims exchange, what it would approve for a planned + treatment before the patient is admitted. +sources: +- url: https://hcxsbx.abdm.gov.in/images/bc1e7d077857fc0fa071.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-NHCX USECASE Postman Collection.zip + hash: sha256:9d15daafa813d6d57e688fe800baa5a73d2540b8d0d12c6a1315f86a424817e4 + fetched: '2026-09-14' + note: AWS(Sandbox)-NHCX USECASE Postman Collection, row 17 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item /v1/predetermination/submit. +- url: https://hcxsbx.abdm.gov.in/images/2c3fbb4e6b09f0834f69.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Implementation Guide for Adoption of FHIR in ABDM and NHCX.pdf + hash: sha256:549377c9c26b1bd23decac3a1b9e5ebedfdc8e0fe99e53ef733859b188f51366 + fetched: '2026-09-14' + note: Implementation Guide for Adoption of FHIR in ABDM and NHCX, row 14 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. API table, rows 5 and 6. +- url: https://hcxsbx.abdm.gov.in/images/af8d243edcc2139a515d.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Usecases.pdf + hash: sha256:8709b2907a0d5a0dbb36f5e63ed8deae269e0c75372b05d71ce7380c8a0929e7 + fetched: '2026-09-14' + note: NHCX Usecases, row 1 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1 to 2, Predetermination Request Submission. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Acceptance scenario. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2 Q3; page 4 Q12 and Q14. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. items 6 and 8. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.predetermination-on-submit + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.session-token + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.status + callbacks: + - nhcx.callback.predetermination-submit + - nhcx.callback.predetermination-on-submit + - nhcx.callback.error + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1003 + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1012 + - nhcx.error.payr-1001 + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.four-message-legs + flows: + - nhcx.flow.predetermination + fhir: + - nhcx.fhir.preauth-request + decisions: + - nhcx.decision.preauth-or-predetermination + sandbox: + - nhcx.sandbox.environments-and-base-urls + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback + - nhcx.troubleshooting.everything-returns-401 +--- + +# POST /v1/predetermination/submit + +## In plain words + +Predetermination asks the insurer for an estimate: what it would approve for a proposed treatment. Your system, as the provider, sends a bundle shaped like a pre-authorisation, with `Claim.use` `predetermination`, to [NHCX](../../shared/glossary/nhcx.md). The payer's estimate arrives later on your `/v1/predetermination/on_submit`. + +An estimate reserves nothing. The treatment still needs a pre-authorisation when it happens. Build this only with a payer that has confirmed it answers predetermination. + +## Before you start + +- A session token that has not expired. See [the session token](../concepts/session-token.md) and [how to get one](session-token.md). +- Your own [participant code](../glossary/participant-code.md), with your callback address registered, reachable from NHCX and answering 202 within 30 seconds. See [callback URL rules](../sandbox/callback-url-requirements.md). +- The payer's participant code, for a payer that has confirmed it supports predetermination. +- The recipient's encryption certificate, fetched with [`/fetch/certs`](fetch-certs.md). You seal the message with its public key. +- A bundle shaped as in [the preauthorisation request bundle](../fhir/preauth-request.md), with `Claim.use` `predetermination` and your predetermination reference in `Claim.identifier[0].value`. +- A handler for [`/v1/error`](../callbacks/error.md), so a request NHCX cannot deliver does not look like one still under review. +- A handler for [`/v1/predetermination/on_submit`](../callbacks/predetermination-on-submit.md). + +## What happens + +Your system, as the provider, calls NHCX on `/v1/predetermination/submit`. NHCX checks the envelope, answers 202 at once, and forwards the same path to the payer's registered address ([receiving `/v1/predetermination/submit`](../callbacks/predetermination-submit.md)). The payer answers later on [`/v1/predetermination/on_submit`](../callbacks/predetermination-on-submit.md), which NHCX delivers to you. + +### 1. Seal the message + +Put these values in the [JWE](../glossary/jwe.md) [protected header](../glossary/protected-header.md) and encrypt the bundle with the recipient's public key. + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-request_id": "", + "x-hcx-correlation_id": "", + "x-hcx-timestamp": "", + "x-hcx-status": "request.initiated", + "x-hcx-ben-abha-id": "" +} +``` + +The `x-hcx-*` values ride inside the JWE [protected header](../glossary/protected-header.md), not as HTTP headers. [The protocol headers](../concepts/protocol-headers.md) explains each one, including the timestamp format. Give each predetermination a new correlation id. No workflow code applies. + +### 2. Send it + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/hcx/v1/predetermination/submit' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --header 'Authorization: Bearer ' \ + --data-raw '{ + "payload": "" + }' +``` + +Send the token on both `bearer_auth` and `Authorization`, with the same value and the word `Bearer` in front. `` is your sealed message: five base64url parts joined by dots. See [the JWE envelope](../concepts/jwe-envelope.md). + +### 3. Retrying + +**Idempotency.** NHCX keys every conversation on `x-hcx-correlation_id`. An initiating request that reuses a correlation id NHCX already holds is refused with [`NHCX-1006`](../errors/nhcx-1006.md). So a blind retry is not safe. If your call timed out, ask [`/v1/status`](status.md) before you resend. `/v1/status` finds a message by its `x-hcx-api_call_id` ([`NHCX-1012`](../errors/nhcx-1012.md) when it cannot), so generate a new one for every call, a retry included. After a request fails for good, NHCX makes its correlation id inactive. Start a new cycle with a new correlation id. + +## How you know it worked + +You receive HTTP `202 Accepted` with the acknowledgement body: `timestamp`, `api_call_id`, `correlation_id`, `result` and an empty `error`. + +- `correlation_id` and `api_call_id` match the values you sealed. +- `error.code` and `error.message` are empty. + +The step is done when [`/v1/predetermination/on_submit`](../callbacks/predetermination-on-submit.md) reaches your callback address with the same `x-hcx-correlation_id`. It carries a `ClaimResponse` with `use` `predetermination` and the estimated benefit in `ClaimResponse.total` under category `benefit`. Your handler answers it 202 within 30 seconds. + +## When it goes wrong + +- `401 Unauthorized`, or [`NHCX-401`](../errors/nhcx-401.md): the session token expired or lacks the `Bearer ` prefix. Get a new token and send again. See [every call returns 401](../troubleshooting/everything-returns-401.md). +- [`NHCX-1003`](../errors/nhcx-1003.md): the recipient code is not registered. A provider used `PayerID` instead of `processingID`. +- [`NHCX-1006`](../errors/nhcx-1006.md): the correlation id was used before. Start the cycle with a new one. +- [`NHCX-1011`](../errors/nhcx-1011.md): `x-hcx-status` is not `request.initiated`. +- You got 202 and nothing more arrives. The recipient may have failed to decrypt ([`PAYR-1001`](../errors/payr-1001.md)) or your callback is unreachable. See [accepted, then no callback](../troubleshooting/accepted-then-no-callback.md). diff --git a/catalogue/nhcx/endpoints/search-on-submit.md b/catalogue/nhcx/endpoints/search-on-submit.md new file mode 100644 index 000000000..7f4a5ac45 --- /dev/null +++ b/catalogue/nhcx/endpoints/search-on-submit.md @@ -0,0 +1,172 @@ +--- +id: nhcx.endpoint.search-on-submit +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /v1/search/on_submit +summary: >- + Send the claim documents an authorised body asked for back to it through the claims + exchange. +sources: +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: 'NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet: Search, /v1/search/on_submit rows.' +- url: https://hcxsbx.abdm.gov.in/searchhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/searchhcxservice.json + hash: sha256:21749dd2ba84a19c5523772da359d76293493d44b48651f1af2e6042d78fa296 + fetched: '2026-09-14' + note: 'API specification: searchhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/search/on_submit.post.' +- url: https://hcxsbx.abdm.gov.in/images/bc1e7d077857fc0fa071.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-NHCX USECASE Postman Collection.zip + hash: sha256:9d15daafa813d6d57e688fe800baa5a73d2540b8d0d12c6a1315f86a424817e4 + fetched: '2026-09-14' + note: AWS(Sandbox)-NHCX USECASE Postman Collection, row 17 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item /v1/search/on_submit. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1 Acceptance and Error scenario; page 2. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 4, Q14. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.search-submit + - nhcx.endpoint.session-token + - nhcx.endpoint.fetch-certs + callbacks: + - nhcx.callback.search-submit + - nhcx.callback.search-on-submit + - nhcx.callback.error + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1012 + - nhcx.error.payr-1517 + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.four-message-legs + - nhcx.concept.retries-and-expiry + flows: + - nhcx.flow.claim-search + fhir: + - nhcx.fhir.task + tests: + - nhcx.test.payer-uc-12 + troubleshooting: + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.everything-returns-401 +--- + +# POST /v1/search/on_submit + +## In plain words + +This answers a search. As a payer, you return the claim documents for the case the search named, sealed, through [NHCX](../../shared/glossary/nhcx.md). The bundle is a Task whose `Task.output` references the `ClaimResponse` for that case. Nothing about the claim changes. + +You call it after you have received a [`/v1/search/submit`](search-submit.md). + +## Before you start + +- A session token that has not expired. See [the session token](../concepts/session-token.md). +- The `/v1/search/submit` you are answering, received on [your registered address](../callbacks/search-submit.md), decrypted, and acknowledged with 202 within 30 seconds. +- That request's `x-hcx-correlation_id` and `x-hcx-sender_code`, stored. You echo the first and address the answer to the second. +- The encryption certificate of the requester, fetched with [`/fetch/certs`](fetch-certs.md). +- A Task bundle with `Task.status` `completed`, the `ClaimResponse` as a bundle entry, and `Task.output` referencing it. +- A handler for [`/v1/error`](../callbacks/error.md), where NHCX reports an answer it could not deliver. + +## What happens + +Your system, as the payer or a TPA acting for it, answers a request it received ([receiving the request](../callbacks/search-submit.md)) by calling NHCX on `/v1/search/on_submit`. NHCX answers 202 at once and delivers the same path to the registered address of the requester ([receiving `/v1/search/on_submit`](../callbacks/search-on-submit.md)). + +### 1. Seal the answer + +Swap the sender and recipient codes of the request. Echo its correlation id. Put these values in the [JWE](../glossary/jwe.md) [protected header](../glossary/protected-header.md): + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-request_id": "", + "x-hcx-correlation_id": "", + "x-hcx-timestamp": "", + "x-hcx-status": "response.complete", + "x-hcx-ben-abha-id": "" +} +``` + +Send `response.complete`, or `response.partial` when more results follow. The `x-hcx-*` values ride inside the JWE [protected header](../glossary/protected-header.md), not as HTTP headers. [The protocol headers](../concepts/protocol-headers.md) explains each one, including the timestamp format. + +### 2. Send it + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/hcx/v1/search/on_submit' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --header 'Authorization: Bearer ' \ + --data-raw '{ + "type": "JWEPayload", + "payload": "" + }' +``` + +Send the token on both `bearer_auth` and `Authorization`, with the same value and the word `Bearer` in front. `` is your sealed message: five base64url parts joined by dots. See [the JWE envelope](../concepts/jwe-envelope.md). + +### 3. Refusing a request + +To refuse the request at protocol level instead, send `"type": "ProtocolResponse"` on this path with `x-hcx-status` `response.error` and `x-hcx-error_details` holding `code`, `message` and `trace`. Keep clinical and business reasons inside the sealed payload. Only protocol errors go in the header. + +### 4. Retrying + +**Idempotency.** Echo the `x-hcx-correlation_id` of the request you are answering. A correlation id NHCX does not hold, or one it has already deleted, is refused with [`NHCX-1010`](../errors/nhcx-1010.md). Generate a new `x-hcx-api_call_id` for every call. `/v1/status` looks a message up by that value ([`NHCX-1012`](../errors/nhcx-1012.md) when it cannot), so never reuse one. + +## How you know it worked + +You receive HTTP `202 Accepted` with this body: + +```json +{ + "timestamp": "
", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "task", + "protocol_status": "request.dispatched" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `correlation_id` matches the request you answered, and `api_call_id` matches the value you sealed. +- `result.entity_type` is `task`. +- `error.code` and `error.message` are empty. + +NHCX then delivers your answer to the requester. The recipient must answer each delivery with 202 and the acknowledgement body within 30 seconds. Otherwise NHCX retries up to five times, then deletes the request and reports it on the sender's [`/v1/error`](../callbacks/error.md). The step is done when you hold the 202 and no report for this correlation id arrives on your `/v1/error`. + +## When it goes wrong + +- [`NHCX-1010`](../errors/nhcx-1010.md): NHCX holds no request with that correlation id. You minted a new one instead of echoing it, or the request was deleted after failed deliveries. +- [`NHCX-1011`](../errors/nhcx-1011.md): `x-hcx-status` is not `response.complete`, `response.partial` or `response.error`. +- [`PAYR-1517`](../errors/payr-1517.md): a refusal arrived as a `JWEPayload`. Protocol refusals travel as `ProtocolResponse`. +- `401 Unauthorized`, or [`NHCX-401`](../errors/nhcx-401.md): get a new session token and send again. +- A report arrives on your [`/v1/error`](../callbacks/error.md): the requester's address did not acknowledge five deliveries. The request is dead on that correlation id. diff --git a/catalogue/nhcx/endpoints/search-submit.md b/catalogue/nhcx/endpoints/search-submit.md new file mode 100644 index 000000000..f9ca41df0 --- /dev/null +++ b/catalogue/nhcx/endpoints/search-submit.md @@ -0,0 +1,179 @@ +--- +id: nhcx.endpoint.search-submit +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /v1/search/submit +summary: >- + Ask an insurer, through the claims exchange, for the claim documents of a known + case, for audit or dispute review. +sources: +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: 'NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet: Search, /v1/search/submit rows.' +- url: https://hcxsbx.abdm.gov.in/searchhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/searchhcxservice.json + hash: sha256:21749dd2ba84a19c5523772da359d76293493d44b48651f1af2e6042d78fa296 + fetched: '2026-09-14' + note: 'API specification: searchhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/search/submit.post.' +- url: https://hcxsbx.abdm.gov.in/images/bc1e7d077857fc0fa071.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-NHCX USECASE Postman Collection.zip + hash: sha256:9d15daafa813d6d57e688fe800baa5a73d2540b8d0d12c6a1315f86a424817e4 + fetched: '2026-09-14' + note: AWS(Sandbox)-NHCX USECASE Postman Collection, row 17 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item /v1/search/submit. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Acceptance scenario. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2 Q3; page 4 Q12 and Q14. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. items 6 and 8. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.search-on-submit + - nhcx.endpoint.session-token + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.status + callbacks: + - nhcx.callback.search-submit + - nhcx.callback.search-on-submit + - nhcx.callback.error + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1003 + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1012 + - nhcx.error.payr-1001 + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.four-message-legs + flows: + - nhcx.flow.claim-search + fhir: + - nhcx.fhir.task + tests: + - nhcx.test.provider-uc-10 + - nhcx.test.payer-uc-12 + sandbox: + - nhcx.sandbox.environments-and-base-urls + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback + - nhcx.troubleshooting.everything-returns-401 +--- + +# POST /v1/search/submit + +## In plain words + +Search lets an authorised entity, for example [NHA](../../shared/glossary/nha.md) or [IRDAI](../glossary/irdai.md), pull the claim documents for a case. Your system sends a Task bundle naming the case to [NHCX](../../shared/glossary/nhcx.md). The payer returns the documents later on your `/v1/search/on_submit`. + +Search only reads. Nothing about the claim changes. + +## Before you start + +- A session token that has not expired. See [the session token](../concepts/session-token.md) and [how to get one](session-token.md). +- Your own [participant code](../glossary/participant-code.md), with your callback address registered, reachable from NHCX and answering 202 within 30 seconds. See [callback URL rules](../sandbox/callback-url-requirements.md). +- The payer's participant code. +- The recipient's encryption certificate, fetched with [`/fetch/certs`](fetch-certs.md). You seal the message with its public key. +- A Task bundle in [FHIR](../../shared/glossary/fhir.md) with `code` `status`, `status` `requested` and `basedOn` your request reference. Its inputs name the claim number, a date range or the policy number. +- A handler for [`/v1/error`](../callbacks/error.md), so a request NHCX cannot deliver does not look like one still under review. +- A handler for [`/v1/search/on_submit`](../callbacks/search-on-submit.md). + +## What happens + +Your system, as an authorised entity, calls NHCX on `/v1/search/submit`. NHCX checks the envelope, answers 202 at once, and forwards the same path to the payer's registered address ([receiving `/v1/search/submit`](../callbacks/search-submit.md)). The payer answers later on [`/v1/search/on_submit`](../callbacks/search-on-submit.md), which NHCX delivers to you. + +### 1. Seal the message + +Put these values in the [JWE](../glossary/jwe.md) [protected header](../glossary/protected-header.md) and encrypt the bundle with the recipient's public key. + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-request_id": "", + "x-hcx-correlation_id": "", + "x-hcx-timestamp": "", + "x-hcx-status": "request.initiated", + "x-hcx-ben-abha-id": "" +} +``` + +The `x-hcx-*` values ride inside the JWE [protected header](../glossary/protected-header.md), not as HTTP headers. [The protocol headers](../concepts/protocol-headers.md) explains each one, including the timestamp format. Give this call a new `x-hcx-correlation_id`, the same UUID as its `x-hcx-api_call_id`. Name the case inside the Task, not in the header. + +### 2. Send it + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/hcx/v1/search/submit' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --header 'Authorization: Bearer ' \ + --data-raw '{ + "payload": "" + }' +``` + +Send the token on both `bearer_auth` and `Authorization`, with the same value and the word `Bearer` in front. `` is your sealed message: five base64url parts joined by dots. See [the JWE envelope](../concepts/jwe-envelope.md). + +### 3. Retrying + +**Idempotency.** NHCX keys every conversation on `x-hcx-correlation_id`. An initiating request that reuses a correlation id NHCX already holds is refused with [`NHCX-1006`](../errors/nhcx-1006.md). So a blind retry is not safe. If your call timed out, ask [`/v1/status`](status.md) before you resend. `/v1/status` finds a message by its `x-hcx-api_call_id` ([`NHCX-1012`](../errors/nhcx-1012.md) when it cannot), so generate a new one for every call, a retry included. After a request fails for good, NHCX makes its correlation id inactive. Start a new cycle with a new correlation id. + +## How you know it worked + +You receive HTTP `202 Accepted` with this body: + +```json +{ + "timestamp": "
", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "task", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `correlation_id` and `api_call_id` match the values you sealed. +- `result.entity_type` is `task`. +- `result.protocol_status` is `request.queued` or `request.dispatched`. +- `error.code` and `error.message` are empty. + +The 202 is a receipt, not a decision. NHCX never returns a decision synchronously. The step is done when [`/v1/search/on_submit`](../callbacks/search-on-submit.md) reaches your callback address with the same `x-hcx-correlation_id`, and your handler has answered it 202 within 30 seconds. Its Task bundle has `Task.output` referencing the `ClaimResponse` for the case. + +## When it goes wrong + +- The payer answers [`PAYR-1102`](../errors/payr-1102.md), invalid search parameter: the Task does not name the case it should search for. +- `401 Unauthorized`, or [`NHCX-401`](../errors/nhcx-401.md): the session token expired or lacks the `Bearer ` prefix. Get a new token and send again. See [every call returns 401](../troubleshooting/everything-returns-401.md). +- [`NHCX-1003`](../errors/nhcx-1003.md): the recipient code is not registered. A provider used `PayerID` instead of `processingID`. +- [`NHCX-1006`](../errors/nhcx-1006.md): the correlation id was used before. Start the cycle with a new one. +- [`NHCX-1011`](../errors/nhcx-1011.md): `x-hcx-status` is not `request.initiated`. +- You got 202 and nothing more arrives. The recipient may have failed to decrypt ([`PAYR-1001`](../errors/payr-1001.md)) or your callback is unreachable. See [accepted, then no callback](../troubleshooting/accepted-then-no-callback.md). diff --git a/catalogue/nhcx/endpoints/session-token.md b/catalogue/nhcx/endpoints/session-token.md new file mode 100644 index 000000000..4576ddf09 --- /dev/null +++ b/catalogue/nhcx/endpoints/session-token.md @@ -0,0 +1,124 @@ +--- +id: nhcx.endpoint.session-token +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /api/hiecm/gateway/v3/sessions +summary: >- + Trade your client id and client secret for the short-lived access token that every + claims exchange call carries. +sources: +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, Q2 base URLs; Q3; page 5, Q20. +- url: https://hcxsbx.abdm.gov.in/images/54d18468412741b759f3.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Authenticating with NHCX.pdf + hash: sha256:0ea90b635634844aaf8981e917cbf8b765ddd83a340f3c934883912599a62d8b + fetched: '2026-09-14' + note: Authenticating with NHCX, row 3 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1. +- url: https://hcxsbx.abdm.gov.in/#/domain-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications.md + hash: sha256:56234dd8a55fe4eb9dd852779b22b522b04760c9bec5c263d5e9bc3ac2c6f167 + fetched: '2026-09-14' + note: Site page /domain-specifications, text as shown on the site. participant onboarding section, Milestone 1 access token. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, items 6 and 9. +verified: + status: unverified +related: + concepts: + - nhcx.concept.session-token + endpoints: + - nhcx.endpoint.get-session + - nhcx.endpoint.fetch-participants-list + decisions: + - nhcx.decision.session-endpoint + errors: + - nhcx.error.nhcx-401 + troubleshooting: + - nhcx.troubleshooting.everything-returns-401 + sandbox: + - nhcx.sandbox.prerequisites + - nhcx.sandbox.going-live +--- + +# POST /api/hiecm/gateway/v3/sessions + +## In plain words + +This call gives you an access token. Every call you make to the National Health Claims Exchange ([NHCX](../../shared/glossary/nhcx.md)) carries it. + +You send the client id and client secret issued to you for [ABDM](../../shared/glossary/abdm.md) [Milestone 1](../../shared/glossary/m1.md). The ABDM [gateway](../../shared/glossary/gateway.md) returns a bearer token and its lifetime in seconds. The token is short lived, so you renew it on a timer. See [the session token](../concepts/session-token.md) for how one token serves every NHCX call. + +## Before you start + +- You hold an ABDM [sandbox](../../shared/glossary/sandbox.md) client id and client secret. See [sandbox prerequisites](../sandbox/prerequisites.md). A provider that already holds these for ABHA integration uses the same pair for NHCX. +- Your system clock is synchronised, because the `TIMESTAMP` header carries the current time. +- Your code can generate a fresh UUID for every call. + +## What happens + +Your system posts its credentials to the session address. The gateway answers on the same connection with the token. No callback follows. + +| Environment | Session address | +|---|---| +| Sandbox | `https://dev.abdm.gov.in/api/hiecm/gateway/v3/sessions` | +| Production | Issued with your production credentials after [going live](../sandbox/going-live.md) | + +```bash +curl -X POST 'https://dev.abdm.gov.in/api/hiecm/gateway/v3/sessions' \ + -H 'Content-Type: application/json' \ + -H 'REQUEST-ID: ' \ + -H 'TIMESTAMP: ' \ + -H 'X-CM-ID: sbx' \ + -d '{ + "clientId": "", + "clientSecret": "", + "grantType": "client_credentials" + }' +``` + +- `` and `` come from your ABDM sandbox registration. +- [`REQUEST-ID`](../../shared/glossary/request-id.md) is a new UUID for this call. Do not copy one from an example. +- [`TIMESTAMP`](../../shared/glossary/timestamp-header.md) is the current UTC time with milliseconds and a trailing `Z`, for example `2026-09-04T06:15:51.975Z`. Take it from the system clock. +- [`X-CM-ID`](../../shared/glossary/x-cm-id.md) is `sbx` on the sandbox. +- `grantType` is always `client_credentials`. + +The earlier address, `https://dev.abdm.gov.in/gateway/v0.5/sessions`, takes the same `clientId`, `clientSecret` and `grantType` body. It also returns `accessToken` and `expiresIn`. [Choosing a session endpoint](../decisions/session-endpoint.md) compares both addresses with [`/get/session`](get-session.md). + +The response body has this shape: + +```json +{ + "accessToken": "", + "expiresIn": , + "refreshTokenIn": , + "refreshToken": "", + "tokenType": "bearer" +} +``` + +Send `accessToken` on every NHCX call as `bearer_auth: Bearer `. Do not hard code a lifetime. Read `expiresIn` from each response and mint a new token before it runs out. + +**Idempotency.** Every call mints a new token. Repeating the call is safe. Keep the newest token and drop the old one. + +## How you know it worked + +You receive HTTP 200 with a non-empty `accessToken` and an integer `expiresIn`. + +Your next participant service call, for example [`/fetch/participants/list`](fetch-participants-list.md), returns 200 rather than 401 when it carries the token in `bearer_auth`. + +Record the time the token arrived. It is valid until that time plus `expiresIn` seconds. + +## When it goes wrong + +- **A later call returns 401 with `Sender is not authorized to execute the operation`.** The token has expired. Call this endpoint again, then retry the failed call once with the new token. See [NHCX-401](../errors/nhcx-401.md). +- **A later call returns 401 although the token is fresh.** The token went out without the `Bearer ` prefix. Send `bearer_auth: Bearer `. See [every call returns 401](../troubleshooting/everything-returns-401.md). +- **The session call itself is refused.** Check that the body carries `grantType` set to `client_credentials`, that `REQUEST-ID` is new, and that `TIMESTAMP` comes from a synchronised clock. +- **A retry with a new token also returns 401.** The credentials are wrong or were replaced. Stop retrying and check the client id and secret. diff --git a/catalogue/nhcx/endpoints/status.md b/catalogue/nhcx/endpoints/status.md new file mode 100644 index 000000000..9150736f2 --- /dev/null +++ b/catalogue/nhcx/endpoints/status.md @@ -0,0 +1,172 @@ +--- +id: nhcx.endpoint.status +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /v1/status +summary: >- + Ask the claims exchange where one of your own sent messages stands, without sending + it again. +sources: +- url: https://hcxsbx.abdm.gov.in/statushcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/statushcxservice.json + hash: sha256:93b6355a234ef56607427fcdfa32da4921124180c9df08ecd73c8af8955c2adf + fetched: '2026-09-14' + note: 'API specification: statushcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/status.post description.' +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: 'NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet: Status, /v1/status rows.' +- url: https://hcxsbx.abdm.gov.in/images/bc1e7d077857fc0fa071.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-NHCX USECASE Postman Collection.zip + hash: sha256:9d15daafa813d6d57e688fe800baa5a73d2540b8d0d12c6a1315f86a424817e4 + fetched: '2026-09-14' + note: AWS(Sandbox)-NHCX USECASE Postman Collection, row 17 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item /v1/status. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Acceptance scenario; Error scenario. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, Q3. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. items 8. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.on-status + - nhcx.endpoint.session-token + callbacks: + - nhcx.callback.status + - nhcx.callback.on-status + - nhcx.callback.error + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1012 + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.four-message-legs + - nhcx.concept.status-lifecycle + - nhcx.concept.retries-and-expiry + flows: + - nhcx.flow.status-check + decisions: + - nhcx.decision.status-poll-or-wait + tests: + - nhcx.test.provider-uc-13 + - nhcx.test.payer-uc-15 + sandbox: + - nhcx.sandbox.environments-and-base-urls + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback + - nhcx.troubleshooting.everything-returns-401 +--- + +# POST /v1/status + +## In plain words + +When an answer has not come back, `/v1/status` tells you whether [NHCX](../../shared/glossary/nhcx.md) still holds your message or has passed it to the recipient. It answers where the message is, not what was decided. You can only ask about messages you sent yourself. + +Ask before you resend anything. Resending creates a duplicate. + +## Before you start + +- A session token that has not expired. See [the session token](../concepts/session-token.md). +- The `x-hcx-api_call_id` of the message you are asking about. Store every one you send. +- The participant code of that message's recipient, and its encryption certificate. +- A handler for [`/v1/on_status`](../callbacks/on-status.md), where the recipient's answer arrives. + +## What happens + +Your system calls NHCX on `/v1/status`. NHCX answers synchronously with the position of the message. If the recipient already has it, NHCX forwards the question ([receiving `/v1/status`](../callbacks/status.md)) and the recipient answers on [`/v1/on_status`](on-status.md). + +### 1. Seal the question + +The sealed payload is an empty string. Everything travels in the [protected header](../glossary/protected-header.md): + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-request_id": "", + "x-hcx-correlation_id": "", + "x-hcx-timestamp": "", + "x-hcx-status": "request.initiated", + "x-hcx-ben-abha-id": "" +} +``` + +Set `x-hcx-correlation_id` to the `x-hcx-api_call_id` of the message you are checking. When the first message of a cycle uses its API call id as its correlation id, the two values are the same. The `x-hcx-*` values ride inside the JWE [protected header](../glossary/protected-header.md), not as HTTP headers. [The protocol headers](../concepts/protocol-headers.md) explains each one, including the timestamp format. + +### 2. Send it + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/hcx/v1/status' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --header 'Authorization: Bearer ' \ + --data-raw '{ + "payload": "" + }' +``` + +Send the token on both `bearer_auth` and `Authorization`, with the same value and the word `Bearer` in front. `` is your sealed message: five base64url parts joined by dots. See [the JWE envelope](../concepts/jwe-envelope.md). + +### 3. Retrying + +A status call changes nothing, so you may repeat it. Give each attempt a new `x-hcx-api_call_id`. Space the attempts out rather than polling in a loop. + +## How you know it worked + +You receive HTTP `202 Accepted` with this body: + +```json +{ + "timestamp": "
", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "", + "protocol_status": "request.dispatched" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `result.protocol_status` `request.queued` means NHCX still holds the message. No callback follows. Wait, then ask again. +- `result.protocol_status` `request.dispatched` means the recipient has it. An answer arrives on [`/v1/on_status`](../callbacks/on-status.md). +- `error.code` and `error.message` are empty. + +The step is done when you hold one of those two values for the message you asked about. + +## When it goes wrong + +- [`NHCX-1012`](../errors/nhcx-1012.md): no record for that API call id. You sent a new UUID as the correlation id instead of the checked message's `x-hcx-api_call_id`, or the original never landed. +- [`NHCX-1006`](../errors/nhcx-1006.md): you resent the original request after `request.queued`. Ask again instead of resending. +- Nothing is found for a message that failed delivery five times. NHCX deleted it and reported it on your `/v1/error`. Start a new cycle with a new correlation id. +- [`NHCX-1011`](../errors/nhcx-1011.md): `x-hcx-status` is not `request.initiated`. +- `401 Unauthorized` or [`NHCX-401`](../errors/nhcx-401.md): get a new session token and ask again. diff --git a/catalogue/nhcx/endpoints/task-on-submit.md b/catalogue/nhcx/endpoints/task-on-submit.md new file mode 100644 index 000000000..a856cd263 --- /dev/null +++ b/catalogue/nhcx/endpoints/task-on-submit.md @@ -0,0 +1,183 @@ +--- +id: nhcx.endpoint.task-on-submit +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /v1/task/on_submit +summary: >- + Send an insurer's outcome on a reprocess or cancellation request back to the hospital + through the claims exchange. +sources: +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: 'NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet: Reprocess, /v1/task/on_submit rows.' +- url: https://hcxsbx.abdm.gov.in/taskhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/taskhcxservice.json + hash: sha256:0418eca6478dece4d72c5a49a6547d50772511f7ffaf32f901f245591ba84656 + fetched: '2026-09-14' + note: 'API specification: taskhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/task/on_submit.post.' +- url: https://hcxsbx.abdm.gov.in/images/bc1e7d077857fc0fa071.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-NHCX USECASE Postman Collection.zip + hash: sha256:9d15daafa813d6d57e688fe800baa5a73d2540b8d0d12c6a1315f86a424817e4 + fetched: '2026-09-14' + note: AWS(Sandbox)-NHCX USECASE Postman Collection, row 17 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item /v1/task/on_submit. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1 Acceptance and Error scenario; page 2. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 10.4 workflow table; 10.5 Response Task resource. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 4, Q14. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.task-submit + - nhcx.endpoint.paymentnotice-request + - nhcx.endpoint.session-token + - nhcx.endpoint.fetch-certs + callbacks: + - nhcx.callback.task-submit + - nhcx.callback.task-on-submit + - nhcx.callback.error + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1012 + - nhcx.error.payr-1517 + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.four-message-legs + - nhcx.concept.retries-and-expiry + - nhcx.concept.reprocess-and-cancel + - nhcx.concept.workflow-codes + flows: + - nhcx.flow.claim-reprocess + - nhcx.flow.preauth-cancel + fhir: + - nhcx.fhir.task + - nhcx.fhir.preauth-cancel + tests: + - nhcx.test.payer-uc-14 + troubleshooting: + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.everything-returns-401 +--- + +# POST /v1/task/on_submit + +## In plain words + +This closes a reprocess or cancellation the provider opened. As a payer, you send a sealed Task bundle to [NHCX](../../shared/glossary/nhcx.md). `Task.status` is `completed` and `Task.output` references a `ClaimResponse` carrying the outcome, in the same shape as an ordinary adjudication. + +You call it after you have received a [`/v1/task/submit`](task-submit.md) and decided it. + +## Before you start + +- A session token that has not expired. See [the session token](../concepts/session-token.md). +- The `/v1/task/submit` you are answering, received on [your registered address](../callbacks/task-submit.md), decrypted, and acknowledged with 202 within 30 seconds. +- That request's `x-hcx-correlation_id` and `x-hcx-sender_code`, stored. You echo the first and address the answer to the second. +- The encryption certificate of the provider, fetched with [`/fetch/certs`](fetch-certs.md). +- A Task bundle in [FHIR](../../shared/glossary/fhir.md), built as in [the Task bundle](../fhir/task.md), with `Task.status` `completed` and `Task.output` referencing the `ClaimResponse`. +- A handler for [`/v1/error`](../callbacks/error.md), where NHCX reports an answer it could not deliver. + +## What happens + +Your system, as the payer or a TPA acting for it, answers a request it received ([receiving the request](../callbacks/task-submit.md)) by calling NHCX on `/v1/task/on_submit`. NHCX answers 202 at once and delivers the same path to the registered address of the provider ([receiving `/v1/task/on_submit`](../callbacks/task-on-submit.md)). + +### 1. Seal the answer + +Swap the sender and recipient codes of the request. Echo its correlation id. Put these values in the [JWE](../glossary/jwe.md) [protected header](../glossary/protected-header.md): + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-request_id": "", + "x-hcx-correlation_id": "", + "x-hcx-workflow_id": "252", + "x-hcx-timestamp": "", + "x-hcx-status": "response.complete", + "x-hcx-ben-abha-id": "" +} +``` + +`x-hcx-workflow_id` names the outcome: `251` received, `252` approved, `253` rejected, `254` queried. The `x-hcx-*` values ride inside the JWE [protected header](../glossary/protected-header.md), not as HTTP headers. [The protocol headers](../concepts/protocol-headers.md) explains each one, including the timestamp format. + +### 2. Send it + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/hcx/v1/task/on_submit' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --header 'Authorization: Bearer ' \ + --data-raw '{ + "type": "JWEPayload", + "payload": "" + }' +``` + +Send the token on both `bearer_auth` and `Authorization`, with the same value and the word `Bearer` in front. `` is your sealed message: five base64url parts joined by dots. See [the JWE envelope](../concepts/jwe-envelope.md). + +### 3. Refusing a request + +To refuse the request at protocol level instead, send `"type": "ProtocolResponse"` on this path with `x-hcx-status` `response.error` and `x-hcx-error_details` holding `code`, `message` and `trace`. Keep clinical and business reasons inside the sealed payload. Only protocol errors go in the header. + +### 4. Retrying + +**Idempotency.** Echo the `x-hcx-correlation_id` of the request you are answering. A correlation id NHCX does not hold, or one it has already deleted, is refused with [`NHCX-1010`](../errors/nhcx-1010.md). Generate a new `x-hcx-api_call_id` for every call. `/v1/status` looks a message up by that value ([`NHCX-1012`](../errors/nhcx-1012.md) when it cannot), so never reuse one. + +## How you know it worked + +You receive HTTP `202 Accepted` with this body: + +```json +{ + "timestamp": "
", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "task", + "protocol_status": "request.dispatched" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `correlation_id` matches the request you answered, and `api_call_id` matches the value you sealed. +- `result.entity_type` is `task`. +- `error.code` and `error.message` are empty. + +NHCX then delivers your answer to the provider. The recipient must answer each delivery with 202 and the acknowledgement body within 30 seconds. Otherwise NHCX retries up to five times, then deletes the request and reports it on the sender's [`/v1/error`](../callbacks/error.md). The step is done when you hold the 202 and no report for this correlation id arrives on your `/v1/error`. + +## When it goes wrong + +- [`NHCX-1010`](../errors/nhcx-1010.md): NHCX holds no request with that correlation id. You minted a new one instead of echoing it, or the request was deleted after failed deliveries. +- [`NHCX-1011`](../errors/nhcx-1011.md): `x-hcx-status` is not `response.complete`, `response.partial` or `response.error`. +- [`PAYR-1517`](../errors/payr-1517.md): a refusal arrived as a `JWEPayload`. Protocol refusals travel as `ProtocolResponse`. +- `401 Unauthorized`, or [`NHCX-401`](../errors/nhcx-401.md): get a new session token and send again. +- A report arrives on your [`/v1/error`](../callbacks/error.md): the requester's address did not acknowledge five deliveries. The request is dead on that correlation id. diff --git a/catalogue/nhcx/endpoints/task-submit.md b/catalogue/nhcx/endpoints/task-submit.md new file mode 100644 index 000000000..15dc031f4 --- /dev/null +++ b/catalogue/nhcx/endpoints/task-submit.md @@ -0,0 +1,190 @@ +--- +id: nhcx.endpoint.task-submit +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /v1/task/submit +summary: >- + Ask an insurer, through the claims exchange, to look again at a rejected or short-paid + claim, or to cancel a pre-authorisation you will not use. +sources: +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: 'NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet: Reprocess, /v1/task/submit rows.' +- url: https://hcxsbx.abdm.gov.in/taskhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/taskhcxservice.json + hash: sha256:0418eca6478dece4d72c5a49a6547d50772511f7ffaf32f901f245591ba84656 + fetched: '2026-09-14' + note: 'API specification: taskhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/task/submit.post.' +- url: https://hcxsbx.abdm.gov.in/images/bc1e7d077857fc0fa071.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-NHCX USECASE Postman Collection.zip + hash: sha256:9d15daafa813d6d57e688fe800baa5a73d2540b8d0d12c6a1315f86a424817e4 + fetched: '2026-09-14' + note: AWS(Sandbox)-NHCX USECASE Postman Collection, row 17 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item /v1/task/submit. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Acceptance scenario. +- url: https://hcxsbx.abdm.gov.in/images/53347f5988b0ce5396f1.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_APIs to be called based on scenario.xlsx + hash: sha256:f92a30673d65dd2cc3cf09e2087c624f23f781dc4ca6b5cd8ec1825e224ac108 + fetched: '2026-09-14' + note: 'NHCX_APIs to be called based on scenario, row 26 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sheet: Scenarios, rows 9, 12 and 14.' +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 7 to 9, sections 22 and 23; page 4 Q12 and Q14. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. items 6, 7 and 8. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.task-on-submit + - nhcx.endpoint.claim-submit + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.session-token + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.status + callbacks: + - nhcx.callback.task-submit + - nhcx.callback.task-on-submit + - nhcx.callback.error + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1003 + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1012 + - nhcx.error.payr-1001 + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.four-message-legs + - nhcx.concept.reprocess-and-cancel + - nhcx.concept.workflow-codes + flows: + - nhcx.flow.claim-reprocess + - nhcx.flow.preauth-cancel + fhir: + - nhcx.fhir.task + - nhcx.fhir.preauth-cancel + tests: + - nhcx.test.provider-uc-12 + - nhcx.test.tc-cl-03 + sandbox: + - nhcx.sandbox.environments-and-base-urls + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback + - nhcx.troubleshooting.everything-returns-401 +--- + +# POST /v1/task/submit + +## In plain words + +A Task asks the payer to act on something that already exists. Your system, as the provider, sends a Task bundle to [NHCX](../../shared/glossary/nhcx.md). It asks the payer to reprocess a rejected or partly paid claim, or to cancel a pre-authorisation. `Task.code` says which: `reprocess` or `cancel`. The payer's outcome arrives later on your `/v1/task/on_submit`. + +A reprocess needs new justification and a supporting document attached. + +## Before you start + +- A session token that has not expired. See [the session token](../concepts/session-token.md) and [how to get one](session-token.md). +- Your own [participant code](../glossary/participant-code.md), with your callback address registered, reachable from NHCX and answering 202 within 30 seconds. See [callback URL rules](../sandbox/callback-url-requirements.md). +- The payer's participant code. Take it from `processingID` in the [`/participant/get/policies`](participant-get-policies.md) response, not from `PayerID`. +- The recipient's encryption certificate, fetched with [`/fetch/certs`](fetch-certs.md). You seal the message with its public key. +- A Task bundle in [FHIR](../../shared/glossary/fhir.md) built as in [the Task bundle](../fhir/task.md). It has `Task.status` `requested`, references the original claim or pre-authorisation, and carries the claim number. +- A handler for [`/v1/error`](../callbacks/error.md), so a request NHCX cannot deliver does not look like one still under review. +- A handler for [`/v1/task/on_submit`](../callbacks/task-on-submit.md). + +## What happens + +Your system, as the provider, calls NHCX on `/v1/task/submit`. NHCX checks the envelope, answers 202 at once, and forwards the same path to the payer's registered address ([receiving `/v1/task/submit`](../callbacks/task-submit.md)). The payer answers later on [`/v1/task/on_submit`](../callbacks/task-on-submit.md), which NHCX delivers to you. + +### 1. Seal the message + +Put these values in the [JWE](../glossary/jwe.md) [protected header](../glossary/protected-header.md) and encrypt the bundle with the recipient's public key. + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-request_id": "", + "x-hcx-correlation_id": "", + "x-hcx-workflow_id": "", + "x-hcx-timestamp": "", + "x-hcx-status": "request.initiated", + "x-hcx-ben-abha-id": "" +} +``` + +The `x-hcx-*` values ride inside the JWE [protected header](../glossary/protected-header.md), not as HTTP headers. [The protocol headers](../concepts/protocol-headers.md) explains each one, including the timestamp format. Take the reprocess or cancellation code for your scheme from [workflow codes](../concepts/workflow-codes.md). Give this call a new `x-hcx-correlation_id`, the same UUID as its `x-hcx-api_call_id`. Name the case inside the Task, not in the header. + +### 2. Send it + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/hcx/v1/task/submit' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --header 'Authorization: Bearer ' \ + --data-raw '{ + "payload": "" + }' +``` + +Send the token on both `bearer_auth` and `Authorization`, with the same value and the word `Bearer` in front. `` is your sealed message: five base64url parts joined by dots. See [the JWE envelope](../concepts/jwe-envelope.md). + +### 3. Retrying + +**Idempotency.** NHCX keys every conversation on `x-hcx-correlation_id`. An initiating request that reuses a correlation id NHCX already holds is refused with [`NHCX-1006`](../errors/nhcx-1006.md). So a blind retry is not safe. If your call timed out, ask [`/v1/status`](status.md) before you resend. `/v1/status` finds a message by its `x-hcx-api_call_id` ([`NHCX-1012`](../errors/nhcx-1012.md) when it cannot), so generate a new one for every call, a retry included. After a request fails for good, NHCX makes its correlation id inactive. Start a new cycle with a new correlation id. + +## How you know it worked + +You receive HTTP `202 Accepted` with this body: + +```json +{ + "timestamp": "
", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "task", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +- `correlation_id` and `api_call_id` match the values you sealed. +- `result.entity_type` is `task`. +- `result.protocol_status` is `request.queued` or `request.dispatched`. +- `error.code` and `error.message` are empty. + +The 202 is a receipt, not a decision. NHCX never returns a decision synchronously. The step is done when [`/v1/task/on_submit`](../callbacks/task-on-submit.md) reaches your callback address with the same `x-hcx-correlation_id`, and your handler has answered it 202 within 30 seconds. Its Task bundle has `Task.output` referencing a `ClaimResponse` that carries the outcome. + +## When it goes wrong + +- `401 Unauthorized`, or [`NHCX-401`](../errors/nhcx-401.md): the session token expired or lacks the `Bearer ` prefix. Get a new token and send again. See [every call returns 401](../troubleshooting/everything-returns-401.md). +- [`NHCX-1003`](../errors/nhcx-1003.md): the recipient code is not registered. A provider used `PayerID` instead of `processingID`. +- [`NHCX-1006`](../errors/nhcx-1006.md): the correlation id was used before. Start the cycle with a new one. +- [`NHCX-1011`](../errors/nhcx-1011.md): `x-hcx-status` is not `request.initiated`. +- You got 202 and nothing more arrives. The recipient may have failed to decrypt ([`PAYR-1001`](../errors/payr-1001.md)) or your callback is unreachable. See [accepted, then no callback](../troubleshooting/accepted-then-no-callback.md). diff --git a/catalogue/nhcx/endpoints/update-validate.md b/catalogue/nhcx/endpoints/update-validate.md new file mode 100644 index 000000000..153dd5051 --- /dev/null +++ b/catalogue/nhcx/endpoints/update-validate.md @@ -0,0 +1,106 @@ +--- +id: nhcx.endpoint.update-validate +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: GET /update/validate +summary: >- + Confirm a production change to your certificate or bridge address with the transaction + id and the passcode sent to your registered mobile. +sources: +- url: https://hcxsbx.abdm.gov.in/images/293a43103f575b4e7f7f.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(PROD)_NHCX-OnBoarding APIs Postman Collection.zip + hash: sha256:b96963e2eead0fe3e718eb7dd2374f1a15f0dbb1aed7197a1ceae59cefbc7214 + fetched: '2026-09-14' + note: AWS(PROD)_NHCX-OnBoarding APIs Postman Collection, row 7 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Postman PROD_NHCX-OnBoarding APIs item /update/validate. +- url: https://hcxsbx.abdm.gov.in/images/260d0dec19a681e80262.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Production.pdf + hash: sha256:c38476fb90101f13fdfea447861292718d561e1dc088ae20950b193606500d2e + fetched: '2026-09-14' + note: Onboarding providers and payers in Production, row 5 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 3, Step 4 Participant Updation confirmation. +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./update/validate.get.' +- url: https://hcxsbx.abdm.gov.in/images/be2e25fede3bf711f783.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/PMJAY Hospital Migration to HMIS via NHCX.docx + hash: sha256:cf5c9bf1c402b214f65bbb7bd0822f3a76d8ccda9b69c7bf77ba131befef3bc6 + fetched: '2026-09-14' + note: PMJAY Hospital Migration to HMIS via NHCX, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments, not named in the NHCX document sheet. Section 3.4 Update Confirmation (Step 4). +- url: https://hcxsbx.abdm.gov.in/images/bc2efb078b98548f8e6b.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Sandbox.pdf + hash: sha256:cbd03baf428655f0305e2f60ca331f8b76700496b070c522cafcc95001710b3a + fetched: '2026-09-14' + note: Onboarding providers and payers in Sandbox, row 4 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 2-3, API Definition - Update Participant. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 3.3 Certificate Fetch. +verified: + status: unverified +related: + flows: + - nhcx.flow.production-onboarding + - nhcx.flow.rotate-certificate + endpoints: + - nhcx.endpoint.v2-participant-update + - nhcx.endpoint.validate + - nhcx.endpoint.v2-update-cert + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.session-token + errors: + - nhcx.error.nhcx-401 + concepts: + - nhcx.concept.encryption-certificate +--- + +# GET /update/validate + +## In plain words + +This call confirms a production change to your [NHCX](../../shared/glossary/nhcx.md) registry record. [`/v2/participant/update`](v2-participant-update.md) stages a new certificate or bridge URL and sends a passcode to your registered mobile number. This call presents that passcode, and the change takes effect. + +It confirms updates only. To confirm a creation, call [`/validate`](validate.md). To replace only the certificate without a passcode, call [`/v2/update/cert`](v2-update-cert.md). + +## Before you start + +- Your participant creation is already confirmed with [`/validate`](validate.md). +- A `transactionid` from [`/v2/participant/update`](v2-participant-update.md), less than 24 hours old. +- The passcode for that transaction, from the registered mobile number. +- A current access token from the [session call](session-token.md). It goes in the `bearer_auth` header as `Bearer `, with `Bearer` and a space in front. + +## What happens + +Your system sends a GET with two query parameters. The registry checks the passcode against the update transaction and answers on the same connection. There is no request body and no callback. + +```bash +curl -G 'https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice/update/validate' \ + -H 'Accept: application/json' \ + -H 'bearer_auth: Bearer ' \ + --data-urlencode 'transactionId=' \ + --data-urlencode 'passcode=' +``` + +The query parameter is `transactionId`, with a capital I. + +This is the production address. In the sandbox, [`/participant/update`](participant-update.md) applies changes directly, with no confirmation step. + +**Idempotency.** Call it once per transaction. Each new update issues a new transaction id and passcode. If the pair has expired, call [`/v2/participant/update`](v2-participant-update.md) again and validate the new pair. + +## How you know it worked + +You receive HTTP 200. The staged certificate and bridge URL are now your live registry values. + +[`/fetch/certs`](fetch-certs.md) with your own participant code returns the new certificate. NHCX delivers your next inbound message to the new bridge URL. + +## When it goes wrong + +- **More than 24 hours have passed.** The pair has expired. Issue the update again with [`/v2/participant/update`](v2-participant-update.md). +- **The passcode belongs to an earlier update.** A later update replaced the pair. Use the passcode that arrived after the latest update call. +- **You lost the transaction id.** Issue the update again. +- **You called `/validate` by mistake.** That call confirms creation. Updates are confirmed here. +- **The old certificate is still served.** Counterparties cache certificates for up to 24 hours. Keep your old private key available until that window has passed. +- **401 Unauthorized.** The token is missing, has expired, or went out without the `Bearer ` prefix. Mint a new token, then retry the call once. See [NHCX-401](../errors/nhcx-401.md) and [every call returns 401](../troubleshooting/everything-returns-401.md). diff --git a/catalogue/nhcx/endpoints/v2-participant-create.md b/catalogue/nhcx/endpoints/v2-participant-create.md new file mode 100644 index 000000000..1c41ce26d --- /dev/null +++ b/catalogue/nhcx/endpoints/v2-participant-create.md @@ -0,0 +1,146 @@ +--- +id: nhcx.endpoint.v2-participant-create +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /v2/participant/create +summary: >- + Start production registration by linking your organisation to its external registry + record, which sends a passcode to your registered mobile. +sources: +- url: https://hcxsbx.abdm.gov.in/images/260d0dec19a681e80262.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Production.pdf + hash: sha256:c38476fb90101f13fdfea447861292718d561e1dc088ae20950b193606500d2e + fetched: '2026-09-14' + note: Onboarding providers and payers in Production, row 5 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Pages 1-2 Step 1 Participant Creation; Page 4 enums. +- url: https://hcxsbx.abdm.gov.in/images/293a43103f575b4e7f7f.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(PROD)_NHCX-OnBoarding APIs Postman Collection.zip + hash: sha256:b96963e2eead0fe3e718eb7dd2374f1a15f0dbb1aed7197a1ceae59cefbc7214 + fetched: '2026-09-14' + note: AWS(PROD)_NHCX-OnBoarding APIs Postman Collection, row 7 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Postman PROD_NHCX-OnBoarding APIs item /v2/participant/create. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1, item 5 In PROD when passing the registry ID. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 3 Q6 and Q9. +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v2/participant/create.post; schema ParticipantCreateV2Resp.' +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. Page 9 Integrator Journey. +verified: + status: unverified +related: + concepts: + - nhcx.concept.participant-registry + - nhcx.concept.participant-code + - nhcx.concept.participant-roles + flows: + - nhcx.flow.production-onboarding + endpoints: + - nhcx.endpoint.validate + - nhcx.endpoint.participant-create + - nhcx.endpoint.v2-participant-update + - nhcx.endpoint.session-token + errors: + - nhcx.error.nhcx-401 + sandbox: + - nhcx.sandbox.going-live +--- + +# POST /v2/participant/create + +## In plain words + +This call starts production registration in the [NHCX](../../shared/glossary/nhcx.md) participant registry. It links your organisation to its record in an external registry. It then sends a passcode to the mobile number on that record. + +You confirm the registration with [`/validate`](validate.md). Your [participant code](../glossary/participant-code.md) is confirmed only after that call succeeds. + +In production, use this call. In the sandbox, use [`/participant/create`](participant-create.md). + +## Before you start + +- Sandbox exit is complete and your production client id carries your role. See [going live](../sandbox/going-live.md). +- A current production access token from the [session call](session-token.md). +- Your registry id. A [provider](../glossary/provider.md) sends its [HFR](../../shared/glossary/hfr.md) ID. A [payer](../glossary/payer.md) or [TPA](../glossary/tpa.md) sends its [IRDAI](../glossary/irdai.md) registry ID without leading zeros: `0123` goes as `123`. +- The mobile number already on record. For a provider it must match the HFR record. For a payer it must match the NHCX payer details. +- The person who holds that phone, ready to read you the passcode within 24 hours. + +## What happens + +1. Your system posts the registry link to the production participant service. +2. The registry validates the registry type, the role and the mobile number. +3. It answers on the same connection with your participant id and a `transactionid`. A passcode goes to the registered mobile number. +4. You call [`/validate`](validate.md) with the `transactionid` and the passcode within 24 hours. + +```bash +curl -X POST 'https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice/v2/participant/create' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -d '{ + "registrytype": "", + "registryid": "", + "role": [""], + "endpoint_url": "", + "mobilenumber": "", + "email": "" + }' +``` + +Send all three headers on every participant service call: `Accept`, `Content-Type` and `bearer_auth`. The token header is `bearer_auth`, not `Authorization`. + +| Field | What to send | +|---|---| +| `registrytype` | HFR `10001`, NIN `10002`, ROHINI `10003` or PAYER `10004`. Providers and EUAs use `10001`. Payers and TPAs use `10004`. | +| `registryid` | HFR ID for a provider. IRDAI ID, without leading zeros, for a payer or TPA. Client id for an [EUA](../../shared/glossary/eua.md). | +| `role` | An array of role codes: PROVIDER `10001`, PAYER `10002`, AGENCY_TPA `10003`, AGENCY_REGULATOR `10004`, RESEARCH `10005`, MEMBER_ISNP `10006`, AGENCY_SPONSOR `10007`, HIE_HIO_HCX `10008`, EUA `10009`. | +| `endpoint_url` | Your bridge URL. | +| `mobilenumber` | The mobile number on record. | +| `email` | Your registered email. | + +The response body has this shape: + +```json +{ + "participantid": "", + "facilityname": "", + "facilitycontact": "", + "facilityemail": "", + "transactionid": "", + "error": { + "code": null, + "message": null, + "trace": null + } +} +``` + +**Idempotency.** Each call generates a new `transactionid` and sends a new passcode. A passcode works only with its own transaction id. Confirm the pair from the call you intend to keep. If you lose the transaction id, call create again and use the new pair. + +## How you know it worked + +You receive HTTP 200 with `participantid` and `transactionid` filled in and `error.code` null. + +A passcode arrives on the registered mobile number. You now hold the transaction id and the passcode, and less than 24 hours have passed since the call. + +The step is complete when [`/validate`](validate.md) returns 200 for that pair. + +## When it goes wrong + +- **The mobile number does not match.** The number must match the HFR record for a provider, or the NHCX payer details for a payer. Send the number on record, or correct the record first. +- **The IRDAI ID has leading zeros.** Strip them: `0123` goes as `123`. +- **Wrong role or registry code.** A wrong mapping leads to rejected requests or misrouted transactions later. `10001` is PROVIDER as a role and HFR as a registry type. +- **The transaction id is lost, or 24 hours have passed.** Call create again. Validate the new pair. +- **401 Unauthorized.** The token is missing, has expired, or went out without the `Bearer ` prefix. Mint a new token, then retry the call once. See [NHCX-401](../errors/nhcx-401.md) and [every call returns 401](../troubleshooting/everything-returns-401.md). diff --git a/catalogue/nhcx/endpoints/v2-participant-delink-abha-policy.md b/catalogue/nhcx/endpoints/v2-participant-delink-abha-policy.md new file mode 100644 index 000000000..3fec43c40 --- /dev/null +++ b/catalogue/nhcx/endpoints/v2-participant-delink-abha-policy.md @@ -0,0 +1,100 @@ +--- +id: nhcx.endpoint.v2-participant-delink-abha-policy +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /V2/participant/delink/abha/policy +summary: >- + The second path for removing products from a beneficiary's policy link; it takes + the same body as the main de-link call. +sources: +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./V2/participant/delink/abha/policy.post.' +- url: https://hcxsbx.abdm.gov.in/images/539853c50347b32b9a5e.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Policy Linking and De-Linking Process.pdf + hash: sha256:420115b9a54e15fa625312a56362164d92d23dd0d6ebf9195135bb00055d1911 + fetched: '2026-09-14' + note: Policy Linking and De-Linking Process, row 8 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 2, Validation for De-Linking. +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1, Use case 3 De-Link ABHA from Policy. +- url: https://hcxsbx.abdm.gov.in/images/b885e59891fedc7e725c.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-PARTICIPANT SERVICE_APIs Postman Collection.zip + hash: sha256:2d082f244ee41d137a62af82380dcd2d5db9ebbab66824fd54a23c506d4d9a7f + fetched: '2026-09-14' + note: AWS(Sandbox)-PARTICIPANT SERVICE_APIs Postman Collection, row 16 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Postman SANDBOX-Participant_APIs item Delink Abha. +verified: + status: unverified +related: + concepts: + - nhcx.concept.policy-linking + flows: + - nhcx.flow.policy-link-and-delink + endpoints: + - nhcx.endpoint.participant-delink-abha-policy + - nhcx.endpoint.v2-participant-link-abha-policy + - nhcx.endpoint.v2-participant-get-policies + errors: + - nhcx.error.nhcx-401 +--- + +# POST /V2/participant/delink/abha/policy + +## In plain words + +This path removes products from a beneficiary's policy link, like [`/participant/delink/abha/policy`](participant-delink-abha-policy.md). It takes the same body and returns the same response. + +Call [`/participant/delink/abha/policy`](participant-delink-abha-policy.md), the path in the payer [sandbox exit](../glossary/sandbox-exit.md). If you use the V2 paths, pair this with [`/V2/participant/link/abha/policy`](v2-participant-link-abha-policy.md) and [`/V2/participant/get/policies`](v2-participant-get-policies.md). + +## Before you start + +- The same as for [`/participant/delink/abha/policy`](participant-delink-abha-policy.md): the products are linked, you are the `payerid` or `processingid` participant, and your token comes from that participant's client id. + +## What happens + +Your system posts the products to remove. NHCX checks the client id in your token against the linking participants, removes the products and answers on the same connection. No callback follows. + +| Environment | Participant service base URL | +|---|---| +| Sandbox | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice` | +| Production | `https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice` | + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/V2/participant/delink/abha/policy' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -d '{ + "requestid": "", + "payerid": "", + "memberid": "", + "processingid": "", + "policies": [ + { + "productid": "", + "productname": "" + } + ] + }' +``` + +The path starts with a capital `V2`. The fields are described on [`/participant/delink/abha/policy`](participant-delink-abha-policy.md). + +**Idempotency.** Send a new `requestid` on every call. A repeat after success returns `There is no policies with requested details`. + +## How you know it worked + +You receive HTTP 200. [`/V2/participant/get/policies`](v2-participant-get-policies.md) no longer returns the removed products for that payer. + +## When it goes wrong + +- **404 on the path.** The path was written with a lower-case `v2`. Write `/V2/participant/delink/abha/policy`. +- **The de-link is refused with an error message.** The token does not belong to the `payerid` or `processingid` participant. +- **`There is no policies with requested details`.** A listed product is not linked for this `payerid` and `memberid`. +- **401 Unauthorized.** The token is missing, has expired, or went out without the `Bearer ` prefix. Mint a new token, then retry the call once. See [NHCX-401](../errors/nhcx-401.md) and [every call returns 401](../troubleshooting/everything-returns-401.md). diff --git a/catalogue/nhcx/endpoints/v2-participant-get-policies.md b/catalogue/nhcx/endpoints/v2-participant-get-policies.md new file mode 100644 index 000000000..e313622eb --- /dev/null +++ b/catalogue/nhcx/endpoints/v2-participant-get-policies.md @@ -0,0 +1,110 @@ +--- +id: nhcx.endpoint.v2-participant-get-policies +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /V2/participant/get/policies +summary: >- + The second path for looking up a beneficiary's linked policies; it takes the same + body as the main lookup. +sources: +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./V2/participant/get/policies.post.' +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 2, item 7 Providers pointing to the PayerID. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 5.6.2 Supported Identifier Types. +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1, Use case 2 Get Policy. +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1, Use case 2 Get Policy. +- url: https://hcxsbx.abdm.gov.in/images/539853c50347b32b9a5e.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Policy Linking and De-Linking Process.pdf + hash: sha256:420115b9a54e15fa625312a56362164d92d23dd0d6ebf9195135bb00055d1911 + fetched: '2026-09-14' + note: Policy Linking and De-Linking Process, row 8 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1, For Sandbox / For Production envBaseUrl. +verified: + status: unverified +related: + concepts: + - nhcx.concept.policy-linking + endpoints: + - nhcx.endpoint.participant-get-policies + - nhcx.endpoint.v2-participant-link-abha-policy + - nhcx.endpoint.v2-participant-delink-abha-policy + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1003 +--- + +# POST /V2/participant/get/policies + +## In plain words + +This path returns the policies linked to a beneficiary, like [`/participant/get/policies`](participant-get-policies.md). It takes the same body and returns the same response. + +Call [`/participant/get/policies`](participant-get-policies.md), the path in the provider and payer [sandbox exit](../glossary/sandbox-exit.md). If you use the V2 paths, pair this with [`/V2/participant/link/abha/policy`](v2-participant-link-abha-policy.md) and [`/V2/participant/delink/abha/policy`](v2-participant-delink-abha-policy.md). + +## Before you start + +- A current access token from the [session call](session-token.md). It goes in the `bearer_auth` header as `Bearer `, with `Bearer` and a space in front. +- A payer or TPA has linked the beneficiary. +- An identifier for the beneficiary: an [ABHA number](../../shared/glossary/abha-number.md), a member id or a mobile number. + +## What happens + +Your system posts one identifier. The registry answers on the same connection with the linked policies. Nothing changes and no callback follows. + +| Environment | Participant service base URL | +|---|---| +| Sandbox | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice` | +| Production | `https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice` | + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/V2/participant/get/policies' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -d '{ + "identifiertype": "", + "identifiervalue": "" + }' +``` + +The path starts with a capital `V2`. + +| Field | What to send | +|---|---| +| `identifiertype` | `AbhaNumber`, `MemberId` or `MobileNo`. | +| `identifiervalue` | The value of that identifier. Send an ABHA number as 14 digits without hyphens. | + +Read the processing id from each returned policy. It goes in `x-hcx-recipient_code`, not the payer id. + +**Idempotency.** The call only reads. Repeating it is safe. + +## How you know it worked + +You receive HTTP 200 with at least one linked policy. You hold a processing participant code, a member id and a product for the patient. + +## When it goes wrong + +- **404 on the path.** The path was written with a lower-case `v2`. Write `/V2/participant/get/policies`. +- **Messages to the payer fail with a receiver error.** The payer id went into `x-hcx-recipient_code`. Use the processing id. See [NHCX-1003](../errors/nhcx-1003.md). +- **Nothing is returned for an ABHA number.** Send 14 digits without hyphens, then try `MemberId` and `MobileNo`. +- **401 Unauthorized.** The token is missing, has expired, or went out without the `Bearer ` prefix. Mint a new token, then retry the call once. See [NHCX-401](../errors/nhcx-401.md) and [every call returns 401](../troubleshooting/everything-returns-401.md). diff --git a/catalogue/nhcx/endpoints/v2-participant-link-abha-policy.md b/catalogue/nhcx/endpoints/v2-participant-link-abha-policy.md new file mode 100644 index 000000000..4408b7b72 --- /dev/null +++ b/catalogue/nhcx/endpoints/v2-participant-link-abha-policy.md @@ -0,0 +1,101 @@ +--- +id: nhcx.endpoint.v2-participant-link-abha-policy +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /V2/participant/link/abha/policy +summary: >- + The second path for linking a beneficiary to the products they hold; it takes + the same body as the main link call. +sources: +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./V2/participant/link/abha/policy.post.' +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 2, item 10 Policy Linking/Delinking auth restriction. +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1, Use case 1 Link ABHA with Policy. +- url: https://hcxsbx.abdm.gov.in/images/539853c50347b32b9a5e.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Policy Linking and De-Linking Process.pdf + hash: sha256:420115b9a54e15fa625312a56362164d92d23dd0d6ebf9195135bb00055d1911 + fetched: '2026-09-14' + note: Policy Linking and De-Linking Process, row 8 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1, Policy Linking Process. +verified: + status: unverified +related: + concepts: + - nhcx.concept.policy-linking + flows: + - nhcx.flow.policy-link-and-delink + endpoints: + - nhcx.endpoint.participant-link-abha-policy + - nhcx.endpoint.v2-participant-get-policies + - nhcx.endpoint.v2-participant-delink-abha-policy + errors: + - nhcx.error.nhcx-401 +--- + +# POST /V2/participant/link/abha/policy + +## In plain words + +This path links a beneficiary's [ABHA number](../../shared/glossary/abha-number.md) and member id to the products they hold, like [`/participant/link/abha/policy`](participant-link-abha-policy.md). It takes the same body and returns the same response. + +Call [`/participant/link/abha/policy`](participant-link-abha-policy.md), the path in the payer [sandbox exit](../glossary/sandbox-exit.md). If you use this V2 path, pair it with [`/V2/participant/get/policies`](v2-participant-get-policies.md) and [`/V2/participant/delink/abha/policy`](v2-participant-delink-abha-policy.md). + +## Before you start + +- The same as for [`/participant/link/abha/policy`](participant-link-abha-policy.md): registered participant codes for the insurer and any TPA, and a token minted with the client id used when that participant was created. + +## What happens + +Your system posts the link to the participant service. The registry records it and answers on the same connection. No callback follows. + +| Environment | Participant service base URL | +|---|---| +| Sandbox | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice` | +| Production | `https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice` | + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/V2/participant/link/abha/policy' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -d '{ + "requestid": "", + "abhanumber": "", + "mobilenumber": "", + "memberid": "", + "payerid": "", + "processingid": "", + "policies": [ + { + "productid": "", + "productname": "" + } + ] + }' +``` + +The path starts with a capital `V2`. The fields are described on [`/participant/link/abha/policy`](participant-link-abha-policy.md). The response is JSON with a `result` string. + +**Idempotency.** Send a new `requestid` on every call. Before you retry a link that timed out, check [`/V2/participant/get/policies`](v2-participant-get-policies.md) for the products. + +## How you know it worked + +You receive HTTP 200 with a `result` string. [`/V2/participant/get/policies`](v2-participant-get-policies.md) with the same ABHA number returns the products you linked. + +## When it goes wrong + +- **404 on the path.** The path was written with a lower-case `v2`. Write `/V2/participant/link/abha/policy`. +- **The link is refused although the token is valid.** The token does not belong to the `payerid` or `processingid` participant. +- **401 Unauthorized.** The token is missing, has expired, or went out without the `Bearer ` prefix. Mint a new token, then retry the call once. See [NHCX-401](../errors/nhcx-401.md) and [every call returns 401](../troubleshooting/everything-returns-401.md). diff --git a/catalogue/nhcx/endpoints/v2-participant-update.md b/catalogue/nhcx/endpoints/v2-participant-update.md new file mode 100644 index 000000000..099f4ddb9 --- /dev/null +++ b/catalogue/nhcx/endpoints/v2-participant-update.md @@ -0,0 +1,120 @@ +--- +id: nhcx.endpoint.v2-participant-update +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /v2/participant/update +summary: >- + Stage a production change to your encryption certificate or bridge address, to + be confirmed with a passcode. +sources: +- url: https://hcxsbx.abdm.gov.in/images/260d0dec19a681e80262.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Production.pdf + hash: sha256:c38476fb90101f13fdfea447861292718d561e1dc088ae20950b193606500d2e + fetched: '2026-09-14' + note: Onboarding providers and payers in Production, row 5 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Pages 2-3, Step 3 Participant Updation and Step 4. +- url: https://hcxsbx.abdm.gov.in/images/293a43103f575b4e7f7f.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(PROD)_NHCX-OnBoarding APIs Postman Collection.zip + hash: sha256:b96963e2eead0fe3e718eb7dd2374f1a15f0dbb1aed7197a1ceae59cefbc7214 + fetched: '2026-09-14' + note: AWS(PROD)_NHCX-OnBoarding APIs Postman Collection, row 7 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Postman PROD_NHCX-OnBoarding APIs item /v2/participant/update. +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v2/participant/update.post; schemas ParticipantCertUpdateRequest, ParticipantCertUpdateResp.' +- url: https://hcxsbx.abdm.gov.in/images/be2e25fede3bf711f783.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/PMJAY Hospital Migration to HMIS via NHCX.docx + hash: sha256:cf5c9bf1c402b214f65bbb7bd0822f3a76d8ccda9b69c7bf77ba131befef3bc6 + fetched: '2026-09-14' + note: PMJAY Hospital Migration to HMIS via NHCX, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments, not named in the NHCX document sheet. Section 3.3 Participant Update (Step 3). +- url: https://hcxsbx.abdm.gov.in/images/ec361a6c3e90e766d227.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Steps to generate encryption Certificate.pdf + hash: sha256:94605e935f05ebb49e24dee50787cb4f3f1c401983a9616a5aaabdbc302f664b + fetched: '2026-09-14' + note: Steps to generate encryption Certificate, row 20 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 3, Step 4 Base64 Encoding. +verified: + status: unverified +related: + concepts: + - nhcx.concept.encryption-certificate + - nhcx.concept.participant-registry + flows: + - nhcx.flow.production-onboarding + - nhcx.flow.rotate-certificate + endpoints: + - nhcx.endpoint.update-validate + - nhcx.endpoint.validate + - nhcx.endpoint.v2-update-cert + - nhcx.endpoint.participant-update + - nhcx.endpoint.session-token + errors: + - nhcx.error.nhcx-401 + troubleshooting: + - nhcx.troubleshooting.recipient-cannot-decrypt +--- + +# POST /v2/participant/update + +## In plain words + +This call stages a change to your production record in the [NHCX](../../shared/glossary/nhcx.md) registry. It carries your public encryption certificate, your bridge URL, or both. The registry sends a passcode to your registered mobile number, and the change takes effect when you confirm it with [`/update/validate`](update-validate.md). + +In production, use this call for your first certificate and bridge URL after creation, and for later changes. For a certificate-only change without a passcode, call [`/v2/update/cert`](v2-update-cert.md). In the sandbox, use [`/participant/update`](participant-update.md). + +## Before you start + +- Your participant code is registered and its creation is confirmed with [`/validate`](validate.md). +- Your certificate, Base64 encoded. See [generate and register a certificate](../flows/generate-and-register-certificate.md). +- The matching private key is already deployed where you decrypt inbound messages. +- The person who holds the registered phone, ready to read you the passcode within 24 hours. +- A current access token from the [session call](session-token.md). It goes in the `bearer_auth` header as `Bearer `, with `Bearer` and a space in front. + +## What happens + +1. Your system posts the change to the production participant service. +2. The registry answers on the same connection with a `transactionid` and sends a passcode to the registered mobile number. +3. You call [`/update/validate`](update-validate.md) with both within 24 hours. The change goes live then. + +```bash +curl -X POST 'https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice/v2/participant/update' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -d '{ + "participantcode": "", + "encryptioncert": "", + "endpointurl": "" + }' +``` + +Send all three headers on every participant service call: `Accept`, `Content-Type` and `bearer_auth`. The token header is `bearer_auth`, not `Authorization`. + +The field names here have no underscores: `participantcode`, `encryptioncert`, `endpointurl`. + +The response body has this shape: + +```json +{ + "participant_code": "", + "status": "", + "transactionid": "" +} +``` + +**Idempotency.** Each call issues a new `transactionid` and a new passcode. A passcode works only with its own transaction id. If you lose the transaction id, issue the update again. + +## How you know it worked + +You receive HTTP 200 with your `participant_code` and a `transactionid`. A passcode arrives on the registered mobile number. + +The change is live only when [`/update/validate`](update-validate.md) returns 200 for that pair. Then [`/fetch/certs`](fetch-certs.md) with your own code returns the new certificate. + +## When it goes wrong + +- **The participant code is refused.** Creation is not yet confirmed. Call [`/validate`](validate.md) first. +- **The certificate is refused.** It went as raw PEM. Base64 encode the whole PEM text. +- **You skipped `/update/validate`.** The old certificate and bridge URL stay live. Validate the pair. +- **Inbound messages stop decrypting after the change.** The new private key was not deployed first. See [recipient cannot decrypt](../troubleshooting/recipient-cannot-decrypt.md). +- **401 Unauthorized.** The token is missing, has expired, or went out without the `Bearer ` prefix. Mint a new token, then retry the call once. See [NHCX-401](../errors/nhcx-401.md) and [every call returns 401](../troubleshooting/everything-returns-401.md). diff --git a/catalogue/nhcx/endpoints/v2-update-cert.md b/catalogue/nhcx/endpoints/v2-update-cert.md new file mode 100644 index 000000000..4e5270f3b --- /dev/null +++ b/catalogue/nhcx/endpoints/v2-update-cert.md @@ -0,0 +1,99 @@ +--- +id: nhcx.endpoint.v2-update-cert +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: POST /v2/update/cert +summary: >- + Replace your production encryption certificate in the registry without a passcode + step. +sources: +- url: https://hcxsbx.abdm.gov.in/images/260d0dec19a681e80262.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Production.pdf + hash: sha256:c38476fb90101f13fdfea447861292718d561e1dc088ae20950b193606500d2e + fetched: '2026-09-14' + note: Onboarding providers and payers in Production, row 5 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 4, Participant Certificate Updation. +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v2/update/cert.post; schema UpdateCertV2.' +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 3.3 Certificate Fetch. +- url: https://hcxsbx.abdm.gov.in/images/ec361a6c3e90e766d227.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Steps to generate encryption Certificate.pdf + hash: sha256:94605e935f05ebb49e24dee50787cb4f3f1c401983a9616a5aaabdbc302f664b + fetched: '2026-09-14' + note: Steps to generate encryption Certificate, row 20 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 3, Step 4 Base64 Encoding. +verified: + status: unverified +related: + concepts: + - nhcx.concept.encryption-certificate + flows: + - nhcx.flow.rotate-certificate + - nhcx.flow.generate-and-register-certificate + endpoints: + - nhcx.endpoint.v2-participant-update + - nhcx.endpoint.participant-update + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.session-token + errors: + - nhcx.error.nhcx-401 + troubleshooting: + - nhcx.troubleshooting.recipient-cannot-decrypt +--- + +# POST /v2/update/cert + +## In plain words + +This call replaces the public encryption certificate on your production record in the [NHCX](../../shared/glossary/nhcx.md) registry. It needs no passcode. Only the certificate changes; your bridge URL stays as it is. + +To change the bridge URL too, call [`/v2/participant/update`](v2-participant-update.md) and confirm with [`/update/validate`](update-validate.md). In the sandbox, change your certificate with [`/participant/update`](participant-update.md). + +## Before you start + +- Your production [participant code](../glossary/participant-code.md). +- The new certificate, Base64 encoded. See [generate and register a certificate](../flows/generate-and-register-certificate.md). +- The matching private key is already deployed where you decrypt inbound messages. +- A current access token from the [session call](session-token.md). It goes in the `bearer_auth` header as `Bearer `, with `Bearer` and a space in front. + +## What happens + +Your system posts the participant id and the new certificate. The registry replaces the certificate and answers on the same connection. No callback follows. + +```bash +curl -X POST 'https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice/v2/update/cert' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -d '{ + "participantId": "", + "certificate": "" + }' +``` + +Send all three headers on every participant service call: `Accept`, `Content-Type` and `bearer_auth`. The token header is `bearer_auth`, not `Authorization`. + +Both fields are mandatory. Note the casing: `participantId` with a capital I, and `certificate`. + +**Idempotency.** Each call writes the certificate you send. Before you retry a call that timed out, fetch your own certificate with [`/fetch/certs`](fetch-certs.md) and compare. + +## How you know it worked + +You receive HTTP 200. [`/fetch/certs`](fetch-certs.md) with your own participant code returns the new certificate. + +Counterparties cache certificates for up to 24 hours. Keep the old private key available for that long, so messages sealed with the old certificate still open. + +## When it goes wrong + +- **The certificate is refused.** It went as raw PEM. Base64 encode the whole PEM text. +- **A field is refused.** The body used `participant_code`, `participantcode` or `encryptioncert`. This call takes `participantId` and `certificate`. +- **Inbound messages stop decrypting.** The new certificate went live before its private key. Deploy the key first. See [recipient cannot decrypt](../troubleshooting/recipient-cannot-decrypt.md). +- **The bridge URL did not change.** This call changes only the certificate. Use [`/v2/participant/update`](v2-participant-update.md). +- **401 Unauthorized.** The token is missing, has expired, or went out without the `Bearer ` prefix. Mint a new token, then retry the call once. See [NHCX-401](../errors/nhcx-401.md) and [every call returns 401](../troubleshooting/everything-returns-401.md). diff --git a/catalogue/nhcx/endpoints/validate.md b/catalogue/nhcx/endpoints/validate.md new file mode 100644 index 000000000..b0e246345 --- /dev/null +++ b/catalogue/nhcx/endpoints/validate.md @@ -0,0 +1,97 @@ +--- +id: nhcx.endpoint.validate +type: endpoint +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: GET /validate +summary: >- + Confirm a production participant creation with the transaction id and the passcode + sent to your registered mobile. +sources: +- url: https://hcxsbx.abdm.gov.in/images/260d0dec19a681e80262.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Production.pdf + hash: sha256:c38476fb90101f13fdfea447861292718d561e1dc088ae20950b193606500d2e + fetched: '2026-09-14' + note: Onboarding providers and payers in Production, row 5 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 2, Step 2 Participant Creation confirmation; Page 3 notes. +- url: https://hcxsbx.abdm.gov.in/images/293a43103f575b4e7f7f.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(PROD)_NHCX-OnBoarding APIs Postman Collection.zip + hash: sha256:b96963e2eead0fe3e718eb7dd2374f1a15f0dbb1aed7197a1ceae59cefbc7214 + fetched: '2026-09-14' + note: AWS(PROD)_NHCX-OnBoarding APIs Postman Collection, row 7 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Postman PROD_NHCX-OnBoarding APIs item /validate. +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./validate.get.' +- url: https://hcxsbx.abdm.gov.in/images/be2e25fede3bf711f783.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/PMJAY Hospital Migration to HMIS via NHCX.docx + hash: sha256:cf5c9bf1c402b214f65bbb7bd0822f3a76d8ccda9b69c7bf77ba131befef3bc6 + fetched: '2026-09-14' + note: PMJAY Hospital Migration to HMIS via NHCX, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments, not named in the NHCX document sheet. Section 3.2 Participant Confirmation (Step 2). +- url: https://hcxsbx.abdm.gov.in/images/bc2efb078b98548f8e6b.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Sandbox.pdf + hash: sha256:cbd03baf428655f0305e2f60ca331f8b76700496b070c522cafcc95001710b3a + fetched: '2026-09-14' + note: Onboarding providers and payers in Sandbox, row 4 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Page 1, API Definition - Create Participant. +verified: + status: unverified +related: + flows: + - nhcx.flow.production-onboarding + endpoints: + - nhcx.endpoint.v2-participant-create + - nhcx.endpoint.update-validate + - nhcx.endpoint.v2-participant-update + - nhcx.endpoint.session-token + errors: + - nhcx.error.nhcx-401 + concepts: + - nhcx.concept.participant-registry +--- + +# GET /validate + +## In plain words + +This call confirms a production participant creation in the [NHCX](../../shared/glossary/nhcx.md) registry. You send the `transactionid` from [`/v2/participant/create`](v2-participant-create.md) and the passcode sent to your registered mobile number. Until it succeeds, your [participant code](../glossary/participant-code.md) is not confirmed. + +It confirms creation only. To confirm an update, call [`/update/validate`](update-validate.md). + +## Before you start + +- A `transactionid` from [`/v2/participant/create`](v2-participant-create.md), less than 24 hours old. +- The passcode for that transaction, from the registered mobile number. A passcode works only with its own transaction id. +- A current access token from the [session call](session-token.md). It goes in the `bearer_auth` header as `Bearer `, with `Bearer` and a space in front. + +## What happens + +Your system sends a GET with two query parameters. The registry checks the passcode against the transaction and answers on the same connection. There is no request body and no callback. + +```bash +curl -G 'https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice/validate' \ + -H 'Accept: application/json' \ + -H 'bearer_auth: Bearer ' \ + --data-urlencode 'transactionId=' \ + --data-urlencode 'passcode=' +``` + +The query parameter is `transactionId`, with a capital I. The create response spells the field `transactionid`. + +This is the production address. In the sandbox, [`/participant/create`](participant-create.md) returns your participant code directly, with no confirmation step. + +**Idempotency.** Call it once per transaction. If it fails, or the pair is older than 24 hours, call [`/v2/participant/create`](v2-participant-create.md) again and validate the new pair. + +## How you know it worked + +You receive HTTP 200. Your participant code is now confirmed. + +[`/v2/participant/update`](v2-participant-update.md) now accepts that code for your certificate and bridge URL. Before confirmation it refuses the code. + +## When it goes wrong + +- **More than 24 hours have passed.** The transaction id and passcode have expired. Start again from [`/v2/participant/create`](v2-participant-create.md). +- **The passcode belongs to another transaction.** Create was called again, so a new pair was issued. Use the passcode that arrived after the latest create, with that call's transaction id. +- **You lost the transaction id.** Call create again and validate the new pair. +- **You called `/update/validate` by mistake.** That call confirms updates. Creation is confirmed here. +- **401 Unauthorized.** The token is missing, has expired, or went out without the `Bearer ` prefix. Mint a new token, then retry the call once. See [NHCX-401](../errors/nhcx-401.md) and [every call returns 401](../troubleshooting/everything-returns-401.md). diff --git a/catalogue/nhcx/errors/err-pyr-clm-007.md b/catalogue/nhcx/errors/err-pyr-clm-007.md new file mode 100644 index 000000000..7d22f0236 --- /dev/null +++ b/catalogue/nhcx/errors/err-pyr-clm-007.md @@ -0,0 +1,73 @@ +--- +id: nhcx.error.err-pyr-clm-007 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'ERR-PYR-CLM-007: no preauthorisation or claim exists for the claim''s case + number' +summary: >- + The national scheme's reference payer found no earlier preauthorisation or claim + under the case number on your claim, so raise the claim under the preauthorisation's + case number. +sources: +- file: catalogue/openapi/.raw/nhcx-package-2026-09-15/nhcx-error.yaml + hash: sha256:d24ac927ed4dd722e60d7bd1d6fed15de370cc29f750d68999ee56fac93c941b + note: Recorded from a sandbox run. On none of the NHA error sheets. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.claim-submit + - nhcx.flow.preauth-submit + - nhcx.flow.pmjay-patient-to-cashless + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + errors: + - nhcx.error.payr-1302 +--- + +# ERR-PYR-CLM-007: no preauthorisation or claim exists for the claim's case number + +## In plain words + +The [PMJAY](../glossary/pmjay.md) payer refused your claim because it found no preauthorisation or claim under the case number you sent. + +It returns this code when a claim carries a case number of its own instead of the preauthorisation's. + +## Before you start + +You sent a request through [NHCX](../../shared/glossary/nhcx.md), and the payer answered it with an error. The answer arrives on the `on_` path paired with your request, such as `/v1/claim/on_submit`. `x-hcx-status` marks it as an error. `x-hcx-error_details` carries the code in `code` and the text in `message`. + +Read these fields from the protected header once you open the [JWE](../glossary/jwe.md). Some payers send the same fields in a plain `ProtocolResponse` body instead. Handle both. + +The code sits outside the PAYR- ranges. Match it by its full text: `No prior preauthorization or claim record found for case number`. + +## What happens + +The PMJAY payer raises this code when: + +- The claim uses a new case number instead of the one the preauthorisation was raised under. +- The case number has a typo. +- No preauthorisation was raised for the case. + +The case number travels as an identifier of the parent resource, the Claim. + +## How you know it worked + +Send the corrected request. The step is done when the payer answers without this code: + +- For a claim, `/v1/claim/on_submit` arrives with no `x-hcx-error_details`, and its bundle carries a `ClaimResponse`. + +## When it goes wrong + +1. Raise the claim under the case number the preauthorisation used. Carry it in the Claim resource's identifier. +2. Keep the case number with the case in your system from preauthorisation onwards. +3. If no preauthorisation exists, submit one first. See [Submit a preauthorisation](../flows/preauth-submit.md). +4. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/nhcx-1001.md b/catalogue/nhcx/errors/nhcx-1001.md new file mode 100644 index 000000000..dff1bca3a --- /dev/null +++ b/catalogue/nhcx/errors/nhcx-1001.md @@ -0,0 +1,82 @@ +--- +id: nhcx.error.nhcx-1001 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'NHCX-1001: the recipient''s system is not reachable' +summary: >- + The exchange could not deliver your message because the recipient's endpoint did + not answer, so send the request again once the recipient is reachable. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet NHCX Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.retries-and-expiry + - nhcx.concept.synchronous-acknowledgement + flows: + - nhcx.flow.send-a-sealed-request + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.status-check + callbacks: + - nhcx.callback.error + errors: + - nhcx.error.nhcx-1006 + sandbox: + - nhcx.sandbox.callback-url-requirements + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback +--- + +# NHCX-1001: the recipient's system is not reachable + +## In plain words + +The [NHCX](../../shared/glossary/nhcx.md) accepted your message but could not deliver it. The recipient's registered endpoint did not answer. + +This is a transport failure. Nothing in your content caused it. + +## Before you start + +You sent a message through NHCX. The exchange returns a gateway code in one of two places: + +- The synchronous acknowledgement to your call. The code is in `error.code` and the text in `error.message`. +- A report posted to your own `/v1/error` endpoint. The code is in `x-hcx-error_details.code`, the text in `x-hcx-error_details.message`, and `x-hcx-correlation_id` names the request. + +The `/v1/error` report is a plain `ProtocolResponse` body, not a sealed payload. Your system must host `/v1/error` to see it. See [Receiving POST /v1/error](../callbacks/error.md). + +When a delivery fails, the exchange retries the same request five times. After the fifth failure it deletes the request and retires its correlation id. The report then arrives on your `/v1/error`. + +## What happens + +The exchange raises this code when: + +- The recipient's registered endpoint is down or refuses the connection. +- The recipient's endpoint does not answer within 30 seconds. +- The recipient's registered endpoint address cannot be reached from the exchange. + +## How you know it worked + +You send the request again with a fresh `x-hcx-correlation_id`. Your call returns HTTP 202 with an acknowledgement in which `error.code` and `error.message` are empty strings. + +No report for the new correlation id arrives on your `/v1/error`. The recipient's answer arrives on the `on_` path paired with your request. + +## When it goes wrong + +### If you sent the request + +1. Mark the case as undelivered. The original request is dead and no answer will come for it. +2. Once the recipient is reachable, send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). +3. If the failures continue, contact the recipient, or NHCX support. See [support contacts](../sandbox/support-contacts.md). + +### If you are the recipient + +1. Check that your registered endpoint is reachable from outside your network over HTTPS. See [callback URL requirements](../sandbox/callback-url-requirements.md). +2. Answer every delivery with HTTP 202 within 30 seconds, then process it. See [the 202 acknowledgement](../concepts/synchronous-acknowledgement.md). diff --git a/catalogue/nhcx/errors/nhcx-1002.md b/catalogue/nhcx/errors/nhcx-1002.md new file mode 100644 index 000000000..19b9067fe --- /dev/null +++ b/catalogue/nhcx/errors/nhcx-1002.md @@ -0,0 +1,71 @@ +--- +id: nhcx.error.nhcx-1002 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'NHCX-1002: the sender is not a registered participant' +summary: >- + The exchange does not know the sender named on your message, so register as a + participant or correct the sender code before sending again. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet NHCX Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.participant-registry + - nhcx.concept.participant-code + flows: + - nhcx.flow.send-a-sealed-request + - nhcx.flow.sandbox-onboarding + - nhcx.flow.production-onboarding + callbacks: + - nhcx.callback.error + endpoints: + - nhcx.endpoint.participant-search +--- + +# NHCX-1002: the sender is not a registered participant + +## In plain words + +The [NHCX](../../shared/glossary/nhcx.md) does not recognise the sender of your message. Your organisation is not registered as a participant, or the sender code on the message is wrong. + +Nothing was forwarded. + +## Before you start + +You sent a message through NHCX. The exchange returns a gateway code in one of two places: + +- The synchronous acknowledgement to your call. The code is in `error.code` and the text in `error.message`. +- A report posted to your own `/v1/error` endpoint. The code is in `x-hcx-error_details.code`, the text in `x-hcx-error_details.message`, and `x-hcx-correlation_id` names the request. + +The `/v1/error` report is a plain `ProtocolResponse` body, not a sealed payload. Your system must host `/v1/error` to see it. See [Receiving POST /v1/error](../callbacks/error.md). + +The exchange checks the sender on your envelope before it forwards anything. + +## What happens + +The exchange raises this code when: + +- Your organisation has not completed participant registration in the environment you are calling. +- `x-hcx-sender_code` in the protected header is not your [participant code](../glossary/participant-code.md). A typo, or a code from the other environment, produces this. + +## How you know it worked + +Send the corrected request. Your call returns HTTP 202 with an acknowledgement in which `error.code` and `error.message` are empty strings. `result.protocol_status` is `request.queued` or `request.dispatched`. + +No report for that `x-hcx-correlation_id` arrives on your `/v1/error`. The recipient's answer arrives later on the `on_` path paired with your request. + +## When it goes wrong + +1. Register your organisation as a participant. See [Onboard as a participant in the NHCX sandbox](../flows/sandbox-onboarding.md) or [Onboard as a participant in production](../flows/production-onboarding.md). +2. Set `x-hcx-sender_code` to the participant code the registry issued you. +3. Confirm the code with [POST /participant/search](../endpoints/participant-search.md). +4. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/nhcx-1003.md b/catalogue/nhcx/errors/nhcx-1003.md new file mode 100644 index 000000000..f81534d89 --- /dev/null +++ b/catalogue/nhcx/errors/nhcx-1003.md @@ -0,0 +1,74 @@ +--- +id: nhcx.error.nhcx-1003 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'NHCX-1003: the recipient is not a registered participant' +summary: >- + The exchange does not know the recipient your message is addressed to, so correct + the recipient code before sending again. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet NHCX Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.participant-registry + - nhcx.concept.participant-code + - nhcx.concept.policy-linking + flows: + - nhcx.flow.send-a-sealed-request + callbacks: + - nhcx.callback.error + endpoints: + - nhcx.endpoint.participant-get-policies + - nhcx.endpoint.v2-participant-get-policies + - nhcx.endpoint.participant-search + errors: + - nhcx.error.nhcx-1004 +--- + +# NHCX-1003: the recipient is not a registered participant + +## In plain words + +The [NHCX](../../shared/glossary/nhcx.md) does not recognise the recipient your message is addressed to. The recipient code is wrong, or that organisation is not registered. + +Nothing was forwarded. + +## Before you start + +You sent a message through NHCX. The exchange returns a gateway code in one of two places: + +- The synchronous acknowledgement to your call. The code is in `error.code` and the text in `error.message`. +- A report posted to your own `/v1/error` endpoint. The code is in `x-hcx-error_details.code`, the text in `x-hcx-error_details.message`, and `x-hcx-correlation_id` names the request. + +The `/v1/error` report is a plain `ProtocolResponse` body, not a sealed payload. Your system must host `/v1/error` to see it. See [Receiving POST /v1/error](../callbacks/error.md). + +The exchange checks the recipient on your envelope before it forwards anything. + +## What happens + +The exchange raises this code when: + +- `x-hcx-recipient_code` matches no participant in the registry. +- As a provider, you used `PayerID` from the policy lookup instead of `processingID`. The processing id is the recipient code. +- The code belongs to the other environment. + +## How you know it worked + +Send the corrected request. Your call returns HTTP 202 with an acknowledgement in which `error.code` and `error.message` are empty strings. `result.protocol_status` is `request.queued` or `request.dispatched`. + +No report for that `x-hcx-correlation_id` arrives on your `/v1/error`. The recipient's answer arrives later on the `on_` path paired with your request. + +## When it goes wrong + +1. Take the recipient code from `processingID` in the policy lookup, not from `PayerID`. See [POST /participant/get/policies](../endpoints/participant-get-policies.md). +2. Confirm the code with [POST /participant/search](../endpoints/participant-search.md). +3. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/nhcx-1004.md b/catalogue/nhcx/errors/nhcx-1004.md new file mode 100644 index 000000000..afaad0add --- /dev/null +++ b/catalogue/nhcx/errors/nhcx-1004.md @@ -0,0 +1,72 @@ +--- +id: nhcx.error.nhcx-1004 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'NHCX-1004: no recipient is registered for the scheme you asked for' +summary: >- + The exchange found no recipient registered for the scheme on your message, so + take the recipient code from the beneficiary's policy and send again. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet NHCX Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.participant-registry + - nhcx.concept.policy-linking + flows: + - nhcx.flow.send-a-sealed-request + callbacks: + - nhcx.callback.error + endpoints: + - nhcx.endpoint.participant-get-policies + - nhcx.endpoint.v2-participant-get-policies + errors: + - nhcx.error.nhcx-1003 +--- + +# NHCX-1004: no recipient is registered for the scheme you asked for + +## In plain words + +The [NHCX](../../shared/glossary/nhcx.md) found no recipient registered for the scheme on your message. The recipient details do not fit the scheme that the policy belongs to. + +Nothing was forwarded. + +## Before you start + +You sent a message through NHCX. The exchange returns a gateway code in one of two places: + +- The synchronous acknowledgement to your call. The code is in `error.code` and the text in `error.message`. +- A report posted to your own `/v1/error` endpoint. The code is in `x-hcx-error_details.code`, the text in `x-hcx-error_details.message`, and `x-hcx-correlation_id` names the request. + +The `/v1/error` report is a plain `ProtocolResponse` body, not a sealed payload. Your system must host `/v1/error` to see it. See [Receiving POST /v1/error](../callbacks/error.md). + +The exchange checks the recipient on your envelope before it forwards anything. + +## What happens + +The exchange raises this code when: + +- The recipient code does not belong to a payer registered for the scheme. +- As a provider, the recipient code did not come from the policy lookup for this beneficiary's policy. + +## How you know it worked + +Send the corrected request. Your call returns HTTP 202 with an acknowledgement in which `error.code` and `error.message` are empty strings. `result.protocol_status` is `request.queued` or `request.dispatched`. + +No report for that `x-hcx-correlation_id` arrives on your `/v1/error`. The recipient's answer arrives later on the `on_` path paired with your request. + +## When it goes wrong + +1. Look up the beneficiary's policies and take `processingID` from the policy you are sending against. See [POST /participant/get/policies](../endpoints/participant-get-policies.md). +2. Put that value in `x-hcx-recipient_code`. +3. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). +4. If the lookup gives no usable recipient for the scheme, contact NHCX support. See [support contacts](../sandbox/support-contacts.md). diff --git a/catalogue/nhcx/errors/nhcx-1005.md b/catalogue/nhcx/errors/nhcx-1005.md new file mode 100644 index 000000000..ab40c38f4 --- /dev/null +++ b/catalogue/nhcx/errors/nhcx-1005.md @@ -0,0 +1,73 @@ +--- +id: nhcx.error.nhcx-1005 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'NHCX-1005: a request header is missing or not valid' +summary: >- + The exchange refused your call because a header is missing or holds a value it + cannot accept, so fill every mandatory header and send again. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet NHCX Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.workflow-codes + flows: + - nhcx.flow.send-a-sealed-request + callbacks: + - nhcx.callback.error + errors: + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1018 +--- + +# NHCX-1005: a request header is missing or not valid + +## In plain words + +The [NHCX](../../shared/glossary/nhcx.md) refused your call because a header is missing or holds a value it cannot accept. + +The fault is in the envelope, not in the sealed content. Nothing was forwarded. + +## Before you start + +You sent a message through NHCX. The exchange returns a gateway code in one of two places: + +- The synchronous acknowledgement to your call. The code is in `error.code` and the text in `error.message`. +- A report posted to your own `/v1/error` endpoint. The code is in `x-hcx-error_details.code`, the text in `x-hcx-error_details.message`, and `x-hcx-correlation_id` names the request. + +The `/v1/error` report is a plain `ProtocolResponse` body, not a sealed payload. Your system must host `/v1/error` to see it. See [Receiving POST /v1/error](../callbacks/error.md). + +## What happens + +The exchange raises this code when: + +- A mandatory header in the [protected header](../glossary/protected-header.md) is missing or empty. The envelope carries `x-hcx-sender_code`, `x-hcx-recipient_code`, `x-hcx-api_call_id`, `x-hcx-correlation_id`, `x-hcx-workflow_id`, `x-hcx-timestamp` and `x-hcx-status`. +- `x-hcx-api_call_id` or `x-hcx-correlation_id` is not a UUID. +- An HTTP header is missing. Every call carries `Accept: application/json`, `Content-Type: application/json` and `bearer_auth`. + +## How you know it worked + +Send the corrected request. Your call returns HTTP 202 with an acknowledgement in which `error.code` and `error.message` are empty strings. `result.protocol_status` is `request.queued` or `request.dispatched`. + +No report for that `x-hcx-correlation_id` arrives on your `/v1/error`. The recipient's answer arrives later on the `on_` path paired with your request. + +## When it goes wrong + +1. Compare your protected header with [the x-hcx protocol headers](../concepts/protocol-headers.md). Fill every mandatory header. +2. Generate a new UUID for each `x-hcx-api_call_id`, and one per request cycle for `x-hcx-correlation_id`. +3. Set `x-hcx-workflow_id` to the code for this stage. See [workflow codes](../concepts/workflow-codes.md). +4. Send `Accept`, `Content-Type` and `bearer_auth` on the HTTP call. +5. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). + +An invalid `x-hcx-status` has its own code, [NHCX-1011](nhcx-1011.md). A badly formatted ABHA number has [NHCX-1018](nhcx-1018.md). diff --git a/catalogue/nhcx/errors/nhcx-1006.md b/catalogue/nhcx/errors/nhcx-1006.md new file mode 100644 index 000000000..ff21700f1 --- /dev/null +++ b/catalogue/nhcx/errors/nhcx-1006.md @@ -0,0 +1,71 @@ +--- +id: nhcx.error.nhcx-1006 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'NHCX-1006: the correlation id has already been used' +summary: >- + The exchange already holds a request with this correlation id, so send the request + again with a new correlation id. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet NHCX Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.message-identifiers + - nhcx.concept.retries-and-expiry + flows: + - nhcx.flow.send-a-sealed-request + - nhcx.flow.status-check + callbacks: + - nhcx.callback.error + troubleshooting: + - nhcx.troubleshooting.duplicate-or-mismatched-correlation +--- + +# NHCX-1006: the correlation id has already been used + +## In plain words + +The [NHCX](../../shared/glossary/nhcx.md) already has a request with the [correlation id](../glossary/correlation-id.md) on your message. Each request cycle needs its own correlation id. + +The exchange refused the new message as a duplicate. + +## Before you start + +You sent a message through NHCX. The exchange returns a gateway code in one of two places: + +- The synchronous acknowledgement to your call. The code is in `error.code` and the text in `error.message`. +- A report posted to your own `/v1/error` endpoint. The code is in `x-hcx-error_details.code`, the text in `x-hcx-error_details.message`, and `x-hcx-correlation_id` names the request. + +The `/v1/error` report is a plain `ProtocolResponse` body, not a sealed payload. Your system must host `/v1/error` to see it. See [Receiving POST /v1/error](../callbacks/error.md). + +The exchange checks the correlation id on your envelope before it forwards anything. + +## What happens + +The exchange raises this code when: + +- You retried a failed request on its old correlation id. After an error or failure, the exchange makes that correlation id inactive, and it cannot be used again. +- Your system reused a correlation id for a second, unrelated request. +- Your system sent the same request twice, for example after a timeout on your side. + +## How you know it worked + +Your request with the new correlation id returns HTTP 202 with an acknowledgement in which `error.code` and `error.message` are empty strings. + +No report for the new correlation id arrives on your `/v1/error`. The recipient's answer arrives on the `on_` path paired with your request. + +## When it goes wrong + +1. Generate a fresh UUID for `x-hcx-correlation_id` and send the request again as a new cycle. +2. Link the old and the new correlation id to the same case in your system. +3. Before retrying after a timeout, check whether the first request got through. See [Check the status of a request](../flows/status-check.md). +4. If this keeps happening, see [Duplicate or mismatched correlation id](../troubleshooting/duplicate-or-mismatched-correlation.md). diff --git a/catalogue/nhcx/errors/nhcx-1007.md b/catalogue/nhcx/errors/nhcx-1007.md new file mode 100644 index 000000000..9ec5efc17 --- /dev/null +++ b/catalogue/nhcx/errors/nhcx-1007.md @@ -0,0 +1,70 @@ +--- +id: nhcx.error.nhcx-1007 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'NHCX-1007: the exchange could not process the request''s structure or values' +summary: >- + The exchange failed while processing your message and points at its structure + or values, so check the body, the headers and the sealed envelope before sending + again. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet NHCX Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + flows: + - nhcx.flow.send-a-sealed-request + callbacks: + - nhcx.callback.error + errors: + - nhcx.error.nhcx-1013 + - nhcx.error.nhcx-1005 +--- + +# NHCX-1007: the exchange could not process the request's structure or values + +## In plain words + +The [NHCX](../../shared/glossary/nhcx.md) failed while processing your message. The message text points at the structure or the values of your request. + +Something in the request is malformed or holds a value the exchange cannot read. + +## Before you start + +You sent a message through NHCX. The exchange returns a gateway code in one of two places: + +- The synchronous acknowledgement to your call. The code is in `error.code` and the text in `error.message`. +- A report posted to your own `/v1/error` endpoint. The code is in `x-hcx-error_details.code`, the text in `x-hcx-error_details.message`, and `x-hcx-correlation_id` names the request. + +The `/v1/error` report is a plain `ProtocolResponse` body, not a sealed payload. Your system must host `/v1/error` to see it. See [Receiving POST /v1/error](../callbacks/error.md). + +## What happens + +The exchange raises this code when: + +- The body is not the expected shape. A request body carries the sealed message in `payload` as a compact [JWE](../glossary/jwe.md) string. +- A header value has the wrong type or form. +- The JWE is not well formed, so the exchange cannot read its protected header. + +## How you know it worked + +Send the corrected request. Your call returns HTTP 202 with an acknowledgement in which `error.code` and `error.message` are empty strings. `result.protocol_status` is `request.queued` or `request.dispatched`. + +No report for that `x-hcx-correlation_id` arrives on your `/v1/error`. The recipient's answer arrives later on the `on_` path paired with your request. + +## When it goes wrong + +1. Check the body: one `payload` field holding the compact JWE string. +2. Check every protected header value against [the x-hcx protocol headers](../concepts/protocol-headers.md). +3. Rebuild the JWE and confirm it has five parts separated by dots. See [the JWE envelope](../concepts/jwe-envelope.md). +4. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/nhcx-1008.md b/catalogue/nhcx/errors/nhcx-1008.md new file mode 100644 index 000000000..5643b6c00 --- /dev/null +++ b/catalogue/nhcx/errors/nhcx-1008.md @@ -0,0 +1,64 @@ +--- +id: nhcx.error.nhcx-1008 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'NHCX-1008: the exchange had a temporary failure' +summary: >- + The exchange failed while processing your message for a reason on its side, so + wait and send the request again. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet NHCX Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.retries-and-expiry + flows: + - nhcx.flow.send-a-sealed-request + callbacks: + - nhcx.callback.error + sandbox: + - nhcx.sandbox.support-contacts +--- + +# NHCX-1008: the exchange had a temporary failure + +## In plain words + +The [NHCX](../../shared/glossary/nhcx.md) failed while processing your message. The message text asks you to try again after some time. + +The code does not point at anything in your request. + +## Before you start + +You sent a message through NHCX. The exchange returns a gateway code in one of two places: + +- The synchronous acknowledgement to your call. The code is in `error.code` and the text in `error.message`. +- A report posted to your own `/v1/error` endpoint. The code is in `x-hcx-error_details.code`, the text in `x-hcx-error_details.message`, and `x-hcx-correlation_id` names the request. + +The `/v1/error` report is a plain `ProtocolResponse` body, not a sealed payload. Your system must host `/v1/error` to see it. See [Receiving POST /v1/error](../callbacks/error.md). + +## What happens + +The exchange raises this code when a temporary failure inside the exchange stops it handling your message. + +The code names no fault in your request. + +## How you know it worked + +Send the corrected request. Your call returns HTTP 202 with an acknowledgement in which `error.code` and `error.message` are empty strings. `result.protocol_status` is `request.queued` or `request.dispatched`. + +No report for that `x-hcx-correlation_id` arrives on your `/v1/error`. The recipient's answer arrives later on the `on_` path paired with your request. + +## When it goes wrong + +1. Wait, then send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). +2. Space your retries out. Do not retry in a tight loop. +3. If the code repeats over a long period, contact NHCX support with the correlation ids and timestamps. See [support contacts](../sandbox/support-contacts.md). diff --git a/catalogue/nhcx/errors/nhcx-1009.md b/catalogue/nhcx/errors/nhcx-1009.md new file mode 100644 index 000000000..79cd7f089 --- /dev/null +++ b/catalogue/nhcx/errors/nhcx-1009.md @@ -0,0 +1,65 @@ +--- +id: nhcx.error.nhcx-1009 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'NHCX-1009: the exchange failed and recorded the cause in its own logs' +summary: >- + The exchange failed while processing your message and the cause is in its own + logs, so keep the identifiers and contact support if a retry fails. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet NHCX Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + flows: + - nhcx.flow.send-a-sealed-request + callbacks: + - nhcx.callback.error + sandbox: + - nhcx.sandbox.support-contacts +--- + +# NHCX-1009: the exchange failed and recorded the cause in its own logs + +## In plain words + +The [NHCX](../../shared/glossary/nhcx.md) failed while processing your message. The detail is in the exchange's own logs, which you cannot see. + +NHCX support can read the cause from those logs. + +## Before you start + +You sent a message through NHCX. The exchange returns a gateway code in one of two places: + +- The synchronous acknowledgement to your call. The code is in `error.code` and the text in `error.message`. +- A report posted to your own `/v1/error` endpoint. The code is in `x-hcx-error_details.code`, the text in `x-hcx-error_details.message`, and `x-hcx-correlation_id` names the request. + +The `/v1/error` report is a plain `ProtocolResponse` body, not a sealed payload. Your system must host `/v1/error` to see it. See [Receiving POST /v1/error](../callbacks/error.md). + +## What happens + +The exchange raises this code when a failure inside it has a cause that the message text does not state. + +A `/v1/error` report can carry more detail in `x-hcx-error_details.trace`. Read it when it is present. + +## How you know it worked + +Send the corrected request. Your call returns HTTP 202 with an acknowledgement in which `error.code` and `error.message` are empty strings. `result.protocol_status` is `request.queued` or `request.dispatched`. + +No report for that `x-hcx-correlation_id` arrives on your `/v1/error`. The recipient's answer arrives later on the `on_` path paired with your request. + +## When it goes wrong + +1. Keep the `x-hcx-correlation_id`, the `x-hcx-api_call_id`, the timestamp and the full response. +2. Check the request against [the x-hcx protocol headers](../concepts/protocol-headers.md). +3. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). +4. If it fails again, contact NHCX support with those identifiers. See [support contacts](../sandbox/support-contacts.md). diff --git a/catalogue/nhcx/errors/nhcx-1010.md b/catalogue/nhcx/errors/nhcx-1010.md new file mode 100644 index 000000000..dd5784d86 --- /dev/null +++ b/catalogue/nhcx/errors/nhcx-1010.md @@ -0,0 +1,75 @@ +--- +id: nhcx.error.nhcx-1010 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'NHCX-1010: no request matches the correlation id on your answer' +summary: >- + The exchange holds no request with the correlation id on your answer, so answer + on the correlation id of the request you received, or check where that request + stands. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet NHCX Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.message-identifiers + - nhcx.concept.retries-and-expiry + flows: + - nhcx.flow.send-a-sealed-request + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.payer-process-a-request + - nhcx.flow.status-check + callbacks: + - nhcx.callback.error + endpoints: + - nhcx.endpoint.status + troubleshooting: + - nhcx.troubleshooting.duplicate-or-mismatched-correlation +--- + +# NHCX-1010: no request matches the correlation id on your answer + +## In plain words + +You sent an answer on an `on_` path, and the [NHCX](../../shared/glossary/nhcx.md) holds no request with its [correlation id](../glossary/correlation-id.md). + +The exchange cannot route an answer to a request it does not have. + +## Before you start + +You sent a message through NHCX. The exchange returns a gateway code in one of two places: + +- The synchronous acknowledgement to your call. The code is in `error.code` and the text in `error.message`. +- A report posted to your own `/v1/error` endpoint. The code is in `x-hcx-error_details.code`, the text in `x-hcx-error_details.message`, and `x-hcx-correlation_id` names the request. + +The `/v1/error` report is a plain `ProtocolResponse` body, not a sealed payload. Your system must host `/v1/error` to see it. See [Receiving POST /v1/error](../callbacks/error.md). + +This code reaches the side that answers, usually the payer or its [TPA](../glossary/tpa.md). + +## What happens + +The exchange raises this code when: + +- The `x-hcx-correlation_id` on your answer differs from the one on the request you received. An answer carries the request's correlation id. +- Your system generated a new correlation id for the answer. +- The original request is gone. After five failed deliveries the exchange deletes a request and retires its correlation id. + +## How you know it worked + +Send the corrected message. Your call returns HTTP 202 with an acknowledgement in which `error.code` and `error.message` are empty strings. + +No report for that `x-hcx-correlation_id` arrives on your `/v1/error`. + +## When it goes wrong + +1. Copy `x-hcx-correlation_id` from the request you received into your answer. Do not generate a new one. +2. Ask the exchange where the original request stands. See [Check the status of a request](../flows/status-check.md). +3. If the original request is gone, your answer cannot be delivered. The sender must start a new cycle. diff --git a/catalogue/nhcx/errors/nhcx-1011.md b/catalogue/nhcx/errors/nhcx-1011.md new file mode 100644 index 000000000..0f759b600 --- /dev/null +++ b/catalogue/nhcx/errors/nhcx-1011.md @@ -0,0 +1,75 @@ +--- +id: nhcx.error.nhcx-1011 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'NHCX-1011: the x-hcx-status value is not valid' +summary: >- + The exchange refused your message because its status header holds a value it does + not accept, so set the status that fits the kind of message you are sending. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet NHCX Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.status-lifecycle + - nhcx.concept.protocol-headers + flows: + - nhcx.flow.send-a-sealed-request + - nhcx.flow.receive-a-sealed-callback + callbacks: + - nhcx.callback.error + errors: + - nhcx.error.nhcx-1005 +--- + +# NHCX-1011: the x-hcx-status value is not valid + +## In plain words + +The [NHCX](../../shared/glossary/nhcx.md) refused your message because `x-hcx-status` in the [protected header](../glossary/protected-header.md) holds a value it does not accept. + +The status must fit the kind of message you are sending. + +## Before you start + +You sent a message through NHCX. The exchange returns a gateway code in one of two places: + +- The synchronous acknowledgement to your call. The code is in `error.code` and the text in `error.message`. +- A report posted to your own `/v1/error` endpoint. The code is in `x-hcx-error_details.code`, the text in `x-hcx-error_details.message`, and `x-hcx-correlation_id` names the request. + +The `/v1/error` report is a plain `ProtocolResponse` body, not a sealed payload. Your system must host `/v1/error` to see it. See [Receiving POST /v1/error](../callbacks/error.md). + +## What happens + +Set `x-hcx-status` by the kind of message: + +| You are sending | `x-hcx-status` | +|---|---| +| A request, such as `/v1/claim/submit` | `request.initiated` | +| An answer on an `on_` path | `response.complete`, `response.partial` or `response.error` | + +The exchange raises this code when: + +- A request carries a response status, or an answer carries a request status. +- The value is misspelt, for example `request.initiate` instead of `request.initiated`. +- An error answer uses `response.fail`. Use `response.error`. + +## How you know it worked + +Send the corrected message. Your call returns HTTP 202 with an acknowledgement in which `error.code` and `error.message` are empty strings. + +No report for that `x-hcx-correlation_id` arrives on your `/v1/error`. + +## When it goes wrong + +1. Set `x-hcx-status` from the table above. See [status values](../concepts/status-lifecycle.md). +2. Build the value from a constant in your code, not from free text. +3. Send the message again. An answer keeps the correlation id of the request it answers. diff --git a/catalogue/nhcx/errors/nhcx-1012.md b/catalogue/nhcx/errors/nhcx-1012.md new file mode 100644 index 000000000..1461791c6 --- /dev/null +++ b/catalogue/nhcx/errors/nhcx-1012.md @@ -0,0 +1,68 @@ +--- +id: nhcx.error.nhcx-1012 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'NHCX-1012: no message matches the api_call_id you gave' +summary: >- + The exchange found no message with the call id you referred to, so use the exact + call id you stored when you sent that message. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet NHCX Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.message-identifiers + flows: + - nhcx.flow.send-a-sealed-request + - nhcx.flow.status-check + callbacks: + - nhcx.callback.error + - nhcx.callback.on-status + endpoints: + - nhcx.endpoint.status +--- + +# NHCX-1012: no message matches the api_call_id you gave + +## In plain words + +The [NHCX](../../shared/glossary/nhcx.md) found no message with the [API call id](../glossary/api-call-id.md) you referred to. + +It cannot look up or act on a message it has no record of. + +## Before you start + +You sent a message through NHCX. The exchange returns a gateway code in one of two places: + +- The synchronous acknowledgement to your call. The code is in `error.code` and the text in `error.message`. +- A report posted to your own `/v1/error` endpoint. The code is in `x-hcx-error_details.code`, the text in `x-hcx-error_details.message`, and `x-hcx-correlation_id` names the request. + +The `/v1/error` report is a plain `ProtocolResponse` body, not a sealed payload. Your system must host `/v1/error` to see it. See [Receiving POST /v1/error](../callbacks/error.md). + +## What happens + +The exchange raises this code when: + +- The id you referred to was never sent, or your system did not keep it. +- The id has a typo, or your system generated it again instead of reading the stored value. +- On `/v1/status`, `x-hcx-correlation_id` must carry the `api_call_id` of the message you ask about. Its correlation id points at no message. + +## How you know it worked + +Send the corrected request. Your call returns HTTP 202 with an acknowledgement in which `error.code` and `error.message` are empty strings. `result.protocol_status` is `request.queued` or `request.dispatched`. + +No report for that `x-hcx-correlation_id` arrives on your `/v1/error`. The recipient's answer arrives later on the `on_` path paired with your request. + +## When it goes wrong + +1. Store the `x-hcx-api_call_id` of every message you send, against its case. +2. Refer to the stored value exactly. For a status check, put it in `x-hcx-correlation_id`. See [POST /v1/status](../endpoints/status.md). +3. Send the message again. diff --git a/catalogue/nhcx/errors/nhcx-1013.md b/catalogue/nhcx/errors/nhcx-1013.md new file mode 100644 index 000000000..05011f268 --- /dev/null +++ b/catalogue/nhcx/errors/nhcx-1013.md @@ -0,0 +1,67 @@ +--- +id: nhcx.error.nhcx-1013 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'NHCX-1013: the request body is empty or not valid' +summary: >- + The exchange received a call with an empty body or one it cannot read as a request, + so send a body carrying the sealed message. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet NHCX Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.send-a-sealed-request + callbacks: + - nhcx.callback.error + errors: + - nhcx.error.nhcx-1007 +--- + +# NHCX-1013: the request body is empty or not valid + +## In plain words + +The [NHCX](../../shared/glossary/nhcx.md) received a call with an empty body, or a body it cannot read as a request. + +There was nothing it could forward. + +## Before you start + +You sent a message through NHCX. The exchange returns a gateway code in one of two places: + +- The synchronous acknowledgement to your call. The code is in `error.code` and the text in `error.message`. +- A report posted to your own `/v1/error` endpoint. The code is in `x-hcx-error_details.code`, the text in `x-hcx-error_details.message`, and `x-hcx-correlation_id` names the request. + +The `/v1/error` report is a plain `ProtocolResponse` body, not a sealed payload. Your system must host `/v1/error` to see it. See [Receiving POST /v1/error](../callbacks/error.md). + +## What happens + +The exchange raises this code when: + +- The body is empty. +- The body is not JSON, or it has no `payload` field. +- `payload` is empty, or is not a compact [JWE](../glossary/jwe.md) string. + +## How you know it worked + +Send the corrected request. Your call returns HTTP 202 with an acknowledgement in which `error.code` and `error.message` are empty strings. `result.protocol_status` is `request.queued` or `request.dispatched`. + +No report for that `x-hcx-correlation_id` arrives on your `/v1/error`. The recipient's answer arrives later on the `on_` path paired with your request. + +## When it goes wrong + +1. Send a JSON body of the form `{"payload": ""}`. +2. Seal the [FHIR](../../shared/glossary/fhir.md) bundle and the headers into the JWE before sending. See [Send a sealed request through NHCX](../flows/send-a-sealed-request.md). +3. Log the exact body you send, so an empty body shows in your own logs. +4. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/nhcx-1014.md b/catalogue/nhcx/errors/nhcx-1014.md new file mode 100644 index 000000000..a91ab0e17 --- /dev/null +++ b/catalogue/nhcx/errors/nhcx-1014.md @@ -0,0 +1,79 @@ +--- +id: nhcx.error.nhcx-1014 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'NHCX-1014: the exchange could not deliver the response to its sender' +summary: >- + The exchange could not deliver a response to the participant it was meant for, + because that participant's endpoint did not take it. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet NHCX Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.retries-and-expiry + flows: + - nhcx.flow.send-a-sealed-request + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.status-check + callbacks: + - nhcx.callback.error + errors: + - nhcx.error.nhcx-1010 + sandbox: + - nhcx.sandbox.callback-url-requirements +--- + +# NHCX-1014: the exchange could not deliver the response to its sender + +## In plain words + +The [NHCX](../../shared/glossary/nhcx.md) could not deliver a response to the participant it was meant for. That participant's registered endpoint did not take it. + +## Before you start + +You sent a message through NHCX. The exchange returns a gateway code in one of two places: + +- The synchronous acknowledgement to your call. The code is in `error.code` and the text in `error.message`. +- A report posted to your own `/v1/error` endpoint. The code is in `x-hcx-error_details.code`, the text in `x-hcx-error_details.message`, and `x-hcx-correlation_id` names the request. + +The `/v1/error` report is a plain `ProtocolResponse` body, not a sealed payload. Your system must host `/v1/error` to see it. See [Receiving POST /v1/error](../callbacks/error.md). + +If you answered on an `on_` path, the code tells you your answer did not reach the original sender. If you started the exchange, your own endpoint is the one that failed. + +## What happens + +The exchange raises this code when: + +- The original sender's registered endpoint is down or refused the delivery. +- The endpoint did not answer HTTP 202 within 30 seconds. +- The endpoint answered with a body that does not follow the acknowledgement format. + +## How you know it worked + +Send the corrected message. Your call returns HTTP 202 with an acknowledgement in which `error.code` and `error.message` are empty strings. + +No report for that `x-hcx-correlation_id` arrives on your `/v1/error`. + +## When it goes wrong + +### If you sent the response + +1. Keep your response and its correlation id. +2. Send it again once the original sender's endpoint is reachable. +3. If the exchange answers [NHCX-1010](nhcx-1010.md), the request is gone. The original sender must start again. + +### If you started the exchange + +1. Check that your registered endpoint is reachable and answers HTTP 202 within 30 seconds. See [callback URL requirements](../sandbox/callback-url-requirements.md). +2. Return the acknowledgement body described in [the 202 acknowledgement](../concepts/synchronous-acknowledgement.md). +3. Ask the exchange where your request stands. See [Check the status of a request](../flows/status-check.md). diff --git a/catalogue/nhcx/errors/nhcx-1015.md b/catalogue/nhcx/errors/nhcx-1015.md new file mode 100644 index 000000000..797ba3763 --- /dev/null +++ b/catalogue/nhcx/errors/nhcx-1015.md @@ -0,0 +1,107 @@ +--- +id: nhcx.error.nhcx-1015 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'NHCX-1015: the recipient answered a delivery in a form the exchange does + not accept' +summary: >- + NHCX-1015 means the recipient's system answered a delivered message with a status + or body the exchange does not accept, so the exchange treats the delivery as failed. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet NHCX Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.retries-and-expiry + flows: + - nhcx.flow.send-a-sealed-request + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.status-check + callbacks: + - nhcx.callback.error + errors: + - nhcx.error.nhcx-1017 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback +--- + +# NHCX-1015: the recipient answered a delivery in a form the exchange does not accept + +## In plain words + +The [NHCX](../../shared/glossary/nhcx.md) delivered a message, and the recipient's system answered in a form the exchange does not accept. The exchange treats that answer as a failed delivery. + +The message text is `Invalid response received from receiver.`. [NHCX-1017](nhcx-1017.md) carries the same text. Handle both codes the same way. + +## Before you start + +You sent a message through NHCX. The exchange returns a gateway code in one of two places: + +- The synchronous acknowledgement to your call. The code is in `error.code` and the text in `error.message`. +- A report posted to your own `/v1/error` endpoint. The code is in `x-hcx-error_details.code`, the text in `x-hcx-error_details.message`, and `x-hcx-correlation_id` names the request. + +The `/v1/error` report is a plain `ProtocolResponse` body, not a sealed payload. Your system must host `/v1/error` to see it. See [Receiving POST /v1/error](../callbacks/error.md). + +The exchange retries a failed delivery five times. If every answer is invalid, it deletes the request and retires its correlation id. The report then reaches the sender's `/v1/error`. + +## What happens + +The recipient's system produced an answer the exchange cannot accept: + +- It answered with an HTTP status other than 202. +- Its acknowledgement body does not follow the published format. The body carries `timestamp`, `api_call_id`, `correlation_id`, `result` and `error`. +- `result.entity_type` is not one of `coverageeligibility`, `preauth`, `claim`, `task`, `payment` or `insuranceplan`. +- `result.protocol_status` is not one of `request.queued`, `request.dispatched` or `request.error`. +- It took longer than 30 seconds to answer. + +## How you know it worked + +Send the corrected request. Your call returns HTTP 202 with an acknowledgement in which `error.code` and `error.message` are empty strings. `result.protocol_status` is `request.queued` or `request.dispatched`. + +No report for that `x-hcx-correlation_id` arrives on your `/v1/error`. The recipient's answer arrives later on the `on_` path paired with your request. + +## When it goes wrong + +### If you sent the request + +The recipient's system is at fault. Tell the recipient which code you received. + +Once the recipient has fixed its acknowledgement, send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). + +### If you are the recipient + +1. Answer every delivery with HTTP 202 and this body before you process it: + +```json +{ + "timestamp": "DD/MM/YYYY hh:mm:ss:sss", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "preauth", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +2. Copy `api_call_id` and `correlation_id` from the delivery you received. +3. Set `entity_type` to the use case of the delivery. +4. Leave `error.code` and `error.message` as empty strings when you accept. + +See [the 202 acknowledgement](../concepts/synchronous-acknowledgement.md). diff --git a/catalogue/nhcx/errors/nhcx-1016.md b/catalogue/nhcx/errors/nhcx-1016.md new file mode 100644 index 000000000..da4973558 --- /dev/null +++ b/catalogue/nhcx/errors/nhcx-1016.md @@ -0,0 +1,67 @@ +--- +id: nhcx.error.nhcx-1016 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'NHCX-1016: the call does not fit the exchange open on this correlation id' +summary: >- + The exchange refused your call because its path is not a valid next step for the + exchange open under this correlation id, so answer on the paired path. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet NHCX Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.four-message-legs + - nhcx.concept.message-identifiers + flows: + - nhcx.flow.send-a-sealed-request + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.status-check + callbacks: + - nhcx.callback.error + endpoints: +--- + +# NHCX-1016: the call does not fit the exchange open on this correlation id + +## In plain words + +The [NHCX](../../shared/glossary/nhcx.md) refused your call because its action does not fit the exchange open under this [correlation id](../glossary/correlation-id.md). + +The path you called is not a valid next step for that thread. + +## Before you start + +You sent a message through NHCX. The exchange returns a gateway code in one of two places: + +- The synchronous acknowledgement to your call. The code is in `error.code` and the text in `error.message`. +- A report posted to your own `/v1/error` endpoint. The code is in `x-hcx-error_details.code`, the text in `x-hcx-error_details.message`, and `x-hcx-correlation_id` names the request. + +The `/v1/error` report is a plain `ProtocolResponse` body, not a sealed payload. Your system must host `/v1/error` to see it. See [Receiving POST /v1/error](../callbacks/error.md). + +## What happens + +The exchange raises this code when: + +- You answered on an `on_` path that is not paired with the request. An answer to `/v1/preauth/submit` belongs on `/v1/preauth/on_submit`. +- You reused a correlation id from one use case on a call for another. + +## How you know it worked + +Send the corrected message. Your call returns HTTP 202 with an acknowledgement in which `error.code` and `error.message` are empty strings. + +No report for that `x-hcx-correlation_id` arrives on your `/v1/error`. + +## When it goes wrong + +1. Answer each request on the `on_` path paired with the path it arrived on. See [the four legs of every exchange](../concepts/four-message-legs.md). +2. Give each new request cycle its own correlation id. +3. Check what the exchange holds for the correlation id before you retry. See [Check the status of a request](../flows/status-check.md). diff --git a/catalogue/nhcx/errors/nhcx-1017.md b/catalogue/nhcx/errors/nhcx-1017.md new file mode 100644 index 000000000..eb67f7fe0 --- /dev/null +++ b/catalogue/nhcx/errors/nhcx-1017.md @@ -0,0 +1,107 @@ +--- +id: nhcx.error.nhcx-1017 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'NHCX-1017: the recipient answered a delivery in a form the exchange does + not accept' +summary: >- + NHCX-1017 means the recipient's system answered a delivered message with a status + or body the exchange does not accept, so the exchange treats the delivery as failed. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet NHCX Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.retries-and-expiry + flows: + - nhcx.flow.send-a-sealed-request + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.status-check + callbacks: + - nhcx.callback.error + errors: + - nhcx.error.nhcx-1015 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback +--- + +# NHCX-1017: the recipient answered a delivery in a form the exchange does not accept + +## In plain words + +The [NHCX](../../shared/glossary/nhcx.md) delivered a message, and the recipient's system answered in a form the exchange does not accept. The exchange treats that answer as a failed delivery. + +The message text is `Invalid response received from receiver`. [NHCX-1015](nhcx-1015.md) carries the same text. Handle both codes the same way. + +## Before you start + +You sent a message through NHCX. The exchange returns a gateway code in one of two places: + +- The synchronous acknowledgement to your call. The code is in `error.code` and the text in `error.message`. +- A report posted to your own `/v1/error` endpoint. The code is in `x-hcx-error_details.code`, the text in `x-hcx-error_details.message`, and `x-hcx-correlation_id` names the request. + +The `/v1/error` report is a plain `ProtocolResponse` body, not a sealed payload. Your system must host `/v1/error` to see it. See [Receiving POST /v1/error](../callbacks/error.md). + +The exchange retries a failed delivery five times. If every answer is invalid, it deletes the request and retires its correlation id. The report then reaches the sender's `/v1/error`. + +## What happens + +The recipient's system produced an answer the exchange cannot accept: + +- It answered with an HTTP status other than 202. +- Its acknowledgement body does not follow the published format. The body carries `timestamp`, `api_call_id`, `correlation_id`, `result` and `error`. +- `result.entity_type` is not one of `coverageeligibility`, `preauth`, `claim`, `task`, `payment` or `insuranceplan`. +- `result.protocol_status` is not one of `request.queued`, `request.dispatched` or `request.error`. +- It took longer than 30 seconds to answer. + +## How you know it worked + +Send the corrected request. Your call returns HTTP 202 with an acknowledgement in which `error.code` and `error.message` are empty strings. `result.protocol_status` is `request.queued` or `request.dispatched`. + +No report for that `x-hcx-correlation_id` arrives on your `/v1/error`. The recipient's answer arrives later on the `on_` path paired with your request. + +## When it goes wrong + +### If you sent the request + +The recipient's system is at fault. Tell the recipient which code you received. + +Once the recipient has fixed its acknowledgement, send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). + +### If you are the recipient + +1. Answer every delivery with HTTP 202 and this body before you process it: + +```json +{ + "timestamp": "DD/MM/YYYY hh:mm:ss:sss", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "preauth", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +2. Copy `api_call_id` and `correlation_id` from the delivery you received. +3. Set `entity_type` to the use case of the delivery. +4. Leave `error.code` and `error.message` as empty strings when you accept. + +See [the 202 acknowledgement](../concepts/synchronous-acknowledgement.md). diff --git a/catalogue/nhcx/errors/nhcx-1018.md b/catalogue/nhcx/errors/nhcx-1018.md new file mode 100644 index 000000000..2aa7de19f --- /dev/null +++ b/catalogue/nhcx/errors/nhcx-1018.md @@ -0,0 +1,71 @@ +--- +id: nhcx.error.nhcx-1018 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'NHCX-1018: the ABHA number is not in the XX-XXXX-XXXX-XXXX form' +summary: >- + The exchange refused the message because the beneficiary's health account number + is not written as fourteen digits in hyphenated groups of two, four, four and + four. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet NHCX Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + flows: + - nhcx.flow.send-a-sealed-request + callbacks: + - nhcx.callback.error + glossary: + - shared.glossary.abha-number + errors: + - nhcx.error.nhcx-1005 +--- + +# NHCX-1018: the ABHA number is not in the XX-XXXX-XXXX-XXXX form + +## In plain words + +The [NHCX](../../shared/glossary/nhcx.md) refused your message because the [ABHA number](../../shared/glossary/abha-number.md) is not in the form it accepts. + +The exchange accepts the ABHA number as `XX-XXXX-XXXX-XXXX`: 14 digits in groups of two, four, four and four, joined by hyphens. + +## Before you start + +You sent a message through NHCX. The exchange returns a gateway code in one of two places: + +- The synchronous acknowledgement to your call. The code is in `error.code` and the text in `error.message`. +- A report posted to your own `/v1/error` endpoint. The code is in `x-hcx-error_details.code`, the text in `x-hcx-error_details.message`, and `x-hcx-correlation_id` names the request. + +The `/v1/error` report is a plain `ProtocolResponse` body, not a sealed payload. Your system must host `/v1/error` to see it. See [Receiving POST /v1/error](../callbacks/error.md). + +The beneficiary's ABHA number travels in the `x-hcx-ben-abha-id` [protected header](../glossary/protected-header.md). + +## What happens + +The exchange raises this code when: + +- The ABHA number was sent without hyphens. +- It has the wrong number of digits, or the hyphens sit in the wrong places. +- An [ABHA address](../../shared/glossary/abha-address.md) was sent where the ABHA number belongs. + +## How you know it worked + +Send the corrected request. Your call returns HTTP 202 with an acknowledgement in which `error.code` and `error.message` are empty strings. `result.protocol_status` is `request.queued` or `request.dispatched`. + +No report for that `x-hcx-correlation_id` arrives on your `/v1/error`. The recipient's answer arrives later on the `on_` path paired with your request. + +## When it goes wrong + +1. Format the ABHA number as `XX-XXXX-XXXX-XXXX` before you place it in `x-hcx-ben-abha-id`. +2. Store the 14 digits once, and format them where you build the header. Every call then uses the same form. +3. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/nhcx-401.md b/catalogue/nhcx/errors/nhcx-401.md new file mode 100644 index 000000000..1eeac62ce --- /dev/null +++ b/catalogue/nhcx/errors/nhcx-401.md @@ -0,0 +1,72 @@ +--- +id: nhcx.error.nhcx-401 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'NHCX-401: the exchange does not accept your authorisation for this call' +summary: >- + The exchange refused the call because it does not accept the token or the caller + behind it, so renew the session token and check your participant may make this + call. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet NHCX Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.session-token + - nhcx.concept.access-control + flows: + - nhcx.flow.send-a-sealed-request + - nhcx.flow.policy-link-and-delink + callbacks: + - nhcx.callback.error + endpoints: + - nhcx.endpoint.session-token + troubleshooting: + - nhcx.troubleshooting.everything-returns-401 +--- + +# NHCX-401: the exchange does not accept your authorisation for this call + +## In plain words + +The [NHCX](../../shared/glossary/nhcx.md) refused your call because it does not accept you as authorised to make it. The message text is `User Unauthorized`. + +Nothing was forwarded to the recipient. + +## Before you start + +You sent a message through NHCX. The exchange returns a gateway code in one of two places: + +- The synchronous acknowledgement to your call. The code is in `error.code` and the text in `error.message`. +- A report posted to your own `/v1/error` endpoint. The code is in `x-hcx-error_details.code`, the text in `x-hcx-error_details.message`, and `x-hcx-correlation_id` names the request. + +The `/v1/error` report is a plain `ProtocolResponse` body, not a sealed payload. Your system must host `/v1/error` to see it. See [Receiving POST /v1/error](../callbacks/error.md). + +## What happens + +The exchange refuses the call when: + +- The session token in `bearer_auth` has expired. Tokens are short lived, so a token that worked earlier can fail now. +- The token is not a valid token from the session call. +- The token was generated with a client id other than the one your participant was created with. Policy linking and de-linking accept only the participants named on the policy. + +## How you know it worked + +Send the corrected request. Your call returns HTTP 202 with an acknowledgement in which `error.code` and `error.message` are empty strings. `result.protocol_status` is `request.queued` or `request.dispatched`. + +No report for that `x-hcx-correlation_id` arrives on your `/v1/error`. The recipient's answer arrives later on the `on_` path paired with your request. + +## When it goes wrong + +1. Call the session endpoint for a new token and retry with it. See [the session token](../concepts/session-token.md) and [POST /api/hiecm/gateway/v3/sessions](../endpoints/session-token.md). +2. Send the token as `bearer_auth: Bearer `. The exchange's own endpoints read `bearer_auth`, not `Authorization`. +3. Generate the token with the client id used when your participant was created. +4. If every call returns this code, see [Every call returns 401](../troubleshooting/everything-returns-401.md). diff --git a/catalogue/nhcx/errors/payr-1001.md b/catalogue/nhcx/errors/payr-1001.md new file mode 100644 index 000000000..1c5722f76 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1001.md @@ -0,0 +1,84 @@ +--- +id: nhcx.error.payr-1001 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1001: the recipient could not decrypt your request' +summary: >- + The receiving payer could not open your sealed request, usually because it was + sealed with the wrong or an outdated certificate, so fetch the current certificate + and send again. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Payer Error Codes, Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.encryption-certificate + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + flows: + - nhcx.flow.send-a-sealed-request + - nhcx.flow.rotate-certificate + endpoints: + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.participant-search + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + - nhcx.callback.coverageeligibility-on-check + troubleshooting: + - nhcx.troubleshooting.recipient-cannot-decrypt +--- + +# PAYR-1001: the recipient could not decrypt your request + +## In plain words + +The recipient could not open the sealed [JWE](../glossary/jwe.md) you sent. Its private key does not match the certificate you sealed with, or the sealed content is malformed. + +The recipient read nothing of your request. + +## Before you start + +You sent a request through [NHCX](../../shared/glossary/nhcx.md), and the payer answered it with an error. The answer arrives on the `on_` path paired with your request. `x-hcx-status` marks it as an error. `x-hcx-error_details` carries the code in `code` and the text in `message`. + +Read these fields from the protected header once you open the [JWE](../glossary/jwe.md). Some payers send the same fields in a plain `ProtocolResponse` body instead. Handle both. + +Both payer code spaces use PAYR-1001 for this failure. The text differs: + +| Message text | Sent by | +|---|---| +| `Error while decrypting request. Please reprocess the request encrypting with valid certificate of the payer.` | A payer using the standard payer codes | +| `Error occurred while decrypting payload for receiver code with correlation id .` | The [PMJAY](../glossary/pmjay.md) payer | + +## What happens + +The recipient raises this code when: + +- You sealed the request with a certificate that is not the recipient's current one. +- You sealed it with your own certificate, or another participant's. +- `x-hcx-recipient_code` names a different participant from the one whose certificate you used. +- The content you sealed is not in the expected key-value form. It carries `x-hcx-sender_code`, `x-hcx-recipient_code`, `x-hcx-api_call_id`, `x-hcx-correlation_id`, `x-hcx-workflow_id`, `x-hcx-timestamp`, `x-hcx-status`, and the sealed [FHIR](../../shared/glossary/fhir.md) bundle as `payload`. + +## How you know it worked + +Your resent request is not answered with PAYR-1001. The payer's answer opens with your private key: + +- The payer's answer arrives on the `on_` path paired with your request, with no `x-hcx-error_details`. + +## When it goes wrong + +1. Confirm the recipient is a registered participant with [POST /participant/search](../endpoints/participant-search.md). +2. Fetch the recipient's current certificate from the registry with [POST /fetch/certs](../endpoints/fetch-certs.md). +3. Seal the request again with that certificate. Check that every header listed above is present. +4. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). +5. If it still fails, contact NHCX support. See [support contacts](../sandbox/support-contacts.md). + +See [the recipient cannot decrypt](../troubleshooting/recipient-cannot-decrypt.md). diff --git a/catalogue/nhcx/errors/payr-1002.md b/catalogue/nhcx/errors/payr-1002.md new file mode 100644 index 000000000..75fee2f68 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1002.md @@ -0,0 +1,76 @@ +--- +id: nhcx.error.payr-1002 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1002: the payer could not encrypt its answer to you' +summary: >- + The payer processed your request but could not seal its answer with the certificate + you registered, so upload a valid certificate and the payer sends the answer. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Payer Error Codes, Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.encryption-certificate + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.rotate-certificate + - nhcx.flow.generate-and-register-certificate + - nhcx.flow.receive-a-sealed-callback + endpoints: + - nhcx.endpoint.v2-update-cert + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + - nhcx.callback.coverageeligibility-on-check +--- + +# PAYR-1002: the payer could not encrypt its answer to you + +## In plain words + +The payer received and processed your request, but could not seal its answer to you. It seals answers with the public certificate your organisation registered in [NHCX](../../shared/glossary/nhcx.md). + +That certificate is missing, expired or not usable. + +## Before you start + +You sent a request through [NHCX](../../shared/glossary/nhcx.md), and the payer answered it with an error. The answer arrives on the `on_` path paired with your request. `x-hcx-status` marks it as an error. `x-hcx-error_details` carries the code in `code` and the text in `message`. + +Read these fields from the protected header once you open the [JWE](../glossary/jwe.md). Some payers send the same fields in a plain `ProtocolResponse` body instead. Handle both. + +Both payer code spaces use PAYR-1002 for this failure. The text differs: + +| Message text | Sent by | +|---|---| +| `Error while encrypting request. Please update encryption certificate in NHCX.` | A payer using the standard payer codes | +| `Error occurred while encrypting payload for receiver code with correlation id .` | The [PMJAY](../glossary/pmjay.md) payer | + +## What happens + +The payer raises this code when: + +- The certificate registered for your participant has expired. +- The registered certificate is not a valid [X.509 certificate](../glossary/x509-certificate.md), or cannot be used for encryption. +- Your organisation is not a valid registered participant. + +## How you know it worked + +After you update the certificate, the payer fetches it from the registry and sends its answer. The answer arrives on the `on_` path paired with your request, for the same `x-hcx-correlation_id`. + +It opens with your private key, and carries no `x-hcx-error_details`. + +## When it goes wrong + +1. Confirm your organisation is a registered participant. +2. Upload a valid encryption certificate to NHCX. See [Rotate your encryption certificate](../flows/rotate-certificate.md) and [POST /v2/update/cert](../endpoints/v2-update-cert.md). +3. Wait for the payer's answer. You do not need to resend the request. +4. If the answer does not arrive, contact NHCX support. See [support contacts](../sandbox/support-contacts.md). diff --git a/catalogue/nhcx/errors/payr-1003.md b/catalogue/nhcx/errors/payr-1003.md new file mode 100644 index 000000000..b8b65154e --- /dev/null +++ b/catalogue/nhcx/errors/payr-1003.md @@ -0,0 +1,90 @@ +--- +id: nhcx.error.payr-1003 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1003: the payer''s system could not reach the exchange and will resend, + or the workflow requested is not valid' +summary: >- + PAYR-1003 means one of two things, the payer's system could not reach the exchange + and will resend or, from the national scheme's reference payer, the workflow requested + is not valid, and the message text that comes with the code tells them apart. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Payer Error Codes, Bridge Error, Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.workflow-codes + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + - nhcx.flow.status-check + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit +--- + +# PAYR-1003: the payer's system could not reach the exchange and will resend, or the workflow requested is not valid + +## In plain words + +PAYR-1003 has two meanings, depending on which payer sent it: + +- From a payer using the standard payer codes: the payer's system could not reach the exchange and will resend. +- From the [PMJAY](../glossary/pmjay.md) payer: the workflow requested is not valid. This PMJAY meaning is deprecated. + +Read the code together with the message text that comes with it. The text tells the two apart. + +## Before you start + +You sent a request through [NHCX](../../shared/glossary/nhcx.md), and the payer answered it with an error. The answer arrives on the `on_` path paired with your request, such as `/v1/preauth/on_submit` or `/v1/claim/on_submit`. `x-hcx-status` marks it as an error. `x-hcx-error_details` carries the code in `code` and the text in `message`. + +Read these fields from the protected header once you open the [JWE](../glossary/jwe.md). Some payers send the same fields in a plain `ProtocolResponse` body instead. Handle both. + +A payer using the standard payer codes sends PAYR-1003 for a transport failure on its own side, on any use case. + +## What happens + +| Message text | Sent by | Meaning | +|---|---|---| +| `Error while connecting to NHCX. System will try to resend the message to NHCX after some time.` | A payer using the standard payer codes | The payer's system could not reach the exchange and will resend. | +| `Invalid workflow requested. Hence request will not be processed further.` | The PMJAY payer | The workflow requested is not valid. This meaning is deprecated. | + +### When the standard meaning applies + +- A network or transport failure between the payer's system and the exchange. The payer resends its message later. + +### When the PMJAY meaning applies + +- `x-hcx-workflow_id` is missing, or holds a code that does not fit the use case of the path you called. + +## How you know it worked + +Send the corrected request. The step is done when the payer answers without this code: + +- For a preauthorisation, `/v1/preauth/on_submit` arrives with no `x-hcx-error_details`. Its `x-hcx-workflow_id` names the decision, for example `21` approved or `24` queried. +- For a claim, `/v1/claim/on_submit` arrives with no `x-hcx-error_details`, and its bundle carries a `ClaimResponse`. + +## When it goes wrong + +### If the text reads `Error while connecting to NHCX` + +Nothing in your request needs to change. The payer resends its message when it reconnects. + +If nothing arrives within the payer's usual turnaround, ask the exchange where the request stands. See [Check the status of a request](../flows/status-check.md). + +### If the text reads `Invalid workflow requested` + +1. Set `x-hcx-workflow_id` to the workflow code for this stage. See [workflow codes](../concepts/workflow-codes.md). +2. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1004.md b/catalogue/nhcx/errors/payr-1004.md new file mode 100644 index 000000000..b6180f3fb --- /dev/null +++ b/catalogue/nhcx/errors/payr-1004.md @@ -0,0 +1,101 @@ +--- +id: nhcx.error.payr-1004 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1004: your facility is not registered with the payer for the policy, + or the FHIR bundle is malformed' +summary: >- + PAYR-1004 means one of two things, your facility is not registered with the payer + for the policy or, from the national scheme's reference payer, the data bundle + is malformed, and the message text that comes with the code tells them apart. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Payer Error Codes, Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.fhir-in-nhcx + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.coverageeligibility-on-check + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.validation + - shared.fhir.hl7-validator-recipe + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1004: your facility is not registered with the payer for the policy, or the FHIR bundle is malformed + +## In plain words + +PAYR-1004 has two meanings, depending on which payer sent it: + +- From a payer using the standard payer codes: your facility is not registered with the payer for the policy. +- From the [PMJAY](../glossary/pmjay.md) payer: the [FHIR](../../shared/glossary/fhir.md) bundle is malformed. + +Read the code together with the message text that comes with it. The text tells the two apart. + +## Before you start + +You sent a request through [NHCX](../../shared/glossary/nhcx.md), and the payer answered it with an error. The answer arrives on the `on_` path paired with your request, such as `/v1/coverageeligibility/on_check`, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. `x-hcx-status` marks it as an error. `x-hcx-error_details` carries the code in `code` and the text in `message`. + +Read these fields from the protected header once you open the [JWE](../glossary/jwe.md). Some payers send the same fields in a plain `ProtocolResponse` body instead. Handle both. + +A payer using the standard payer codes sends PAYR-1004 for coverage eligibility, preauthorisation and claim. + +## What happens + +| Message text | Sent by | Meaning | +|---|---|---| +| `Provider is not registered with the payer for requested policy.` | A payer using the standard payer codes | Your facility is not registered with the payer for the policy. | +| `Received FHIR bundle is malformed. Please correct the bundle and try again. ` | The PMJAY payer | The FHIR bundle is malformed. | + +### When the standard meaning applies + +- Your facility is not registered with this payer for the policy named in the request. +- The request names a policy your facility is not registered for. + +### When the PMJAY meaning applies + +- The payer's structure check rejected the bundle. The message ends with the check's own details in place of ``. + +## How you know it worked + +Send the corrected request. The step is done when the payer answers without this code: + +- For a coverage eligibility check, `/v1/coverageeligibility/on_check` arrives for your `x-hcx-correlation_id` with no `x-hcx-error_details`. +- For a preauthorisation, `/v1/preauth/on_submit` arrives with no `x-hcx-error_details`. Its `x-hcx-workflow_id` names the decision, for example `21` approved or `24` queried. +- For a claim, `/v1/claim/on_submit` arrives with no `x-hcx-error_details`, and its bundle carries a `ClaimResponse`. + +## When it goes wrong + +### If the text reads `Provider is not registered with the payer for requested policy` + +1. Confirm with the payer that your facility is registered for this policy. +2. Check that the request names the beneficiary's policy. +3. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). + +### If the text reads `Received FHIR bundle is malformed` + +1. Read the details at the end of the message and fix what they name. +2. Validate the bundle with the [NRCeS](../../shared/glossary/nrces.md) validator. See [the validator recipe](../../shared/fhir/hl7-validator-recipe.md) and [validating an NHCX bundle](../fhir/validation.md). +3. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). +4. If it still fails, contact NHCX support. See [support contacts](../sandbox/support-contacts.md). diff --git a/catalogue/nhcx/errors/payr-1005.md b/catalogue/nhcx/errors/payr-1005.md new file mode 100644 index 000000000..1dcb6fca7 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1005.md @@ -0,0 +1,99 @@ +--- +id: nhcx.error.payr-1005 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1005: the beneficiary is not a covered member of the policy, or the + request is more than 24 hours old' +summary: >- + PAYR-1005 means one of two things, the beneficiary is not a covered member of + the policy or, from the national scheme's reference payer, the request is more + than 24 hours old, and the message text that comes with the code tells them apart. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Payer Error Codes, Bridge Error, Coverage Error Codes, Preauth Error Codes, Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.retries-and-expiry + - nhcx.concept.protocol-headers + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.coverageeligibility-on-check + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit +--- + +# PAYR-1005: the beneficiary is not a covered member of the policy, or the request is more than 24 hours old + +## In plain words + +PAYR-1005 has two meanings, depending on which payer sent it: + +- From a payer using the standard payer codes: the beneficiary is not a covered member of the policy. +- From the [PMJAY](../glossary/pmjay.md) payer: the request is more than 24 hours old. + +Read the code together with the message text that comes with it. The text tells the two apart. + +## Before you start + +You sent a request through [NHCX](../../shared/glossary/nhcx.md), and the payer answered it with an error. The answer arrives on the `on_` path paired with your request, such as `/v1/coverageeligibility/on_check`, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. `x-hcx-status` marks it as an error. `x-hcx-error_details` carries the code in `code` and the text in `message`. + +Read these fields from the protected header once you open the [JWE](../glossary/jwe.md). Some payers send the same fields in a plain `ProtocolResponse` body instead. Handle both. + +A payer using the standard payer codes sends PAYR-1005 for coverage eligibility, preauthorisation and claim. + +## What happens + +| Message text | Sent by | Meaning | +|---|---|---| +| `Beneficiary is not a covered member for requested policy. Please enroll beneficiary for the policy and try again.` | A payer using the standard payer codes | The beneficiary is not a covered member of the policy. | +| `Maximum time limit exceeded in receiving the request. Please try again.` | The PMJAY payer | The request is more than 24 hours old. | + +### When the standard meaning applies + +- The beneficiary is not enrolled as a member of the policy named in the request. +- The request names a policy other than the one covering this beneficiary. + +### When the PMJAY meaning applies + +- `x-hcx-timestamp` is more than 24 hours before the time the payer received the request. +- Your system stamped the request long before sending it, or resent an old sealed request unchanged. +- Your server clock is wrong. + +## How you know it worked + +Send the corrected request. The step is done when the payer answers without this code: + +- For a coverage eligibility check, `/v1/coverageeligibility/on_check` arrives for your `x-hcx-correlation_id` with no `x-hcx-error_details`. +- For a preauthorisation, `/v1/preauth/on_submit` arrives with no `x-hcx-error_details`. Its `x-hcx-workflow_id` names the decision, for example `21` approved or `24` queried. +- For a claim, `/v1/claim/on_submit` arrives with no `x-hcx-error_details`, and its bundle carries a `ClaimResponse`. + +## When it goes wrong + +### If the text reads `Beneficiary is not a covered member for requested policy` + +1. Confirm membership with a coverage eligibility check. See [Check coverage eligibility](../flows/coverage-eligibility-check.md). +2. Enrol the beneficiary for the policy with the payer, or use the policy that covers them. +3. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). + +### If the text reads `Maximum time limit exceeded in receiving the request` + +1. Set `x-hcx-timestamp` to the current time when you build each request. +2. Rebuild and seal the request again. Do not resend the old sealed request. +3. Keep your server clock synchronised. +4. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1006.md b/catalogue/nhcx/errors/payr-1006.md new file mode 100644 index 000000000..3c7ab4a19 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1006.md @@ -0,0 +1,94 @@ +--- +id: nhcx.error.payr-1006 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1006: the policy does not exist, or a name in the request is not valid' +summary: >- + PAYR-1006 means one of two things, the policy does not exist or, from the national + scheme's reference payer, a name in the request is not valid, and the message + text that comes with the code tells them apart. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Payer Error Codes, Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.policy-linking + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + - nhcx.endpoint.participant-get-policies + callbacks: + - nhcx.callback.coverageeligibility-on-check + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit +--- + +# PAYR-1006: the policy does not exist, or a name in the request is not valid + +## In plain words + +PAYR-1006 has two meanings, depending on which payer sent it: + +- From a payer using the standard payer codes: the policy does not exist. +- From the [PMJAY](../glossary/pmjay.md) payer: a name in the request is not valid. This PMJAY meaning is deprecated. + +Read the code together with the message text that comes with it. The text tells the two apart. + +## Before you start + +You sent a request through [NHCX](../../shared/glossary/nhcx.md), and the payer answered it with an error. The answer arrives on the `on_` path paired with your request, such as `/v1/coverageeligibility/on_check`, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. `x-hcx-status` marks it as an error. `x-hcx-error_details` carries the code in `code` and the text in `message`. + +Read these fields from the protected header once you open the [JWE](../glossary/jwe.md). Some payers send the same fields in a plain `ProtocolResponse` body instead. Handle both. + +A payer using the standard payer codes sends PAYR-1006 for coverage eligibility, preauthorisation and claim. + +## What happens + +| Message text | Sent by | Meaning | +|---|---|---| +| `Policy does not exist. Please try with a valid policy.` | A payer using the standard payer codes | The policy does not exist. | +| `Invalid name in request. Hence request will not be processed further.` | The PMJAY payer | A name in the request is not valid. This meaning is deprecated. | + +### When the standard meaning applies + +- The policy number in the request is wrong. +- The policy belongs to a different payer from the one you addressed. + +### When the PMJAY meaning applies + +- A name in the request, such as the patient's name in the Patient resource, is missing or not valid. + +## How you know it worked + +Send the corrected request. The step is done when the payer answers without this code: + +- For a coverage eligibility check, `/v1/coverageeligibility/on_check` arrives for your `x-hcx-correlation_id` with no `x-hcx-error_details`. +- For a preauthorisation, `/v1/preauth/on_submit` arrives with no `x-hcx-error_details`. Its `x-hcx-workflow_id` names the decision, for example `21` approved or `24` queried. +- For a claim, `/v1/claim/on_submit` arrives with no `x-hcx-error_details`, and its bundle carries a `ClaimResponse`. + +## When it goes wrong + +### If the text reads `Policy does not exist` + +1. Take the policy from the beneficiary's policy lookup. See [POST /participant/get/policies](../endpoints/participant-get-policies.md). +2. Address the request to the payer that holds that policy. +3. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). + +### If the text reads `Invalid name in request` + +1. Check every name in the request, starting with the patient's name in the Patient resource. +2. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1007.md b/catalogue/nhcx/errors/payr-1007.md new file mode 100644 index 000000000..5f7694bf9 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1007.md @@ -0,0 +1,92 @@ +--- +id: nhcx.error.payr-1007 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1007: the policy has expired, or the gender in the request is not valid' +summary: >- + PAYR-1007 means one of two things, the policy has expired or, from the national + scheme's reference payer, the gender in the request is not valid, and the message + text that comes with the code tells them apart. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Payer Error Codes, Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + - nhcx.endpoint.participant-get-policies + callbacks: + - nhcx.callback.coverageeligibility-on-check + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit +--- + +# PAYR-1007: the policy has expired, or the gender in the request is not valid + +## In plain words + +PAYR-1007 has two meanings, depending on which payer sent it: + +- From a payer using the standard payer codes: the policy has expired. +- From the [PMJAY](../glossary/pmjay.md) payer: the gender in the request is not valid. This PMJAY meaning is deprecated. + +Read the code together with the message text that comes with it. The text tells the two apart. + +## Before you start + +You sent a request through [NHCX](../../shared/glossary/nhcx.md), and the payer answered it with an error. The answer arrives on the `on_` path paired with your request, such as `/v1/coverageeligibility/on_check`, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. `x-hcx-status` marks it as an error. `x-hcx-error_details` carries the code in `code` and the text in `message`. + +Read these fields from the protected header once you open the [JWE](../glossary/jwe.md). Some payers send the same fields in a plain `ProtocolResponse` body instead. Handle both. + +A payer using the standard payer codes sends PAYR-1007 for coverage eligibility, preauthorisation and claim. + +## What happens + +| Message text | Sent by | Meaning | +|---|---|---| +| `Requested policy is expired. Please try with a valid policy.` | A payer using the standard payer codes | The policy has expired. | +| `Invalid gender in request. Hence request will not be processed further.` | The PMJAY payer | The gender in the request is not valid. This meaning is deprecated. | + +### When the standard meaning applies + +- The policy's period of cover ended before the date of the request or of the service. + +### When the PMJAY meaning applies + +- The gender in the request is missing, or is not a code from the [FHIR](../../shared/glossary/fhir.md) administrative gender value set. + +## How you know it worked + +Send the corrected request. The step is done when the payer answers without this code: + +- For a coverage eligibility check, `/v1/coverageeligibility/on_check` arrives for your `x-hcx-correlation_id` with no `x-hcx-error_details`. +- For a preauthorisation, `/v1/preauth/on_submit` arrives with no `x-hcx-error_details`. Its `x-hcx-workflow_id` names the decision, for example `21` approved or `24` queried. +- For a claim, `/v1/claim/on_submit` arrives with no `x-hcx-error_details`, and its bundle carries a `ClaimResponse`. + +## When it goes wrong + +### If the text reads `Requested policy is expired` + +1. Check the beneficiary's current policy with a coverage eligibility check. See [Check coverage eligibility](../flows/coverage-eligibility-check.md). +2. Send the request against a policy that is in force. +3. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). + +### If the text reads `Invalid gender in request` + +1. Send the gender as a code from the value set at https://hl7.org/fhir/R4/valueset-administrative-gender.html. +2. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1008.md b/catalogue/nhcx/errors/payr-1008.md new file mode 100644 index 000000000..cbeeb50d4 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1008.md @@ -0,0 +1,97 @@ +--- +id: nhcx.error.payr-1008 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1008: the beneficiary''s remaining cover is not enough for the request, + or the FHIR bundle is not valid or cannot be parsed' +summary: >- + PAYR-1008 means one of two things, the beneficiary's remaining cover is not enough + for the request or, from the national scheme's reference payer, the data bundle + is not valid or cannot be parsed, and the message text that comes with the code + tells them apart. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Payer Error Codes, Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.fhir-in-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.validation + - shared.fhir.hl7-validator-recipe + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1008: the beneficiary's remaining cover is not enough for the request, or the FHIR bundle is not valid or cannot be parsed + +## In plain words + +PAYR-1008 has two meanings, depending on which payer sent it: + +- From a payer using the standard payer codes: the beneficiary's remaining cover is not enough for the request. +- From the [PMJAY](../glossary/pmjay.md) payer: the [FHIR](../../shared/glossary/fhir.md) bundle is not valid or cannot be parsed. + +Read the code together with the message text that comes with it. The text tells the two apart. + +## Before you start + +You sent a request through [NHCX](../../shared/glossary/nhcx.md), and the payer answered it with an error. The answer arrives on the `on_` path paired with your request, such as `/v1/preauth/on_submit` or `/v1/claim/on_submit`. `x-hcx-status` marks it as an error. `x-hcx-error_details` carries the code in `code` and the text in `message`. + +Read these fields from the protected header once you open the [JWE](../glossary/jwe.md). Some payers send the same fields in a plain `ProtocolResponse` body instead. Handle both. + +A payer using the standard payer codes sends PAYR-1008 for preauthorisation and claim. + +## What happens + +| Message text | Sent by | Meaning | +|---|---|---| +| `Eligible coverage amount of the beneficiary for the requested policy is insufficient to process the request.` | A payer using the standard payer codes | The beneficiary's remaining cover is not enough for the request. | +| `Invalid FHIR bundle received. Hence request will not be processed further.` | The PMJAY payer | The FHIR bundle is not valid or cannot be parsed. | + +### When the standard meaning applies + +- The amount requested is more than the beneficiary's remaining cover under the policy. + +### When the PMJAY meaning applies + +- The bundle is not valid, or the payer cannot parse it. + +## How you know it worked + +Send the corrected request. The step is done when the payer answers without this code: + +- For a preauthorisation, `/v1/preauth/on_submit` arrives with no `x-hcx-error_details`. Its `x-hcx-workflow_id` names the decision, for example `21` approved or `24` queried. +- For a claim, `/v1/claim/on_submit` arrives with no `x-hcx-error_details`, and its bundle carries a `ClaimResponse`. + +## When it goes wrong + +### If the text reads `Eligible coverage amount of the beneficiary for the requested policy is insufficient to process the request` + +1. Check the remaining cover with a coverage eligibility check. See [Check coverage eligibility](../flows/coverage-eligibility-check.md). +2. Request no more than the remaining cover. +3. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). + +### If the text reads `Invalid FHIR bundle received` + +1. Validate the bundle with the [NRCeS](../../shared/glossary/nrces.md) validator. See [the validator recipe](../../shared/fhir/hl7-validator-recipe.md) and [validating an NHCX bundle](../fhir/validation.md). +2. Fix every error the validator reports. +3. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). +4. If it still fails, contact NHCX support. See [support contacts](../sandbox/support-contacts.md). diff --git a/catalogue/nhcx/errors/payr-1009.md b/catalogue/nhcx/errors/payr-1009.md new file mode 100644 index 000000000..ec10c9734 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1009.md @@ -0,0 +1,92 @@ +--- +id: nhcx.error.payr-1009 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1009: the requested items are not valid or not covered, or the Patient + resource has no identifier' +summary: >- + PAYR-1009 means one of two things, the requested items are not valid or not covered + or, from the national scheme's reference payer, the Patient resource has no identifier, + and the message text that comes with the code tells them apart. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Payer Error Codes, Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.insurance-plan + - nhcx.concept.fhir-in-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit +--- + +# PAYR-1009: the requested items are not valid or not covered, or the Patient resource has no identifier + +## In plain words + +PAYR-1009 has two meanings, depending on which payer sent it: + +- From a payer using the standard payer codes: the requested items are not valid or not covered. +- From the [PMJAY](../glossary/pmjay.md) payer: the Patient resource has no identifier. + +Read the code together with the message text that comes with it. The text tells the two apart. + +## Before you start + +You sent a request through [NHCX](../../shared/glossary/nhcx.md), and the payer answered it with an error. The answer arrives on the `on_` path paired with your request, such as `/v1/preauth/on_submit` or `/v1/claim/on_submit`. `x-hcx-status` marks it as an error. `x-hcx-error_details` carries the code in `code` and the text in `message`. + +Read these fields from the protected header once you open the [JWE](../glossary/jwe.md). Some payers send the same fields in a plain `ProtocolResponse` body instead. Handle both. + +A payer using the standard payer codes sends PAYR-1009 for preauthorisation and claim. + +## What happens + +| Message text | Sent by | Meaning | +|---|---|---| +| `Requested items are not valid or not covered. Please try again with valid or covered items.` | A payer using the standard payer codes | The requested items are not valid or not covered. | +| `No identifier found for patient component. Hence request will not be processed further. https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html` | The PMJAY payer | The Patient resource has no identifier. | + +### When the standard meaning applies + +- An item code in the request is not valid for the policy. +- An item is valid but the policy does not cover it. + +### When the PMJAY meaning applies + +- The Patient resource in the bundle has no `identifier`. + +## How you know it worked + +Send the corrected request. The step is done when the payer answers without this code: + +- For a preauthorisation, `/v1/preauth/on_submit` arrives with no `x-hcx-error_details`. Its `x-hcx-workflow_id` names the decision, for example `21` approved or `24` queried. +- For a claim, `/v1/claim/on_submit` arrives with no `x-hcx-error_details`, and its bundle carries a `ClaimResponse`. + +## When it goes wrong + +### If the text reads `Requested items are not valid or not covered` + +1. Check each item against the policy's covered items. See [the insurance plan](../concepts/insurance-plan.md) and [Request a patient's insurance plan](../flows/insurance-plan-request.md). +2. Remove or replace items the policy does not cover. +3. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). + +### If the text reads `No identifier found for patient component` + +1. Add an `identifier` to the Patient resource. The profile is at https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html. +2. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1010.md b/catalogue/nhcx/errors/payr-1010.md new file mode 100644 index 000000000..79117a3f2 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1010.md @@ -0,0 +1,91 @@ +--- +id: nhcx.error.payr-1010 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1010: a preauthorisation was required but not obtained, or the Patient + identifier has no type' +summary: >- + PAYR-1010 means one of two things, a preauthorisation was required but not obtained + or, from the national scheme's reference payer, the Patient identifier has no + type, and the message text that comes with the code tells them apart. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Payer Error Codes, Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit +--- + +# PAYR-1010: a preauthorisation was required but not obtained, or the Patient identifier has no type + +## In plain words + +PAYR-1010 has two meanings, depending on which payer sent it: + +- From a payer using the standard payer codes: a preauthorisation was required but not obtained. +- From the [PMJAY](../glossary/pmjay.md) payer: the Patient identifier has no type. + +Read the code together with the message text that comes with it. The text tells the two apart. + +## Before you start + +You sent a request through [NHCX](../../shared/glossary/nhcx.md), and the payer answered it with an error. The answer arrives on the `on_` path paired with your request, such as `/v1/preauth/on_submit` or `/v1/claim/on_submit`. `x-hcx-status` marks it as an error. `x-hcx-error_details` carries the code in `code` and the text in `message`. + +Read these fields from the protected header once you open the [JWE](../glossary/jwe.md). Some payers send the same fields in a plain `ProtocolResponse` body instead. Handle both. + +A payer using the standard payer codes sends PAYR-1010 for enhancements, resubmissions and claims. + +## What happens + +| Message text | Sent by | Meaning | +|---|---|---| +| `Preauthorization is required to process the request but was not obtained.` | A payer using the standard payer codes | A preauthorisation was required but not obtained. | +| `No type found for patient component identifier. Hence request will not be processed further. https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html` | The PMJAY payer | The Patient identifier has no type. | + +### When the standard meaning applies + +- You sent a claim, an enhancement or a resubmission for treatment that needed a preauthorisation first. +- No approved preauthorisation exists for the case. + +### When the PMJAY meaning applies + +- The Patient resource's `identifier` has no `type`. + +## How you know it worked + +Send the corrected request. The step is done when the payer answers without this code: + +- For a preauthorisation, `/v1/preauth/on_submit` arrives with no `x-hcx-error_details`. Its `x-hcx-workflow_id` names the decision, for example `21` approved or `24` queried. +- For a claim, `/v1/claim/on_submit` arrives with no `x-hcx-error_details`, and its bundle carries a `ClaimResponse`. + +## When it goes wrong + +### If the text reads `Preauthorization is required to process the request but was not obtained` + +1. Obtain a preauthorisation before the claim or enhancement. See [Submit a preauthorisation](../flows/preauth-submit.md). +2. Carry the approved preauthorisation's reference in the later request. +3. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). + +### If the text reads `No type found for patient component identifier` + +1. Give every `identifier` a `type`, starting with the Patient identifier. The profile is at https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html. +2. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1011.md b/catalogue/nhcx/errors/payr-1011.md new file mode 100644 index 000000000..978f8cd68 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1011.md @@ -0,0 +1,85 @@ +--- +id: nhcx.error.payr-1011 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1011: the approved package does not support enhancement, or the Claim + resource has no identifier' +summary: >- + PAYR-1011 means one of two things, the approved package does not support enhancement + or, from the national scheme's reference payer, the Claim resource has no identifier, + and the message text that comes with the code tells them apart. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Payer Error Codes, Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.insurance-plan + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit +--- + +# PAYR-1011: the approved package does not support enhancement, or the Claim resource has no identifier + +## In plain words + +PAYR-1011 has two meanings, depending on which payer sent it: + +- From a payer using the standard payer codes: the approved package does not support enhancement. +- From the [PMJAY](../glossary/pmjay.md) payer: the Claim resource has no identifier. + +Read the code together with the message text that comes with it. The text tells the two apart. + +## Before you start + +You sent a request through [NHCX](../../shared/glossary/nhcx.md), and the payer answered it with an error. The answer arrives on the `on_` path paired with your request, such as `/v1/preauth/on_submit`. `x-hcx-status` marks it as an error. `x-hcx-error_details` carries the code in `code` and the text in `message`. + +Read these fields from the protected header once you open the [JWE](../glossary/jwe.md). Some payers send the same fields in a plain `ProtocolResponse` body instead. Handle both. + +A payer using the standard payer codes sends PAYR-1011 for preauthorisation enhancements. + +## What happens + +| Message text | Sent by | Meaning | +|---|---|---| +| `Enhancement request can not be processed as the prior approved package/procedure does not support enhancement.` | A payer using the standard payer codes | The approved package does not support enhancement. | +| `No identifier found for claim component. Hence request will not be processed further.` | The PMJAY payer | The Claim resource has no identifier. | + +### When the standard meaning applies + +- You sent an enhancement against a package or procedure that does not allow one. + +### When the PMJAY meaning applies + +- The Claim resource in the bundle has no `identifier`. + +## How you know it worked + +Send the corrected request. The step is done when the payer answers without this code: + +- For a preauthorisation, `/v1/preauth/on_submit` arrives with no `x-hcx-error_details`. Its `x-hcx-workflow_id` names the decision, for example `21` approved or `24` queried. + +## When it goes wrong + +### If the text reads `Enhancement request can not be processed as the prior approved package/procedure does not support enhancement` + +1. Do not resend the same enhancement. The payer refuses it again. +2. Check whether a package allows enhancement before you send one. See [the insurance plan](../concepts/insurance-plan.md). + +### If the text reads `No identifier found for claim component` + +1. Add an `identifier` to the Claim resource. +2. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1012.md b/catalogue/nhcx/errors/payr-1012.md new file mode 100644 index 000000000..ab3478858 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1012.md @@ -0,0 +1,86 @@ +--- +id: nhcx.error.payr-1012 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1012: the claim amount is more than the approved preauthorisation amount, + or the Claim identifier has no type' +summary: >- + PAYR-1012 means one of two things, the claim amount is more than the approved + preauthorisation amount or, from the national scheme's reference payer, the Claim + identifier has no type, and the message text that comes with the code tells them + apart. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Payer Error Codes, Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.claim-submit + - nhcx.flow.preauth-enhancement + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit +--- + +# PAYR-1012: the claim amount is more than the approved preauthorisation amount, or the Claim identifier has no type + +## In plain words + +PAYR-1012 has two meanings, depending on which payer sent it: + +- From a payer using the standard payer codes: the claim amount is more than the approved preauthorisation amount. +- From the [PMJAY](../glossary/pmjay.md) payer: the Claim identifier has no type. + +Read the code together with the message text that comes with it. The text tells the two apart. + +## Before you start + +You sent a request through [NHCX](../../shared/glossary/nhcx.md), and the payer answered it with an error. The answer arrives on the `on_` path paired with your request, such as `/v1/claim/on_submit`. `x-hcx-status` marks it as an error. `x-hcx-error_details` carries the code in `code` and the text in `message`. + +Read these fields from the protected header once you open the [JWE](../glossary/jwe.md). Some payers send the same fields in a plain `ProtocolResponse` body instead. Handle both. + +A payer using the standard payer codes sends PAYR-1012 for claims. + +## What happens + +| Message text | Sent by | Meaning | +|---|---|---| +| `Claim amount requested is more than the preauthorization approved amount.` | A payer using the standard payer codes | The claim amount is more than the approved preauthorisation amount. | +| `No type found for claim component identifier. Hence request will not be processed further.` | The PMJAY payer | The Claim identifier has no type. | + +### When the standard meaning applies + +- The total claimed is higher than the amount the preauthorisation approved. + +### When the PMJAY meaning applies + +- The Claim resource's `identifier` has no `type`. + +## How you know it worked + +Send the corrected request. The step is done when the payer answers without this code: + +- For a claim, `/v1/claim/on_submit` arrives with no `x-hcx-error_details`, and its bundle carries a `ClaimResponse`. + +## When it goes wrong + +### If the text reads `Claim amount requested is more than the preauthorization approved amount` + +1. Compare the claimed total with the approved amount in the preauthorisation's `ClaimResponse`. +2. Reduce the claim to the approved amount, or obtain an enhancement first. See [Request a preauthorisation enhancement](../flows/preauth-enhancement.md). +3. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). + +### If the text reads `No type found for claim component identifier` + +1. Give the Claim resource's `identifier` a `type`. +2. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1013.md b/catalogue/nhcx/errors/payr-1013.md new file mode 100644 index 000000000..4ca639aa3 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1013.md @@ -0,0 +1,91 @@ +--- +id: nhcx.error.payr-1013 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1013: the procedures or packages have no prior approval, or the provider + Organization resource has no identifier' +summary: >- + PAYR-1013 means one of two things, the procedures or packages have no prior approval + or, from the national scheme's reference payer, the provider Organization resource + has no identifier, and the message text that comes with the code tells them apart. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Payer Error Codes, Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + glossary: + - shared.glossary.hfr +--- + +# PAYR-1013: the procedures or packages have no prior approval, or the provider Organization resource has no identifier + +## In plain words + +PAYR-1013 has two meanings, depending on which payer sent it: + +- From a payer using the standard payer codes: the procedures or packages have no prior approval. +- From the [PMJAY](../glossary/pmjay.md) payer: the provider Organization resource has no identifier. + +Read the code together with the message text that comes with it. The text tells the two apart. + +## Before you start + +You sent a request through [NHCX](../../shared/glossary/nhcx.md), and the payer answered it with an error. The answer arrives on the `on_` path paired with your request, such as `/v1/preauth/on_submit` or `/v1/claim/on_submit`. `x-hcx-status` marks it as an error. `x-hcx-error_details` carries the code in `code` and the text in `message`. + +Read these fields from the protected header once you open the [JWE](../glossary/jwe.md). Some payers send the same fields in a plain `ProtocolResponse` body instead. Handle both. + +A payer using the standard payer codes sends PAYR-1013 for enhancements and claims. + +## What happens + +| Message text | Sent by | Meaning | +|---|---|---| +| `No prior approval for the requested procedures/packages obtained.` | A payer using the standard payer codes | The procedures or packages have no prior approval. | +| `No identifier found for organization component for provider. Hence request will not be processed further.` | The PMJAY payer | The provider Organization resource has no identifier. | + +### When the standard meaning applies + +- The request includes a procedure or package that the preauthorisation did not approve. + +### When the PMJAY meaning applies + +- The provider's Organization resource in the bundle has no `identifier`. + +## How you know it worked + +Send the corrected request. The step is done when the payer answers without this code: + +- For a preauthorisation, `/v1/preauth/on_submit` arrives with no `x-hcx-error_details`. Its `x-hcx-workflow_id` names the decision, for example `21` approved or `24` queried. +- For a claim, `/v1/claim/on_submit` arrives with no `x-hcx-error_details`, and its bundle carries a `ClaimResponse`. + +## When it goes wrong + +### If the text reads `No prior approval for the requested procedures/packages obtained` + +1. Claim or enhance only procedures and packages the preauthorisation approved. +2. Obtain approval for any other procedure first. See [Submit a preauthorisation](../flows/preauth-submit.md). +3. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). + +### If the text reads `No identifier found for organization component for provider` + +1. Add an `identifier` to the provider Organization resource. Send your [HFR](../../shared/glossary/hfr.md) ID as that identifier, with type code `NPI`. +2. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1014.md b/catalogue/nhcx/errors/payr-1014.md new file mode 100644 index 000000000..637068737 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1014.md @@ -0,0 +1,95 @@ +--- +id: nhcx.error.payr-1014 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1014: the date of birth is after the date of service, or the provider + Organization identifier has no type' +summary: >- + PAYR-1014 means one of two things, the date of birth is after the date of service + or, from the national scheme's reference payer, the provider Organization identifier + has no type, and the message text that comes with the code tells them apart. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Payer Error Codes, Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.coverageeligibility-on-check + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + glossary: + - shared.glossary.hfr +--- + +# PAYR-1014: the date of birth is after the date of service, or the provider Organization identifier has no type + +## In plain words + +PAYR-1014 has two meanings, depending on which payer sent it: + +- From a payer using the standard payer codes: the date of birth is after the date of service. +- From the [PMJAY](../glossary/pmjay.md) payer: the provider Organization identifier has no type. + +Read the code together with the message text that comes with it. The text tells the two apart. + +## Before you start + +You sent a request through [NHCX](../../shared/glossary/nhcx.md), and the payer answered it with an error. The answer arrives on the `on_` path paired with your request, such as `/v1/coverageeligibility/on_check`, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. `x-hcx-status` marks it as an error. `x-hcx-error_details` carries the code in `code` and the text in `message`. + +Read these fields from the protected header once you open the [JWE](../glossary/jwe.md). Some payers send the same fields in a plain `ProtocolResponse` body instead. Handle both. + +A payer using the standard payer codes sends PAYR-1014 for coverage eligibility, preauthorisation and claim. + +## What happens + +| Message text | Sent by | Meaning | +|---|---|---| +| `Date of birth of the beneficiary can not be after date of service.` | A payer using the standard payer codes | The date of birth is after the date of service. | +| `No type found for organization component identifier for provider. Hence request will not be processed further.` | The PMJAY payer | The provider Organization identifier has no type. | + +### When the standard meaning applies + +- The Patient `birthDate` is later than a service date in the request. +- One of the two dates was entered wrongly. + +### When the PMJAY meaning applies + +- The provider Organization resource's `identifier` has no `type`. + +## How you know it worked + +Send the corrected request. The step is done when the payer answers without this code: + +- For a coverage eligibility check, `/v1/coverageeligibility/on_check` arrives for your `x-hcx-correlation_id` with no `x-hcx-error_details`. +- For a preauthorisation, `/v1/preauth/on_submit` arrives with no `x-hcx-error_details`. Its `x-hcx-workflow_id` names the decision, for example `21` approved or `24` queried. +- For a claim, `/v1/claim/on_submit` arrives with no `x-hcx-error_details`, and its bundle carries a `ClaimResponse`. + +## When it goes wrong + +### If the text reads `Date of birth of the beneficiary can not be after date of service` + +1. Check the Patient `birthDate` and every service date in the request. +2. Correct whichever date is wrong. +3. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). + +### If the text reads `No type found for organization component identifier for provider` + +1. Give the provider Organization identifier a `type`. For the [HFR](../../shared/glossary/hfr.md) ID, the type code is `NPI`. +2. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1015.md b/catalogue/nhcx/errors/payr-1015.md new file mode 100644 index 000000000..d6652a5ab --- /dev/null +++ b/catalogue/nhcx/errors/payr-1015.md @@ -0,0 +1,84 @@ +--- +id: nhcx.error.payr-1015 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1015: the date of service is after the date of death, or the payer + Organization resource has no identifier' +summary: >- + PAYR-1015 means one of two things, the date of service is after the date of death + or, from the national scheme's reference payer, the payer Organization resource + has no identifier, and the message text that comes with the code tells them apart. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Payer Error Codes, Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit +--- + +# PAYR-1015: the date of service is after the date of death, or the payer Organization resource has no identifier + +## In plain words + +PAYR-1015 has two meanings, depending on which payer sent it: + +- From a payer using the standard payer codes: the date of service is after the date of death. +- From the [PMJAY](../glossary/pmjay.md) payer: the payer Organization resource has no identifier. + +Read the code together with the message text that comes with it. The text tells the two apart. + +## Before you start + +You sent a request through [NHCX](../../shared/glossary/nhcx.md), and the payer answered it with an error. The answer arrives on the `on_` path paired with your request, such as `/v1/claim/on_submit`. `x-hcx-status` marks it as an error. `x-hcx-error_details` carries the code in `code` and the text in `message`. + +Read these fields from the protected header once you open the [JWE](../glossary/jwe.md). Some payers send the same fields in a plain `ProtocolResponse` body instead. Handle both. + +A payer using the standard payer codes sends PAYR-1015 for claims. + +## What happens + +| Message text | Sent by | Meaning | +|---|---|---| +| `Date of service cannot be after date of death.` | A payer using the standard payer codes | The date of service is after the date of death. | +| `No identifier found for organization component for payer. Hence request will not be processed further.` | The PMJAY payer | The payer Organization resource has no identifier. | + +### When the standard meaning applies + +- A service date in the claim is later than the patient's recorded date of death. + +### When the PMJAY meaning applies + +- The payer's Organization resource in the bundle has no `identifier`. + +## How you know it worked + +Send the corrected request. The step is done when the payer answers without this code: + +- For a claim, `/v1/claim/on_submit` arrives with no `x-hcx-error_details`, and its bundle carries a `ClaimResponse`. + +## When it goes wrong + +### If the text reads `Date of service cannot be after date of death` + +1. Check the service dates and the date of death in the claim. +2. Correct whichever date is wrong. +3. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). + +### If the text reads `No identifier found for organization component for payer` + +1. Add an `identifier` to the payer Organization resource. +2. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1016.md b/catalogue/nhcx/errors/payr-1016.md new file mode 100644 index 000000000..80deff7c9 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1016.md @@ -0,0 +1,86 @@ +--- +id: nhcx.error.payr-1016 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1016: the claim duplicates one already submitted for the same services + and dates, or the payer Organization identifier has no type' +summary: >- + PAYR-1016 means one of two things, the claim duplicates one already submitted + for the same services and dates or, from the national scheme's reference payer, + the payer Organization identifier has no type, and the message text that comes + with the code tells them apart. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Payer Error Codes, Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.claim-submit + - nhcx.flow.status-check + - nhcx.flow.claim-search + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit +--- + +# PAYR-1016: the claim duplicates one already submitted for the same services and dates, or the payer Organization identifier has no type + +## In plain words + +PAYR-1016 has two meanings, depending on which payer sent it: + +- From a payer using the standard payer codes: the claim duplicates one already submitted for the same services and dates. +- From the [PMJAY](../glossary/pmjay.md) payer: the payer Organization identifier has no type. + +Read the code together with the message text that comes with it. The text tells the two apart. + +## Before you start + +You sent a request through [NHCX](../../shared/glossary/nhcx.md), and the payer answered it with an error. The answer arrives on the `on_` path paired with your request, such as `/v1/claim/on_submit`. `x-hcx-status` marks it as an error. `x-hcx-error_details` carries the code in `code` and the text in `message`. + +Read these fields from the protected header once you open the [JWE](../glossary/jwe.md). Some payers send the same fields in a plain `ProtocolResponse` body instead. Handle both. + +A payer using the standard payer codes sends PAYR-1016 for claims. + +## What happens + +| Message text | Sent by | Meaning | +|---|---|---| +| `Duplicate claim submitted based on service codes and dates.` | A payer using the standard payer codes | The claim duplicates one already submitted for the same services and dates. | +| `No type found for organization component identifier for payer. Hence request will not be processed further.` | The PMJAY payer | The payer Organization identifier has no type. | + +### When the standard meaning applies + +- A claim with the same service codes and dates already exists with the payer. + +### When the PMJAY meaning applies + +- The payer Organization resource's `identifier` has no `type`. + +## How you know it worked + +Send the corrected request. The step is done when the payer answers without this code: + +- For a claim, `/v1/claim/on_submit` arrives with no `x-hcx-error_details`, and its bundle carries a `ClaimResponse`. + +## When it goes wrong + +### If the text reads `Duplicate claim submitted based on service codes and dates` + +1. Check whether you already submitted a claim for these services and dates. See [Search for claims](../flows/claim-search.md). +2. Do not submit it again. Follow the first claim instead. See [Check the status of a request](../flows/status-check.md). + +### If the text reads `No type found for organization component identifier for payer` + +1. Give the payer Organization identifier a `type`. +2. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1017.md b/catalogue/nhcx/errors/payr-1017.md new file mode 100644 index 000000000..c4e3df0ac --- /dev/null +++ b/catalogue/nhcx/errors/payr-1017.md @@ -0,0 +1,97 @@ +--- +id: nhcx.error.payr-1017 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1017: the amount calculations are not correct, or the Task resource + has no task code' +summary: >- + PAYR-1017 means one of two things, the amount calculations are not correct or, + from the national scheme's reference payer, the Task resource has no task code, + and the message text that comes with the code tells them apart. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Payer Error Codes, Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.reprocess-and-cancel + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + - nhcx.flow.claim-reprocess + - nhcx.flow.preauth-cancel + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + - nhcx.endpoint.task-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + - nhcx.callback.task-on-submit + fhir: + - nhcx.fhir.task +--- + +# PAYR-1017: the amount calculations are not correct, or the Task resource has no task code + +## In plain words + +PAYR-1017 has two meanings, depending on which payer sent it: + +- From a payer using the standard payer codes: the amount calculations are not correct. +- From the [PMJAY](../glossary/pmjay.md) payer: the Task resource has no task code. + +Read the code together with the message text that comes with it. The text tells the two apart. + +## Before you start + +You sent a request through [NHCX](../../shared/glossary/nhcx.md), and the payer answered it with an error. The answer arrives on the `on_` path paired with your request, such as `/v1/preauth/on_submit` or `/v1/claim/on_submit`. `x-hcx-status` marks it as an error. `x-hcx-error_details` carries the code in `code` and the text in `message`. + +Read these fields from the protected header once you open the [JWE](../glossary/jwe.md). Some payers send the same fields in a plain `ProtocolResponse` body instead. Handle both. + +A payer using the standard payer codes sends PAYR-1017 for preauthorisation and claim. + +## What happens + +| Message text | Sent by | Meaning | +|---|---|---| +| `Amount calculations are not correct. Please verify calculated amount.` | A payer using the standard payer codes | The amount calculations are not correct. | +| `No task code received. Hence request will not be processed further.` | The PMJAY payer | The Task resource has no task code. | + +### When the standard meaning applies + +- An item's net amount does not match its quantity and unit price. +- The total does not match the sum of the items. + +### When the PMJAY meaning applies + +- A task request, such as a reprocess or a cancellation, arrived with no `Task.code`. + +## How you know it worked + +Send the corrected request. The step is done when the payer answers without this code: + +- For a preauthorisation, `/v1/preauth/on_submit` arrives with no `x-hcx-error_details`. Its `x-hcx-workflow_id` names the decision, for example `21` approved or `24` queried. +- For a claim, `/v1/claim/on_submit` arrives with no `x-hcx-error_details`, and its bundle carries a `ClaimResponse`. +- For a task, `/v1/task/on_submit` arrives with no `x-hcx-error_details`. + +## When it goes wrong + +### If the text reads `Amount calculations are not correct` + +1. Recompute each item's net amount from its quantity and unit price. +2. Recompute the total from the items. +3. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). + +### If the text reads `No task code received` + +1. Set `Task.code`, for example `reprocess` or `cancel`. See [Reprocess, cancel and the task resource](../concepts/reprocess-and-cancel.md). +2. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1018.md b/catalogue/nhcx/errors/payr-1018.md new file mode 100644 index 000000000..96eb7466a --- /dev/null +++ b/catalogue/nhcx/errors/payr-1018.md @@ -0,0 +1,96 @@ +--- +id: nhcx.error.payr-1018 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1018: the time limit for submission has expired, or the Task resource + has no reason code' +summary: >- + PAYR-1018 means one of two things, the time limit for submission has expired or, + from the national scheme's reference payer, the Task resource has no reason code, + and the message text that comes with the code tells them apart. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Payer Error Codes, Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.reprocess-and-cancel + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.claim-submit + - nhcx.flow.claim-reprocess + - nhcx.flow.preauth-cancel + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + - nhcx.endpoint.task-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + - nhcx.callback.task-on-submit + fhir: + - nhcx.fhir.task +--- + +# PAYR-1018: the time limit for submission has expired, or the Task resource has no reason code + +## In plain words + +PAYR-1018 has two meanings, depending on which payer sent it: + +- From a payer using the standard payer codes: the time limit for submission has expired. +- From the [PMJAY](../glossary/pmjay.md) payer: the Task resource has no reason code. + +Read the code together with the message text that comes with it. The text tells the two apart. + +## Before you start + +You sent a request through [NHCX](../../shared/glossary/nhcx.md), and the payer answered it with an error. The answer arrives on the `on_` path paired with your request, such as `/v1/preauth/on_submit` or `/v1/claim/on_submit`. `x-hcx-status` marks it as an error. `x-hcx-error_details` carries the code in `code` and the text in `message`. + +Read these fields from the protected header once you open the [JWE](../glossary/jwe.md). Some payers send the same fields in a plain `ProtocolResponse` body instead. Handle both. + +A payer using the standard payer codes sends PAYR-1018 for enhancements, resubmissions and claims. + +## What happens + +| Message text | Sent by | Meaning | +|---|---|---| +| `Time limit for submission expired.` | A payer using the standard payer codes | The time limit for submission has expired. | +| `No task reason code received. Hence request will not be processed further.` | The PMJAY payer | The Task resource has no reason code. | + +### When the standard meaning applies + +- You sent the enhancement, resubmission or claim after the payer's deadline for it. + +### When the PMJAY meaning applies + +- A task request arrived with no `Task.reasonCode`. + +## How you know it worked + +Send the corrected request. The step is done when the payer answers without this code: + +- For a preauthorisation, `/v1/preauth/on_submit` arrives with no `x-hcx-error_details`. Its `x-hcx-workflow_id` names the decision, for example `21` approved or `24` queried. +- For a claim, `/v1/claim/on_submit` arrives with no `x-hcx-error_details`, and its bundle carries a `ClaimResponse`. +- For a task, `/v1/task/on_submit` arrives with no `x-hcx-error_details`. + +## When it goes wrong + +### If the text reads `Time limit for submission expired` + +1. Submit within the payer's time limit for each stage. +2. For a submission that is already late, contact the payer. Resending it returns the same code. + +### If the text reads `No task reason code received` + +1. Set `Task.reasonCode`, for example `claimrejected` for a reprocess, or a cancellation reason such as `patientrequest`. The input, code and reason code must form a valid combination. +2. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1019.md b/catalogue/nhcx/errors/payr-1019.md new file mode 100644 index 000000000..214cfcd81 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1019.md @@ -0,0 +1,92 @@ +--- +id: nhcx.error.payr-1019 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1019: the additional information the payer asked for did not arrive + in time, or a supporting info sequence is not valid' +summary: >- + PAYR-1019 means one of two things, the additional information the payer asked + for did not arrive in time or, from the national scheme's reference payer, a supporting + info sequence is not valid, and the message text that comes with the code tells + them apart. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Payer Error Codes, Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.queries-and-communication + flows: + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-query-response + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit +--- + +# PAYR-1019: the additional information the payer asked for did not arrive in time, or a supporting info sequence is not valid + +## In plain words + +PAYR-1019 has two meanings, depending on which payer sent it: + +- From a payer using the standard payer codes: the additional information the payer asked for did not arrive in time. +- From the [PMJAY](../glossary/pmjay.md) payer: a supporting info sequence is not valid. + +Read the code together with the message text that comes with it. The text tells the two apart. + +## Before you start + +You sent a request through [NHCX](../../shared/glossary/nhcx.md), and the payer answered it with an error. The answer arrives on the `on_` path paired with your request, such as `/v1/preauth/on_submit` or `/v1/claim/on_submit`. `x-hcx-status` marks it as an error. `x-hcx-error_details` carries the code in `code` and the text in `message`. + +Read these fields from the protected header once you open the [JWE](../glossary/jwe.md). Some payers send the same fields in a plain `ProtocolResponse` body instead. Handle both. + +A payer using the standard payer codes sends PAYR-1019 for queries on preauthorisations and claims. + +## What happens + +| Message text | Sent by | Meaning | +|---|---|---| +| `Requested additional information was not received or was not received within time limit` | A payer using the standard payer codes | The additional information the payer asked for did not arrive in time. | +| `Invalid sequence received in supporting info element. Hence request will not be processed further.` | The PMJAY payer | A supporting info sequence is not valid. | + +### When the standard meaning applies + +- The payer queried the case, and your answer did not arrive, or arrived after the time limit. + +### When the PMJAY meaning applies + +- A `supportingInfo` entry has a missing or repeated `sequence`, or an item refers to a sequence that does not exist. + +## How you know it worked + +Send the corrected request. The step is done when the payer answers without this code: + +- For a preauthorisation, `/v1/preauth/on_submit` arrives with no `x-hcx-error_details`. Its `x-hcx-workflow_id` names the decision, for example `21` approved or `24` queried. +- For a claim, `/v1/claim/on_submit` arrives with no `x-hcx-error_details`, and its bundle carries a `ClaimResponse`. + +## When it goes wrong + +### If the text reads `Requested additional information was not received or was not received within time limit` + +1. Answer each payer query within the time limit, with every document asked for. See [Answer a payer query on a preauthorisation](../flows/preauth-query-response.md) and [Answer a payer query on a claim](../flows/claim-query-response.md). +2. For a query already past its limit, contact the payer. + +### If the text reads `Invalid sequence received in supporting info element` + +1. Number each `supportingInfo` entry with a unique `sequence`. +2. Use those numbers wherever the bundle refers to a supporting info entry. +3. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1020.md b/catalogue/nhcx/errors/payr-1020.md new file mode 100644 index 000000000..74f356e32 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1020.md @@ -0,0 +1,86 @@ +--- +id: nhcx.error.payr-1020 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1020: the payer holds no valid bank details for your facility, or a + supporting info category is not valid' +summary: >- + PAYR-1020 means one of two things, the payer holds no valid bank details for your + facility or, from the national scheme's reference payer, a supporting info category + is not valid, and the message text that comes with the code tells them apart. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Payer Error Codes, Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.payment-notice + - nhcx.flow.claim-submit + callbacks: + - nhcx.callback.paymentnotice-request + - nhcx.callback.claim-on-submit + endpoints: + - nhcx.endpoint.claim-submit +--- + +# PAYR-1020: the payer holds no valid bank details for your facility, or a supporting info category is not valid + +## In plain words + +PAYR-1020 has two meanings, depending on which payer sent it: + +- From a payer using the standard payer codes: the payer holds no valid bank details for your facility. +- From the [PMJAY](../glossary/pmjay.md) payer: a supporting info category is not valid. + +Read the code together with the message text that comes with it. The text tells the two apart. + +## Before you start + +You sent a request through [NHCX](../../shared/glossary/nhcx.md), and the payer answered it with an error. The answer arrives on the `on_` path paired with your request, such as `/v1/claim/on_submit`. `x-hcx-status` marks it as an error. `x-hcx-error_details` carries the code in `code` and the text in `message`. + +Read these fields from the protected header once you open the [JWE](../glossary/jwe.md). Some payers send the same fields in a plain `ProtocolResponse` body instead. Handle both. + +A payer using the standard payer codes sends PAYR-1020 for payment. + +## What happens + +| Message text | Sent by | Meaning | +|---|---|---| +| `Unable to process payment as no valid bank details found for the provider.` | A payer using the standard payer codes | The payer holds no valid bank details for your facility. | +| `Invalid category received in supporting info element for sequence %s. Hence request will not be processed further.` | The PMJAY payer | A supporting info category is not valid. | + +### When the standard meaning applies + +- The payer has no bank details for your facility, or the details it holds are not valid. + +### When the PMJAY meaning applies + +- The `supportingInfo` entry named in the message has a missing or unknown `category`. The payer puts the entry's sequence number in place of `%s`. + +## How you know it worked + +Send the corrected request. The step is done when the payer answers without this code: + +- For a payment, the payer's payment exchange for the claim completes without `x-hcx-error_details`. +- For a claim, `/v1/claim/on_submit` arrives with no `x-hcx-error_details`, and its bundle carries a `ClaimResponse`. + +## When it goes wrong + +### If the text reads `Unable to process payment as no valid bank details found for the provider` + +1. Contact the payer to register or correct your facility's bank details. +2. Payment for the claim can go ahead once the payer holds valid details. + +### If the text reads `Invalid category received in supporting info element for sequence %s` + +1. Set `category` on the entry named in the message to a code from https://www.nrces.in/ndhm/fhir/r4/ValueSet-ndhm-supportinginfo-category.html. +2. Send the request again with a fresh `x-hcx-correlation_id`. Reusing the old one returns [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1021.md b/catalogue/nhcx/errors/payr-1021.md new file mode 100644 index 000000000..5fa8e8030 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1021.md @@ -0,0 +1,122 @@ +--- +id: nhcx.error.payr-1021 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1021, a supporting info entry has an invalid code +summary: >- + The payer rejected your preauthorisation or claim because one supporting information + entry carries a code that does not fit it. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + - nhcx.fhir.terminologies + errors: + - nhcx.error.payr-1019 + - nhcx.error.payr-1020 + - nhcx.error.payr-1095 + - nhcx.error.payr-1098 + - nhcx.error.payr-1099 + - nhcx.error.payr-1502 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1021, a supporting info entry has an invalid code + +## In plain words + +Your [FHIR](../../shared/glossary/fhir.md) bundle lists supporting information, such as dates, discharge details and documents. Each entry has a category and a code. The payer rejected the request because one entry's code is not valid for it. + +## Before you start + +You sent a [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) bundle through [NHCX](../../shared/glossary/nhcx.md), on `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1021`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1021` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> Invalid code received in supporting info element for sequence `%s`. Hence request will not be processed further. + +The payer puts the `sequence` of the rejected supporting info entry in place of `%s`. + +The payer returns this code when: + +- An entry in `Claim.supportingInfo` has no `code`, or its `code` is not one the payer accepts. +- The `code` does not belong with the entry's `category`. A discharge date, for example, needs category `ONS` with code `DSDE`. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit`, matching the path you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1021`. The decrypted payload is a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Find the `Claim.supportingInfo` entry whose `sequence` matches the number in the message. +2. Check its `category` and `code` as a pair. The payer reads these pairs: + +| Content | `category` | `code` | +|---|---|---| +| Registration date | `OTH` | `EDT` | +| Admission date | `ONS` | `ADDD` | +| Surgery date | `ONS` | `PSP` | +| Discharge date | `ONS` | `DSDE` | +| Death date | `ONS` | `DTM` | +| Discharge information | `DIS` | `LAMA`, `DAMA`, `DTH` or `DTM` | +| Case remarks in a query response | `NMI` | `CQD` | +| Reference to a policy or case QuestionnaireResponse | `INF` | `ODN` | + +3. Take codes from the [NRCeS](../../shared/glossary/nrces.md) supporting info code value set, `https://www.nrces.in/ndhm/fhir/r4/ValueSet-ndhm-supportinginfo-code.html`. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare the rejected element with the [preauthorisation request bundle](../fhir/preauth-request.md) or the [claim request bundle](../fhir/claim-request.md). If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1019](payr-1019.md), [PAYR-1020](payr-1020.md), [PAYR-1095](payr-1095.md), [PAYR-1098](payr-1098.md), [PAYR-1099](payr-1099.md) and [PAYR-1502](payr-1502.md). diff --git a/catalogue/nhcx/errors/payr-1023.md b/catalogue/nhcx/errors/payr-1023.md new file mode 100644 index 000000000..5afa38090 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1023.md @@ -0,0 +1,105 @@ +--- +id: nhcx.error.payr-1023 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1023, a procedure has an invalid category +summary: >- + The payer rejected your preauthorisation or claim because a procedure in it has + a missing or unaccepted category. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + - nhcx.fhir.terminologies + errors: + - nhcx.error.payr-1024 + - nhcx.error.payr-1025 + - nhcx.error.payr-1041 + - nhcx.error.payr-1042 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1023, a procedure has an invalid category + +## In plain words + +Your [FHIR](../../shared/glossary/fhir.md) bundle describes each procedure in a Procedure resource. The payer rejected the request because a procedure's category is missing or not one it accepts. + +## Before you start + +You sent a [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) bundle through [NHCX](../../shared/glossary/nhcx.md), on `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1023`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1023` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> Invalid procedure category received for procedure component. Hence request will not be processed further. + +The payer returns this code when: + +- A Procedure resource in the bundle has no `category`. +- The `category` coding is not one the payer accepts. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit`, matching the path you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1023`. The decrypted payload is a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Open each Procedure resource in the bundle. +2. Give it a `category` coding. The sample bundles use code `Stratification` with system `http://hl7.org/fhir/ValueSet/procedure-category`. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare the rejected element with the [preauthorisation request bundle](../fhir/preauth-request.md) or the [claim request bundle](../fhir/claim-request.md). If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1024](payr-1024.md), [PAYR-1025](payr-1025.md), [PAYR-1041](payr-1041.md) and [PAYR-1042](payr-1042.md). diff --git a/catalogue/nhcx/errors/payr-1024.md b/catalogue/nhcx/errors/payr-1024.md new file mode 100644 index 000000000..092d2188d --- /dev/null +++ b/catalogue/nhcx/errors/payr-1024.md @@ -0,0 +1,104 @@ +--- +id: nhcx.error.payr-1024 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1024, a procedure has an invalid status +summary: >- + The payer rejected your preauthorisation or claim because a procedure in it has + a missing or unaccepted status. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + errors: + - nhcx.error.payr-1023 + - nhcx.error.payr-1025 + - nhcx.error.payr-1210 + - nhcx.error.payr-1345 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1024, a procedure has an invalid status + +## In plain words + +Your [FHIR](../../shared/glossary/fhir.md) bundle describes each procedure in a Procedure resource, with a status. The payer rejected the request because a procedure's status is missing or not valid. + +## Before you start + +You sent a [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) bundle through [NHCX](../../shared/glossary/nhcx.md), on `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1024`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1024` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> Invalid procedure status received for procedure component. Hence request will not be processed further. + +The payer returns this code when: + +- A Procedure resource in the bundle has no `status`. +- The `status` is not a code the payer accepts. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit`, matching the path you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1024`. The decrypted payload is a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Open each Procedure resource in the bundle. +2. Set `Procedure.status`. The sample preauthorisation and claim bundles use `preparation`. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare the rejected element with the [preauthorisation request bundle](../fhir/preauth-request.md) or the [claim request bundle](../fhir/claim-request.md). If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1023](payr-1023.md), [PAYR-1025](payr-1025.md), [PAYR-1210](payr-1210.md) and [PAYR-1345](payr-1345.md). diff --git a/catalogue/nhcx/errors/payr-1025.md b/catalogue/nhcx/errors/payr-1025.md new file mode 100644 index 000000000..54d42dbcc --- /dev/null +++ b/catalogue/nhcx/errors/payr-1025.md @@ -0,0 +1,103 @@ +--- +id: nhcx.error.payr-1025 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1025, a procedure has an invalid sequence +summary: >- + The payer rejected your preauthorisation or claim because it cannot read a valid + sequence number for one of its procedures. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + errors: + - nhcx.error.payr-1026 + - nhcx.error.payr-1028 + - nhcx.error.payr-1072 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1025, a procedure has an invalid sequence + +## In plain words + +A claim in a [FHIR](../../shared/glossary/fhir.md) bundle lists its procedures with sequence numbers. Items point at procedures by that number. The payer rejected the request because a procedure's sequence is missing or not valid. + +## Before you start + +You sent a [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) bundle through [NHCX](../../shared/glossary/nhcx.md), on `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1025`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1025` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> Invalid procedure sequence received for procedure component. Hence request will not be processed further. + +The payer returns this code when: + +- An entry in `Claim.procedure` has no `sequence`. +- The `sequence` is not a positive whole number, or two procedures share one. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit`, matching the path you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1025`. The decrypted payload is a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Number the `Claim.procedure` entries from 1 in `sequence`, one number per procedure. +2. Make each item's `procedureSequence` name one of those numbers. The sample preauthorisation bundle sets `procedureSequence` to 1 on its item. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare the rejected element with the [preauthorisation request bundle](../fhir/preauth-request.md) or the [claim request bundle](../fhir/claim-request.md). If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1026](payr-1026.md), [PAYR-1028](payr-1028.md) and [PAYR-1072](payr-1072.md). diff --git a/catalogue/nhcx/errors/payr-1026.md b/catalogue/nhcx/errors/payr-1026.md new file mode 100644 index 000000000..85c901966 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1026.md @@ -0,0 +1,105 @@ +--- +id: nhcx.error.payr-1026 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1026, the claim references a procedure that is not in the bundle +summary: >- + The payer rejected your preauthorisation or claim because the claim points at + a procedure record that the bundle does not contain. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + errors: + - nhcx.error.payr-1040 + - nhcx.error.payr-1072 + - nhcx.error.payr-1086 + - nhcx.error.payr-1087 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1026, the claim references a procedure that is not in the bundle + +## In plain words + +The Claim resource in your [FHIR](../../shared/glossary/fhir.md) bundle points at each procedure through a reference. The payer rejected the request because one of those references finds no Procedure resource in the bundle. + +## Before you start + +You sent a [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) bundle through [NHCX](../../shared/glossary/nhcx.md), on `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1026`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1026` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> No procedure component found for reference in claim component. Hence request will not be processed further. + +The payer returns this code when: + +- A `Claim.procedure` entry has a `procedureReference` whose target is not an entry in the bundle. +- The target exists, but its `fullUrl` does not match the reference. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit`, matching the path you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1026`. The decrypted payload is a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. List the `procedureReference` values in `Claim.procedure`. +2. For each one, add the Procedure resource to the bundle, or correct the reference. +3. Make the reference resolve to the Procedure entry's `fullUrl`. The sample bundles pair `procedureReference` `procedure/1` with a Procedure entry whose `fullUrl` ends in `claim/procedure/1`. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare the rejected element with the [preauthorisation request bundle](../fhir/preauth-request.md) or the [claim request bundle](../fhir/claim-request.md). If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1040](payr-1040.md), [PAYR-1072](payr-1072.md), [PAYR-1086](payr-1086.md) and [PAYR-1087](payr-1087.md). diff --git a/catalogue/nhcx/errors/payr-1027.md b/catalogue/nhcx/errors/payr-1027.md new file mode 100644 index 000000000..ed20816b7 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1027.md @@ -0,0 +1,102 @@ +--- +id: nhcx.error.payr-1027 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1027, a claim item has an invalid id +summary: >- + The payer rejected your preauthorisation or claim because one of the billed items + has a missing or unreadable id. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + errors: + - nhcx.error.payr-1028 + - nhcx.error.payr-1045 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1027, a claim item has an invalid id + +## In plain words + +Each billed item in the Claim resource of your [FHIR](../../shared/glossary/fhir.md) bundle carries an id. The payer rejected the request because an item's id is missing or not valid. + +## Before you start + +You sent a [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) bundle through [NHCX](../../shared/glossary/nhcx.md), on `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1027`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1027` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> Invalid item id found for item in claim component. Hence request will not be processed further. + +The payer returns this code when: + +- A `Claim.item` entry has no `id`. +- The `id` is empty or not in a form the payer reads. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit`, matching the path you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1027`. The decrypted payload is a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Open each entry in `Claim.item`. +2. Give it an `id`. The sample preauthorisation bundle gives its first item the id `Item/1`. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare the rejected element with the [preauthorisation request bundle](../fhir/preauth-request.md) or the [claim request bundle](../fhir/claim-request.md). If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1028](payr-1028.md) and [PAYR-1045](payr-1045.md). diff --git a/catalogue/nhcx/errors/payr-1028.md b/catalogue/nhcx/errors/payr-1028.md new file mode 100644 index 000000000..9dc73862c --- /dev/null +++ b/catalogue/nhcx/errors/payr-1028.md @@ -0,0 +1,104 @@ +--- +id: nhcx.error.payr-1028 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1028, a claim item has an invalid sequence +summary: >- + The payer rejected your preauthorisation or claim because one of the billed items + has a missing or unreadable sequence number. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + errors: + - nhcx.error.payr-1027 + - nhcx.error.payr-1025 + - nhcx.error.payr-1081 + - nhcx.error.payr-1361 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1028, a claim item has an invalid sequence + +## In plain words + +Each billed item in the Claim resource of your [FHIR](../../shared/glossary/fhir.md) bundle carries a sequence number. The payer rejected the request because an item's sequence is missing or not valid. + +## Before you start + +You sent a [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) bundle through [NHCX](../../shared/glossary/nhcx.md), on `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1028`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1028` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> Invalid item sequence received for item in claim component. Hence request will not be processed further. + +The payer returns this code when: + +- A `Claim.item` entry has no `sequence`. +- The `sequence` is not a positive whole number, or two items share one. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit`, matching the path you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1028`. The decrypted payload is a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Number the `Claim.item` entries from 1 in `sequence`, one number per item. +2. Keep the item's `careTeamSequence`, `diagnosisSequence` and `procedureSequence` pointing at real entries. The sample preauthorisation bundle gives its only item sequence 1. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare the rejected element with the [preauthorisation request bundle](../fhir/preauth-request.md) or the [claim request bundle](../fhir/claim-request.md). If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1027](payr-1027.md), [PAYR-1025](payr-1025.md), [PAYR-1081](payr-1081.md) and [PAYR-1361](payr-1361.md). diff --git a/catalogue/nhcx/errors/payr-1029.md b/catalogue/nhcx/errors/payr-1029.md new file mode 100644 index 000000000..e2285dfdd --- /dev/null +++ b/catalogue/nhcx/errors/payr-1029.md @@ -0,0 +1,106 @@ +--- +id: nhcx.error.payr-1029 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1029, the bundle id is invalid +summary: >- + The payer rejected your request because the outer bundle that carries it has a + missing or unreadable id. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.coverageeligibility-on-check + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.collection-bundle + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + errors: + - nhcx.error.payr-1031 + - nhcx.error.payr-1049 + - nhcx.error.payr-1004 + - nhcx.error.payr-1008 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1029, the bundle id is invalid + +## In plain words + +Every request carries one [FHIR](../../shared/glossary/fhir.md) bundle, and the bundle has an id. The payer rejected the request because the bundle's id is missing or not valid. + +## Before you start + +You sent a request through [NHCX](../../shared/glossary/nhcx.md) on a use case path, such as `/v1/coverageeligibility/check`, `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired `on_` path, for example `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1029`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1029` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> Invalid bundle id received for FHIR bundle. Hence request will not be processed further. + +The payer returns this code when: + +- The bundle has no `id`. +- The `id` is empty or not a valid FHIR id. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on the `on_` path paired with the one you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1029`. The decrypted payload is the response bundle for your use case, such as a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Set `Bundle.id` on the outer bundle. +2. Use a plain identifier. The sample bundles use ids such as `PreAuth` and `CLAIM`. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare your bundle with the [collection bundle](../fhir/collection-bundle.md) and the bundle for your use case. If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1031](payr-1031.md), [PAYR-1049](payr-1049.md), [PAYR-1004](payr-1004.md) and [PAYR-1008](payr-1008.md). diff --git a/catalogue/nhcx/errors/payr-1030.md b/catalogue/nhcx/errors/payr-1030.md new file mode 100644 index 000000000..edadd7807 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1030.md @@ -0,0 +1,109 @@ +--- +id: nhcx.error.payr-1030 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1030, a questionnaire id in the bundle is invalid +summary: >- + The payer rejected your preauthorisation or claim because the id of a questionnaire + answer in it is not valid. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + - nhcx.fhir.pmjay-insurance-plan + - nhcx.fhir.insurance-plan-bundle + errors: + - nhcx.error.payr-1084 + - nhcx.error.payr-1085 + - nhcx.error.payr-1505 + - nhcx.error.payr-1365 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1030, a questionnaire id in the bundle is invalid + +## In plain words + +Some policies ask the provider to answer questionnaires. The answers travel as QuestionnaireResponse resources in the [FHIR](../../shared/glossary/fhir.md) bundle. The payer rejected the request because a questionnaire id in the bundle is not valid. + +## Before you start + +You sent a [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) bundle through [NHCX](../../shared/glossary/nhcx.md), on `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1030`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1030` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> Invalid questionnaire id received in FHIR bundle for questionnaire component. Hence request will not be processed further. + +The payer returns this code when: + +- A QuestionnaireResponse entry has no `id`, or its `id` is not valid. +- The questionnaire it answers is not one published in the [insurance plan](../glossary/insurance-plan.md) for the policy. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit`, matching the path you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1030`. The decrypted payload is a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Fetch the insurance plan for the policy. See [request an insurance plan](../flows/insurance-plan-request.md). +2. Take questionnaire ids from the plan. Do not build them yourself. +3. Give each QuestionnaireResponse a valid `id`. +4. Reference it from `Claim.supportingInfo` with category `INF` and code `ODN`. For a questionnaire tied to a procedure code, use category `STG`. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare the rejected element with the [preauthorisation request bundle](../fhir/preauth-request.md) or the [claim request bundle](../fhir/claim-request.md). If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1084](payr-1084.md), [PAYR-1085](payr-1085.md), [PAYR-1505](payr-1505.md) and [PAYR-1365](payr-1365.md). diff --git a/catalogue/nhcx/errors/payr-1031.md b/catalogue/nhcx/errors/payr-1031.md new file mode 100644 index 000000000..7aeefec1d --- /dev/null +++ b/catalogue/nhcx/errors/payr-1031.md @@ -0,0 +1,106 @@ +--- +id: nhcx.error.payr-1031 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1031, a bundle entry has an invalid URL +summary: >- + The payer rejected your request because one of the entries in its bundle has a + missing or unreadable address. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.coverageeligibility-on-check + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.collection-bundle + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + errors: + - nhcx.error.payr-1040 + - nhcx.error.payr-1029 + - nhcx.error.payr-1026 + - nhcx.error.payr-1048 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1031, a bundle entry has an invalid URL + +## In plain words + +Every resource in a [FHIR](../../shared/glossary/fhir.md) bundle sits in an entry with a full URL. References between resources use that URL. The payer rejected the request because an entry's URL is missing or not valid. + +## Before you start + +You sent a request through [NHCX](../../shared/glossary/nhcx.md) on a use case path, such as `/v1/coverageeligibility/check`, `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired `on_` path, for example `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1031`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1031` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> Invalid url received for bundle entry in FHIR bundle. Hence request will not be processed further. Please reach out to technical team. + +The payer returns this code when: + +- A `Bundle.entry` has no `fullUrl`. +- The `fullUrl` is not an absolute URL or a `urn:uuid:` value. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on the `on_` path paired with the one you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1031`. The decrypted payload is the response bundle for your use case, such as a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Give every entry a `fullUrl`. The sample bundles use either an `https://` URL or a `urn:uuid:` value. +2. Make every reference in the bundle match the `fullUrl` of the entry it points at. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare your bundle with the [collection bundle](../fhir/collection-bundle.md) and the bundle for your use case. If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1040](payr-1040.md), [PAYR-1029](payr-1029.md), [PAYR-1026](payr-1026.md) and [PAYR-1048](payr-1048.md). diff --git a/catalogue/nhcx/errors/payr-1032.md b/catalogue/nhcx/errors/payr-1032.md new file mode 100644 index 000000000..8f634a796 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1032.md @@ -0,0 +1,97 @@ +--- +id: nhcx.error.payr-1032 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1032, the eligibility check has an invalid purpose +summary: >- + The payer rejected your eligibility check because it does not say, in a form the + payer accepts, what you want to know. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.coverage-eligibility-purposes + flows: + - nhcx.flow.coverage-eligibility-check + endpoints: + - nhcx.endpoint.coverageeligibility-check + callbacks: + - nhcx.callback.coverageeligibility-on-check + fhir: + - nhcx.fhir.coverage-eligibility-request + decisions: + - nhcx.decision.eligibility-purpose + errors: + - nhcx.error.payr-1033 + - nhcx.error.payr-1101 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1032, the eligibility check has an invalid purpose + +## In plain words + +A coverage eligibility check states what the provider wants to know, in its purpose. The payer rejected the check because the purpose in your [FHIR](../../shared/glossary/fhir.md) bundle is missing or not one it supports. + +## Before you start + +You sent a [coverage eligibility](../glossary/coverage-eligibility.md) check through [NHCX](../../shared/glossary/nhcx.md), on `/v1/coverageeligibility/check`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on `/v1/coverageeligibility/on_check`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1032`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1032` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> Invalid purpose received for coverage eligibility request. Hence request will not be processed further. Please try again with valid purpose details. + +The payer returns this code when: + +- `CoverageEligibilityRequest.purpose` is empty or absent. +- It carries a value other than `auth-requirements`, `benefits` or `validation`. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected check with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on `/v1/coverageeligibility/on_check` with your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1032`. The decrypted payload is a CoverageEligibilityResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Set `CoverageEligibilityRequest.purpose` to `auth-requirements`, `benefits` or `validation`. +2. Choose by what you need to learn. See [which purpose to send](../decisions/eligibility-purpose.md). + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare your request with the [coverage eligibility request bundle](../fhir/coverage-eligibility-request.md). If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1033](payr-1033.md) and [PAYR-1101](payr-1101.md). diff --git a/catalogue/nhcx/errors/payr-1033.md b/catalogue/nhcx/errors/payr-1033.md new file mode 100644 index 000000000..191219748 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1033.md @@ -0,0 +1,97 @@ +--- +id: nhcx.error.payr-1033 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1033, the eligibility check has no items for its purpose +summary: >- + The payer rejected your eligibility check because it asks about treatment but + lists no treatment items. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.coverage-eligibility-purposes + flows: + - nhcx.flow.coverage-eligibility-check + endpoints: + - nhcx.endpoint.coverageeligibility-check + callbacks: + - nhcx.callback.coverageeligibility-on-check + fhir: + - nhcx.fhir.coverage-eligibility-request + decisions: + - nhcx.decision.eligibility-purpose + errors: + - nhcx.error.payr-1032 + - nhcx.error.payr-1107 + - nhcx.error.payr-1118 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1033, the eligibility check has no items for its purpose + +## In plain words + +Some eligibility questions are about a specific package or treatment. The [FHIR](../../shared/glossary/fhir.md) bundle names it in an item. The payer rejected the check because the purpose needs items and the check carries none. + +## Before you start + +You sent a [coverage eligibility](../glossary/coverage-eligibility.md) check through [NHCX](../../shared/glossary/nhcx.md), on `/v1/coverageeligibility/check`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on `/v1/coverageeligibility/on_check`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1033`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1033` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> No items received for coverage eligibility purpose. Since items are mandatory for the requested purpose, hence request will not be processed further. Please try again with valid item details. + +The payer returns this code when: + +- The purpose you sent needs items, and `CoverageEligibilityRequest.item` is empty or absent. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected check with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on `/v1/coverageeligibility/on_check` with your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1033`. The decrypted payload is a CoverageEligibilityResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Add at least one `item` to the CoverageEligibilityRequest. +2. Name the package you are asking about in that item. The sample checks name the package this way. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare your request with the [coverage eligibility request bundle](../fhir/coverage-eligibility-request.md). If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1032](payr-1032.md), [PAYR-1107](payr-1107.md) and [PAYR-1118](payr-1118.md). diff --git a/catalogue/nhcx/errors/payr-1034.md b/catalogue/nhcx/errors/payr-1034.md new file mode 100644 index 000000000..85a536374 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1034.md @@ -0,0 +1,106 @@ +--- +id: nhcx.error.payr-1034 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1034, a procedure code is invalid +summary: >- + The payer rejected your preauthorisation or claim because a procedure code in + it is not one the payer accepts. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + - nhcx.fhir.pmjay-insurance-plan + errors: + - nhcx.error.payr-1204 + - nhcx.error.payr-1106 + - nhcx.error.payr-1344 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1034, a procedure code is invalid + +## In plain words + +Each procedure and billed item in your [FHIR](../../shared/glossary/fhir.md) bundle names a package by its code. The payer rejected the request because a procedure code is not valid. + +## Before you start + +You sent a [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) bundle through [NHCX](../../shared/glossary/nhcx.md), on `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1034`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1034` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> Invalid procedure code received. Please try again with valid procedure details. + +The payer returns this code when: + +- A procedure code in the bundle is empty. +- The code is not a package code the payer offers under the policy. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit`, matching the path you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1034`. The decrypted payload is a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Fetch the insurance plan for the policy. See [request an insurance plan](../flows/insurance-plan-request.md). +2. Take procedure codes from the plan. The procedure code is the code of each benefit's type, under the plan's specific cost. +3. Use the same code in `Procedure.code` and in the item's `productOrService`, as the sample bundles do. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare the rejected element with the [preauthorisation request bundle](../fhir/preauth-request.md) or the [claim request bundle](../fhir/claim-request.md). If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1204](payr-1204.md), [PAYR-1106](payr-1106.md) and [PAYR-1344](payr-1344.md). diff --git a/catalogue/nhcx/errors/payr-1035.md b/catalogue/nhcx/errors/payr-1035.md new file mode 100644 index 000000000..d0d4e6bf0 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1035.md @@ -0,0 +1,108 @@ +--- +id: nhcx.error.payr-1035 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1035, the policy code is invalid +summary: >- + The payer rejected your request because the insurance policy it names is not one + the payer recognises. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + - nhcx.endpoint.insuranceplan-request + callbacks: + - nhcx.callback.coverageeligibility-on-check + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + - nhcx.callback.insuranceplan-on-request + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.insurance-plan-bundle + errors: + - nhcx.error.payr-1117 + - nhcx.error.payr-1402 + - nhcx.error.payr-1006 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1035, the policy code is invalid + +## In plain words + +Every request names the insurance policy it is made under. The payer rejected the request because the policy code in your [FHIR](../../shared/glossary/fhir.md) bundle is not valid. + +## Before you start + +You sent a request through [NHCX](../../shared/glossary/nhcx.md) that names a policy, such as `/v1/coverageeligibility/check`, `/v1/preauth/submit`, `/v1/claim/submit` or `/v1/insuranceplan/request`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired `on_` path, for example `/v1/insuranceplan/on_request`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1035`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1035` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> Invalid policy code received. Please try again with valid policy details. + +The payer returns this code when: + +- The policy code in the request is empty. +- The payer holds no policy with that code. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on the `on_` path paired with the one you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1035`. The decrypted payload is the response bundle for your use case, such as a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Check the policy details in the Coverage resource of your bundle. +2. For an insurance plan request, check the `PolicyNumber` input of the Task. +3. Correct the code, then resend. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare your request with the [coverage eligibility request bundle](../fhir/coverage-eligibility-request.md), the [claim request bundle](../fhir/claim-request.md) or the [insurance plan bundles](../fhir/insurance-plan-bundle.md). If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1117](payr-1117.md), [PAYR-1402](payr-1402.md) and [PAYR-1006](payr-1006.md). diff --git a/catalogue/nhcx/errors/payr-1036.md b/catalogue/nhcx/errors/payr-1036.md new file mode 100644 index 000000000..1140ffcc0 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1036.md @@ -0,0 +1,106 @@ +--- +id: nhcx.error.payr-1036 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1036, a supporting info entry lacks a valid attachment +summary: >- + The payer rejected your preauthorisation or claim because a supporting document + entry does not carry a usable document. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + errors: + - nhcx.error.payr-1046 + - nhcx.error.payr-1047 + - nhcx.error.payr-1048 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1036, a supporting info entry lacks a valid attachment + +## In plain words + +Some supporting information entries in your [FHIR](../../shared/glossary/fhir.md) bundle carry a document, such as a clinical note or a report. The payer rejected the request because an entry that must carry a document has no valid attachment. + +## Before you start + +You sent a [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) bundle through [NHCX](../../shared/glossary/nhcx.md), on `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1036`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1036` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> Invalid attachment received in supporting info with sequence number `%s`. Please try again with valid attachment details as attachment value is expected. If issue is not resolved, please reach out to technical team. + +The payer puts the `sequence` of the rejected supporting info entry in place of `%s`. + +The payer returns this code when: + +- The entry named in the message has no `valueAttachment`. +- The entry carries a string or a reference where the payer expects a document. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit`, matching the path you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1036`. The decrypted payload is a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Find the `Claim.supportingInfo` entry whose `sequence` matches the number in the message. +2. Put the document in `valueAttachment`. Encode it as Base64 in `data`, give it a non-empty `title`, and set `contentType`. +3. Use an accepted content type: `application/pdf`, `application/jpg`, `application/jpeg`, `application/png` or `application/fhir+json`. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare the rejected element with the [preauthorisation request bundle](../fhir/preauth-request.md) or the [claim request bundle](../fhir/claim-request.md). If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1046](payr-1046.md), [PAYR-1047](payr-1047.md) and [PAYR-1048](payr-1048.md). diff --git a/catalogue/nhcx/errors/payr-1037.md b/catalogue/nhcx/errors/payr-1037.md new file mode 100644 index 000000000..efeb5ef8b --- /dev/null +++ b/catalogue/nhcx/errors/payr-1037.md @@ -0,0 +1,90 @@ +--- +id: nhcx.error.payr-1037 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1037, the communication has no identifier +summary: >- + The payer rejected your answer to its communication request because the message + in it carries no identifier. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.queries-and-communication + endpoints: + - nhcx.endpoint.communication-on-request + callbacks: + - nhcx.callback.communication-request + fhir: + - nhcx.fhir.collection-bundle + errors: + - nhcx.error.payr-1038 + - nhcx.error.payr-1039 + - nhcx.error.payr-1520 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1037, the communication has no identifier + +## In plain words + +When a payer sends a communication request, you answer with a [FHIR](../../shared/glossary/fhir.md) bundle that carries a Communication resource. The payer rejected your answer because the Communication resource has no identifier. + +## Before you start + +The [payer](../glossary/payer.md) sent you a [communication request](../glossary/communication-request.md) on `/v1/communication/request`. You answered through [NHCX](../../shared/glossary/nhcx.md) on `/v1/communication/on_request`, with an acknowledgement bundle that carries a Communication resource. + +The payer could not read that Communication resource and rejected your acknowledgement. The rejection carries: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1037`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1037` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> No identifier found for communication component. Hence request will not be processed further. + +The payer returns this code when: + +- The Communication resource in your acknowledgement bundle has no `identifier`. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected acknowledgement bundle on `/v1/communication/on_request`. NHCX answers with 202. + +No rejection with `x-hcx-status` set to `response.error` and `PAYR-1037` in `x-hcx-error_details` follows for that `x-hcx-correlation_id`. + +## When it goes wrong + +### Fix the bundle + +1. Add an `identifier` to the Communication resource, with a `type`, a `system` and a `value`. +2. The sample acknowledgement uses identifier type `MR`. + +### Send it again + +1. Send the corrected acknowledgement bundle on `/v1/communication/on_request`. +2. Keep the `x-hcx-correlation_id` of the payer's communication request. The payer links your acknowledgement to its request by that id. + +### If the same code comes back + +Contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1038](payr-1038.md), [PAYR-1039](payr-1039.md) and [PAYR-1520](payr-1520.md). diff --git a/catalogue/nhcx/errors/payr-1038.md b/catalogue/nhcx/errors/payr-1038.md new file mode 100644 index 000000000..4473354c3 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1038.md @@ -0,0 +1,89 @@ +--- +id: nhcx.error.payr-1038 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1038, the communication identifier has no type +summary: >- + The payer rejected your answer to its communication request because the message + identifier in it has no type. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.queries-and-communication + endpoints: + - nhcx.endpoint.communication-on-request + callbacks: + - nhcx.callback.communication-request + fhir: + - nhcx.fhir.collection-bundle + errors: + - nhcx.error.payr-1037 + - nhcx.error.payr-1039 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1038, the communication identifier has no type + +## In plain words + +When a payer sends a communication request, you answer with a [FHIR](../../shared/glossary/fhir.md) bundle that carries a Communication resource. The payer rejected your answer because the Communication resource's identifier has no type. + +## Before you start + +The [payer](../glossary/payer.md) sent you a [communication request](../glossary/communication-request.md) on `/v1/communication/request`. You answered through [NHCX](../../shared/glossary/nhcx.md) on `/v1/communication/on_request`, with an acknowledgement bundle that carries a Communication resource. + +The payer could not read that Communication resource and rejected your acknowledgement. The rejection carries: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1038`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1038` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> No type found for communication component identifier. Hence request will not be processed further. + +The payer returns this code when: + +- An `identifier` on the Communication resource has no `type`. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected acknowledgement bundle on `/v1/communication/on_request`. NHCX answers with 202. + +No rejection with `x-hcx-status` set to `response.error` and `PAYR-1038` in `x-hcx-error_details` follows for that `x-hcx-correlation_id`. + +## When it goes wrong + +### Fix the bundle + +1. Give each Communication `identifier` a `type` coding. +2. The sample acknowledgement uses code `MR`, Medical record number. + +### Send it again + +1. Send the corrected acknowledgement bundle on `/v1/communication/on_request`. +2. Keep the `x-hcx-correlation_id` of the payer's communication request. The payer links your acknowledgement to its request by that id. + +### If the same code comes back + +Contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1037](payr-1037.md) and [PAYR-1039](payr-1039.md). diff --git a/catalogue/nhcx/errors/payr-1039.md b/catalogue/nhcx/errors/payr-1039.md new file mode 100644 index 000000000..9baa290db --- /dev/null +++ b/catalogue/nhcx/errors/payr-1039.md @@ -0,0 +1,90 @@ +--- +id: nhcx.error.payr-1039 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1039, the communication has no payload +summary: >- + The payer rejected your answer to its communication request because the message + in it carries no content. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.queries-and-communication + endpoints: + - nhcx.endpoint.communication-on-request + callbacks: + - nhcx.callback.communication-request + fhir: + - nhcx.fhir.collection-bundle + errors: + - nhcx.error.payr-1037 + - nhcx.error.payr-1038 + - nhcx.error.payr-1520 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1039, the communication has no payload + +## In plain words + +When a payer sends a communication request, you answer with a [FHIR](../../shared/glossary/fhir.md) bundle that carries a Communication resource. The payer rejected your answer because the Communication resource has no payload. + +## Before you start + +The [payer](../glossary/payer.md) sent you a [communication request](../glossary/communication-request.md) on `/v1/communication/request`. You answered through [NHCX](../../shared/glossary/nhcx.md) on `/v1/communication/on_request`, with an acknowledgement bundle that carries a Communication resource. + +The payer could not read that Communication resource and rejected your acknowledgement. The rejection carries: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1039`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1039` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> No payload found for communication component. Hence request will not be processed further. + +The payer returns this code when: + +- The Communication resource has no `payload`. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected acknowledgement bundle on `/v1/communication/on_request`. NHCX answers with 202. + +No rejection with `x-hcx-status` set to `response.error` and `PAYR-1039` in `x-hcx-error_details` follows for that `x-hcx-correlation_id`. + +## When it goes wrong + +### Fix the bundle + +1. Add a `payload` to the Communication resource. +2. Put the content in `payload.contentAttachment`. The acknowledgement must carry it. + +### Send it again + +1. Send the corrected acknowledgement bundle on `/v1/communication/on_request`. +2. Keep the `x-hcx-correlation_id` of the payer's communication request. The payer links your acknowledgement to its request by that id. + +### If the same code comes back + +Contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1037](payr-1037.md), [PAYR-1038](payr-1038.md) and [PAYR-1520](payr-1520.md). diff --git a/catalogue/nhcx/errors/payr-1040.md b/catalogue/nhcx/errors/payr-1040.md new file mode 100644 index 000000000..8f43099a7 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1040.md @@ -0,0 +1,108 @@ +--- +id: nhcx.error.payr-1040 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1040, a reference points at a resource that is not in the bundle +summary: >- + The payer rejected your request because one record in it points at another record + that the bundle does not contain. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.coverageeligibility-on-check + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.collection-bundle + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + errors: + - nhcx.error.payr-1026 + - nhcx.error.payr-1048 + - nhcx.error.payr-1084 + - nhcx.error.payr-1086 + - nhcx.error.payr-1031 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1040, a reference points at a resource that is not in the bundle + +## In plain words + +Resources in a [FHIR](../../shared/glossary/fhir.md) bundle point at each other through references. The payer rejected the request because a reference points at a resource that is not in the bundle. + +## Before you start + +You sent a request through [NHCX](../../shared/glossary/nhcx.md) on a use case path, such as `/v1/coverageeligibility/check`, `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired `on_` path, for example `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1040`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1040` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> No component found for given reference. Hence request will not be processed further. + +The payer returns this code when: + +- A reference in any resource names a target that no `Bundle.entry` carries. +- The target entry exists, but its `fullUrl` does not match the reference. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on the `on_` path paired with the one you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1040`. The decrypted payload is the response bundle for your use case, such as a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Collect every `reference` value in the bundle. +2. Match each one to the `fullUrl` of an entry. +3. Add the missing resource, or correct the reference. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare your bundle with the [collection bundle](../fhir/collection-bundle.md) and the bundle for your use case. If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1026](payr-1026.md), [PAYR-1048](payr-1048.md), [PAYR-1084](payr-1084.md), [PAYR-1086](payr-1086.md) and [PAYR-1031](payr-1031.md). diff --git a/catalogue/nhcx/errors/payr-1041.md b/catalogue/nhcx/errors/payr-1041.md new file mode 100644 index 000000000..af9065baa --- /dev/null +++ b/catalogue/nhcx/errors/payr-1041.md @@ -0,0 +1,102 @@ +--- +id: nhcx.error.payr-1041 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1041, a procedure has no identifier +summary: >- + The payer rejected your preauthorisation or claim because a procedure record in + it carries no identifier. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + errors: + - nhcx.error.payr-1042 + - nhcx.error.payr-1023 + - nhcx.error.payr-1024 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1041, a procedure has no identifier + +## In plain words + +Each Procedure resource in your [FHIR](../../shared/glossary/fhir.md) bundle carries an identifier, its serial number. The payer rejected the request because a Procedure resource has no identifier. + +## Before you start + +You sent a [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) bundle through [NHCX](../../shared/glossary/nhcx.md), on `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1041`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1041` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> No identifier found for procedure component. Hence request will not be processed further. + +The payer returns this code when: + +- A Procedure resource in the bundle has no `identifier`. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit`, matching the path you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1041`. The decrypted payload is a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Add an `identifier` to every Procedure resource. +2. The sample bundles use identifier type `SNO`, Serial Number, from the `v2-0203` code system, with system `https://bis.pmjay.gov.in`. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare the rejected element with the [preauthorisation request bundle](../fhir/preauth-request.md) or the [claim request bundle](../fhir/claim-request.md). If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1042](payr-1042.md), [PAYR-1023](payr-1023.md) and [PAYR-1024](payr-1024.md). diff --git a/catalogue/nhcx/errors/payr-1042.md b/catalogue/nhcx/errors/payr-1042.md new file mode 100644 index 000000000..da1cde602 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1042.md @@ -0,0 +1,102 @@ +--- +id: nhcx.error.payr-1042 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1042, a procedure identifier has no type +summary: >- + The payer rejected your preauthorisation or claim because a procedure record's + identifier does not say what kind of identifier it is. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + errors: + - nhcx.error.payr-1041 + - nhcx.error.payr-1010 + - nhcx.error.payr-1012 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1042, a procedure identifier has no type + +## In plain words + +Each Procedure resource in your [FHIR](../../shared/glossary/fhir.md) bundle carries an identifier with a type. The payer rejected the request because a procedure identifier has no type. + +## Before you start + +You sent a [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) bundle through [NHCX](../../shared/glossary/nhcx.md), on `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1042`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1042` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> No type found for procedure component identifier. Hence request will not be processed further. + +The payer returns this code when: + +- An `identifier` on a Procedure resource has no `type`. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit`, matching the path you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1042`. The decrypted payload is a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Give each Procedure `identifier` a `type` coding. +2. The sample bundles use code `SNO`, Serial Number, from the `v2-0203` code system. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare the rejected element with the [preauthorisation request bundle](../fhir/preauth-request.md) or the [claim request bundle](../fhir/claim-request.md). If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1041](payr-1041.md), [PAYR-1010](payr-1010.md) and [PAYR-1012](payr-1012.md). diff --git a/catalogue/nhcx/errors/payr-1043.md b/catalogue/nhcx/errors/payr-1043.md new file mode 100644 index 000000000..42cb181b6 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1043.md @@ -0,0 +1,108 @@ +--- +id: nhcx.error.payr-1043 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1043, a date is in the wrong format +summary: >- + The payer rejected your request because a date in it is not written in the standard + date format. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.coverageeligibility-on-check + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.collection-bundle + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + errors: + - nhcx.error.payr-1044 + - nhcx.error.payr-1242 + - nhcx.error.payr-1244 + - nhcx.error.payr-1327 + - nhcx.error.payr-1328 + - nhcx.error.payr-1330 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1043, a date is in the wrong format + +## In plain words + +Dates in a [FHIR](../../shared/glossary/fhir.md) bundle follow the date format of the [NRCeS](../../shared/glossary/nrces.md) profiles. The payer rejected the request because a date does not. + +## Before you start + +You sent a request through [NHCX](../../shared/glossary/nhcx.md) on a use case path, such as `/v1/coverageeligibility/check`, `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired `on_` path, for example `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1043`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1043` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> Date received in the request does not adhere to the NRCES date datatype format. Hence request will not be processed further. Please refere to the date format in NRCES portal. + +The payer returns this code when: + +- An element of the FHIR `date` type holds a value that is not a valid FHIR date. +- The message does not name the element, so any date in the bundle can be the cause. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on the `on_` path paired with the one you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1043`. The decrypted payload is the response bundle for your use case, such as a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Check every element of the FHIR `date` type in the bundle. +2. Write each as year, month and day, for example `2026-02-27`. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare your bundle with the [collection bundle](../fhir/collection-bundle.md) and the bundle for your use case. If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1044](payr-1044.md), [PAYR-1242](payr-1242.md), [PAYR-1244](payr-1244.md), [PAYR-1327](payr-1327.md), [PAYR-1328](payr-1328.md) and [PAYR-1330](payr-1330.md). diff --git a/catalogue/nhcx/errors/payr-1044.md b/catalogue/nhcx/errors/payr-1044.md new file mode 100644 index 000000000..91f401263 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1044.md @@ -0,0 +1,108 @@ +--- +id: nhcx.error.payr-1044 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1044, a date and time is in the wrong format +summary: >- + The payer rejected your request because a date with a time in it is not written + in the standard format. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.coverageeligibility-on-check + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.collection-bundle + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + errors: + - nhcx.error.payr-1043 + - nhcx.error.payr-1242 + - nhcx.error.payr-1244 + - nhcx.error.payr-1327 + - nhcx.error.payr-1328 + - nhcx.error.payr-1330 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1044, a date and time is in the wrong format + +## In plain words + +Dates with times in a [FHIR](../../shared/glossary/fhir.md) bundle follow the date and time format of the [NRCeS](../../shared/glossary/nrces.md) profiles. The payer rejected the request because one does not. + +## Before you start + +You sent a request through [NHCX](../../shared/glossary/nhcx.md) on a use case path, such as `/v1/coverageeligibility/check`, `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired `on_` path, for example `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1044`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1044` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> Date and time received in the request does not adhere to the NRCES date datatype format. Hence request will not be processed further. Please refere to the date time format in NRCES portal. + +The payer returns this code when: + +- An element of the FHIR `dateTime` type holds a value that is not a valid FHIR dateTime. +- The message does not name the element, so any date and time in the bundle can be the cause. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on the `on_` path paired with the one you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1044`. The decrypted payload is the response bundle for your use case, such as a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Check every element of the FHIR `dateTime` type in the bundle. +2. Write each with a time zone, for example `2026-02-27T08:40:02+05:30`, as the sample claim does. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare your bundle with the [collection bundle](../fhir/collection-bundle.md) and the bundle for your use case. If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1043](payr-1043.md), [PAYR-1242](payr-1242.md), [PAYR-1244](payr-1244.md), [PAYR-1327](payr-1327.md), [PAYR-1328](payr-1328.md) and [PAYR-1330](payr-1330.md). diff --git a/catalogue/nhcx/errors/payr-1045.md b/catalogue/nhcx/errors/payr-1045.md new file mode 100644 index 000000000..8ce3930c5 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1045.md @@ -0,0 +1,105 @@ +--- +id: nhcx.error.payr-1045 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1045, a claim item has an invalid quantity +summary: >- + The payer rejected your preauthorisation or claim because a billed item does not + state a usable number of units. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + errors: + - nhcx.error.payr-1027 + - nhcx.error.payr-1028 + - nhcx.error.payr-1115 + - nhcx.error.payr-1208 + - nhcx.error.payr-1349 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1045, a claim item has an invalid quantity + +## In plain words + +Each billed item in the Claim resource of your [FHIR](../../shared/glossary/fhir.md) bundle states how many units it bills. The payer rejected the request because an item's quantity is missing or not valid. + +## Before you start + +You sent a [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) bundle through [NHCX](../../shared/glossary/nhcx.md), on `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1045`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1045` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> Invalid quantity received for item. Hence request will not be processed further. + +The payer returns this code when: + +- A `Claim.item` entry has no `quantity`. +- The `quantity` carries no numeric `value`. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit`, matching the path you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1045`. The decrypted payload is a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Open each entry in `Claim.item`. +2. Give it a `quantity` with a numeric `value`. The sample bundles bill one unit, quantity 1. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare the rejected element with the [preauthorisation request bundle](../fhir/preauth-request.md) or the [claim request bundle](../fhir/claim-request.md). If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1027](payr-1027.md), [PAYR-1028](payr-1028.md), [PAYR-1115](payr-1115.md), [PAYR-1208](payr-1208.md) and [PAYR-1349](payr-1349.md). diff --git a/catalogue/nhcx/errors/payr-1046.md b/catalogue/nhcx/errors/payr-1046.md new file mode 100644 index 000000000..c1d26b050 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1046.md @@ -0,0 +1,108 @@ +--- +id: nhcx.error.payr-1046 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1046, a supporting info entry has no value or date +summary: >- + The payer rejected your preauthorisation or claim because a supporting information + entry carries no content at all. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + errors: + - nhcx.error.payr-1036 + - nhcx.error.payr-1047 + - nhcx.error.payr-1048 + - nhcx.error.payr-1098 + - nhcx.error.payr-1099 + - nhcx.error.payr-1502 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1046, a supporting info entry has no value or date + +## In plain words + +Every supporting information entry in your [FHIR](../../shared/glossary/fhir.md) bundle carries its content, either a value or a date. The payer rejected the request because one entry carries neither. + +## Before you start + +You sent a [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) bundle through [NHCX](../../shared/glossary/nhcx.md), on `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1046`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1046` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> No value or timing details received for supporting info for sequence `%s`. Hence request will not be processed further. Please reach out to technical team. + +The payer puts the `sequence` of the rejected supporting info entry in place of `%s`. + +The payer returns this code when: + +- The entry named in the message has no `value[x]` and no `timing[x]`. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit`, matching the path you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1046`. The decrypted payload is a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Find the `Claim.supportingInfo` entry whose `sequence` matches the number in the message. +2. Give it the content its `category` and `code` call for. +3. Send dates in `timingDate`, `timingPeriod` or `valueString`. Send documents in `valueAttachment`. Point at clinical records with `valueReference`. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare the rejected element with the [preauthorisation request bundle](../fhir/preauth-request.md) or the [claim request bundle](../fhir/claim-request.md). If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1036](payr-1036.md), [PAYR-1047](payr-1047.md), [PAYR-1048](payr-1048.md), [PAYR-1098](payr-1098.md), [PAYR-1099](payr-1099.md) and [PAYR-1502](payr-1502.md). diff --git a/catalogue/nhcx/errors/payr-1047.md b/catalogue/nhcx/errors/payr-1047.md new file mode 100644 index 000000000..46673244d --- /dev/null +++ b/catalogue/nhcx/errors/payr-1047.md @@ -0,0 +1,107 @@ +--- +id: nhcx.error.payr-1047 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1047, a supporting info entry has an invalid reference +summary: >- + The payer rejected your preauthorisation or claim because a supporting information + entry points at another record in an unusable way. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + errors: + - nhcx.error.payr-1048 + - nhcx.error.payr-1040 + - nhcx.error.payr-1085 + - nhcx.error.payr-1505 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1047, a supporting info entry has an invalid reference + +## In plain words + +A supporting information entry can point at another resource in your [FHIR](../../shared/glossary/fhir.md) bundle, such as a clinical record. The payer rejected the request because an entry's reference is not valid. + +## Before you start + +You sent a [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) bundle through [NHCX](../../shared/glossary/nhcx.md), on `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1047`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1047` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> Invalid reference received in supporting info with sequence number `%s`. Please try again with valid resource as reference value. + +The payer puts the `sequence` of the rejected supporting info entry in place of `%s`. + +The payer returns this code when: + +- The `valueReference` of the entry named in the message is empty or malformed. +- The `valueReference` does not point at a resource the entry can carry. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit`, matching the path you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1047`. The decrypted payload is a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Find the `Claim.supportingInfo` entry whose `sequence` matches the number in the message. +2. Point `valueReference.reference` at an entry in the bundle, using that entry's `fullUrl`. +3. Reference a Composition for a clinical record, as the sample bundles do. Reference a QuestionnaireResponse for category `INF` with code `ODN`. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare the rejected element with the [preauthorisation request bundle](../fhir/preauth-request.md) or the [claim request bundle](../fhir/claim-request.md). If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1048](payr-1048.md), [PAYR-1040](payr-1040.md), [PAYR-1085](payr-1085.md) and [PAYR-1505](payr-1505.md). diff --git a/catalogue/nhcx/errors/payr-1048.md b/catalogue/nhcx/errors/payr-1048.md new file mode 100644 index 000000000..6e88b5afe --- /dev/null +++ b/catalogue/nhcx/errors/payr-1048.md @@ -0,0 +1,107 @@ +--- +id: nhcx.error.payr-1048 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1048, a supporting info entry references a resource that is not in the + bundle +summary: >- + The payer rejected your preauthorisation or claim because a supporting information + entry points at a record the bundle does not contain. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + errors: + - nhcx.error.payr-1047 + - nhcx.error.payr-1040 + - nhcx.error.payr-1084 + - nhcx.error.payr-1086 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1048, a supporting info entry references a resource that is not in the bundle + +## In plain words + +A supporting information entry can point at another resource in your [FHIR](../../shared/glossary/fhir.md) bundle. The payer rejected the request because the resource the entry points at is not in the bundle. + +## Before you start + +You sent a [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) bundle through [NHCX](../../shared/glossary/nhcx.md), on `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1048`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1048` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> No reference resource received for supporting info with sequence number `%s`. Please try again with valid resource for reference value. + +The payer puts the `sequence` of the rejected supporting info entry in place of `%s`. + +The payer returns this code when: + +- The `valueReference` of the entry named in the message names a resource that no `Bundle.entry` carries. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit`, matching the path you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1048`. The decrypted payload is a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Find the `Claim.supportingInfo` entry whose `sequence` matches the number in the message. +2. Add the referenced resource to the bundle, or correct the reference. +3. Make the reference match the new entry's `fullUrl`. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare the rejected element with the [preauthorisation request bundle](../fhir/preauth-request.md) or the [claim request bundle](../fhir/claim-request.md). If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1047](payr-1047.md), [PAYR-1040](payr-1040.md), [PAYR-1084](payr-1084.md) and [PAYR-1086](payr-1086.md). diff --git a/catalogue/nhcx/errors/payr-1049.md b/catalogue/nhcx/errors/payr-1049.md new file mode 100644 index 000000000..82dab40be --- /dev/null +++ b/catalogue/nhcx/errors/payr-1049.md @@ -0,0 +1,104 @@ +--- +id: nhcx.error.payr-1049 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1049, the payer cannot accept the bundle +summary: >- + The payer rejected your request because it could not accept the bundle as a whole. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.coverageeligibility-on-check + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.collection-bundle + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + errors: + - nhcx.error.payr-1004 + - nhcx.error.payr-1008 + - nhcx.error.payr-1029 + - nhcx.error.payr-1031 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1049, the payer cannot accept the bundle + +## In plain words + +The payer could not accept your [FHIR](../../shared/glossary/fhir.md) bundle as a whole. The message names no element. + +## Before you start + +You sent a request through [NHCX](../../shared/glossary/nhcx.md) on a use case path, such as `/v1/coverageeligibility/check`, `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired `on_` path, for example `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1049`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1049` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> Invalid FHIR bundle received. Hence request will not be processed further. please reach out to technical team. + +The payer returns this code when: + +- The payer cannot read the bundle as a valid FHIR bundle. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on the `on_` path paired with the one you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1049`. The decrypted payload is the response bundle for your use case, such as a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Validate the whole bundle against the [NRCeS](../../shared/glossary/nrces.md) profiles. See [validating a bundle](../fhir/validation.md). +2. Fix every error the validator reports. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare your bundle with the [collection bundle](../fhir/collection-bundle.md) and the bundle for your use case. If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1004](payr-1004.md), [PAYR-1008](payr-1008.md), [PAYR-1029](payr-1029.md) and [PAYR-1031](payr-1031.md). diff --git a/catalogue/nhcx/errors/payr-1050.md b/catalogue/nhcx/errors/payr-1050.md new file mode 100644 index 000000000..262aab05f --- /dev/null +++ b/catalogue/nhcx/errors/payr-1050.md @@ -0,0 +1,102 @@ +--- +id: nhcx.error.payr-1050 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1050, a practitioner identifier has no type +summary: >- + The payer rejected your preauthorisation or claim because a doctor's identifier + in it does not say what kind of identifier it is. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + errors: + - nhcx.error.payr-1080 + - nhcx.error.payr-1083 + - nhcx.error.payr-1079 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1050, a practitioner identifier has no type + +## In plain words + +Practitioners in your [FHIR](../../shared/glossary/fhir.md) bundle carry identifiers, such as their [HPR](../../shared/glossary/hpr.md) id. The payer rejected the request because a practitioner's identifier has no type. + +## Before you start + +You sent a [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) bundle through [NHCX](../../shared/glossary/nhcx.md), on `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1050`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1050` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> No type found for practitioner component identifier. Hence request will not be processed further. + +The payer returns this code when: + +- An `identifier` on a Practitioner resource has no `type`. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit`, matching the path you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1050`. The decrypted payload is a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Give every Practitioner `identifier` a `type` coding. +2. For the HPR id, use type code `HPIN`. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare the rejected element with the [preauthorisation request bundle](../fhir/preauth-request.md) or the [claim request bundle](../fhir/claim-request.md). If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1080](payr-1080.md), [PAYR-1083](payr-1083.md) and [PAYR-1079](payr-1079.md). diff --git a/catalogue/nhcx/errors/payr-1051.md b/catalogue/nhcx/errors/payr-1051.md new file mode 100644 index 000000000..798826e92 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1051.md @@ -0,0 +1,102 @@ +--- +id: nhcx.error.payr-1051 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1051, a clinical record has no section +summary: >- + The payer rejected your preauthorisation or claim because an attached clinical + record has no sections. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + errors: + - nhcx.error.payr-1052 + - nhcx.error.payr-1054 + - nhcx.error.payr-1088 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1051, a clinical record has no section + +## In plain words + +Clinical records attached to a preauthorisation or claim travel as Composition resources in the [FHIR](../../shared/glossary/fhir.md) bundle. A Composition groups its content into sections. The payer rejected the request because a Composition has no section. + +## Before you start + +You sent a [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) bundle through [NHCX](../../shared/glossary/nhcx.md), on `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1051`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1051` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> No section found for composition component. Hence request will not be processed further. + +The payer returns this code when: + +- A Composition resource in the bundle has no `section`. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit`, matching the path you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1051`. The decrypted payload is a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Give every Composition at least one `section`. +2. List the section's resources in `section.entry`. The sample bundles attach diagnostic reports and invoices this way. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare the rejected element with the [preauthorisation request bundle](../fhir/preauth-request.md) or the [claim request bundle](../fhir/claim-request.md). If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1052](payr-1052.md), [PAYR-1054](payr-1054.md) and [PAYR-1088](payr-1088.md). diff --git a/catalogue/nhcx/errors/payr-1052.md b/catalogue/nhcx/errors/payr-1052.md new file mode 100644 index 000000000..173eb3172 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1052.md @@ -0,0 +1,103 @@ +--- +id: nhcx.error.payr-1052 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1052, a clinical record section has no references +summary: >- + The payer rejected your preauthorisation or claim because a section of an attached + clinical record lists no records. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + errors: + - nhcx.error.payr-1051 + - nhcx.error.payr-1053 + - nhcx.error.payr-1054 + - nhcx.error.payr-1040 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1052, a clinical record section has no references + +## In plain words + +Clinical records in your [FHIR](../../shared/glossary/fhir.md) bundle are Composition resources. Each section lists its content as references. The payer rejected the request because a section has no references. + +## Before you start + +You sent a [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) bundle through [NHCX](../../shared/glossary/nhcx.md), on `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1052`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1052` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> No references found in composition section. Hence request will not be processed further. + +The payer returns this code when: + +- A `Composition.section` has no `entry` references. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit`, matching the path you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1052`. The decrypted payload is a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. List the section's resources in `section.entry`. +2. Make each reference match the `fullUrl` of an entry in the bundle. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare the rejected element with the [preauthorisation request bundle](../fhir/preauth-request.md) or the [claim request bundle](../fhir/claim-request.md). If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1051](payr-1051.md), [PAYR-1053](payr-1053.md), [PAYR-1054](payr-1054.md) and [PAYR-1040](payr-1040.md). diff --git a/catalogue/nhcx/errors/payr-1053.md b/catalogue/nhcx/errors/payr-1053.md new file mode 100644 index 000000000..6113473b8 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1053.md @@ -0,0 +1,102 @@ +--- +id: nhcx.error.payr-1053 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1053, a nested clinical record section has an invalid reference +summary: >- + The payer rejected your preauthorisation or claim because a section inside an + attached clinical record points at something invalid. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + errors: + - nhcx.error.payr-1052 + - nhcx.error.payr-1040 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1053, a nested clinical record section has an invalid reference + +## In plain words + +A Composition section in your [FHIR](../../shared/glossary/fhir.md) bundle can hold child sections, each with references. The payer rejected the request because a reference in a child section is not valid. + +## Before you start + +You sent a [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) bundle through [NHCX](../../shared/glossary/nhcx.md), on `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1053`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1053` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> Invalid reference found in child sections of composition section. Hence request will not be processed further. + +The payer returns this code when: + +- An `entry` in a nested `section.section` is empty or malformed. +- The `entry` names a resource that is not in the bundle. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit`, matching the path you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1053`. The decrypted payload is a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Check every `entry` in the nested sections of each Composition. +2. Point each one at the `fullUrl` of an entry in the bundle. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare the rejected element with the [preauthorisation request bundle](../fhir/preauth-request.md) or the [claim request bundle](../fhir/claim-request.md). If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1052](payr-1052.md) and [PAYR-1040](payr-1040.md). diff --git a/catalogue/nhcx/errors/payr-1054.md b/catalogue/nhcx/errors/payr-1054.md new file mode 100644 index 000000000..a8669d9d4 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1054.md @@ -0,0 +1,101 @@ +--- +id: nhcx.error.payr-1054 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1054, a clinical record section is empty +summary: >- + The payer rejected your preauthorisation or claim because a section of an attached + clinical record has no content. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + errors: + - nhcx.error.payr-1051 + - nhcx.error.payr-1052 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1054, a clinical record section is empty + +## In plain words + +Clinical records in your [FHIR](../../shared/glossary/fhir.md) bundle are Composition resources made of sections. The payer rejected the request because a section carries no content. + +## Before you start + +You sent a [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) bundle through [NHCX](../../shared/glossary/nhcx.md), on `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1054`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1054` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> No section content found for composition component. Hence request will not be processed further. + +The payer returns this code when: + +- A `Composition.section` is present but holds nothing. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit`, matching the path you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1054`. The decrypted payload is a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Find the empty section in each Composition. +2. Fill it with `entry` references to the resources it holds, or remove it. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare the rejected element with the [preauthorisation request bundle](../fhir/preauth-request.md) or the [claim request bundle](../fhir/claim-request.md). If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1051](payr-1051.md) and [PAYR-1052](payr-1052.md). diff --git a/catalogue/nhcx/errors/payr-1055.md b/catalogue/nhcx/errors/payr-1055.md new file mode 100644 index 000000000..d8b916250 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1055.md @@ -0,0 +1,108 @@ +--- +id: nhcx.error.payr-1055 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1055, a clinical record has no subject or its subject is not a patient +summary: >- + The payer rejected your preauthorisation or claim because an attached clinical + record does not name the patient it is about. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + errors: + - nhcx.error.payr-1056 + - nhcx.error.payr-1057 + - nhcx.error.payr-1058 + - nhcx.error.payr-1060 + - nhcx.error.payr-1077 + - nhcx.error.payr-1078 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1055, a clinical record has no subject or its subject is not a patient + +## In plain words + +Each clinical record in your [FHIR](../../shared/glossary/fhir.md) bundle is a Composition that names the patient it is about, in its subject. The payer rejected the request because a Composition has no subject, or its subject is not a Patient. + +## Before you start + +You sent a [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) bundle through [NHCX](../../shared/glossary/nhcx.md), on `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1055`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1055` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. It returns this code for either of two failed checks: + +> No subject found for composition component. Hence request will not be processed further. + +> Invalid subject type found for composition component. This should be of type Patient. Hence request will not be processed further. Please try again with valid subject type for the composition. + +The payer returns this code when: + +- A Composition resource has no `subject`. +- `Composition.subject` points at a resource that is not a Patient. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit`, matching the path you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1055`. The decrypted payload is a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Set `Composition.subject` on every Composition. +2. Point it at the Patient resource in the bundle. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare the rejected element with the [preauthorisation request bundle](../fhir/preauth-request.md) or the [claim request bundle](../fhir/claim-request.md). If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1056](payr-1056.md), [PAYR-1057](payr-1057.md), [PAYR-1058](payr-1058.md), [PAYR-1060](payr-1060.md), [PAYR-1077](payr-1077.md) and [PAYR-1078](payr-1078.md). diff --git a/catalogue/nhcx/errors/payr-1056.md b/catalogue/nhcx/errors/payr-1056.md new file mode 100644 index 000000000..2f888b2f8 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1056.md @@ -0,0 +1,102 @@ +--- +id: nhcx.error.payr-1056 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1056, the patient's contact organization is not an Organization +summary: >- + The payer rejected your preauthorisation or claim because the patient in an attached + clinical record has a contact of the wrong kind. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + errors: + - nhcx.error.payr-1055 + - nhcx.error.payr-1057 + - nhcx.error.payr-1058 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1056, the patient's contact organization is not an Organization + +## In plain words + +The payer checks the Patient that each clinical record in your [FHIR](../../shared/glossary/fhir.md) bundle is about. It rejected the request because that patient's contact organization is not an Organization. + +## Before you start + +You sent a [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) bundle through [NHCX](../../shared/glossary/nhcx.md), on `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1056`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1056` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> Invalid contact organization found for subject in composition component. This should be of type Organization. Hence request will not be processed further. Please try again with valid data. + +The payer returns this code when: + +- The Patient referenced by `Composition.subject` has a `contact.organization` that does not reference an Organization resource. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit`, matching the path you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1056`. The decrypted payload is a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Open the Patient that each Composition names in `subject`. +2. Point `Patient.contact.organization` at an Organization resource in the bundle, or remove it. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare the rejected element with the [preauthorisation request bundle](../fhir/preauth-request.md) or the [claim request bundle](../fhir/claim-request.md). If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1055](payr-1055.md), [PAYR-1057](payr-1057.md) and [PAYR-1058](payr-1058.md). diff --git a/catalogue/nhcx/errors/payr-1057.md b/catalogue/nhcx/errors/payr-1057.md new file mode 100644 index 000000000..28abb2f8f --- /dev/null +++ b/catalogue/nhcx/errors/payr-1057.md @@ -0,0 +1,103 @@ +--- +id: nhcx.error.payr-1057 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1057, the patient's general practitioner has the wrong type +summary: >- + The payer rejected your preauthorisation or claim because the patient in an attached + clinical record names a general practitioner of the wrong kind. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + errors: + - nhcx.error.payr-1055 + - nhcx.error.payr-1056 + - nhcx.error.payr-1058 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1057, the patient's general practitioner has the wrong type + +## In plain words + +The payer checks the Patient that each clinical record in your [FHIR](../../shared/glossary/fhir.md) bundle is about. It rejected the request because that patient's general practitioner is the wrong type of resource. + +## Before you start + +You sent a [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) bundle through [NHCX](../../shared/glossary/nhcx.md), on `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1057`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1057` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> Invalid general practioner type found for subject in composition component. This should be of type Organization/Practitioner/PractitionerRole. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html + +The payer returns this code when: + +- The Patient referenced by `Composition.subject` has a `generalPractitioner` that does not reference an Organization, Practitioner or PractitionerRole. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit`, matching the path you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1057`. The decrypted payload is a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Open the Patient that each Composition names in `subject`. +2. Point each `Patient.generalPractitioner` at an Organization, Practitioner or PractitionerRole resource in the bundle. +3. Check the Patient against the [NRCeS](../../shared/glossary/nrces.md) Patient profile, `https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html`. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare the rejected element with the [preauthorisation request bundle](../fhir/preauth-request.md) or the [claim request bundle](../fhir/claim-request.md). If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1055](payr-1055.md), [PAYR-1056](payr-1056.md) and [PAYR-1058](payr-1058.md). diff --git a/catalogue/nhcx/errors/payr-1058.md b/catalogue/nhcx/errors/payr-1058.md new file mode 100644 index 000000000..4bb0d24fc --- /dev/null +++ b/catalogue/nhcx/errors/payr-1058.md @@ -0,0 +1,103 @@ +--- +id: nhcx.error.payr-1058 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1058, the patient's managing organization is not an Organization +summary: >- + The payer rejected your preauthorisation or claim because the patient in an attached + clinical record names a managing organization of the wrong kind. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + errors: + - nhcx.error.payr-1055 + - nhcx.error.payr-1056 + - nhcx.error.payr-1057 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1058, the patient's managing organization is not an Organization + +## In plain words + +The payer checks the Patient that each clinical record in your [FHIR](../../shared/glossary/fhir.md) bundle is about. It rejected the request because that patient's managing organization is not an Organization. + +## Before you start + +You sent a [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) bundle through [NHCX](../../shared/glossary/nhcx.md), on `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1058`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1058` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> Invalid managing organization type found for subject in composition component. This should be of type Organization. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html + +The payer returns this code when: + +- The Patient referenced by `Composition.subject` has a `managingOrganization` that does not reference an Organization resource. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit`, matching the path you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1058`. The decrypted payload is a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Open the Patient that each Composition names in `subject`. +2. Point `Patient.managingOrganization` at an Organization resource in the bundle. +3. Check the Patient against the [NRCeS](../../shared/glossary/nrces.md) Patient profile, `https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html`. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare the rejected element with the [preauthorisation request bundle](../fhir/preauth-request.md) or the [claim request bundle](../fhir/claim-request.md). If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1055](payr-1055.md), [PAYR-1056](payr-1056.md) and [PAYR-1057](payr-1057.md). diff --git a/catalogue/nhcx/errors/payr-1059.md b/catalogue/nhcx/errors/payr-1059.md new file mode 100644 index 000000000..312ff4e31 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1059.md @@ -0,0 +1,104 @@ +--- +id: nhcx.error.payr-1059 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1059, a clinical record points at something other than an encounter +summary: >- + The payer rejected your preauthorisation or claim because an attached clinical + record or observation points at the wrong kind of record for its visit. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + errors: + - nhcx.error.payr-1060 + - nhcx.error.payr-1061 + - nhcx.error.payr-1062 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1059, a clinical record points at something other than an encounter + +## In plain words + +Clinical records and observations in your [FHIR](../../shared/glossary/fhir.md) bundle point at the visit they belong to, an Encounter. The payer rejected the request because a Composition or Observation points at something other than an Encounter. + +## Before you start + +You sent a [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) bundle through [NHCX](../../shared/glossary/nhcx.md), on `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1059`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1059` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. This check failed: + +> Invalid encounter type found for composition/observation component. This should be of type Encounter. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-DiagnosticReportRecord.html + +The payer returns this code when: + +- `Composition.encounter` references a resource that is not an Encounter. +- `Observation.encounter` references a resource that is not an Encounter. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit`, matching the path you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1059`. The decrypted payload is a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Check `encounter` on every Composition and Observation. +2. Point each one at an Encounter resource in the bundle. +3. Check the record against the [NRCeS](../../shared/glossary/nrces.md) DiagnosticReportRecord profile, `https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-DiagnosticReportRecord.html`. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare the rejected element with the [preauthorisation request bundle](../fhir/preauth-request.md) or the [claim request bundle](../fhir/claim-request.md). If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1060](payr-1060.md), [PAYR-1061](payr-1061.md) and [PAYR-1062](payr-1062.md). diff --git a/catalogue/nhcx/errors/payr-1060.md b/catalogue/nhcx/errors/payr-1060.md new file mode 100644 index 000000000..7bfc49785 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1060.md @@ -0,0 +1,107 @@ +--- +id: nhcx.error.payr-1060 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PAYR-1060, a clinical record has no encounter or its encounter has no subject +summary: >- + The payer rejected your preauthorisation or claim because an attached clinical + record does not name its visit, or the visit does not name the patient. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + errors: + - nhcx.error.payr-1059 + - nhcx.error.payr-1061 + - nhcx.error.payr-1093 + - nhcx.error.payr-1055 + - nhcx.error.nhcx-1006 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# PAYR-1060, a clinical record has no encounter or its encounter has no subject + +## In plain words + +Clinical records and observations in your [FHIR](../../shared/glossary/fhir.md) bundle point at the visit they belong to, an Encounter. That Encounter names the patient. The payer rejected the request because one of these links is missing. + +## Before you start + +You sent a [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) bundle through [NHCX](../../shared/glossary/nhcx.md), on `/v1/preauth/submit` or `/v1/claim/submit`. NHCX answered with 202. + +The [payer](../glossary/payer.md) answered later on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. You decrypted the response with your private key. Its protected headers carry: + +- `x-hcx-status` set to `response.error`. +- `x-hcx-error_details`, with `code` set to `PAYR-1060`, a `message`, and a `trace` when the payer adds one. + +`PAYR-1060` is a reference payer code. The [PMJAY](../glossary/pmjay.md) payer implementation on NHCX sends it. The standard payer codes stop at `PAYR-1020`. Read [error code spaces](../concepts/error-code-spaces.md) before you act on any `PAYR-` code. + +## What happens + +The payer checks the structure of your bundle before it adjudicates anything. It returns this code for either of two failed checks: + +> No encounter found for composition/observation component. Hence request will not be processed further. + +> No subject found for encounter in composition component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + +The payer returns this code when: + +- A Composition or Observation has no `encounter`. +- The Encounter a Composition references has no `subject`. + +The request is not processed further. Nothing in it is adjudicated. + +## How you know it worked + +You send the corrected bundle with a new `x-hcx-correlation_id`. NHCX answers with 202. + +The payer's response arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit`, matching the path you called. It carries your new `x-hcx-correlation_id`. `x-hcx-status` is not `response.error`, and `x-hcx-error_details` does not name `PAYR-1060`. The decrypted payload is a ClaimResponse bundle. + +If a different `PAYR-` code arrives, look up that code next. + +## When it goes wrong + +### Fix the bundle + +1. Give every Composition and Observation an `encounter` that references an Encounter resource in the bundle. +2. Give that Encounter a `subject` that references the Patient. +3. Check the Encounter against the [NRCeS](../../shared/glossary/nrces.md) Encounter profile, `https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html`. + +### Send it again + +1. Validate the corrected bundle before you send it. See [validating a bundle](../fhir/validation.md). +2. Send the request with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. The failed correlation id is inactive. Reusing it returns [NHCX-1006](nhcx-1006.md). + +### If the same code comes back + +Compare the rejected element with the [preauthorisation request bundle](../fhir/preauth-request.md) or the [claim request bundle](../fhir/claim-request.md). If your bundle matches and the code persists, contact [NHCX support](../sandbox/support-contacts.md). Give them the `x-hcx-correlation_id` and the `trace` from `x-hcx-error_details`. + +The payer runs related checks under [PAYR-1059](payr-1059.md), [PAYR-1061](payr-1061.md), [PAYR-1093](payr-1093.md) and [PAYR-1055](payr-1055.md). diff --git a/catalogue/nhcx/errors/payr-1061.md b/catalogue/nhcx/errors/payr-1061.md new file mode 100644 index 000000000..91149edfe --- /dev/null +++ b/catalogue/nhcx/errors/payr-1061.md @@ -0,0 +1,100 @@ +--- +id: nhcx.error.payr-1061 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1061: an encounter''s subject has the wrong resource type' +summary: >- + The payer rejected your preauthorisation or claim because an encounter in the + bundle names a subject that is not a patient. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1094 + - nhcx.error.payr-1093 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1061: an encounter's subject has the wrong resource type + +## In plain words + +Your bundle carries clinical records as Composition and Observation resources. Each can point at an Encounter, the visit the record belongs to. One of those Encounters names a subject of a type the payer does not accept, so the payer stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1061`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> Invalid subject type found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + +It is produced when: + +- A Composition or an Observation in the bundle points at an Encounter. +- That Encounter's `subject` points at a resource that is not a Patient. + +`PAYR-1094` carries the same message. Fix both the same way. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1061` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Find each Encounter that a Composition's `encounter` or an Observation points at. +2. Set its `subject.reference` to the `fullUrl` of the Patient entry in the same bundle. Use the Patient that the Composition's `subject` points at. +3. Check the Encounter against the [NRCES Encounter profile](https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html). +4. Validate the corrected bundle in the [NRCES](../../shared/glossary/nrces.md) validator before you send it. +5. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +6. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1062.md b/catalogue/nhcx/errors/payr-1062.md new file mode 100644 index 000000000..c79e26766 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1062.md @@ -0,0 +1,97 @@ +--- +id: nhcx.error.payr-1062 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1062: an encounter has no episode of care the payer can find' +summary: >- + The payer rejected your preauthorisation or claim because it could not find the + episode of care for an encounter in the bundle. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1063 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1062: an encounter has no episode of care the payer can find + +## In plain words + +Your bundle carries clinical records as Composition and Observation resources. Each can point at an Encounter, the visit the record belongs to. The payer could not find an episode of care for one of those Encounters, so it stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1062`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> No episode of care found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + +It is produced when: + +- A Composition or an Observation in the bundle points at an Encounter. +- The payer finds no episode of care for that Encounter in the bundle. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1062` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Add an episode of care reference to the Encounter. The [NRCES Encounter profile](https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html) names the element and the target types it allows. +2. Include the resource it points at as an entry in the same bundle. +3. Make the reference match that entry's `fullUrl` exactly. +4. Validate the corrected bundle in the [NRCES](../../shared/glossary/nrces.md) validator before you send it. +5. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +6. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1063.md b/catalogue/nhcx/errors/payr-1063.md new file mode 100644 index 000000000..9bb793d72 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1063.md @@ -0,0 +1,97 @@ +--- +id: nhcx.error.payr-1063 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1063: an encounter''s episode of care has the wrong resource type' +summary: >- + The payer rejected your preauthorisation or claim because an encounter's episode + of care points at the wrong kind of record. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1062 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1063: an encounter's episode of care has the wrong resource type + +## In plain words + +Your bundle carries clinical records as Composition and Observation resources. Each can point at an Encounter, the visit the record belongs to. One of those Encounters has an episode of care reference that points at the wrong kind of resource, so the payer stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1063`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> Invalid episode of care type found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + +It is produced when: + +- A Composition or an Observation in the bundle points at an Encounter. +- That Encounter's episode of care reference points at a resource of a type the payer does not accept. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1063` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Find the episode of care reference on each Encounter that a Composition or an Observation points at. +2. Open the [NRCES Encounter profile](https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html) and read the target types it allows for that element. +3. Point the reference at an entry of an allowed type, and make it match that entry's `fullUrl` exactly. +4. Validate the corrected bundle in the [NRCES](../../shared/glossary/nrces.md) validator before you send it. +5. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +6. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1064.md b/catalogue/nhcx/errors/payr-1064.md new file mode 100644 index 000000000..60e4568ab --- /dev/null +++ b/catalogue/nhcx/errors/payr-1064.md @@ -0,0 +1,97 @@ +--- +id: nhcx.error.payr-1064 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1064: an encounter has no based-on reference the payer can find' +summary: >- + The payer rejected your preauthorisation or claim because it could not find what + an encounter in the bundle is based on. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1065 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1064: an encounter has no based-on reference the payer can find + +## In plain words + +Your bundle carries clinical records as Composition and Observation resources. Each can point at an Encounter, the visit the record belongs to. The payer could not find the based-on reference for one of those Encounters, so it stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1064`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> No based on found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + +It is produced when: + +- A Composition or an Observation in the bundle points at an Encounter. +- The payer finds no based-on reference for that Encounter in the bundle. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1064` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Add a based-on reference to the Encounter. The [NRCES Encounter profile](https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html) names the element and the target types it allows. +2. Include the resource it points at as an entry in the same bundle. +3. Make the reference match that entry's `fullUrl` exactly. +4. Validate the corrected bundle in the [NRCES](../../shared/glossary/nrces.md) validator before you send it. +5. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +6. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1065.md b/catalogue/nhcx/errors/payr-1065.md new file mode 100644 index 000000000..b384524a1 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1065.md @@ -0,0 +1,97 @@ +--- +id: nhcx.error.payr-1065 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1065: an encounter''s based-on reference has the wrong resource type' +summary: >- + The payer rejected your preauthorisation or claim because an encounter's based-on + reference points at the wrong kind of record. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1064 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1065: an encounter's based-on reference has the wrong resource type + +## In plain words + +Your bundle carries clinical records as Composition and Observation resources. Each can point at an Encounter, the visit the record belongs to. One of those Encounters has a based-on reference that points at the wrong kind of resource, so the payer stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1065`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> Invalid based on type found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + +It is produced when: + +- A Composition or an Observation in the bundle points at an Encounter. +- That Encounter's based-on reference points at a resource of a type the payer does not accept. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1065` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Find the based-on reference on each Encounter that a Composition or an Observation points at. +2. Open the [NRCES Encounter profile](https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html) and read the target types it allows for that element. +3. Point the reference at an entry of an allowed type, and make it match that entry's `fullUrl` exactly. +4. Validate the corrected bundle in the [NRCES](../../shared/glossary/nrces.md) validator before you send it. +5. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +6. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1066.md b/catalogue/nhcx/errors/payr-1066.md new file mode 100644 index 000000000..c7f96965c --- /dev/null +++ b/catalogue/nhcx/errors/payr-1066.md @@ -0,0 +1,99 @@ +--- +id: nhcx.error.payr-1066 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1066: an encounter has no appointment the payer can find' +summary: >- + The payer rejected your preauthorisation or claim because it could not find the + appointment for an encounter in the bundle. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1067 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1066: an encounter has no appointment the payer can find + +## In plain words + +Your bundle carries clinical records as Composition and Observation resources. Each can point at an Encounter, the visit the record belongs to. The payer could not find an appointment for one of those Encounters, so it stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1066`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> No appointment found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + +It is produced when: + +- A Composition or an Observation in the bundle points at an Encounter. +- The payer finds no appointment for that Encounter in the bundle. + +An Appointment entry that no Encounter points at does not count. The Encounter must reference it. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1066` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Add an appointment reference to the Encounter. The [NRCES Encounter profile](https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html) names the element and the target types it allows. +2. Include the Appointment resource it points at as an entry in the same bundle. +3. Make the reference match that entry's `fullUrl` exactly. +4. Validate the corrected bundle in the [NRCES](../../shared/glossary/nrces.md) validator before you send it. +5. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +6. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1067.md b/catalogue/nhcx/errors/payr-1067.md new file mode 100644 index 000000000..d44b57a00 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1067.md @@ -0,0 +1,97 @@ +--- +id: nhcx.error.payr-1067 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1067: an encounter''s appointment has the wrong resource type' +summary: >- + The payer rejected your preauthorisation or claim because an encounter's appointment + reference points at something that is not an appointment. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1066 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1067: an encounter's appointment has the wrong resource type + +## In plain words + +Your bundle carries clinical records as Composition and Observation resources. Each can point at an Encounter, the visit the record belongs to. One of those Encounters has an appointment reference that points at the wrong kind of resource, so the payer stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1067`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> Invalid appointment type found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + +It is produced when: + +- A Composition or an Observation in the bundle points at an Encounter. +- That Encounter's appointment reference points at a resource that is not an Appointment. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1067` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Find the appointment reference on each Encounter that a Composition or an Observation points at. +2. Open the [NRCES Encounter profile](https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html) and read the target types it allows for that element. +3. Point the reference at an Appointment entry, and make it match that entry's `fullUrl` exactly. +4. Validate the corrected bundle in the [NRCES](../../shared/glossary/nrces.md) validator before you send it. +5. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +6. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1068.md b/catalogue/nhcx/errors/payr-1068.md new file mode 100644 index 000000000..16c000f52 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1068.md @@ -0,0 +1,97 @@ +--- +id: nhcx.error.payr-1068 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1068: an encounter has no reason reference the payer can find' +summary: >- + The payer rejected your preauthorisation or claim because it could not find the + reason for an encounter in the bundle. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1069 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1068: an encounter has no reason reference the payer can find + +## In plain words + +Your bundle carries clinical records as Composition and Observation resources. Each can point at an Encounter, the visit the record belongs to. The payer could not find the reason reference for one of those Encounters, so it stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1068`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> No reason reference found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + +It is produced when: + +- A Composition or an Observation in the bundle points at an Encounter. +- The payer finds no reason reference for that Encounter in the bundle. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1068` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Add a reason reference to the Encounter. The [NRCES Encounter profile](https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html) names the element and the target types it allows. +2. Include the resource it points at as an entry in the same bundle. +3. Make the reference match that entry's `fullUrl` exactly. +4. Validate the corrected bundle in the [NRCES](../../shared/glossary/nrces.md) validator before you send it. +5. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +6. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1069.md b/catalogue/nhcx/errors/payr-1069.md new file mode 100644 index 000000000..60aec8169 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1069.md @@ -0,0 +1,97 @@ +--- +id: nhcx.error.payr-1069 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1069: an encounter''s reason reference has the wrong resource type' +summary: >- + The payer rejected your preauthorisation or claim because an encounter's reason + reference points at the wrong kind of record. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1068 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1069: an encounter's reason reference has the wrong resource type + +## In plain words + +Your bundle carries clinical records as Composition and Observation resources. Each can point at an Encounter, the visit the record belongs to. One of those Encounters has a reason reference that points at the wrong kind of resource, so the payer stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1069`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> Invalid reason reference type found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + +It is produced when: + +- A Composition or an Observation in the bundle points at an Encounter. +- That Encounter's reason reference points at a resource of a type the payer does not accept. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1069` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Find the reason reference on each Encounter that a Composition or an Observation points at. +2. Open the [NRCES Encounter profile](https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html) and read the target types it allows for that element. +3. Point the reference at an entry of an allowed type, and make it match that entry's `fullUrl` exactly. +4. Validate the corrected bundle in the [NRCES](../../shared/glossary/nrces.md) validator before you send it. +5. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +6. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1070.md b/catalogue/nhcx/errors/payr-1070.md new file mode 100644 index 000000000..806c180e6 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1070.md @@ -0,0 +1,97 @@ +--- +id: nhcx.error.payr-1070 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1070: a composition has no author' +summary: >- + The payer rejected your preauthorisation or claim because a clinical document + in the bundle does not say who wrote it. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1071 + - nhcx.error.payr-1088 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1070: a composition has no author + +## In plain words + +Your bundle carries clinical documents as Composition resources. One of them does not say who wrote it, so the payer stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1070`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> No author found for composition component. Hence request will not be processed further. + +It is produced when: + +- A Composition in the bundle has no `author`. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1070` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Add `author` to every Composition in the bundle. +2. Point `author[0].reference` at an entry in the bundle, such as the Practitioner who wrote the record. +3. Make the reference match that entry's `fullUrl` exactly. +4. Validate the corrected bundle in the [NRCES](../../shared/glossary/nrces.md) validator before you send it. +5. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +6. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1071.md b/catalogue/nhcx/errors/payr-1071.md new file mode 100644 index 000000000..d61c4bd96 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1071.md @@ -0,0 +1,98 @@ +--- +id: nhcx.error.payr-1071 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1071: a composition''s author has the wrong resource type' +summary: >- + The payer rejected your preauthorisation or claim because a clinical document + names an author of a kind it does not accept. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1070 + - nhcx.error.payr-1088 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1071: a composition's author has the wrong resource type + +## In plain words + +Your bundle carries clinical documents as Composition resources. One of them names an author of a type the payer does not accept, so the payer stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1071`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> Invalid author type found for composition component. This should be of type Practitioner / PractitionerRole / Organization / Patient / Device / RelatedPerson. Hence request will not be processed further. Please try again with valid author type for the composition. + +It is produced when: + +- A Composition's `author` points at a resource of a type the payer does not accept. +- The accepted types are Practitioner, PractitionerRole, Organization, Patient, Device and RelatedPerson. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1071` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Find the `author` reference on each Composition in the bundle. +2. Point it at an entry of one of the six accepted types, such as the Practitioner who wrote the record. +3. Make the reference match that entry's `fullUrl` exactly. +4. Validate the corrected bundle in the [NRCES](../../shared/glossary/nrces.md) validator before you send it. +5. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +6. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1072.md b/catalogue/nhcx/errors/payr-1072.md new file mode 100644 index 000000000..d6f05aaa3 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1072.md @@ -0,0 +1,108 @@ +--- +id: nhcx.error.payr-1072 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1072: a claim procedure has no procedure reference' +summary: >- + The payer rejected your preauthorisation or claim because a procedure listed on + the claim does not point at its procedure record. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1026 + - nhcx.error.payr-1086 + - nhcx.error.payr-1087 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1072: a claim procedure has no procedure reference + +## In plain words + +The Claim resource in your bundle lists procedures in `procedure`. One entry does not say which Procedure resource it means, so the payer stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1072`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> No procedure reference received for procedure element in claim resource. Hence request will not be processed further. + +It is produced when: + +- An entry in `Claim.procedure` has no `procedureReference`. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1072` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Give every `Claim.procedure` entry a `procedureReference` that points at a Procedure entry in the bundle: + + ```json + "procedure": [ + { + "sequence": 1, + "procedureReference": { "reference": "" } + } + ] + ``` + + `` is the `fullUrl` of the Procedure entry in your bundle. +2. Include that Procedure resource as an entry, with a `fullUrl` that matches the reference exactly. +3. Validate the corrected bundle in the [NRCES](../../shared/glossary/nrces.md) validator before you send it. +4. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +5. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1073.md b/catalogue/nhcx/errors/payr-1073.md new file mode 100644 index 000000000..65042db96 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1073.md @@ -0,0 +1,96 @@ +--- +id: nhcx.error.payr-1073 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1073: an observation has no based-on reference' +summary: >- + The payer rejected your preauthorisation or claim because it could not find what + an observation in the bundle is based on. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1074 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1073: an observation has no based-on reference + +## In plain words + +Your bundle carries test results and other findings as Observation resources. The payer could not find the based-on reference for one of them, so it stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1073`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> No based on found for observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Observation.html + +It is produced when: + +- The payer finds no based-on reference for an Observation in the bundle. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1073` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Add a based-on reference to every Observation in the bundle. The [NRCES Observation profile](https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Observation.html) names the element and the target types it allows. +2. Include the resource it points at as an entry in the same bundle. +3. Make the reference match that entry's `fullUrl` exactly. +4. Validate the corrected bundle in the [NRCES](../../shared/glossary/nrces.md) validator before you send it. +5. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +6. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1074.md b/catalogue/nhcx/errors/payr-1074.md new file mode 100644 index 000000000..85ca25c6e --- /dev/null +++ b/catalogue/nhcx/errors/payr-1074.md @@ -0,0 +1,96 @@ +--- +id: nhcx.error.payr-1074 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1074: an observation''s based-on reference has the wrong resource type' +summary: >- + The payer rejected your preauthorisation or claim because an observation's based-on + reference points at the wrong kind of record. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1073 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1074: an observation's based-on reference has the wrong resource type + +## In plain words + +Your bundle carries test results and other findings as Observation resources. One of them has a based-on reference that points at the wrong kind of resource, so the payer stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1074`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> Invalid based on type found for observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Observation.html + +It is produced when: + +- An Observation's based-on reference points at a resource of a type the payer does not accept. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1074` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Find the based-on reference on each Observation in the bundle. +2. Open the [NRCES Observation profile](https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Observation.html) and read the target types it allows for that element. +3. Point the reference at an entry of an allowed type, and make it match that entry's `fullUrl` exactly. +4. Validate the corrected bundle in the [NRCES](../../shared/glossary/nrces.md) validator before you send it. +5. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +6. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1075.md b/catalogue/nhcx/errors/payr-1075.md new file mode 100644 index 000000000..607d8348e --- /dev/null +++ b/catalogue/nhcx/errors/payr-1075.md @@ -0,0 +1,96 @@ +--- +id: nhcx.error.payr-1075 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1075: an observation has no part-of reference' +summary: >- + The payer rejected your preauthorisation or claim because it could not find what + an observation in the bundle is part of. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1076 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1075: an observation has no part-of reference + +## In plain words + +Your bundle carries test results and other findings as Observation resources. The payer could not find the part-of reference for one of them, so it stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1075`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> No part of found for observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Observation.html + +It is produced when: + +- The payer finds no part-of reference for an Observation in the bundle. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1075` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Add a part-of reference to every Observation in the bundle. The [NRCES Observation profile](https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Observation.html) names the element and the target types it allows. +2. Include the resource it points at as an entry in the same bundle. +3. Make the reference match that entry's `fullUrl` exactly. +4. Validate the corrected bundle in the [NRCES](../../shared/glossary/nrces.md) validator before you send it. +5. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +6. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1076.md b/catalogue/nhcx/errors/payr-1076.md new file mode 100644 index 000000000..2ae8f299c --- /dev/null +++ b/catalogue/nhcx/errors/payr-1076.md @@ -0,0 +1,96 @@ +--- +id: nhcx.error.payr-1076 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1076: an observation''s part-of reference has the wrong resource type' +summary: >- + The payer rejected your preauthorisation or claim because an observation's part-of + reference points at the wrong kind of record. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1075 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1076: an observation's part-of reference has the wrong resource type + +## In plain words + +Your bundle carries test results and other findings as Observation resources. One of them has a part-of reference that points at the wrong kind of resource, so the payer stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1076`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> Invalid part of type found for observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Observation.html + +It is produced when: + +- An Observation's part-of reference points at a resource of a type the payer does not accept. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1076` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Find the part-of reference on each Observation in the bundle. +2. Open the [NRCES Observation profile](https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Observation.html) and read the target types it allows for that element. +3. Point the reference at an entry of an allowed type, and make it match that entry's `fullUrl` exactly. +4. Validate the corrected bundle in the [NRCES](../../shared/glossary/nrces.md) validator before you send it. +5. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +6. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1077.md b/catalogue/nhcx/errors/payr-1077.md new file mode 100644 index 000000000..3dfdb2a07 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1077.md @@ -0,0 +1,95 @@ +--- +id: nhcx.error.payr-1077 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1077: an observation has no subject' +summary: >- + The payer rejected your preauthorisation or claim because an observation in the + bundle does not say which patient it is about. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1078 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1077: an observation has no subject + +## In plain words + +Your bundle carries test results and other findings as Observation resources. One of them does not say which patient it is about, so the payer stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1077`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> No subject found for observation component. Hence request will not be processed further. + +It is produced when: + +- An Observation in the bundle has no `subject`. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1077` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Give every Observation a `subject` whose `reference` is the `fullUrl` of the Patient entry in the bundle. +2. Send the `reference` even when you already send `subject.display`. A display names the patient but does not point at the Patient entry. +3. Validate the corrected bundle in the [NRCES](../../shared/glossary/nrces.md) validator before you send it. +4. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +5. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1078.md b/catalogue/nhcx/errors/payr-1078.md new file mode 100644 index 000000000..99ca28970 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1078.md @@ -0,0 +1,95 @@ +--- +id: nhcx.error.payr-1078 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1078: an observation''s subject is not a Patient' +summary: >- + The payer rejected your preauthorisation or claim because an observation's subject + points at something other than the patient. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1077 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1078: an observation's subject is not a Patient + +## In plain words + +Your bundle carries test results and other findings as Observation resources. One of them names a subject that is not a Patient, so the payer stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1078`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> Invalid subject type found for observation component. This should be of type Patient. Hence request will not be processed further. Please try again with valid subject type for the observation. + +It is produced when: + +- An Observation's `subject` points at a resource that is not a Patient. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1078` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Find the `subject` on each Observation in the bundle. +2. Set `subject.reference` to the `fullUrl` of the Patient entry in the same bundle. +3. Validate the corrected bundle in the [NRCES](../../shared/glossary/nrces.md) validator before you send it. +4. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +5. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1079.md b/catalogue/nhcx/errors/payr-1079.md new file mode 100644 index 000000000..1ae3c6c2c --- /dev/null +++ b/catalogue/nhcx/errors/payr-1079.md @@ -0,0 +1,107 @@ +--- +id: nhcx.error.payr-1079 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1079: the claim has no care team' +summary: >- + The payer rejected your preauthorisation or claim because the claim does not name + the care team treating the patient. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1080 + - nhcx.error.payr-1083 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1079: the claim has no care team + +## In plain words + +The Claim resource in your bundle must name the practitioners treating the patient in `careTeam`. It has none, so the payer stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1079`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> No care team details received. Hence request will not be processed further. Please add the care team details and try again. + +It is produced when: + +- The Claim resource has no `careTeam` entry. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1079` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Add a `careTeam` entry to the Claim for the treating practitioner: + + ```json + "careTeam": [ + { + "sequence": 1, + "provider": { "reference": "" } + } + ] + ``` + + `` is the `fullUrl` of the Practitioner entry in your bundle. +2. Point each `Claim.item` at that entry through `careTeamSequence`, using the same `sequence` number. +3. Validate the corrected bundle in the [NRCES](../../shared/glossary/nrces.md) validator before you send it. +4. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +5. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1080.md b/catalogue/nhcx/errors/payr-1080.md new file mode 100644 index 000000000..387fd0771 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1080.md @@ -0,0 +1,120 @@ +--- +id: nhcx.error.payr-1080 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1080: a practitioner''s HPR id is not valid' +summary: >- + The payer rejected your preauthorisation or claim because a practitioner in the + bundle carries a professional registry id it does not accept. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1083 + - nhcx.error.payr-1050 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.hpr + - shared.glossary.nrces +--- + +# PAYR-1080: a practitioner's HPR id is not valid + +## In plain words + +Each Practitioner in your bundle carries the practitioner's [HPR](../../shared/glossary/hpr.md) id. The payer did not accept the id on one of them, so it stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1080`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> Invalid HPR details received for practioner resource with url `%s`. Hence request will not be processed further. Please try again with valid HPR id. + +It is produced when: + +- The Practitioner entry at the url in the message carries HPR details the payer does not accept. + +`%s` is the url of the Practitioner entry, as your references name it. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1080` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Find the Practitioner entry whose `fullUrl` matches the url in the message. +2. Check its HPR identifier against the practitioner's HPR registration. +3. Send the identifier with type code `HPIN` and system `https://hpr.abdm.gov.in`: + + ```json + "identifier": [ + { + "type": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code", + "code": "HPIN", + "display": "Health Practitioner ID issued by NDHM" + } + ] + }, + "system": "https://hpr.abdm.gov.in", + "value": "" + } + ] + ``` + + `` is the practitioner's id from their HPR registration. +4. Validate the corrected bundle in the [NRCES](../../shared/glossary/nrces.md) validator before you send it. +5. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +6. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1081.md b/catalogue/nhcx/errors/payr-1081.md new file mode 100644 index 000000000..5a4145422 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1081.md @@ -0,0 +1,100 @@ +--- +id: nhcx.error.payr-1081 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1081: an item''s service date is not valid' +summary: >- + The payer rejected your preauthorisation or claim because the service date on + one of the billed items is not valid. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1043 + - nhcx.error.payr-1044 + - nhcx.error.payr-1028 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1081: an item's service date is not valid + +## In plain words + +Each item in the Claim resource carries the date or period of service. The payer did not accept the date on one item, so it stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1081`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> Invalid service date received for item with sequence `%s` in claim resource. Hence request will not be processed further. Please try again with valid item service date. + +It is produced when: + +- The `Claim.item` with the sequence in the message carries a service date the payer does not accept. + +`%s` is the `sequence` of the item. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1081` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Find the `Claim.item` whose `sequence` matches the message. +2. Correct its service date. In a preauthorisation bundle it sits in `servicedPeriod.start` and `servicedPeriod.end`, for example `2026-02-22`. +3. Use the [NRCES](../../shared/glossary/nrces.md) date format. `PAYR-1043` and `PAYR-1044` cover date format failures. +4. Validate the corrected bundle in the NRCES validator before you send it. +5. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +6. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1082.md b/catalogue/nhcx/errors/payr-1082.md new file mode 100644 index 000000000..3186310b9 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1082.md @@ -0,0 +1,101 @@ +--- +id: nhcx.error.payr-1082 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1082: a composition linked from supporting info has an invalid title' +summary: >- + The payer rejected your preauthorisation or claim because a document attached + through supporting information has a title it does not accept. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1088 + - nhcx.error.payr-1047 + - nhcx.error.payr-1048 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1082: a composition linked from supporting info has an invalid title + +## In plain words + +Supporting information on the Claim can point at a Composition, such as a lab report. The payer did not accept the title of one of those Compositions, so it stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1082`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> Invalid title received for composition for supporting info with sequence `%s` in claim resource. Hence request will not be processed further. Please try again with valid composition title. + +It is produced when: + +- A `Claim.supportingInfo` entry with the sequence in the message points at a Composition through `valueReference`. +- That Composition's `title` is not one the payer accepts. + +`%s` is the `sequence` of the supporting info entry. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1082` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Find the `Claim.supportingInfo` entry whose `sequence` matches the message. +2. Follow its `valueReference` to the Composition entry in the bundle. +3. Correct that Composition's `title`, and check the Composition against its [NRCES](../../shared/glossary/nrces.md) profile. +4. Validate the corrected bundle in the NRCES validator before you send it. +5. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +6. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1083.md b/catalogue/nhcx/errors/payr-1083.md new file mode 100644 index 000000000..aaa830fc8 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1083.md @@ -0,0 +1,119 @@ +--- +id: nhcx.error.payr-1083 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1083: a practitioner has no HPR id' +summary: >- + The payer rejected your preauthorisation or claim because a practitioner in the + bundle carries no professional registry id. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1080 + - nhcx.error.payr-1050 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.hpr + - shared.glossary.nrces +--- + +# PAYR-1083: a practitioner has no HPR id + +## In plain words + +Each Practitioner in your bundle must carry the practitioner's [HPR](../../shared/glossary/hpr.md) id. One of them has none, so the payer stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1083`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> No HPR details found for the practitioner for resource `%s`. Hence request will not be processed further. Please send the details in the identifier for Practitioner resource with category code as HPIN. + +It is produced when: + +- The Practitioner resource named in the message has no identifier with type code `HPIN`. + +`%s` is the Practitioner resource, as your references name it. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1083` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Find the Practitioner resource named in the message. +2. Add the practitioner's HPR id to its `identifier`, with type code `HPIN` and system `https://hpr.abdm.gov.in`: + + ```json + "identifier": [ + { + "type": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code", + "code": "HPIN", + "display": "Health Practitioner ID issued by NDHM" + } + ] + }, + "system": "https://hpr.abdm.gov.in", + "value": "" + } + ] + ``` + + `` is the practitioner's id from their HPR registration. +3. Validate the corrected bundle in the [NRCES](../../shared/glossary/nrces.md) validator before you send it. +4. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +5. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1084.md b/catalogue/nhcx/errors/payr-1084.md new file mode 100644 index 000000000..cf020a5a1 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1084.md @@ -0,0 +1,101 @@ +--- +id: nhcx.error.payr-1084 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1084: a reference points at a questionnaire response that is not in + the bundle' +summary: >- + The payer rejected your preauthorisation or claim because the bundle refers to + a questionnaire response it does not contain. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1085 + - nhcx.error.payr-1505 + - nhcx.error.payr-1254 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1084: a reference points at a questionnaire response that is not in the bundle + +## In plain words + +Supporting information can point at a QuestionnaireResponse, for example the answers to a policy or treatment questionnaire. One reference points at a url with no QuestionnaireResponse behind it, so the payer stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1084`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> No questionnaire response resource found for url `%s`. Hence request will not be processed further. Please add the resources for all the references given in the FHIR bundle and try again. + +It is produced when: + +- A reference in the bundle points at the url in the message. +- No QuestionnaireResponse entry in the bundle has that url as its `fullUrl`. + +`%s` is the url the reference points at. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1084` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Add the QuestionnaireResponse as an entry whose `fullUrl` is exactly the url in the message. +2. Check every other reference in the bundle the same way. Each must match the `fullUrl` of an entry. +3. Validate the corrected bundle in the [NRCES](../../shared/glossary/nrces.md) validator before you send it. +4. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +5. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1085.md b/catalogue/nhcx/errors/payr-1085.md new file mode 100644 index 000000000..28b519a90 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1085.md @@ -0,0 +1,100 @@ +--- +id: nhcx.error.payr-1085 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1085: a questionnaire response reference points at the wrong resource + type' +summary: >- + The payer rejected your preauthorisation or claim because a reference meant for + a questionnaire response points at a different kind of record. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1084 + - nhcx.error.payr-1505 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1085: a questionnaire response reference points at the wrong resource type + +## In plain words + +Supporting information can point at a QuestionnaireResponse. One such reference points at an entry of another resource type, so the payer stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1085`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> Invalid questionnaire response resource type found in the FHIR bundle for url `%s`. Hence request will not be processed further. + +It is produced when: + +- A reference that must point at a QuestionnaireResponse points at the url in the message. +- The entry at that url is not a QuestionnaireResponse. + +`%s` is the url the reference points at. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1085` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Find the entry whose `fullUrl` is the url in the message. +2. Point the reference at the QuestionnaireResponse entry instead, or correct the entry so it holds the QuestionnaireResponse. +3. Validate the corrected bundle in the [NRCES](../../shared/glossary/nrces.md) validator before you send it. +4. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +5. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1086.md b/catalogue/nhcx/errors/payr-1086.md new file mode 100644 index 000000000..ffb93449f --- /dev/null +++ b/catalogue/nhcx/errors/payr-1086.md @@ -0,0 +1,100 @@ +--- +id: nhcx.error.payr-1086 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1086: a reference points at a procedure that is not in the bundle' +summary: >- + The payer rejected your preauthorisation or claim because the bundle refers to + a procedure record it does not contain. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1087 + - nhcx.error.payr-1072 + - nhcx.error.payr-1026 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1086: a reference points at a procedure that is not in the bundle + +## In plain words + +Each `Claim.procedure` entry points at a Procedure resource in the bundle. One reference points at a url with no Procedure behind it, so the payer stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1086`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> No procedure resource found for url `%s`. Hence request will not be processed further. Please add the resources for all the references given in the FHIR bundle and try again. + +It is produced when: + +- A reference in the bundle points at the url in the message. +- No Procedure entry in the bundle has that url as its `fullUrl`. + +`%s` is the url the reference points at. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1086` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Add the Procedure as an entry whose `fullUrl` is exactly the url in the message. +2. Check every other reference in the bundle the same way. Each must match the `fullUrl` of an entry. +3. Validate the corrected bundle in the [NRCES](../../shared/glossary/nrces.md) validator before you send it. +4. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +5. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1087.md b/catalogue/nhcx/errors/payr-1087.md new file mode 100644 index 000000000..70caa2167 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1087.md @@ -0,0 +1,99 @@ +--- +id: nhcx.error.payr-1087 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1087: a procedure reference points at the wrong resource type' +summary: >- + The payer rejected your preauthorisation or claim because a reference meant for + a procedure record points at a different kind of record. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1086 + - nhcx.error.payr-1072 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1087: a procedure reference points at the wrong resource type + +## In plain words + +Each `Claim.procedure` entry points at a Procedure resource in the bundle. One reference points at an entry of another resource type, so the payer stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1087`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> Invalid procedure resource type found in the FHIR bundle for url `%s`. Hence request will not be processed further. Procedure resource type is expected. + +It is produced when: + +- A reference that must point at a Procedure points at the url in the message. +- The entry at that url is not a Procedure. + +`%s` is the url the reference points at. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1087` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Find the entry whose `fullUrl` is the url in the message. +2. Point the reference at the Procedure entry instead, or correct the entry so it holds the Procedure. +3. Validate the corrected bundle in the [NRCES](../../shared/glossary/nrces.md) validator before you send it. +4. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +5. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1088.md b/catalogue/nhcx/errors/payr-1088.md new file mode 100644 index 000000000..b2de09838 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1088.md @@ -0,0 +1,104 @@ +--- +id: nhcx.error.payr-1088 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1088: a composition failed the payer''s checks' +summary: >- + The payer rejected your preauthorisation or claim because a clinical document + in the bundle failed its checks. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1051 + - nhcx.error.payr-1052 + - nhcx.error.payr-1053 + - nhcx.error.payr-1054 + - nhcx.error.payr-1055 + - nhcx.error.payr-1070 + - nhcx.error.payr-1071 + - nhcx.error.payr-1082 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1088: a composition failed the payer's checks + +## In plain words + +Your bundle carries clinical documents as Composition resources. One of them failed the payer's checks, and the message does not name the element. The payer stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1088`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> Invalid composition details. + +It is produced when: + +- A Composition in the bundle fails the payer's checks. +- The message names no element, so check each Composition in full. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1088` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Check every Composition for these elements, each pointing at an entry in the bundle: `title`, `author`, `subject`, `encounter` and each `section[].entry[].reference`. +2. Compare each Composition with the [NRCES](../../shared/glossary/nrces.md) profile named in its `meta.profile`. +3. The codes for the single-element failures are `PAYR-1051` to `PAYR-1055`, `PAYR-1070`, `PAYR-1071` and `PAYR-1082`. +4. Validate the corrected bundle in the NRCES validator before you send it. +5. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +6. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1089.md b/catalogue/nhcx/errors/payr-1089.md new file mode 100644 index 000000000..0cb91e50a --- /dev/null +++ b/catalogue/nhcx/errors/payr-1089.md @@ -0,0 +1,108 @@ +--- +id: nhcx.error.payr-1089 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1089: the claim has no billing items' +summary: >- + The payer rejected your preauthorisation or claim because the claim lists nothing + to bill. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1027 + - nhcx.error.payr-1028 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1089: the claim has no billing items + +## In plain words + +The Claim resource lists what you are billing for in `item`. It has no items, so the payer stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1089`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> No billing items found. Hence request will not be processed further. Please try again with valid billing items. + +It is produced when: + +- The Claim resource has no `item` entry. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1089` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Add at least one `Claim.item` for the package you are billing: + + ```json + "item": [ + { + "sequence": 1, + "productOrService": { "coding": [ { "code": "" } ] }, + "quantity": { "value": 1 } + } + ] + ``` + + `` is the package or procedure code from the payer's insurance plan for the policy. +2. Validate the corrected bundle in the [NRCES](../../shared/glossary/nrces.md) validator before you send it. +3. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +4. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1090.md b/catalogue/nhcx/errors/payr-1090.md new file mode 100644 index 000000000..f51844964 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1090.md @@ -0,0 +1,118 @@ +--- +id: nhcx.error.payr-1090 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1090: the coverage has no identifier' +summary: >- + The payer rejected your request because the policy record in the bundle carries + no identifier. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.send-a-sealed-request + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.coverageeligibility-on-check + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.policy-linking + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1091 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1090: the coverage has no identifier + +## In plain words + +Every eligibility, preauthorisation and claim bundle carries a Coverage resource for the beneficiary's policy. Yours has no identifier, so the payer could not tell which policy you mean. + +## Before you start + +You sent a sealed request through [NHCX](../../shared/glossary/nhcx.md), for example `POST /v1/coverageeligibility/check`, `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired `on_` path, for example `/v1/coverageeligibility/on_check` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1090`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> No identifier found for coverage component. Hence request will not be processed further. + +It is produced when: + +- The Coverage resource in the bundle has no `identifier`. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on the paired `on_` path of the request you sent with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1090` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `CoverageEligibilityResponse` bundle for a coverage check, or a `ClaimResponse` bundle for a preauthorisation or a claim. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Add an `identifier` to the Coverage resource, carrying the policy id: + + ```json + "identifier": [ + { + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + "code": "NH", + "display": "National Health Plan Identifier" + } + ] + }, + "system": "", + "value": "" + } + ] + ``` + + `` is the policy code the payer issued for the beneficiary. `` is the identifier system the payer uses for policies. +2. Validate the corrected bundle in the [NRCES](../../shared/glossary/nrces.md) validator before you send it. +3. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +4. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1091.md b/catalogue/nhcx/errors/payr-1091.md new file mode 100644 index 000000000..81e2a24e6 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1091.md @@ -0,0 +1,117 @@ +--- +id: nhcx.error.payr-1091 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1091: the coverage identifier has no type' +summary: >- + The payer rejected your request because the identifier on the policy record in + the bundle does not say what kind of identifier it is. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.send-a-sealed-request + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.coverageeligibility-on-check + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1090 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1091: the coverage identifier has no type + +## In plain words + +Every eligibility, preauthorisation and claim bundle carries a Coverage resource for the beneficiary's policy. Its identifier has no type, so the payer stopped processing your request. + +## Before you start + +You sent a sealed request through [NHCX](../../shared/glossary/nhcx.md), for example `POST /v1/coverageeligibility/check`, `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired `on_` path, for example `/v1/coverageeligibility/on_check` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1091`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> No type found for coverage component identifier. Hence request will not be processed further. + +It is produced when: + +- The Coverage resource's `identifier` has no `type`. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on the paired `on_` path of the request you sent with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1091` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `CoverageEligibilityResponse` bundle for a coverage check, or a `ClaimResponse` bundle for a preauthorisation or a claim. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Give the Coverage identifier a `type` with code `NH` from `http://terminology.hl7.org/CodeSystem/v2-0203`: + + ```json + "identifier": [ + { + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + "code": "NH", + "display": "National Health Plan Identifier" + } + ] + }, + "system": "", + "value": "" + } + ] + ``` + + `` is the policy code the payer issued for the beneficiary. `` is the identifier system the payer uses for policies. +2. Validate the corrected bundle in the [NRCES](../../shared/glossary/nrces.md) validator before you send it. +3. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +4. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1092.md b/catalogue/nhcx/errors/payr-1092.md new file mode 100644 index 000000000..ab329c473 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1092.md @@ -0,0 +1,95 @@ +--- +id: nhcx.error.payr-1092 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1092: the payer failed while processing your request' +summary: >- + The payer could not finish processing your request and asks you to start a new + one. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.send-a-sealed-request + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.coverageeligibility-on-check + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1092: the payer failed while processing your request + +## In plain words + +The payer hit a failure while processing your request. The message names no element in your bundle. It asks you to start a new request. + +## Before you start + +You sent a sealed request through [NHCX](../../shared/glossary/nhcx.md), for example `POST /v1/coverageeligibility/check`, `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer failed while processing your request and answered on the paired `on_` path, for example `/v1/coverageeligibility/on_check` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1092`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> Something went wrong while processing request, kindly intiate new request + +It is produced when: + +- The payer failed while processing the request. +- The message names no element, so there is nothing in the bundle to correct first. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on the paired `on_` path of the request you sent with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1092` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `CoverageEligibilityResponse` bundle for a coverage check, or a `ClaimResponse` bundle for a preauthorisation or a claim. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Send the same content as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +2. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1093.md b/catalogue/nhcx/errors/payr-1093.md new file mode 100644 index 000000000..7e62ecaea --- /dev/null +++ b/catalogue/nhcx/errors/payr-1093.md @@ -0,0 +1,101 @@ +--- +id: nhcx.error.payr-1093 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1093: an encounter linked from a composition has no subject' +summary: >- + The payer rejected your preauthorisation or claim because the visit record behind + a clinical document does not say which patient it is about. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1060 + - nhcx.error.payr-1061 + - nhcx.error.payr-1094 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1093: an encounter linked from a composition has no subject + +## In plain words + +Your bundle carries clinical records as Composition and Observation resources. Each can point at an Encounter, the visit the record belongs to. The Encounter behind one Composition does not say which patient it is about, so the payer stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1093`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> No subject found for encounter in composition component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + +It is produced when: + +- A Composition's `encounter` points at an Encounter that has no `subject`. +- The Composition's structure does not follow the [NRCES](../../shared/glossary/nrces.md) guidelines for the Encounter. + +`PAYR-1060` can carry the same message. Fix both the same way. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1093` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Find the Encounter that each Composition's `encounter` points at. +2. Set the Encounter's `subject.reference` to the `fullUrl` of the Patient entry. Use the Patient that the Composition's `subject` points at. +3. Check the Encounter against the [NRCES Encounter profile](https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html). +4. Validate the corrected bundle in the NRCES validator before you send it. +5. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +6. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1094.md b/catalogue/nhcx/errors/payr-1094.md new file mode 100644 index 000000000..dc07048b6 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1094.md @@ -0,0 +1,101 @@ +--- +id: nhcx.error.payr-1094 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1094: an encounter''s subject has the wrong resource type' +summary: >- + The payer rejected your preauthorisation or claim because an encounter in the + bundle names a subject that is not a patient. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1061 + - nhcx.error.payr-1093 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1094: an encounter's subject has the wrong resource type + +## In plain words + +Your bundle carries clinical records as Composition and Observation resources. Each can point at an Encounter, the visit the record belongs to. One of those Encounters names a subject of a type the payer does not accept, so the payer stopped processing your request. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1094`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> Invalid subject type found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + +It is produced when: + +- A Composition or an Observation in the bundle points at an Encounter. +- That Encounter's `subject` points at a resource that is not a Patient. +- The Composition's structure does not follow the [NRCES](../../shared/glossary/nrces.md) guidelines for the Encounter. + +`PAYR-1061` carries the same message. Fix both the same way. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1094` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Find each Encounter that a Composition's `encounter` or an Observation points at. +2. Set its `subject.reference` to the `fullUrl` of the Patient entry in the same bundle. Use the Patient that the Composition's `subject` points at. +3. Check the Encounter against the [NRCES Encounter profile](https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html). +4. Validate the corrected bundle in the NRCES validator before you send it. +5. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +6. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1095.md b/catalogue/nhcx/errors/payr-1095.md new file mode 100644 index 000000000..42e30222e --- /dev/null +++ b/catalogue/nhcx/errors/payr-1095.md @@ -0,0 +1,95 @@ +--- +id: nhcx.error.payr-1095 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1095: the claim carries no valid discharge information' +summary: >- + The payer rejected your claim because it carries no valid information about how + the patient was discharged. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1096 + - nhcx.error.payr-1514 + - nhcx.error.payr-1099 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1095: the claim carries no valid discharge information + +## In plain words + +A claim must say how the patient was discharged. Yours carries no valid discharge information, so the payer stopped processing it. + +## Before you start + +You sent a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1095`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> Invalid discharge information received for claim request. Hence request will not be processed further. Please send the discharge information in supporting info in claim resource, with category as DIS (refer - https://www.nrces.in/ndhm/fhir/r4/ValueSet-ndhm-supportinginfo-category.html), and codes in LAMA/DAMA/DTH/DTM (refer - https://www.nrces.in/ndhm/fhir/r4/ValueSet-ndhm-supportinginfo-code.html). + +It is produced when: + +- The claim bundle carries no discharge information in `Claim.supportingInfo`. +- Or the discharge entry does not use category `DIS` with one of the codes `LAMA`, `DAMA`, `DTH` or `DTM`. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1095` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Add a `Claim.supportingInfo` entry with category `DIS` and one of the codes `LAMA`, `DAMA`, `DTH` or `DTM`. The value sets are [supporting info category](https://www.nrces.in/ndhm/fhir/r4/ValueSet-ndhm-supportinginfo-category.html) and [supporting info code](https://www.nrces.in/ndhm/fhir/r4/ValueSet-ndhm-supportinginfo-code.html). +2. Send its value as a string naming the discharge stage: `After Surgery`, `Before Surgery` or `During Surgery`. `PAYR-1514` covers a wrong value type. +3. Give the entry a `sequence` no other supporting info entry uses. +4. Validate the corrected bundle in the [NRCES](../../shared/glossary/nrces.md) validator before you send it. +5. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +6. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1096.md b/catalogue/nhcx/errors/payr-1096.md new file mode 100644 index 000000000..b0cde552f --- /dev/null +++ b/catalogue/nhcx/errors/payr-1096.md @@ -0,0 +1,94 @@ +--- +id: nhcx.error.payr-1096 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1096: a death discharge carries no valid death date' +summary: >- + The payer rejected your claim because the patient's discharge type is death and + the claim carries no valid date of death. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1095 + - nhcx.error.payr-1503 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1096: a death discharge carries no valid death date + +## In plain words + +When the discharge type is death, the claim must carry the date of death. Yours carries no valid death date, so the payer stopped processing it. + +## Before you start + +You sent a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1096`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> Invalid death date received for claim request. Hence request will not be processed further. Please send the death date information in supporting info in claim resource, with category as ONS (refer - https://www.nrces.in/ndhm/fhir/r4/ValueSet-ndhm-supportinginfo-category.html), and code as DTM (refer - https://www.nrces.in/ndhm/fhir/r4/ValueSet-ndhm-supportinginfo-code.html). + +It is produced when: + +- The claim's discharge type is death. +- No `Claim.supportingInfo` entry with category `ONS` and code `DTM` carries the death date. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1096` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Add a `Claim.supportingInfo` entry with category `ONS` and code `DTM`, carrying the date of death. The value sets are [supporting info category](https://www.nrces.in/ndhm/fhir/r4/ValueSet-ndhm-supportinginfo-category.html) and [supporting info code](https://www.nrces.in/ndhm/fhir/r4/ValueSet-ndhm-supportinginfo-code.html). +2. Send the date as a timing (a date or a period) or as a string value. `PAYR-1503` covers a wrong value type. +3. Give the entry a `sequence` no other supporting info entry uses. +4. Validate the corrected bundle in the [NRCES](../../shared/glossary/nrces.md) validator before you send it. +5. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +6. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1097.md b/catalogue/nhcx/errors/payr-1097.md new file mode 100644 index 000000000..c9eb44ca1 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1097.md @@ -0,0 +1,107 @@ +--- +id: nhcx.error.payr-1097 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1097: the request arrived with no encrypted payload' +summary: >- + The payer rejected your request because it found no encrypted content inside it. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.send-a-sealed-request + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.coverageeligibility-on-check + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.jwe-envelope + - nhcx.concept.encryption-certificate + errors: + - nhcx.error.nhcx-1006 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces + troubleshooting: + - nhcx.troubleshooting.recipient-cannot-decrypt +--- + +# PAYR-1097: the request arrived with no encrypted payload + +## In plain words + +Every request carries your [FHIR](../../shared/glossary/fhir.md) bundle, encrypted, in the `payload` property of the request body. The payer opened your request and found no encrypted payload. + +## Before you start + +You sent a sealed request through [NHCX](../../shared/glossary/nhcx.md), for example `POST /v1/coverageeligibility/check`, `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer found no encrypted payload when it opened your request and answered on the paired `on_` path, for example `/v1/coverageeligibility/on_check` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1097`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> No payload found in the request. Please ensure that the request that is being sent, contains encrypted payload within the mandatory payload properties. + +It is produced when: + +- The `payload` property of your request body is missing or empty. +- Or the ciphertext part of the JWE compact string carries no encrypted bundle. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on the paired `on_` path of the request you sent with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1097` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `CoverageEligibilityResponse` bundle for a coverage check, or a `ClaimResponse` bundle for a preauthorisation or a claim. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Encrypt the FHIR bundle with the payer's public certificate. +2. Put the resulting compact string in `payload`: + + ```json + { "payload": "" } + ``` + + `` is the output of encrypting your bundle. +3. Check that the ciphertext part of the compact string is not empty before you send it. +4. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +5. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1098.md b/catalogue/nhcx/errors/payr-1098.md new file mode 100644 index 000000000..d25b41512 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1098.md @@ -0,0 +1,101 @@ +--- +id: nhcx.error.payr-1098 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1098: the registration date has the wrong value type' +summary: >- + The payer rejected your preauthorisation or claim because the patient's registration + date is sent in a form it does not accept. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1099 + - nhcx.error.payr-1502 + - nhcx.error.payr-1020 + - nhcx.error.payr-1021 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1098: the registration date has the wrong value type + +## In plain words + +The Claim resource carries the patient's registration date as a supporting info entry with category `OTH` and code `EDT`. That entry's value has a type the payer does not accept. + +## Before you start + +You sent a preauthorisation or a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/preauth/submit` or `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on the paired path, `/v1/preauth/on_submit` or `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1098`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> Value type received as `%s` for category - OTH and code - EDT for item with sequence `%s` in supporting info in claim resource. In supporting info list, item with category - OTH and code - EDT combination is used to get the registration date. So the registration date should be sent as timing (date or period) or as a string value, adhering to the NRCES standards, with the category - OTH and code - EDT. + +It is produced when: + +- A `Claim.supportingInfo` entry with category `OTH` and code `EDT` carries a value of the type named in the message. +- The payer accepts the registration date only as a timing (a date or a period) or as a string. + +The first `%s` is the value type you sent. The second `%s` is the `sequence` of the supporting info entry. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1098` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Find the `Claim.supportingInfo` entry whose `sequence` matches the message. +2. Send the registration date as a timing (a date or a period) or as `valueString`, in [NRCES](../../shared/glossary/nrces.md) date format. +3. Validate the corrected bundle in the NRCES validator before you send it. +4. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +5. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1099.md b/catalogue/nhcx/errors/payr-1099.md new file mode 100644 index 000000000..9e600e840 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1099.md @@ -0,0 +1,97 @@ +--- +id: nhcx.error.payr-1099 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1099: the discharge date has the wrong value type' +summary: >- + The payer rejected your claim because the patient's discharge date is sent in + a form it does not accept. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1098 + - nhcx.error.payr-1095 + - nhcx.error.payr-1501 + - nhcx.error.payr-1502 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.nrces +--- + +# PAYR-1099: the discharge date has the wrong value type + +## In plain words + +The claim carries the discharge date as a supporting info entry with category `ONS` and code `DSDE`. That entry's value has a type the payer does not accept. + +## Before you start + +You sent a claim through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/claim/submit`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer checked the structure of your [FHIR](../../shared/glossary/fhir.md) bundle and answered on `/v1/claim/on_submit`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1099`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +## What happens + +The payer returns this message: + +> Value type received as `%s` for category - ONS and code - DSDE for item with sequence `%s` in supporting info in claim resource. In supporting info list, item with category - ONS and code - DSDE combination is used to get the discharge date. So the discharge date should be sent as timing (date or period) or as a string value, adhering to the NRCES standards, with the category - ONS and code - DSDE. + +It is produced when: + +- A `Claim.supportingInfo` entry with category `ONS` and code `DSDE` carries a value of the type named in the message. +- The payer accepts the discharge date only as a timing (a date or a period) or as a string. + +The first `%s` is the value type you sent. The second `%s` is the `sequence` of the supporting info entry. + +## How you know it worked + +Send the corrected request as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/claim/on_submit` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1099` does not appear anywhere in it. +- `x-hcx-status` is neither `response.error` nor `response.fail`. +- The decrypted payload is a `ClaimResponse` bundle for your case. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Find the `Claim.supportingInfo` entry whose `sequence` matches the message. +2. Send the discharge date with category `ONS` and code `DSDE`, as a timing (a date or a period) or as `valueString`, in [NRCES](../../shared/glossary/nrces.md) date format. +3. Validate the corrected bundle in the NRCES validator before you send it. +4. Send it as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +5. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1101.md b/catalogue/nhcx/errors/payr-1101.md new file mode 100644 index 000000000..cb298ef17 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1101.md @@ -0,0 +1,98 @@ +--- +id: nhcx.error.payr-1101 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1101: the eligibility purpose is not valid' +summary: >- + The payer returned no result because the purpose of your eligibility check is + not one it accepts. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Coverage Error Codes, Preauth Error Codes. +verified: + status: unverified +related: + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.coverageeligibility-on-check + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.coverage-eligibility-response + - nhcx.fhir.preauth-request + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.coverage-eligibility-purposes + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1032 + - nhcx.error.payr-1033 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id +--- + +# PAYR-1101: the eligibility purpose is not valid + +## In plain words + +Every eligibility check says what you want to know, in `CoverageEligibilityRequest.purpose`. The payer did not accept the purpose you sent, so it returned no result. + +## Before you start + +You sent a coverage eligibility check through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/coverageeligibility/check`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer evaluated the policy, the beneficiary and your hospital's configuration and answered on `/v1/coverageeligibility/on_check`. This code arrives in that answer. The same code can answer a preauthorisation, on `/v1/preauth/on_submit`. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1101`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +The payer can also embed business error detail inside the sealed `CoverageEligibilityResponse`. Decrypt the payload with your private key and read it as well. + +## What happens + +The payer returns this message: + +> Invalid purpose received as (`%s`) for beneficiary id (`%s`) from hospital id (`%s`). Hence no result will be returned. Please try again with a valid purpose. + +It is produced when: + +- The `purpose` on your CoverageEligibilityRequest is not one the payer accepts for this beneficiary and hospital. + +The first `%s` is the purpose you sent. The second is the beneficiary id, and the third is your hospital id. + +## How you know it worked + +Send the corrected check as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/coverageeligibility/on_check` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1101` does not appear anywhere in it. +- `x-hcx-status` reads `response.complete`. +- The decrypted payload holds a `CoverageEligibilityResponse` with `outcome` set to `complete`. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Set `CoverageEligibilityRequest.purpose` to `discovery`, `validation`, `benefits` or `auth-requirements`. +2. For `auth-requirements`, include the procedures you are asking about in `item`. `PAYR-1033` covers a check with no items. +3. When you do not have the policy code, send `discovery` first. Then send `validation` with the `policy_code` you receive. +4. Send the corrected check as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +5. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1102.md b/catalogue/nhcx/errors/payr-1102.md new file mode 100644 index 000000000..ad9620852 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1102.md @@ -0,0 +1,103 @@ +--- +id: nhcx.error.payr-1102 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1102: the id you searched with is not valid' +summary: >- + The payer could not find a beneficiary because the id your request searched with + is not valid. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Coverage Error Codes, Preauth Error Codes, Claim Error Codes. +verified: + status: unverified +related: + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + - nhcx.endpoint.participant-get-policies + callbacks: + - nhcx.callback.coverageeligibility-on-check + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.coverage-eligibility-response + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1104 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.abha + - nhcx.glossary.pmjay +--- + +# PAYR-1102: the id you searched with is not valid + +## In plain words + +The payer looks up the beneficiary from the id in your request. The id you sent is not one it recognises. + +## Before you start + +You sent a coverage eligibility check through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/coverageeligibility/check`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer evaluated the policy, the beneficiary and your hospital's configuration and answered on `/v1/coverageeligibility/on_check`. This code arrives in that answer. The same code can answer a preauthorisation on `/v1/preauth/on_submit` or a claim on `/v1/claim/on_submit`. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1102`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +The payer can also embed business error detail inside the sealed `CoverageEligibilityResponse`. Decrypt the payload with your private key and read it as well. + +## What happens + +The payer returns this message: + +> Invalid search parameter requested. Please try again with a valid id. + +> Invalid PMJAY ID requested. Please try again with a valid id. + +It is produced when: + +- The id the payer searches with is not valid. + +The first message answers a coverage eligibility check or a claim. The second answers a preauthorisation, where the id is the [PMJAY](../glossary/pmjay.md) id. + +## How you know it worked + +Send the corrected check as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/coverageeligibility/on_check` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1102` does not appear anywhere in it. +- `x-hcx-status` reads `response.complete`. +- The decrypted payload holds a `CoverageEligibilityResponse` with `outcome` set to `complete`. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Correct the beneficiary identifiers on the Patient resource. An eligibility check must carry the PMJAY member id, the [ABHA](../../shared/glossary/abha.md) number, or both. +2. Send the corrected check as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +3. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1103.md b/catalogue/nhcx/errors/payr-1103.md new file mode 100644 index 000000000..527a70b91 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1103.md @@ -0,0 +1,94 @@ +--- +id: nhcx.error.payr-1103 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1103: the care plan id is not valid' +summary: >- + The payer rejected your request because the care plan id in it is not valid. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Coverage Error Codes, Preauth Error Codes. +verified: + status: unverified +related: + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.coverageeligibility-on-check + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.coverage-eligibility-response + - nhcx.fhir.preauth-request + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1353 + - nhcx.error.payr-1211 + - nhcx.error.payr-1352 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id +--- + +# PAYR-1103: the care plan id is not valid + +## In plain words + +Your request carries a care plan id. The payer does not recognise the id you sent, so it stopped processing the request. + +## Before you start + +You sent a coverage eligibility check through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/coverageeligibility/check`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer evaluated the policy, the beneficiary and your hospital's configuration and answered on `/v1/coverageeligibility/on_check`. This code arrives in that answer. The same code can answer a preauthorisation, on `/v1/preauth/on_submit`. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1103`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +The payer can also embed business error detail inside the sealed `CoverageEligibilityResponse`. Decrypt the payload with your private key and read it as well. + +## What happens + +The payer returns this message: + +> Invalid careplan id received. Please try again with valid careplan id. + +It is produced when: + +- The care plan id in your request is not one the payer accepts. + +## How you know it worked + +Send the corrected check as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/coverageeligibility/on_check` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1103` does not appear anywhere in it. +- `x-hcx-status` reads `response.complete`. +- The decrypted payload holds a `CoverageEligibilityResponse` with `outcome` set to `complete`. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Correct the care plan id in your request. +2. Send the check again with a valid care plan id. +3. Send the corrected check as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +4. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1104.md b/catalogue/nhcx/errors/payr-1104.md new file mode 100644 index 000000000..009f75f75 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1104.md @@ -0,0 +1,94 @@ +--- +id: nhcx.error.payr-1104 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1104: more than one beneficiary record matches' +summary: >- + The payer stopped processing your request because the beneficiary details you + sent match more than one of its records. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Coverage Error Codes, Preauth Error Codes. +verified: + status: unverified +related: + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.coverageeligibility-on-check + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.coverage-eligibility-response + - nhcx.fhir.preauth-request + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1102 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.abha + - nhcx.glossary.pmjay +--- + +# PAYR-1104: more than one beneficiary record matches + +## In plain words + +The payer looks up the beneficiary from the identifiers in your request. They match more than one record in its system, so it cannot tell which person you mean. + +## Before you start + +You sent a coverage eligibility check through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/coverageeligibility/check`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer evaluated the policy, the beneficiary and your hospital's configuration and answered on `/v1/coverageeligibility/on_check`. This code arrives in that answer. The same code can answer a preauthorisation, on `/v1/preauth/on_submit`. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1104`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +The payer can also embed business error detail inside the sealed `CoverageEligibilityResponse`. Decrypt the payload with your private key and read it as well. + +## What happens + +The payer returns this message: + +> Multiple records found for the beneficiary. Hence request will not be processed further. + +It is produced when: + +- The beneficiary identifiers in your request match more than one beneficiary record at the payer. + +## How you know it worked + +Send the corrected check as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/coverageeligibility/on_check` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1104` does not appear anywhere in it. +- `x-hcx-status` reads `response.complete`. +- The decrypted payload holds a `CoverageEligibilityResponse` with `outcome` set to `complete`. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Send identifiers that point at one person. Put both the [PMJAY](../glossary/pmjay.md) member id and the [ABHA](../../shared/glossary/abha.md) number on the Patient resource when you have them. +2. If the request already carries both, contact the [support team](../sandbox/support-contacts.md). The payer must resolve the duplicate record. +3. Send the corrected check as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. diff --git a/catalogue/nhcx/errors/payr-1105.md b/catalogue/nhcx/errors/payr-1105.md new file mode 100644 index 000000000..517b795eb --- /dev/null +++ b/catalogue/nhcx/errors/payr-1105.md @@ -0,0 +1,96 @@ +--- +id: nhcx.error.payr-1105 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1105: the payer has no configuration for your hospital' +summary: >- + The payer stopped processing your check because it holds no configuration for + your hospital. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Coverage Error Codes. +verified: + status: unverified +related: + flows: + - nhcx.flow.coverage-eligibility-check + endpoints: + - nhcx.endpoint.coverageeligibility-check + callbacks: + - nhcx.callback.coverageeligibility-on-check + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.coverage-eligibility-response + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.participant-registry + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1239 + - nhcx.error.payr-1334 + - nhcx.error.payr-1405 + - nhcx.error.payr-1116 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.hfr +--- + +# PAYR-1105: the payer has no configuration for your hospital + +## In plain words + +The payer keeps a configuration for each hospital it deals with. It found none for yours, so it could not process your check. + +## Before you start + +You sent a coverage eligibility check through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/coverageeligibility/check`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer evaluated the policy, the beneficiary and your hospital's configuration and answered on `/v1/coverageeligibility/on_check`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1105`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +The payer can also embed business error detail inside the sealed `CoverageEligibilityResponse`. Decrypt the payload with your private key and read it as well. + +## What happens + +The payer returns this message: + +> Hospital configuration not found. Please contact support team. + +It is produced when: + +- The payer holds no configuration for the hospital that sent the request. + +`PAYR-1239` on a preauthorisation and `PAYR-1334` on a claim carry the same message. + +## How you know it worked + +Send the corrected check as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/coverageeligibility/on_check` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1105` does not appear anywhere in it. +- `x-hcx-status` reads `response.complete`. +- The decrypted payload holds a `CoverageEligibilityResponse` with `outcome` set to `complete`. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Check the provider Organization in your bundle. It must carry your [HFR](../../shared/glossary/hfr.md) id as an identifier with type code `NPI`. +2. The HFR id must match the registry id recorded in NHCX for your participant code. +3. Contact the [support team](../sandbox/support-contacts.md) to have the payer set up your hospital's configuration. +4. Once the payer confirms the setup, send the check as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. diff --git a/catalogue/nhcx/errors/payr-1106.md b/catalogue/nhcx/errors/payr-1106.md new file mode 100644 index 000000000..553a04c5b --- /dev/null +++ b/catalogue/nhcx/errors/payr-1106.md @@ -0,0 +1,98 @@ +--- +id: nhcx.error.payr-1106 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1106: the payer has no details for a requested procedure' +summary: >- + The payer found no details for a procedure you asked about in your eligibility + check. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Coverage Error Codes. +verified: + status: unverified +related: + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.coverageeligibility-check + callbacks: + - nhcx.callback.coverageeligibility-on-check + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.coverage-eligibility-response + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.insurance-plan + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1240 + - nhcx.error.payr-1344 + - nhcx.error.payr-1113 + - nhcx.error.payr-1118 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id +--- + +# PAYR-1106: the payer has no details for a requested procedure + +## In plain words + +An `auth-requirements` check lists the procedures you want to know about. The payer holds no details for one of them. + +## Before you start + +You sent a coverage eligibility check through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/coverageeligibility/check`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer evaluated the policy, the beneficiary and your hospital's configuration and answered on `/v1/coverageeligibility/on_check`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1106`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +The payer can also embed business error detail inside the sealed `CoverageEligibilityResponse`. Decrypt the payload with your private key and read it as well. + +## What happens + +The payer returns this message: + +> No details found for the requested procedures in the system. + +It is produced when: + +- An item in your check carries a procedure code the payer holds no details for. + +`PAYR-1240` on a preauthorisation and `PAYR-1344` on a claim carry the same message. + +## How you know it worked + +Send the corrected check as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/coverageeligibility/on_check` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1106` does not appear anywhere in it. +- `x-hcx-status` reads `response.complete`. +- The decrypted payload holds a `CoverageEligibilityResponse` with `outcome` set to `complete`. +- `x-hcx-correlation_id` matches the one you sent on the new request. +- For an `auth-requirements` check, the response carries an entry for each item you asked about, with `authorizationRequired` and `excluded`. + +## When it goes wrong + +1. Check each `item[*].productOrService.coding.code` in the request. +2. Use the procedure code from the payer's insurance plan: the code of the type of the benefit component of the specific cost of the plan. +3. Fetch the insurance plan for the policy when you do not have it. +4. Send the corrected check as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +5. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1107.md b/catalogue/nhcx/errors/payr-1107.md new file mode 100644 index 000000000..f2f75c0f2 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1107.md @@ -0,0 +1,94 @@ +--- +id: nhcx.error.payr-1107 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1107: the check carries no billable item' +summary: >- + The payer rejected your eligibility check because it carries no item it can bill + against. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Coverage Error Codes. +verified: + status: unverified +related: + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.coverageeligibility-check + callbacks: + - nhcx.callback.coverageeligibility-on-check + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.coverage-eligibility-response + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.coverage-eligibility-purposes + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1033 + - nhcx.error.payr-1118 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id +--- + +# PAYR-1107: the check carries no billable item + +## In plain words + +An `auth-requirements` check must list the procedures you want to know about. Yours carries no item the payer can bill against. + +## Before you start + +You sent a coverage eligibility check through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/coverageeligibility/check`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer evaluated the policy, the beneficiary and your hospital's configuration and answered on `/v1/coverageeligibility/on_check`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1107`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +The payer can also embed business error detail inside the sealed `CoverageEligibilityResponse`. Decrypt the payload with your private key and read it as well. + +## What happens + +The payer returns this message: + +> No billable item received. Please try again with valid item data. + +It is produced when: + +- The check carries no billable item in `item`. + +## How you know it worked + +Send the corrected check as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/coverageeligibility/on_check` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1107` does not appear anywhere in it. +- `x-hcx-status` reads `response.complete`. +- The decrypted payload holds a `CoverageEligibilityResponse` with `outcome` set to `complete`. +- `x-hcx-correlation_id` matches the one you sent on the new request. +- For an `auth-requirements` check, the response carries an entry for each item you asked about, with `authorizationRequired` and `excluded`. + +## When it goes wrong + +1. Add at least one `item` to the CoverageEligibilityRequest. +2. Give each item a speciality in `category.coding.code`, a package or procedure code in `productOrService.coding.code`, and a `quantity.value`. +3. Take the codes from the payer's insurance plan for the policy. +4. Send the corrected check as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +5. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1108.md b/catalogue/nhcx/errors/payr-1108.md new file mode 100644 index 000000000..29f6db63e --- /dev/null +++ b/catalogue/nhcx/errors/payr-1108.md @@ -0,0 +1,93 @@ +--- +id: nhcx.error.payr-1108 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1108: the payer has no details for the requested stratification' +summary: >- + The payer found no details for the stratification you asked about in your eligibility + check. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Coverage Error Codes. +verified: + status: unverified +related: + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.coverageeligibility-check + callbacks: + - nhcx.callback.coverageeligibility-on-check + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.coverage-eligibility-response + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.insurance-plan + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1106 + - nhcx.error.payr-1118 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id +--- + +# PAYR-1108: the payer has no details for the requested stratification + +## In plain words + +An item in an eligibility check can carry a stratification, such as a ward or care level. The payer holds no details for the one you sent. + +## Before you start + +You sent a coverage eligibility check through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/coverageeligibility/check`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer evaluated the policy, the beneficiary and your hospital's configuration and answered on `/v1/coverageeligibility/on_check`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1108`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +The payer can also embed business error detail inside the sealed `CoverageEligibilityResponse`. Decrypt the payload with your private key and read it as well. + +## What happens + +The payer returns this message: + +> No details found for the requested stratification in the system. + +It is produced when: + +- An item in your check carries a stratification code in `item[*].modifier.coding.code` that the payer holds no details for. + +## How you know it worked + +Send the corrected check as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/coverageeligibility/on_check` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1108` does not appear anywhere in it. +- `x-hcx-status` reads `response.complete`. +- The decrypted payload holds a `CoverageEligibilityResponse` with `outcome` set to `complete`. +- `x-hcx-correlation_id` matches the one you sent on the new request. +- For an `auth-requirements` check, the response carries an entry for each item you asked about, with `authorizationRequired` and `excluded`. + +## When it goes wrong + +1. Check each `item[*].modifier.coding.code` in the request. +2. Use a stratification code the payer holds for that package in its insurance plan. +3. Send the corrected check as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +4. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1109.md b/catalogue/nhcx/errors/payr-1109.md new file mode 100644 index 000000000..b84c1ab7d --- /dev/null +++ b/catalogue/nhcx/errors/payr-1109.md @@ -0,0 +1,95 @@ +--- +id: nhcx.error.payr-1109 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1109: the payer has no details for a requested investigation' +summary: >- + The payer found no details for an investigation you asked about in your eligibility + check. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Coverage Error Codes. +verified: + status: unverified +related: + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.coverageeligibility-check + callbacks: + - nhcx.callback.coverageeligibility-on-check + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.coverage-eligibility-response + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.insurance-plan + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1320 + - nhcx.error.payr-1118 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id +--- + +# PAYR-1109: the payer has no details for a requested investigation + +## In plain words + +An eligibility check can ask about investigations, such as laboratory tests. The payer holds no details for one you sent. + +## Before you start + +You sent a coverage eligibility check through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/coverageeligibility/check`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer evaluated the policy, the beneficiary and your hospital's configuration and answered on `/v1/coverageeligibility/on_check`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1109`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +The payer can also embed business error detail inside the sealed `CoverageEligibilityResponse`. Decrypt the payload with your private key and read it as well. + +## What happens + +The payer returns this message: + +> No details found for the requested investigations in the system. + +It is produced when: + +- An item in your check carries an investigation code the payer holds no details for. + +`PAYR-1320` on a claim carries a similar message. + +## How you know it worked + +Send the corrected check as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/coverageeligibility/on_check` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1109` does not appear anywhere in it. +- `x-hcx-status` reads `response.complete`. +- The decrypted payload holds a `CoverageEligibilityResponse` with `outcome` set to `complete`. +- `x-hcx-correlation_id` matches the one you sent on the new request. +- For an `auth-requirements` check, the response carries an entry for each item you asked about, with `authorizationRequired` and `excluded`. + +## When it goes wrong + +1. Check the investigation codes in `item[*].productOrService.coding.code`. +2. Use an investigation code the payer holds in its insurance plan for the policy. +3. Send the corrected check as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +4. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1110.md b/catalogue/nhcx/errors/payr-1110.md new file mode 100644 index 000000000..508bf104d --- /dev/null +++ b/catalogue/nhcx/errors/payr-1110.md @@ -0,0 +1,95 @@ +--- +id: nhcx.error.payr-1110 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1110: the payer has no details for a requested implant' +summary: >- + The payer found no details for an implant you asked about in your eligibility + check. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Coverage Error Codes. +verified: + status: unverified +related: + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.coverageeligibility-check + callbacks: + - nhcx.callback.coverageeligibility-on-check + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.coverage-eligibility-response + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.insurance-plan + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1355 + - nhcx.error.payr-1118 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id +--- + +# PAYR-1110: the payer has no details for a requested implant + +## In plain words + +An eligibility check can ask about implants used in a procedure. The payer holds no details for one you sent. + +## Before you start + +You sent a coverage eligibility check through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/coverageeligibility/check`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer evaluated the policy, the beneficiary and your hospital's configuration and answered on `/v1/coverageeligibility/on_check`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1110`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +The payer can also embed business error detail inside the sealed `CoverageEligibilityResponse`. Decrypt the payload with your private key and read it as well. + +## What happens + +The payer returns this message: + +> No details found for the requested implants in the system. + +It is produced when: + +- An item in your check carries an implant code the payer holds no details for. + +`PAYR-1355` on a claim carries a similar message. + +## How you know it worked + +Send the corrected check as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/coverageeligibility/on_check` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1110` does not appear anywhere in it. +- `x-hcx-status` reads `response.complete`. +- The decrypted payload holds a `CoverageEligibilityResponse` with `outcome` set to `complete`. +- `x-hcx-correlation_id` matches the one you sent on the new request. +- For an `auth-requirements` check, the response carries an entry for each item you asked about, with `authorizationRequired` and `excluded`. + +## When it goes wrong + +1. Check the implant codes in `item[*].productOrService.coding.code`. +2. Use an implant code the payer holds in its insurance plan for the policy. +3. Send the corrected check as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +4. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1111.md b/catalogue/nhcx/errors/payr-1111.md new file mode 100644 index 000000000..793b43524 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1111.md @@ -0,0 +1,92 @@ +--- +id: nhcx.error.payr-1111 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1111: a payer rule rejected the request' +summary: >- + A business rule at the payer rejected your eligibility check, and the message + does not name the rule. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Coverage Error Codes. +verified: + status: unverified +related: + flows: + - nhcx.flow.coverage-eligibility-check + endpoints: + - nhcx.endpoint.coverageeligibility-check + callbacks: + - nhcx.callback.coverageeligibility-on-check + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.coverage-eligibility-response + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1245 + - nhcx.error.payr-1354 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id +--- + +# PAYR-1111: a payer rule rejected the request + +## In plain words + +The payer applies business rules to every check. One of them rejected yours. The message does not say which rule failed. + +## Before you start + +You sent a coverage eligibility check through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/coverageeligibility/check`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer evaluated the policy, the beneficiary and your hospital's configuration and answered on `/v1/coverageeligibility/on_check`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1111`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +The payer can also embed business error detail inside the sealed `CoverageEligibilityResponse`. Decrypt the payload with your private key and read it as well. + +## What happens + +The payer returns this message: + +> Rule failure. + +It is produced when: + +- A business rule in the payer's system rejected the check. +- The message names no rule and no element. + +`PAYR-1245` on a preauthorisation and `PAYR-1354` on a claim carry the same message. + +## How you know it worked + +Send the corrected check as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/coverageeligibility/on_check` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1111` does not appear anywhere in it. +- `x-hcx-status` reads `response.complete`. +- The decrypted payload holds a `CoverageEligibilityResponse` with `outcome` set to `complete`. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Contact the [support team](../sandbox/support-contacts.md) with the correlation id of the failed check. The payer can name the rule that failed. +2. Correct the request once you know the rule. +3. Send the corrected check as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. diff --git a/catalogue/nhcx/errors/payr-1112.md b/catalogue/nhcx/errors/payr-1112.md new file mode 100644 index 000000000..bd4787d81 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1112.md @@ -0,0 +1,92 @@ +--- +id: nhcx.error.payr-1112 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1112: the payer id is not valid' +summary: >- + The payer rejected your eligibility check because the payer id in it is not valid. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Coverage Error Codes. +verified: + status: unverified +related: + flows: + - nhcx.flow.coverage-eligibility-check + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.participant-get-policies + callbacks: + - nhcx.callback.coverageeligibility-on-check + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.coverage-eligibility-response + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.participant-code + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1119 + - nhcx.error.payr-1246 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - nhcx.glossary.participant-code +--- + +# PAYR-1112: the payer id is not valid + +## In plain words + +Your check names the payer it is for. The payer id you sent is not valid, so the payer stopped processing the check. + +## Before you start + +You sent a coverage eligibility check through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/coverageeligibility/check`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer evaluated the policy, the beneficiary and your hospital's configuration and answered on `/v1/coverageeligibility/on_check`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1112`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +The payer can also embed business error detail inside the sealed `CoverageEligibilityResponse`. Decrypt the payload with your private key and read it as well. + +## What happens + +The payer returns this message: + +> Invalid payer id received. Please try again ith valid payer details + +It is produced when: + +- The payer id in your check is not one the payer accepts. + +## How you know it worked + +Send the corrected check as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/coverageeligibility/on_check` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1112` does not appear anywhere in it. +- `x-hcx-status` reads `response.complete`. +- The decrypted payload holds a `CoverageEligibilityResponse` with `outcome` set to `complete`. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Check `x-hcx-recipient_code` in the protected header and the insurer Organization in the bundle. +2. Use the `processingID` from the get policies response as the recipient code, not the `PayerID`. +3. Send the corrected check as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +4. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1113.md b/catalogue/nhcx/errors/payr-1113.md new file mode 100644 index 000000000..4160827c8 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1113.md @@ -0,0 +1,94 @@ +--- +id: nhcx.error.payr-1113 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1113: an item code is not valid' +summary: >- + The payer rejected your eligibility check because an item code in it is not valid. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Coverage Error Codes. +verified: + status: unverified +related: + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.coverageeligibility-check + callbacks: + - nhcx.callback.coverageeligibility-on-check + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.coverage-eligibility-response + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1248 + - nhcx.error.payr-1360 + - nhcx.error.payr-1106 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id +--- + +# PAYR-1113: an item code is not valid + +## In plain words + +Each item in an eligibility check carries a package or procedure code. The payer did not accept the code named in the message. + +## Before you start + +You sent a coverage eligibility check through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/coverageeligibility/check`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer evaluated the policy, the beneficiary and your hospital's configuration and answered on `/v1/coverageeligibility/on_check`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1113`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +The payer can also embed business error detail inside the sealed `CoverageEligibilityResponse`. Decrypt the payload with your private key and read it as well. + +## What happens + +The payer returns this message: + +> Invalid item code received as `%s`. Please try again with valid data + +It is produced when: + +- An item carries the code named in the message, and the payer does not accept it. + +`%s` is the item code you sent. + +## How you know it worked + +Send the corrected check as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/coverageeligibility/on_check` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1113` does not appear anywhere in it. +- `x-hcx-status` reads `response.complete`. +- The decrypted payload holds a `CoverageEligibilityResponse` with `outcome` set to `complete`. +- `x-hcx-correlation_id` matches the one you sent on the new request. +- For an `auth-requirements` check, the response carries an entry for each item you asked about, with `authorizationRequired` and `excluded`. + +## When it goes wrong + +1. Find the item whose `productOrService.coding.code` matches the message. +2. Replace it with a package or procedure code from the payer's insurance plan for the policy. +3. Send the corrected check as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +4. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1114.md b/catalogue/nhcx/errors/payr-1114.md new file mode 100644 index 000000000..dd0a79d60 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1114.md @@ -0,0 +1,96 @@ +--- +id: nhcx.error.payr-1114 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1114: an item''s speciality code is not valid' +summary: >- + The payer rejected your eligibility check because the speciality code on one item + is not valid. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Coverage Error Codes. +verified: + status: unverified +related: + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.coverageeligibility-check + callbacks: + - nhcx.callback.coverageeligibility-on-check + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.coverage-eligibility-response + - nhcx.fhir.insurance-plan-bundle + - nhcx.fhir.pmjay-insurance-plan + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1202 + - nhcx.error.payr-1351 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id +--- + +# PAYR-1114: an item's speciality code is not valid + +## In plain words + +Each item in an eligibility check carries a speciality code, such as the code for general medicine. The payer did not accept the one on the item named in the message. + +## Before you start + +You sent a coverage eligibility check through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/coverageeligibility/check`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer evaluated the policy, the beneficiary and your hospital's configuration and answered on `/v1/coverageeligibility/on_check`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1114`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +The payer can also embed business error detail inside the sealed `CoverageEligibilityResponse`. Decrypt the payload with your private key and read it as well. + +## What happens + +The payer returns this message: + +> Invalid speciality code received as `%s` for item `%s`. Please try again with valid data. Speciality code is available as the code of the category for specific cost of plan in isurance plan + +It is produced when: + +- The item named in the message carries a speciality code the payer does not accept. + +The first `%s` is the speciality code you sent. The second is the item. + +## How you know it worked + +Send the corrected check as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/coverageeligibility/on_check` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1114` does not appear anywhere in it. +- `x-hcx-status` reads `response.complete`. +- The decrypted payload holds a `CoverageEligibilityResponse` with `outcome` set to `complete`. +- `x-hcx-correlation_id` matches the one you sent on the new request. +- For an `auth-requirements` check, the response carries an entry for each item you asked about, with `authorizationRequired` and `excluded`. + +## When it goes wrong + +1. Find the item named in the message and its `category.coding.code`. +2. Replace it with the speciality code from the payer's insurance plan: the code of the category of the specific cost of the plan. +3. Send the corrected check as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +4. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1115.md b/catalogue/nhcx/errors/payr-1115.md new file mode 100644 index 000000000..c598093ed --- /dev/null +++ b/catalogue/nhcx/errors/payr-1115.md @@ -0,0 +1,93 @@ +--- +id: nhcx.error.payr-1115 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1115: an item''s quantity is not valid' +summary: >- + The payer rejected your eligibility check because the quantity on one item is + not valid. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Coverage Error Codes. +verified: + status: unverified +related: + flows: + - nhcx.flow.coverage-eligibility-check + endpoints: + - nhcx.endpoint.coverageeligibility-check + callbacks: + - nhcx.callback.coverageeligibility-on-check + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.coverage-eligibility-response + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1208 + - nhcx.error.payr-1349 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id +--- + +# PAYR-1115: an item's quantity is not valid + +## In plain words + +Each item in an eligibility check carries a quantity. The payer did not accept the quantity on the item named in the message. + +## Before you start + +You sent a coverage eligibility check through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/coverageeligibility/check`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer evaluated the policy, the beneficiary and your hospital's configuration and answered on `/v1/coverageeligibility/on_check`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1115`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +The payer can also embed business error detail inside the sealed `CoverageEligibilityResponse`. Decrypt the payload with your private key and read it as well. + +## What happens + +The payer returns this message: + +> Invalid procedure quantity received as `%s` for item `%s`. Please try again with valid data. Item quantity should be greater than 1 + +It is produced when: + +- The item named in the message carries a quantity the payer does not accept. + +The first `%s` is the quantity you sent. The second is the item. + +## How you know it worked + +Send the corrected check as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/coverageeligibility/on_check` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1115` does not appear anywhere in it. +- `x-hcx-status` reads `response.complete`. +- The decrypted payload holds a `CoverageEligibilityResponse` with `outcome` set to `complete`. +- `x-hcx-correlation_id` matches the one you sent on the new request. +- For an `auth-requirements` check, the response carries an entry for each item you asked about, with `authorizationRequired` and `excluded`. + +## When it goes wrong + +1. Find the item named in the message. +2. Correct its `quantity.value` to the number of units you are asking about. +3. Send the corrected check as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +4. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1116.md b/catalogue/nhcx/errors/payr-1116.md new file mode 100644 index 000000000..939fab42e --- /dev/null +++ b/catalogue/nhcx/errors/payr-1116.md @@ -0,0 +1,92 @@ +--- +id: nhcx.error.payr-1116 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1116: your hospital is not authorised under the policy' +summary: >- + The payer stopped processing your check because your hospital is not authorised + to raise cases under the policy. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Coverage Error Codes. +verified: + status: unverified +related: + flows: + - nhcx.flow.coverage-eligibility-check + endpoints: + - nhcx.endpoint.coverageeligibility-check + callbacks: + - nhcx.callback.coverageeligibility-on-check + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.coverage-eligibility-response + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1004 + - nhcx.error.payr-1401 + - nhcx.error.payr-1105 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id +--- + +# PAYR-1116: your hospital is not authorised under the policy + +## In plain words + +A hospital can raise cases only under the policies it is authorised for. Yours is not authorised under the policy in the message. + +## Before you start + +You sent a coverage eligibility check through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/coverageeligibility/check`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer evaluated the policy, the beneficiary and your hospital's configuration and answered on `/v1/coverageeligibility/on_check`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1116`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +The payer can also embed business error detail inside the sealed `CoverageEligibilityResponse`. Decrypt the payload with your private key and read it as well. + +## What happens + +The payer returns this message: + +> Hospital is not authorized to raise any case under policy `%s`. Hence request will not be processed further. Please connect with the support team to get the required authorization + +It is produced when: + +- Your hospital has no authorisation from the payer to raise cases under the policy named in the message. + +`%s` is the policy code. + +## How you know it worked + +Send the corrected check as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/coverageeligibility/on_check` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1116` does not appear anywhere in it. +- `x-hcx-status` reads `response.complete`. +- The decrypted payload holds a `CoverageEligibilityResponse` with `outcome` set to `complete`. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Contact the [support team](../sandbox/support-contacts.md) to get your hospital authorised under the policy named in the message. +2. Raise no cases under that policy until the authorisation is in place. +3. Once the authorisation is in place, send the check as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. diff --git a/catalogue/nhcx/errors/payr-1117.md b/catalogue/nhcx/errors/payr-1117.md new file mode 100644 index 000000000..adf1c3d0d --- /dev/null +++ b/catalogue/nhcx/errors/payr-1117.md @@ -0,0 +1,97 @@ +--- +id: nhcx.error.payr-1117 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1117: the payer has no details for the policy' +summary: >- + The payer stopped processing your check because it holds no details for the policy + you named. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Coverage Error Codes. +verified: + status: unverified +related: + flows: + - nhcx.flow.coverage-eligibility-check + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.participant-get-policies + callbacks: + - nhcx.callback.coverageeligibility-on-check + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.coverage-eligibility-response + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.coverage-eligibility-purposes + - nhcx.concept.policy-linking + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1006 + - nhcx.error.payr-1402 + - nhcx.error.payr-1121 + - nhcx.error.payr-1122 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id +--- + +# PAYR-1117: the payer has no details for the policy + +## In plain words + +Your check names the beneficiary's policy. The payer holds no details for the policy named in the message. + +## Before you start + +You sent a coverage eligibility check through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/coverageeligibility/check`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer evaluated the policy, the beneficiary and your hospital's configuration and answered on `/v1/coverageeligibility/on_check`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1117`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +The payer can also embed business error detail inside the sealed `CoverageEligibilityResponse`. Decrypt the payload with your private key and read it as well. + +## What happens + +The payer returns this message: + +> No policy details found for `%s`. Hence request will not be processed further + +It is produced when: + +- The payer holds no policy details for the policy code in your request. + +`%s` is the policy code you sent. + +## How you know it worked + +Send the corrected check as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/coverageeligibility/on_check` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1117` does not appear anywhere in it. +- `x-hcx-status` reads `response.complete`. +- The decrypted payload holds a `CoverageEligibilityResponse` with `outcome` set to `complete`. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Check the policy code in the Coverage resource's `identifier.value`. +2. When you do not have the policy code, send a check with purpose `discovery` to fetch the active `policy_code`. Then send `validation` with it. +3. Send the corrected check as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +4. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1118.md b/catalogue/nhcx/errors/payr-1118.md new file mode 100644 index 000000000..d9d18a825 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1118.md @@ -0,0 +1,95 @@ +--- +id: nhcx.error.payr-1118 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1118: the payer has no details for the requested items' +summary: >- + The payer stopped processing your eligibility check because it holds no details + for the items you asked about. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Coverage Error Codes. +verified: + status: unverified +related: + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.coverageeligibility-check + callbacks: + - nhcx.callback.coverageeligibility-on-check + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.coverage-eligibility-response + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1106 + - nhcx.error.payr-1108 + - nhcx.error.payr-1109 + - nhcx.error.payr-1110 + - nhcx.error.payr-1113 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id +--- + +# PAYR-1118: the payer has no details for the requested items + +## In plain words + +An `auth-requirements` check lists the items you want to know about. The payer holds no details for them. + +## Before you start + +You sent a coverage eligibility check through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/coverageeligibility/check`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer evaluated the policy, the beneficiary and your hospital's configuration and answered on `/v1/coverageeligibility/on_check`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1118`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +The payer can also embed business error detail inside the sealed `CoverageEligibilityResponse`. Decrypt the payload with your private key and read it as well. + +## What happens + +The payer returns this message: + +> No details found for requested items. Hence request will not be processed further + +It is produced when: + +- The items in your check carry codes the payer holds no details for. + +## How you know it worked + +Send the corrected check as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/coverageeligibility/on_check` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1118` does not appear anywhere in it. +- `x-hcx-status` reads `response.complete`. +- The decrypted payload holds a `CoverageEligibilityResponse` with `outcome` set to `complete`. +- `x-hcx-correlation_id` matches the one you sent on the new request. +- For an `auth-requirements` check, the response carries an entry for each item you asked about, with `authorizationRequired` and `excluded`. + +## When it goes wrong + +1. Check every item's `productOrService.coding.code`, `category.coding.code` and `modifier.coding.code`. +2. Take each code from the payer's insurance plan for the policy. +3. Send the corrected check as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +4. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1119.md b/catalogue/nhcx/errors/payr-1119.md new file mode 100644 index 000000000..bb904bd65 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1119.md @@ -0,0 +1,96 @@ +--- +id: nhcx.error.payr-1119 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1119: the payer received no details for the payer id from the exchange' +summary: >- + The payer stopped processing your check because the exchange returned no details + for the payer id you sent. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Coverage Error Codes. +verified: + status: unverified +related: + flows: + - nhcx.flow.coverage-eligibility-check + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.participant-search + - nhcx.endpoint.participant-get-policies + callbacks: + - nhcx.callback.coverageeligibility-on-check + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.coverage-eligibility-response + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.participant-registry + - nhcx.concept.participant-code + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1112 + - nhcx.error.payr-1247 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id +--- + +# PAYR-1119: the payer received no details for the payer id from the exchange + +## In plain words + +The payer looks up the payer id in your request with the exchange. The exchange returned no details for the id in the message. + +## Before you start + +You sent a coverage eligibility check through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/coverageeligibility/check`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer evaluated the policy, the beneficiary and your hospital's configuration and answered on `/v1/coverageeligibility/on_check`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1119`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +The payer can also embed business error detail inside the sealed `CoverageEligibilityResponse`. Decrypt the payload with your private key and read it as well. + +## What happens + +The payer returns this message: + +> No payer details received for payer id `%s` from HCX. Please try again with valid payer details. + +It is produced when: + +- The payer id in your request is not one the exchange holds participant details for. + +`%s` is the payer id you sent. + +## How you know it worked + +Send the corrected check as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/coverageeligibility/on_check` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1119` does not appear anywhere in it. +- `x-hcx-status` reads `response.complete`. +- The decrypted payload holds a `CoverageEligibilityResponse` with `outcome` set to `complete`. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Look up the payer in the participant registry, and use the participant code it returns. +2. Use the `processingID` from the get policies response as the recipient code, not the `PayerID`. +3. Send the corrected check as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +4. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1120.md b/catalogue/nhcx/errors/payr-1120.md new file mode 100644 index 000000000..ad3825add --- /dev/null +++ b/catalogue/nhcx/errors/payr-1120.md @@ -0,0 +1,90 @@ +--- +id: nhcx.error.payr-1120 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1120: the reference id has been used before' +summary: >- + The payer rejected your eligibility check because its reference id repeats one + it has already seen. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Coverage Error Codes. +verified: + status: unverified +related: + flows: + - nhcx.flow.coverage-eligibility-check + endpoints: + - nhcx.endpoint.coverageeligibility-check + callbacks: + - nhcx.callback.coverageeligibility-on-check + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.coverage-eligibility-response + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id +--- + +# PAYR-1120: the reference id has been used before + +## In plain words + +Each request carries a reference id. The payer has already received one with the id in the message. + +## Before you start + +You sent a coverage eligibility check through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/coverageeligibility/check`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer evaluated the policy, the beneficiary and your hospital's configuration and answered on `/v1/coverageeligibility/on_check`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1120`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +The payer can also embed business error detail inside the sealed `CoverageEligibilityResponse`. Decrypt the payload with your private key and read it as well. + +## What happens + +The payer returns this message: + +> Duplicate reference id found as `%s`. Please try again with valid reference details. + +It is produced when: + +- The reference id in your request matches one the payer has already received. + +`%s` is the reference id you sent. + +## How you know it worked + +Send the corrected check as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/coverageeligibility/on_check` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1120` does not appear anywhere in it. +- `x-hcx-status` reads `response.complete`. +- The decrypted payload holds a `CoverageEligibilityResponse` with `outcome` set to `complete`. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Give every request its own reference id. +2. Send the check again with a reference id you have not used before. +3. Send the corrected check as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +4. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1121.md b/catalogue/nhcx/errors/payr-1121.md new file mode 100644 index 000000000..6265bd512 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1121.md @@ -0,0 +1,97 @@ +--- +id: nhcx.error.payr-1121 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1121: the policy is not found for this beneficiary' +summary: >- + The payer stopped processing your check because it holds no record of the named + policy for this beneficiary. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Coverage Error Codes. +verified: + status: unverified +related: + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.policy-link-and-delink + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.participant-get-policies + callbacks: + - nhcx.callback.coverageeligibility-on-check + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.coverage-eligibility-response + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.policy-linking + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1117 + - nhcx.error.payr-1122 + - nhcx.error.payr-1123 + - nhcx.error.payr-1005 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id +--- + +# PAYR-1121: the policy is not found for this beneficiary + +## In plain words + +The payer checks that the beneficiary holds the policy in your request. It holds no record of that policy for that beneficiary. + +## Before you start + +You sent a coverage eligibility check through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/coverageeligibility/check`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer evaluated the policy, the beneficiary and your hospital's configuration and answered on `/v1/coverageeligibility/on_check`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1121`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +The payer can also embed business error detail inside the sealed `CoverageEligibilityResponse`. Decrypt the payload with your private key and read it as well. + +## What happens + +The payer returns this message: + +> No policy details found for `%s` for beneficiary `%s`. Hence request will not be processed further. + +It is produced when: + +- The payer holds no details of the policy in the message for the beneficiary in the message. + +The first `%s` is the policy code. The second is the beneficiary id. + +## How you know it worked + +Send the corrected check as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/coverageeligibility/on_check` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1121` does not appear anywhere in it. +- `x-hcx-status` reads `response.complete`. +- The decrypted payload holds a `CoverageEligibilityResponse` with `outcome` set to `complete`. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Fetch the beneficiary's linked policies with the get policies call, and use a policy code from the result. +2. When no policy is linked, send a check with purpose `discovery` to fetch the active `policy_code`. +3. Send the corrected check as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +4. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1122.md b/catalogue/nhcx/errors/payr-1122.md new file mode 100644 index 000000000..78bbddc12 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1122.md @@ -0,0 +1,96 @@ +--- +id: nhcx.error.payr-1122 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1122: the beneficiary has no policy with the payer' +summary: >- + The payer stopped processing your check because it holds no policy for the beneficiary. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Coverage Error Codes. +verified: + status: unverified +related: + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.policy-link-and-delink + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.participant-get-policies + callbacks: + - nhcx.callback.coverageeligibility-on-check + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.coverage-eligibility-response + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1121 + - nhcx.error.payr-1123 + - nhcx.error.payr-1102 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id + - shared.glossary.abha + - nhcx.glossary.pmjay +--- + +# PAYR-1122: the beneficiary has no policy with the payer + +## In plain words + +The payer looks for the policies held by the beneficiary in your request. It found none. + +## Before you start + +You sent a coverage eligibility check through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/coverageeligibility/check`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer evaluated the policy, the beneficiary and your hospital's configuration and answered on `/v1/coverageeligibility/on_check`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1122`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +The payer can also embed business error detail inside the sealed `CoverageEligibilityResponse`. Decrypt the payload with your private key and read it as well. + +## What happens + +The payer returns this message: + +> No policy details found for beneficiary `%s`. Hence request will not be processed further. + +It is produced when: + +- The payer holds no policy details for the beneficiary in the message. + +`%s` is the beneficiary id. + +## How you know it worked + +Send the corrected check as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/coverageeligibility/on_check` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1122` does not appear anywhere in it. +- `x-hcx-status` reads `response.complete`. +- The decrypted payload holds a `CoverageEligibilityResponse` with `outcome` set to `complete`. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Check the beneficiary identifiers on the Patient resource: the [PMJAY](../glossary/pmjay.md) member id, the [ABHA](../../shared/glossary/abha.md) number, or both. +2. Confirm the beneficiary holds a policy with this payer. Fetch linked policies with the get policies call. +3. Send the corrected check as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +4. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1123.md b/catalogue/nhcx/errors/payr-1123.md new file mode 100644 index 000000000..4c3640803 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1123.md @@ -0,0 +1,96 @@ +--- +id: nhcx.error.payr-1123 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1123: the beneficiary is not covered by this payer' +summary: >- + The payer stopped processing your check because the beneficiary is not a covered + member of any of its policies. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Coverage Error Codes. +verified: + status: unverified +related: + flows: + - nhcx.flow.coverage-eligibility-check + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.participant-get-policies + callbacks: + - nhcx.callback.coverageeligibility-on-check + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.coverage-eligibility-response + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.policy-linking + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1005 + - nhcx.error.payr-1121 + - nhcx.error.payr-1122 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nhcx + - nhcx.glossary.jwe + - nhcx.glossary.correlation-id +--- + +# PAYR-1123: the beneficiary is not covered by this payer + +## In plain words + +You sent the check to a payer that does not cover the beneficiary. The beneficiary must be enrolled in one of its policies first. + +## Before you start + +You sent a coverage eligibility check through [NHCX](../../shared/glossary/nhcx.md) with `POST /v1/coverageeligibility/check`. NHCX accepted it with a 202 and forwarded it to the payer. + +The payer evaluated the policy, the beneficiary and your hospital's configuration and answered on `/v1/coverageeligibility/on_check`. This code arrives in that answer. + +Read `x-hcx-error_details` from the answer's protocol headers. In a sealed answer they sit in the [JWE](../glossary/jwe.md) protected header. In a `ProtocolResponse` object they sit at the top level. `x-hcx-error_details.code` holds `PAYR-1123`, and `x-hcx-error_details.message` holds the text shown in the next section. + +`x-hcx-status` on the answer reads `response.error` or `response.fail`. Treat either value as a rejected request. + +The payer can also embed business error detail inside the sealed `CoverageEligibilityResponse`. Decrypt the payload with your private key and read it as well. + +## What happens + +The payer returns this message: + +> Beneficiary is not a covered member for requested payer. Please enroll beneficiary for applicable policy of requested payer and try again. + +It is produced when: + +- The beneficiary is not a covered member of any applicable policy of the payer you sent the check to. + +`PAYR-1005` means the same for a single policy. + +## How you know it worked + +Send the corrected check as a new request. NHCX answers with a 202. + +You know the fix worked when the payer's answer arrives on `/v1/coverageeligibility/on_check` with these properties: + +- The answer carries no `x-hcx-error_details`, and `PAYR-1123` does not appear anywhere in it. +- `x-hcx-status` reads `response.complete`. +- The decrypted payload holds a `CoverageEligibilityResponse` with `outcome` set to `complete`. +- `x-hcx-correlation_id` matches the one you sent on the new request. + +## When it goes wrong + +1. Confirm which payer covers the beneficiary. Fetch the beneficiary's policies with the get policies call. +2. Send the check to the `processingID` from that response as the recipient code, not the `PayerID`. +3. If no policy of this payer covers the beneficiary, the beneficiary must be enrolled for an applicable policy first. +4. Send the corrected check as a new request with a new `x-hcx-correlation_id`. After a failure the old correlation id is inactive, and reusing it returns `NHCX-1006`. +5. If the same code comes back after these steps, contact the [NHCX support team](../sandbox/support-contacts.md). Give them the correlation id of the failed request. diff --git a/catalogue/nhcx/errors/payr-1201.md b/catalogue/nhcx/errors/payr-1201.md new file mode 100644 index 000000000..710442d26 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1201.md @@ -0,0 +1,84 @@ +--- +id: nhcx.error.payr-1201 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1201: claimed amount is zero or above the wallet balance' +summary: >- + The payer refused the request because the amount claimed was zero, or larger than + the balance left in the beneficiary's scheme wallet. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes, Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1233 + - nhcx.error.payr-1235 +--- + +# PAYR-1201: claimed amount is zero or above the wallet balance + +## In plain words + +The amount you asked the [payer](../glossary/payer.md) to approve is not allowed. It is zero or less, or more than the balance left in the beneficiary's wallet. A [PMJAY](../glossary/pmjay.md) family shares one wallet across every member's treatment. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1201` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid claimed amount received for case number %s. Please try again with a valid claim amount. Claimed amount should be greater than INR 0 and less than equals to balance wallet amount of the beneficiary. +``` + +The same code and message can arrive on `/v1/claim/on_submit` when you submit a claim. See [Submit a claim](../flows/claim-submit.md). + +`PAYR-1201` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +The payer refuses the request when either condition holds: + +- The claimed amount for the case is not greater than INR 0. +- The claimed amount is greater than the beneficiary's balance wallet amount. + +The claimed amount is the total you request, sent in `Claim.total`. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1201`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Check the balance before you submit. Run a [coverage eligibility check](../flows/coverage-eligibility-check.md) with purpose `validation`. It returns the used amount, the available balance and the wallet liability. +2. Set `Claim.total` above `0` and no higher than the available balance. +3. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1202.md b/catalogue/nhcx/errors/payr-1202.md new file mode 100644 index 000000000..185d01dd0 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1202.md @@ -0,0 +1,82 @@ +--- +id: nhcx.error.payr-1202 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1202: speciality code is not in the insurance plan' +summary: >- + The payer refused the request because an item names a speciality code that the + hospital's insurance plan does not carry. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + - nhcx.concept.insurance-plan + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.pmjay-insurance-plan + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1203 + - nhcx.error.payr-1204 +--- + +# PAYR-1202: speciality code is not in the insurance plan + +## In plain words + +An item in your request names a speciality the payer does not recognise for your hospital. Speciality codes must come from the hospital's [insurance plan](../concepts/insurance-plan.md). + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1202` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid speciality code received as %s for item %s for case number %s. Please try again with valid data. Speciality code is available as the code of the category for specific cost of plan in isurance plan. +``` + +`PAYR-1202` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The speciality code on the item named in the message matches no speciality in the insurance plan. +- On the request, the speciality is the item's category, `Claim.item.category`. For example, `MP` is General medicine. +- In the insurance plan, each speciality is the `category` of a `specificCost` entry under `plan`. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1202`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Fetch the current insurance plan for your hospital and the beneficiary's policy. See [Fetch the insurance plan](../flows/insurance-plan-request.md). +2. Find the package under `plan.specificCost`. Copy that entry's `category` code into `Claim.item.category` for the named item. +3. Resend the request. + +Refresh your stored insurance plan at least weekly, and whenever the payer renews or amends the policy. Outdated tariff versions cause automatic rejection. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1203.md b/catalogue/nhcx/errors/payr-1203.md new file mode 100644 index 000000000..d06af28f4 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1203.md @@ -0,0 +1,86 @@ +--- +id: nhcx.error.payr-1203 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1203: speciality description does not match the insurance plan' +summary: >- + The payer refused the request because a speciality description differs from the + one in the hospital's insurance plan. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes, Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + - nhcx.concept.insurance-plan + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.insurance-plan-request + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.pmjay-insurance-plan + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1202 + - nhcx.error.payr-1205 +--- + +# PAYR-1203: speciality description does not match the insurance plan + +## In plain words + +The speciality description you sent for a procedure does not match the payer's text for that speciality. Descriptions must come from the hospital's [insurance plan](../concepts/insurance-plan.md), word for word. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1203` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid speciality description received as %s for procedure %s for case number %s. Please try again with valid data. Speciality description is available as the display of the category for specific cost of plan in isurance plan. +``` + +The same code and message can arrive on `/v1/claim/on_submit` when you submit a claim. See [Submit a claim](../flows/claim-submit.md). + +`PAYR-1203` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The speciality description in the message, sent for the procedure named in the message, differs from the payer's description. +- In the insurance plan, the description is the `display` of the `category` of a `specificCost` entry under `plan`. +- On the request, the speciality sits in `Claim.item.category`. Its `display` carries the description. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1203`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Fetch the current insurance plan for your hospital and the beneficiary's policy. See [Fetch the insurance plan](../flows/insurance-plan-request.md). +2. Copy the `display` of the matching `category` exactly as the plan carries it. +3. Take the code and the description from the same plan entry. +4. Resend the request. + +Refresh your stored insurance plan at least weekly, and whenever the payer renews or amends the policy. Outdated tariff versions cause automatic rejection. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1204.md b/catalogue/nhcx/errors/payr-1204.md new file mode 100644 index 000000000..398f6d802 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1204.md @@ -0,0 +1,87 @@ +--- +id: nhcx.error.payr-1204 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1204: procedure code is not in the insurance plan' +summary: >- + The payer refused the request because a procedure code is not one the hospital's + insurance plan offers. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes, Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + - nhcx.concept.insurance-plan + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.insurance-plan-request + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.pmjay-insurance-plan + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1205 + - nhcx.error.payr-1240 + - nhcx.error.payr-1248 +--- + +# PAYR-1204: procedure code is not in the insurance plan + +## In plain words + +You requested a procedure code that the payer does not offer at your hospital. Procedure codes must come from the hospital's [insurance plan](../concepts/insurance-plan.md). + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1204` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid procedure code received as %s for case number %s. Please try again with valid data. Procedure code is available as the code of the type for benefit component, of specific cost, of plan in isurance plan. +``` + +The same code and message can arrive on `/v1/claim/on_submit` when you submit a claim. See [Submit a claim](../flows/claim-submit.md). + +`PAYR-1204` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The procedure code in the message matches no benefit in the insurance plan. +- In the insurance plan, the procedure code is the code of the `type` of a `benefit` inside a `specificCost` entry under `plan`. +- On the request, the package code sits in `Claim.item.productOrService`, for example `MG0111A`. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1204`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Fetch the current insurance plan for your hospital and the beneficiary's policy. See [Fetch the insurance plan](../flows/insurance-plan-request.md). +2. Pick the package from the plan. Copy the benefit `type` code into `Claim.item.productOrService`. +3. Do not type package codes by hand. +4. Resend the request. + +Refresh your stored insurance plan at least weekly, and whenever the payer renews or amends the policy. Outdated tariff versions cause automatic rejection. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1205.md b/catalogue/nhcx/errors/payr-1205.md new file mode 100644 index 000000000..dd436f7a5 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1205.md @@ -0,0 +1,83 @@ +--- +id: nhcx.error.payr-1205 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1205: procedure description does not match the insurance plan' +summary: >- + The payer refused the request because a procedure description differs from the + one in the hospital's insurance plan. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + - nhcx.concept.insurance-plan + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.pmjay-insurance-plan + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1204 + - nhcx.error.payr-1203 +--- + +# PAYR-1205: procedure description does not match the insurance plan + +## In plain words + +The description you sent for a procedure does not match the payer's text for that procedure code. Descriptions must come from the hospital's [insurance plan](../concepts/insurance-plan.md), word for word. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1205` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid procedure description received as %s for procedure %s for case number %s. Please try again with valid data. Procedure description is available as the display of the type for benefit component, of specific cost, of plan in isurance plan. +``` + +`PAYR-1205` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The procedure description in the message differs from the payer's description of the procedure named in the message. +- In the insurance plan, the description is the `display` of the `type` of a `benefit` inside a `specificCost` entry under `plan`. +- On the request, the description is the `display` in `Claim.item.productOrService`. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1205`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Fetch the current insurance plan for your hospital and the beneficiary's policy. See [Fetch the insurance plan](../flows/insurance-plan-request.md). +2. Copy the benefit `type` `display` exactly as the plan carries it. +3. Take the code and the description from the same plan entry. +4. Resend the request. + +Refresh your stored insurance plan at least weekly, and whenever the payer renews or amends the policy. Outdated tariff versions cause automatic rejection. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1206.md b/catalogue/nhcx/errors/payr-1206.md new file mode 100644 index 000000000..957e33ad4 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1206.md @@ -0,0 +1,77 @@ +--- +id: nhcx.error.payr-1206 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1206: procedure type is not accepted' +summary: >- + The payer refused the request because the type sent for a procedure is not one + it accepts. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1207 + - nhcx.error.payr-1210 +--- + +# PAYR-1206: procedure type is not accepted + +## In plain words + +The type you gave a requested procedure is not one the payer accepts for it. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1206` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid procedure type received as %s for procedure %s for case number %s. Please try again with valid data. +``` + +`PAYR-1206` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The procedure type in the message is not valid for the procedure named in the message. +- Each `Claim.procedure` entry carries a `type`. For example, a conservative treatment carries code `conservative`, display `Conservative`. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1206`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Set every procedure component to the value the insurance plan response gives for the package. Do not derive these values by hand. +2. Correct the `type` on the named `Claim.procedure` entry. +3. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1207.md b/catalogue/nhcx/errors/payr-1207.md new file mode 100644 index 000000000..7eaf43183 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1207.md @@ -0,0 +1,77 @@ +--- +id: nhcx.error.payr-1207 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1207: procedure factor is not accepted' +summary: >- + The payer refused the request because the factor sent for a procedure is not one + it accepts. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1206 + - nhcx.error.payr-1208 +--- + +# PAYR-1207: procedure factor is not accepted + +## In plain words + +The factor you sent for a requested procedure is not one the payer accepts. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1207` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid procedure factor received as %s for procedure %s for case number %s. Please try again with valid data. +``` + +`PAYR-1207` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The factor in the message is not valid for the procedure named in the message. +- The request carries factors on its items, in `Claim.item.factor`. A factor is a decimal, for example `0.5`. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1207`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Set every procedure component to the value the insurance plan response gives for the package. +2. Correct the factor for the named procedure. +3. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1208.md b/catalogue/nhcx/errors/payr-1208.md new file mode 100644 index 000000000..0faffa155 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1208.md @@ -0,0 +1,77 @@ +--- +id: nhcx.error.payr-1208 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1208: item quantity is not accepted' +summary: >- + The payer refused the request because the quantity sent for an item failed its + check. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1209 + - nhcx.error.payr-1228 +--- + +# PAYR-1208: item quantity is not accepted + +## In plain words + +The quantity you sent for an item is not one the payer accepts. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1208` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid procedure quantity received as %s for item %s for case number %s. Please try again with valid data. Item quantity should be greater than 1. +``` + +`PAYR-1208` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The quantity in the message, sent for the item named in the message, fails the payer's quantity check. +- The quantity sits in `Claim.item.quantity.value`. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1208`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Correct `Claim.item.quantity.value` for the named item. +2. Check it against the package in the insurance plan. +3. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1209.md b/catalogue/nhcx/errors/payr-1209.md new file mode 100644 index 000000000..36aa26d2d --- /dev/null +++ b/catalogue/nhcx/errors/payr-1209.md @@ -0,0 +1,77 @@ +--- +id: nhcx.error.payr-1209 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1209: item net amount is zero or less' +summary: >- + The payer refused the request because an item's net amount was not greater than + zero. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1201 + - nhcx.error.payr-1229 +--- + +# PAYR-1209: item net amount is zero or less + +## In plain words + +An item in your request has a net amount of zero or less. Every item must carry a positive amount. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1209` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid net amount received as INR %s for item %s for case number %s. Please try again with valid data. Item net amount should be greater than INR 0. +``` + +`PAYR-1209` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The net amount in the message, for the item named in the message, is not greater than INR 0. +- The item's net amount sits in `Claim.item.net`. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1209`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Give every item a net amount above `0`. +2. Take package prices from the insurance plan. Cost values there are in rupees, with `unit` `INR`. +3. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1210.md b/catalogue/nhcx/errors/payr-1210.md new file mode 100644 index 000000000..6e5e5cb03 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1210.md @@ -0,0 +1,76 @@ +--- +id: nhcx.error.payr-1210 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1210: procedure status is not accepted' +summary: >- + The payer refused the request because the status sent for a procedure is not one + it accepts. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1206 +--- + +# PAYR-1210: procedure status is not accepted + +## In plain words + +The status you sent for a requested procedure is not one the payer accepts. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1210` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid procedure status received as %s for procedure %s for case number %s. Please try again with valid data. +``` + +`PAYR-1210` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The procedure status in the message is not valid for the procedure named in the message. +- The status sits on the `Procedure` resource that the `Claim.procedure` entry references. +- A procedure planned in a preauthorisation request carries status `preparation`. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1210`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Use `preparation` in `Procedure.status` for a procedure that has not happened yet. +2. Check that every `Claim.procedure` reference points at a `Procedure` in the bundle. +3. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1211.md b/catalogue/nhcx/errors/payr-1211.md new file mode 100644 index 000000000..a33fecbd7 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1211.md @@ -0,0 +1,77 @@ +--- +id: nhcx.error.payr-1211 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1211: beneficiary and care plan match no rule at this hospital' +summary: >- + The payer refused the request because the beneficiary and the care plan met none + of its criteria for treatment at your hospital. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + - nhcx.concept.coverage-eligibility-purposes + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.coverage-eligibility-check + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1352 +--- + +# PAYR-1211: beneficiary and care plan match no rule at this hospital + +## In plain words + +The payer found no rule that lets this beneficiary receive this care plan at your hospital. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1211` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Requested beneficary details and careplan details does not match any criteria for processing the case at this hospital. Please try again with valid data. +``` + +`PAYR-1211` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The beneficiary details and the care plan details in the request match none of the payer's criteria for your hospital. +- The same message returns [`PAYR-1352`](payr-1352.md) on a claim. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1211`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Run a [coverage eligibility check](../flows/coverage-eligibility-check.md) with purpose `auth-requirements` for the same beneficiary and procedures. It tells you whether the treatment is covered for this member at your hospital. +2. Correct the beneficiary or care plan details to match, or choose a package the check covers. +3. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1212.md b/catalogue/nhcx/errors/payr-1212.md new file mode 100644 index 000000000..4a18da976 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1212.md @@ -0,0 +1,78 @@ +--- +id: nhcx.error.payr-1212 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1212: enhancement has no approved preauthorisation' +summary: >- + The payer refused an enhancement because it holds no approved preauthorisation + for that case. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.preauth-enhancement + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1213 + - nhcx.error.payr-1217 +--- + +# PAYR-1212: enhancement has no approved preauthorisation + +## In plain words + +You asked to extend a preauthorisation the payer never approved. An [enhancement](../glossary/enhancement.md) only extends a preauthorisation that is already approved. + +## Before you start + +- You sent an enhancement, workflow `13`, on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Enhance a preauthorisation](../flows/preauth-enhancement.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1212` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +No previous preauthorization approved record found for the enhancement request for case number %s. Hence request will not be processed further. Please initiate a new preauthorization. +``` + +`PAYR-1212` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- You sent an enhancement, workflow `13`, for the case number in the message. +- The payer holds no approved preauthorisation for that case number. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1212`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `22`. +- Denied: workflow `231`. +- Queried: workflow `241`. + +## When it goes wrong + +1. Check the case number. It must be the one your approved preauthorisation carries in `Claim.identifier`. +2. If the case has no approval, send a new preauthorisation with workflow `12`, as the message instructs. +3. Send the enhancement only after approval arrives on `/v1/preauth/on_submit` with workflow `21`. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1213.md b/catalogue/nhcx/errors/payr-1213.md new file mode 100644 index 000000000..cccb3ba0c --- /dev/null +++ b/catalogue/nhcx/errors/payr-1213.md @@ -0,0 +1,77 @@ +--- +id: nhcx.error.payr-1213 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1213: enhancement sent while the case is still in progress' +summary: >- + The payer refused an enhancement because it is still deciding an earlier request + on the same case. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-enhancement + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.preauth-enhancement + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1212 + - nhcx.error.payr-1215 + - nhcx.error.payr-1216 +--- + +# PAYR-1213: enhancement sent while the case is still in progress + +## In plain words + +The payer is still deciding an earlier request on this case. It accepts no enhancement until that [adjudication](../glossary/adjudication.md) is complete. + +## Before you start + +- You sent an enhancement, workflow `13`, on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Enhance a preauthorisation](../flows/preauth-enhancement.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1213` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Existing case in progress found for case number %s. Hence enhancement request will not be accepted. Please try after the adjudication is completed for the current case. +``` + +`PAYR-1213` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- You sent an enhancement, workflow `13`, for the case number in the message. +- An earlier request on the same case is still in progress with the payer. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1213`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `22`. +- Denied: workflow `231`. +- Queried: workflow `241`. + +## When it goes wrong + +1. Wait for the payer's decision on the earlier request. It arrives on `/v1/preauth/on_submit`. +2. Send the enhancement again after that decision arrives. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1214.md b/catalogue/nhcx/errors/payr-1214.md new file mode 100644 index 000000000..d72bccbdb --- /dev/null +++ b/catalogue/nhcx/errors/payr-1214.md @@ -0,0 +1,76 @@ +--- +id: nhcx.error.payr-1214 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1214: resubmission has no approved preauthorisation' +summary: >- + The payer refused a resubmission because it holds no approved preauthorisation + for that case. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-query-response + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1215 + - nhcx.error.payr-1212 +--- + +# PAYR-1214: resubmission has no approved preauthorisation + +## In plain words + +You resubmitted a preauthorisation that the payer holds no approval for. It processes the request no further. + +## Before you start + +- You sent a resubmission, workflow `121`, on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1214` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +No previous preauthorization approved record found for the resubmission request for case number %s. Hence request will not be processed further. Please initiate a new preauthorization. +``` + +`PAYR-1214` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- You sent a resubmission, workflow `121`, for the case number in the message. +- The payer holds no approved preauthorisation for that case number. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1214`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Check that the case number matches `Claim.identifier` on the original preauthorisation. +2. If no approved preauthorisation exists, send a new preauthorisation with workflow `12`, as the message instructs. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1215.md b/catalogue/nhcx/errors/payr-1215.md new file mode 100644 index 000000000..5f304ecce --- /dev/null +++ b/catalogue/nhcx/errors/payr-1215.md @@ -0,0 +1,77 @@ +--- +id: nhcx.error.payr-1215 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1215: resubmission sent while the case is still in progress' +summary: >- + The payer refused a resubmission because it is still deciding an earlier request + on the same case. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-query-response + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1214 + - nhcx.error.payr-1213 + - nhcx.error.payr-1216 +--- + +# PAYR-1215: resubmission sent while the case is still in progress + +## In plain words + +The payer is still deciding an earlier request on this case. It accepts no resubmission until that [adjudication](../glossary/adjudication.md) is complete. + +## Before you start + +- You sent a resubmission, workflow `121`, on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1215` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Existing case in progress found for case number %s. Hence resubmission request will not be accepted. Please try after the adjudication is completed for the current case. +``` + +`PAYR-1215` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- You sent a resubmission, workflow `121`, for the case number in the message. +- An earlier request on the same case is still in progress with the payer. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1215`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Wait for the payer's decision on the earlier request. It arrives on `/v1/preauth/on_submit`. +2. Send the resubmission again after that decision arrives. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1216.md b/catalogue/nhcx/errors/payr-1216.md new file mode 100644 index 000000000..3f4b9ab7d --- /dev/null +++ b/catalogue/nhcx/errors/payr-1216.md @@ -0,0 +1,77 @@ +--- +id: nhcx.error.payr-1216 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1216: new preauthorisation sent for a case already in progress' +summary: >- + The payer refused a new preauthorisation because a request on the same case is + still in progress. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1213 + - nhcx.error.payr-1215 + - nhcx.error.payr-1217 +--- + +# PAYR-1216: new preauthorisation sent for a case already in progress + +## In plain words + +A request on this case is still in progress with the payer. It accepts no new preauthorisation on the case until that finishes. + +## Before you start + +- You sent a new preauthorisation, workflow `12`, on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1216` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Existing case in progress found for case number %s. Hence new preauthorization request will not be accepted. +``` + +`PAYR-1216` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- You sent a new preauthorisation, workflow `12`, with the case number in the message. +- The payer is still processing an earlier request on that case number. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1216`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Do not open a second preauthorisation on a case that is in progress. +2. Wait for the decision on the first request. It arrives on `/v1/preauth/on_submit`. +3. If the new request is for a different admission, give it its own case number in `Claim.identifier`. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1217.md b/catalogue/nhcx/errors/payr-1217.md new file mode 100644 index 000000000..2cc5490c1 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1217.md @@ -0,0 +1,77 @@ +--- +id: nhcx.error.payr-1217 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1217: new preauthorisation sent for a case already approved' +summary: >- + The payer refused a new preauthorisation because the case already has an approved + one. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1216 + - nhcx.error.payr-1212 +--- + +# PAYR-1217: new preauthorisation sent for a case already approved + +## In plain words + +This case already has an approved preauthorisation. To change it, extend it or resubmit it. Do not open a new one. + +## Before you start + +- You sent a new preauthorisation, workflow `12`, on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1217` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Previous preauthorization approved record found for the new preauthorization request for case number %s. Hence request will not be processed further. Please initiate enhancement/resubmission. +``` + +`PAYR-1217` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- You sent a new preauthorisation, workflow `12`, with the case number in the message. +- The payer already holds an approved preauthorisation for that case number. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1217`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. To add treatment to the approved case, send an enhancement with workflow `13`. See [Enhance a preauthorisation](../flows/preauth-enhancement.md). +2. To resubmit the case, send workflow `121`. +3. If the request is for a different admission, give it its own case number in `Claim.identifier`. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1218.md b/catalogue/nhcx/errors/payr-1218.md new file mode 100644 index 000000000..efdf99057 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1218.md @@ -0,0 +1,76 @@ +--- +id: nhcx.error.payr-1218 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1218: query response sent for a case that was not queried' +summary: >- + The payer refused a query response because it holds no queried preauthorisation + for that case. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + - nhcx.concept.queries-and-communication + flows: + - nhcx.flow.preauth-query-response + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1219 +--- + +# PAYR-1218: query response sent for a case that was not queried + +## In plain words + +You answered a query the payer never raised. It holds no queried preauthorisation for this case. + +## Before you start + +- You sent a query response, workflow `19`, on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Answer a preauthorisation query](../flows/preauth-query-response.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1218` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +No queried preauthorization record found for the query update request for case number %s. Hence request will not be processed further. +``` + +`PAYR-1218` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- You sent a query response, workflow `19`, for the case number in the message. +- The payer holds no preauthorisation in the queried state for that case number. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1218`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Send a query response only after the payer queries the case. A query arrives on `/v1/preauth/on_submit` with workflow `24` and adjudication reason `queried`. +2. Check that the case number matches the queried case. +3. If the case was not queried, wait for the payer's decision instead. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1219.md b/catalogue/nhcx/errors/payr-1219.md new file mode 100644 index 000000000..1b12be278 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1219.md @@ -0,0 +1,75 @@ +--- +id: nhcx.error.payr-1219 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1219: case is not in the queried state' +summary: >- + The payer refused a query response because the case it names has not been queried. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + - nhcx.concept.queries-and-communication + flows: + - nhcx.flow.preauth-query-response + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1218 +--- + +# PAYR-1219: case is not in the queried state + +## In plain words + +You sent a query response for a case the payer has not queried. It processes the request no further. + +## Before you start + +- You sent a query response, workflow `19`, on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Answer a preauthorisation query](../flows/preauth-query-response.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1219` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Case number %s is not queried. Hence query updation request will not be processed further. +``` + +`PAYR-1219` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- You sent a query response, workflow `19`, for the case number in the message. +- That case is not in the queried state with the payer. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1219`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Send a query response only after the payer queries the case. A query arrives on `/v1/preauth/on_submit` with workflow `24` and adjudication reason `queried`. +2. Check that the case number matches the queried case. +3. If the case was not queried, wait for the payer's decision instead. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1220.md b/catalogue/nhcx/errors/payr-1220.md new file mode 100644 index 000000000..341b34fd8 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1220.md @@ -0,0 +1,82 @@ +--- +id: nhcx.error.payr-1220 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1220: investigation description does not match its code' +summary: >- + The payer refused the request because an investigation's description does not + match the payer's description for its code. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes, Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1221 + - nhcx.error.payr-1222 + - nhcx.error.payr-1223 +--- + +# PAYR-1220: investigation description does not match its code + +## In plain words + +An investigation in your request carries a description that does not match its code. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1220` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid investigation description received as %s for investigation code %s for case number %s. Please try again with valid data. +``` + +The same code and message can arrive on `/v1/claim/on_submit` when you submit a claim. See [Submit a claim](../flows/claim-submit.md). + +`PAYR-1220` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The description in the message does not match the payer's description for the investigation code in the message. +- Investigations travel as `supportingInfo` entries with category `INV`, Document Type - Investigation. +- Each entry's `code` carries the code and its `display`. For example, code `MAND0409` has display `any investigations done`. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1220`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Take investigation codes and descriptions from the coverage eligibility `auth-requirements` response. It lists the documents a preauthorisation needs. +2. Copy the `display` exactly as the payer published it. +3. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1221.md b/catalogue/nhcx/errors/payr-1221.md new file mode 100644 index 000000000..ab6bf81cd --- /dev/null +++ b/catalogue/nhcx/errors/payr-1221.md @@ -0,0 +1,80 @@ +--- +id: nhcx.error.payr-1221 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1221: investigation code is not valid' +summary: >- + The payer refused the request because an investigation code is not one it recognises. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes, Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1220 + - nhcx.error.payr-1232 +--- + +# PAYR-1221: investigation code is not valid + +## In plain words + +An investigation in your request carries a code the payer does not recognise. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1221` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid investigation code received as %s for case number %s. Please try again with valid data. +``` + +The same code and message can arrive on `/v1/claim/on_submit` when you submit a claim. See [Submit a claim](../flows/claim-submit.md). + +`PAYR-1221` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The investigation code in the message is not one the payer accepts for the case. +- Investigations travel as `supportingInfo` entries with category `INV`, Document Type - Investigation. +- Each entry's `code` carries the code and its `display`. For example, code `MAND0409` has display `any investigations done`. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1221`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Take investigation codes and descriptions from the coverage eligibility `auth-requirements` response. It lists the documents a preauthorisation needs. +2. Copy the code exactly as the payer published it. +3. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1222.md b/catalogue/nhcx/errors/payr-1222.md new file mode 100644 index 000000000..9027a7859 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1222.md @@ -0,0 +1,77 @@ +--- +id: nhcx.error.payr-1222 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1222: investigation status is not accepted' +summary: >- + The payer refused the request because the status sent for an investigation is + not one it accepts. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1220 + - nhcx.error.payr-1223 +--- + +# PAYR-1222: investigation status is not accepted + +## In plain words + +The status you sent for an investigation is not one the payer accepts. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1222` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid investigation status received as %s for investigation %s for case number %s. Please try again with valid data. +``` + +`PAYR-1222` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The status in the message is not valid for the investigation named in the message. +- Investigations travel as `supportingInfo` entries with category `INV`, Document Type - Investigation. +- Each entry's `code` carries the code and its `display`. For example, code `MAND0409` has display `any investigations done`. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1222`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Correct the status on the named investigation. +2. Resend the request. +3. If the value matches your clinical record, contact the support team with the case number. See [Support contacts](../sandbox/support-contacts.md). + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1223.md b/catalogue/nhcx/errors/payr-1223.md new file mode 100644 index 000000000..4f9322b3c --- /dev/null +++ b/catalogue/nhcx/errors/payr-1223.md @@ -0,0 +1,82 @@ +--- +id: nhcx.error.payr-1223 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1223: investigation attachment is not valid' +summary: >- + The payer refused the request because a document attached to an investigation + failed its checks. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1222 + - nhcx.error.payr-1227 +--- + +# PAYR-1223: investigation attachment is not valid + +## In plain words + +The document attached to an investigation could not be accepted. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1223` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid investigation attachment received for investigation %s for case number %s. Please try again with valid data. +``` + +`PAYR-1223` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The attachment on the investigation named in the message is not valid. +- Every attachment must meet these rules: + +- The value is Base64 encoded. +- The attachment has a name. +- The content type is `application/pdf`, `application/jpg`, `application/jpeg`, `application/png` or `application/fhir+json`. +- Each file is 2 MB or less, and the whole bundle stays within 20 MB. +- Each item carries one document. Merge several documents into one file. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1223`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Re-encode the file as Base64. Check its name and content type against the rules above. +2. Keep each file within 2 MB. Merge several documents into one file when an item needs them. +3. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1224.md b/catalogue/nhcx/errors/payr-1224.md new file mode 100644 index 000000000..84e4e84dd --- /dev/null +++ b/catalogue/nhcx/errors/payr-1224.md @@ -0,0 +1,82 @@ +--- +id: nhcx.error.payr-1224 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1224: implant description does not match its code' +summary: >- + The payer refused the request because an implant's description does not match + the payer's description for its code. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes, Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + - nhcx.concept.insurance-plan + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.insurance-plan-request + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1225 +--- + +# PAYR-1224: implant description does not match its code + +## In plain words + +An implant in your request carries a description that does not match its code. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1224` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid implant description received as %s for implant code %s for case number %s. Please try again with valid data. +``` + +The same code and message can arrive on `/v1/claim/on_submit` when you submit a claim. See [Submit a claim](../flows/claim-submit.md). + +`PAYR-1224` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The implant description in the message does not match the payer's description for the implant code in the message. +- In the insurance plan, implants appear as `cost` lines of type `Implant` on the benefits under `plan.specificCost`. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1224`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Fetch the current insurance plan for your hospital and the beneficiary's policy. See [Fetch the insurance plan](../flows/insurance-plan-request.md). +2. Take the implant code and its description from the same `Implant` cost line. +3. Resend the request. + +Refresh your stored insurance plan at least weekly, and whenever the payer renews or amends the policy. Outdated tariff versions cause automatic rejection. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1225.md b/catalogue/nhcx/errors/payr-1225.md new file mode 100644 index 000000000..349666f7f --- /dev/null +++ b/catalogue/nhcx/errors/payr-1225.md @@ -0,0 +1,81 @@ +--- +id: nhcx.error.payr-1225 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1225: implant code is not valid' +summary: >- + The payer refused the request because an implant code is not one it recognises. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes, Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + - nhcx.concept.insurance-plan + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.insurance-plan-request + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1224 +--- + +# PAYR-1225: implant code is not valid + +## In plain words + +An implant in your request carries a code the payer does not recognise. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1225` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid implant code received as %s for case number %s. Please try again with valid data. +``` + +The same code and message can arrive on `/v1/claim/on_submit` when you submit a claim. See [Submit a claim](../flows/claim-submit.md). + +`PAYR-1225` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The implant code in the message is not one the payer accepts for the case. +- In the insurance plan, implants appear as `cost` lines of type `Implant` on the benefits under `plan.specificCost`. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1225`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Fetch the current insurance plan for your hospital and the beneficiary's policy. See [Fetch the insurance plan](../flows/insurance-plan-request.md). +2. Use only implant codes from the plan's `Implant` cost lines for the package. +3. Resend the request. + +Refresh your stored insurance plan at least weekly, and whenever the payer renews or amends the policy. Outdated tariff versions cause automatic rejection. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1226.md b/catalogue/nhcx/errors/payr-1226.md new file mode 100644 index 000000000..f96edd17f --- /dev/null +++ b/catalogue/nhcx/errors/payr-1226.md @@ -0,0 +1,76 @@ +--- +id: nhcx.error.payr-1226 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1226: implant status is not accepted' +summary: >- + The payer refused the request because the status sent for an implant is not one + it accepts. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1227 + - nhcx.error.payr-1222 +--- + +# PAYR-1226: implant status is not accepted + +## In plain words + +The status you sent for an implant is not one the payer accepts. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1226` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid implant status received as %s for investigation %s for case number %s. Please try again with valid data. +``` + +`PAYR-1226` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The implant status in the message is not one the payer accepts. +- In the insurance plan, implants appear as `cost` lines of type `Implant` on the benefits under `plan.specificCost`. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1226`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Correct the status on the named implant. +2. Resend the request. +3. If the value matches your clinical record, contact the support team with the case number. See [Support contacts](../sandbox/support-contacts.md). + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1227.md b/catalogue/nhcx/errors/payr-1227.md new file mode 100644 index 000000000..1bba4909d --- /dev/null +++ b/catalogue/nhcx/errors/payr-1227.md @@ -0,0 +1,82 @@ +--- +id: nhcx.error.payr-1227 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1227: implant attachment is not valid' +summary: >- + The payer refused the request because a document attached to an implant failed + its checks. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1226 + - nhcx.error.payr-1223 +--- + +# PAYR-1227: implant attachment is not valid + +## In plain words + +The document attached to an implant could not be accepted. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1227` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid implant attachment received for investigation %s for case number %s. Please try again with valid data. +``` + +`PAYR-1227` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The implant attachment named in the message is not valid. +- Every attachment must meet these rules: + +- The value is Base64 encoded. +- The attachment has a name. +- The content type is `application/pdf`, `application/jpg`, `application/jpeg`, `application/png` or `application/fhir+json`. +- Each file is 2 MB or less, and the whole bundle stays within 20 MB. +- Each item carries one document. Merge several documents into one file. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1227`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Re-encode the file as Base64. Check its name and content type against the rules above. +2. Keep each file within 2 MB. Merge several documents into one file when an item needs them. +3. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1228.md b/catalogue/nhcx/errors/payr-1228.md new file mode 100644 index 000000000..ef8e74988 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1228.md @@ -0,0 +1,77 @@ +--- +id: nhcx.error.payr-1228 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1228: implant quantity is not accepted' +summary: >- + The payer refused the request because the quantity sent for an implant failed + its check. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1229 + - nhcx.error.payr-1208 +--- + +# PAYR-1228: implant quantity is not accepted + +## In plain words + +The quantity you sent for an implant is not one the payer accepts. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1228` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid implant quantity received as %s for implant %s for case number %s. Please try again with valid data. +``` + +`PAYR-1228` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The quantity in the message, sent for the implant named in the message, fails the payer's check. +- In the insurance plan, implants appear as `cost` lines of type `Implant` on the benefits under `plan.specificCost`. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1228`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Correct the quantity for the named implant. +2. Check it against the implant's cost line in the insurance plan. +3. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1229.md b/catalogue/nhcx/errors/payr-1229.md new file mode 100644 index 000000000..c0e10fb0c --- /dev/null +++ b/catalogue/nhcx/errors/payr-1229.md @@ -0,0 +1,77 @@ +--- +id: nhcx.error.payr-1229 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1229: implant net amount is not accepted' +summary: >- + The payer refused the request because the net amount sent for an implant failed + its check. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1230 + - nhcx.error.payr-1209 +--- + +# PAYR-1229: implant net amount is not accepted + +## In plain words + +The net amount you sent for an implant is not one the payer accepts. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1229` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid implant net amount received as INR %s for implant %s for case number %s. Please try again with valid data. +``` + +`PAYR-1229` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The net amount in the message, in rupees, is not valid for the implant named in the message. +- In the insurance plan, implants appear as `cost` lines of type `Implant` on the benefits under `plan.specificCost`. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1229`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Fetch the current insurance plan for your hospital and the beneficiary's policy. See [Fetch the insurance plan](../flows/insurance-plan-request.md). +2. Work the implant's net amount from the price on its `Implant` cost line. Cost values are in rupees, with `unit` `INR`. +3. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1230.md b/catalogue/nhcx/errors/payr-1230.md new file mode 100644 index 000000000..1669ed64a --- /dev/null +++ b/catalogue/nhcx/errors/payr-1230.md @@ -0,0 +1,78 @@ +--- +id: nhcx.error.payr-1230 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1230: implant unit price is not accepted' +summary: >- + The payer refused the request because the unit price sent for an implant failed + its check. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1229 +--- + +# PAYR-1230: implant unit price is not accepted + +## In plain words + +The unit price you sent for an implant is not one the payer accepts. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1230` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid implant unit price received as INR %s for implant %s for case number %s. Please try again with valid data. +``` + +`PAYR-1230` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The unit price in the message, in rupees, is not valid for the implant named in the message. +- In the insurance plan, implants appear as `cost` lines of type `Implant` on the benefits under `plan.specificCost`. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1230`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Fetch the current insurance plan for your hospital and the beneficiary's policy. See [Fetch the insurance plan](../flows/insurance-plan-request.md). +2. Use the price on the implant's `Implant` cost line. Cost values are in rupees, with `unit` `INR`. +3. Resend the request. + +Refresh your stored insurance plan at least weekly, and whenever the payer renews or amends the policy. Outdated tariff versions cause automatic rejection. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1231.md b/catalogue/nhcx/errors/payr-1231.md new file mode 100644 index 000000000..5a3624ca4 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1231.md @@ -0,0 +1,65 @@ +--- +id: nhcx.error.payr-1231 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1231: claim already raised for this case' +summary: >- + The payer refused a preauthorisation request because the final claim for the case + has already been raised. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request +--- + +# PAYR-1231: claim already raised for this case + +## In plain words + +The final claim for this case is already raised. After that, the payer accepts no preauthorisation request on the case. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1231` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Claim has already been raised for case number %s. Hence preauthorization request will not be accepted. +``` + +`PAYR-1231` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- You sent a preauthorisation request for the case number in the message. +- A claim has already been raised for that case number. + +## How you know it worked + +Your system stops sending preauthorisation requests for this case. The case continues on the claim, and the claim's decision arrives on `/v1/claim/on_submit`. + +## When it goes wrong + +1. Do not send further preauthorisation requests for this case number. +2. Continue the case on the claim. See [Submit a claim](../flows/claim-submit.md). diff --git a/catalogue/nhcx/errors/payr-1232.md b/catalogue/nhcx/errors/payr-1232.md new file mode 100644 index 000000000..afc83e28b --- /dev/null +++ b/catalogue/nhcx/errors/payr-1232.md @@ -0,0 +1,77 @@ +--- +id: nhcx.error.payr-1232 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1232: investigations missing for a private hospital' +summary: >- + The payer refused the request because a private hospital sent no investigation + details for the case. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.coverage-eligibility-check + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1221 + - nhcx.error.payr-1223 +--- + +# PAYR-1232: investigations missing for a private hospital + +## In plain words + +Your request carries no investigation details. For a private hospital, investigation details are mandatory. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1232` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +No investigation found for case number %s. Investigation details are mandatory for private hospitals. +``` + +`PAYR-1232` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- Your hospital is a private hospital. +- The request for the case number in the message carries no investigation. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1232`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Run a [coverage eligibility check](../flows/coverage-eligibility-check.md) with purpose `auth-requirements`. Its response lists the documents the preauthorisation needs. +2. Attach each investigation as a `supportingInfo` entry with category `INV`, Document Type - Investigation. +3. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1233.md b/catalogue/nhcx/errors/payr-1233.md new file mode 100644 index 000000000..f4087100a --- /dev/null +++ b/catalogue/nhcx/errors/payr-1233.md @@ -0,0 +1,79 @@ +--- +id: nhcx.error.payr-1233 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1233: wallet short and patient liability not allowed' +summary: >- + The payer refused the request because the beneficiary's wallet cannot cover it + and your hospital may not charge the shortfall to the patient. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.coverage-eligibility-check + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1201 + - nhcx.error.payr-1235 + - nhcx.error.payr-1356 +--- + +# PAYR-1233: wallet short and patient liability not allowed + +## In plain words + +The request costs more than the beneficiary's wallet holds. Patient liability does not apply at your hospital, so the shortfall cannot move to the patient. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1233` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Patient liability is not aplicable for the hospital and beneficiary do not have enough wallet balance with deficit amount INR %s for the requested preauthorization for case number %s. +``` + +`PAYR-1233` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The requested amount exceeds the wallet balance by the deficit in the message, in rupees. +- Patient liability is not applicable for your hospital. +- The same message returns [`PAYR-1356`](payr-1356.md) on a claim. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1233`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Run a [coverage eligibility check](../flows/coverage-eligibility-check.md) with purpose `validation`. It returns the used amount, the available balance and the wallet liability. +2. Reduce the request so it fits within the available balance. +3. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1234.md b/catalogue/nhcx/errors/payr-1234.md new file mode 100644 index 000000000..50a13f8c3 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1234.md @@ -0,0 +1,76 @@ +--- +id: nhcx.error.payr-1234 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1234: no preauthorisation found for the case number' +summary: >- + The payer refused the request because it holds no preauthorisation for the case + number sent. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1212 + - nhcx.error.payr-1214 +--- + +# PAYR-1234: no preauthorisation found for the case number + +## In plain words + +Your request refers to a case the payer holds no preauthorisation for. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1234` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +No preauthorization record found for case number %s. Hence the request will not be processed. +``` + +`PAYR-1234` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The request names the case number in the message. +- The payer holds no preauthorisation record for that case number. +- The case number travels in `Claim.identifier`, with identifier type `CLN`, Claim number. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1234`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Check the case number against the one on the original preauthorisation. +2. If no preauthorisation exists, send a new one with workflow `12`. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1235.md b/catalogue/nhcx/errors/payr-1235.md new file mode 100644 index 000000000..751fe53df --- /dev/null +++ b/catalogue/nhcx/errors/payr-1235.md @@ -0,0 +1,78 @@ +--- +id: nhcx.error.payr-1235 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1235: wallet balance is insufficient' +summary: >- + The payer refused the request because the beneficiary's wallet balance cannot + cover it. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.coverage-eligibility-check + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1201 + - nhcx.error.payr-1233 + - nhcx.error.payr-1323 +--- + +# PAYR-1235: wallet balance is insufficient + +## In plain words + +The beneficiary's wallet does not hold enough balance for this request. A [PMJAY](../glossary/pmjay.md) family shares one wallet, so treatment for any member draws it down. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1235` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Insufficient wallet balance. Hence the request will not be processed. +``` + +`PAYR-1235` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The wallet balance for the beneficiary is lower than the amount the request needs. +- The same message returns [`PAYR-1323`](payr-1323.md) on a claim. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1235`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Run a [coverage eligibility check](../flows/coverage-eligibility-check.md) with purpose `validation`. It returns the used amount, the available balance and the wallet liability. +2. Reduce the request so it fits within the available balance. +3. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1236.md b/catalogue/nhcx/errors/payr-1236.md new file mode 100644 index 000000000..957179fbb --- /dev/null +++ b/catalogue/nhcx/errors/payr-1236.md @@ -0,0 +1,74 @@ +--- +id: nhcx.error.payr-1236 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1236: claim type is not in-patient or out-patient' +summary: >- + The payer refused the request because the claim type was missing or not an accepted + in-patient or out-patient value. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1333 +--- + +# PAYR-1236: claim type is not in-patient or out-patient + +## In plain words + +The request does not say, in a form the payer accepts, whether this is in-patient or out-patient care. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1236` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid claim type (in-patient/out-patient) received. Hence the request will not be processed. +``` + +`PAYR-1236` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The claim type in the request is missing or is not a value the payer accepts. +- The claim type sits in `Claim.type`. A preauthorisation for an admission carries code `737481003`, Inpatient care management, from `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-claim-type`. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1236`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Set `Claim.type` with the system and code above for an in-patient case. +2. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1237.md b/catalogue/nhcx/errors/payr-1237.md new file mode 100644 index 000000000..80786be41 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1237.md @@ -0,0 +1,76 @@ +--- +id: nhcx.error.payr-1237 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1237: beneficiary has an active preauthorisation at another hospital' +summary: >- + The payer refused the request because the beneficiary already has an active preauthorisation + at another hospital. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-cancel + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1238 + - nhcx.error.payr-1268 +--- + +# PAYR-1237: beneficiary has an active preauthorisation at another hospital + +## In plain words + +The beneficiary already has an active preauthorisation at another hospital. The payer refuses a second one while that stays active. + +## Before you start + +- You sent a new preauthorisation, workflow `12`, on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1237` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Beneficiary is having an active preauthorization request at %s. Hence the request will not be processed. Kindly inform %s to cancel the active preauthorization request or raise a claim to proceed with current preauthorization. +``` + +`PAYR-1237` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The beneficiary in your request has an active preauthorisation at the hospital named in the message. +- That preauthorisation is neither cancelled nor claimed. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1237`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Ask the hospital named in the message to cancel its active preauthorisation, or to raise its claim. +2. Resend your request once that hospital confirms. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1238.md b/catalogue/nhcx/errors/payr-1238.md new file mode 100644 index 000000000..febe33693 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1238.md @@ -0,0 +1,79 @@ +--- +id: nhcx.error.payr-1238 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1238: beneficiary has an active preauthorisation at your hospital' +summary: >- + The payer refused the request because the beneficiary already has an active preauthorisation + at your hospital. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-cancel + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1237 + - nhcx.error.payr-1267 +--- + +# PAYR-1238: beneficiary has an active preauthorisation at your hospital + +## In plain words + +The beneficiary already has an active preauthorisation at your hospital. Close it before you open another. + +## Before you start + +- You sent a new preauthorisation, workflow `12`, on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1238` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Beneficiary is having an active preauthorization request at this hospital with reference number %s. Hence the request will not be processed. Kindly cancel the active preauthorization request or raise a claim to proceed with current preauthorization. +``` + +`PAYR-1238` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The beneficiary in your request has an active preauthorisation at your hospital. +- The message gives its reference number. +- That preauthorisation is neither cancelled nor claimed. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1238`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Find the active preauthorisation by the reference number in the message. +2. Cancel it, or raise its claim. See [Cancel a preauthorisation](../flows/preauth-cancel.md) and [Submit a claim](../flows/claim-submit.md). +3. Resend your request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1239.md b/catalogue/nhcx/errors/payr-1239.md new file mode 100644 index 000000000..142aecfd4 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1239.md @@ -0,0 +1,75 @@ +--- +id: nhcx.error.payr-1239 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1239: hospital configuration not found' +summary: >- + The payer refused the request because it has no configuration set up for your + hospital. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1105 + - nhcx.error.payr-1334 +--- + +# PAYR-1239: hospital configuration not found + +## In plain words + +The payer has no configuration for your hospital, so it cannot process the request. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1239` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Hospital configuration not found. Please contact support team. +``` + +`PAYR-1239` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The payer holds no hospital configuration for the hospital that sent the request. +- The same message returns [`PAYR-1105`](payr-1105.md) on a coverage eligibility check and [`PAYR-1334`](payr-1334.md) on a claim. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1239`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Contact the support team, as the message instructs. See [Support contacts](../sandbox/support-contacts.md). +2. Resend the request once the support team confirms your configuration. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1240.md b/catalogue/nhcx/errors/payr-1240.md new file mode 100644 index 000000000..57e1cdd13 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1240.md @@ -0,0 +1,80 @@ +--- +id: nhcx.error.payr-1240 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1240: requested procedures not found' +summary: >- + The payer refused the request because it holds no details for the procedures requested. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + - nhcx.concept.insurance-plan + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1204 + - nhcx.error.payr-1106 + - nhcx.error.payr-1344 +--- + +# PAYR-1240: requested procedures not found + +## In plain words + +The payer holds no details for one or more procedures in your request. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1240` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +No details found for the requested procedures in the system. +``` + +`PAYR-1240` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- A procedure in the request is not in the payer's system. +- The same message returns [`PAYR-1106`](payr-1106.md) on a coverage eligibility check and [`PAYR-1344`](payr-1344.md) on a claim. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1240`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Fetch the current insurance plan for your hospital and the beneficiary's policy. See [Fetch the insurance plan](../flows/insurance-plan-request.md). +2. Use only package codes from the current plan in `Claim.item.productOrService`. +3. Resend the request. + +Refresh your stored insurance plan at least weekly, and whenever the payer renews or amends the policy. Outdated tariff versions cause automatic rejection. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1241.md b/catalogue/nhcx/errors/payr-1241.md new file mode 100644 index 000000000..33d0d73dc --- /dev/null +++ b/catalogue/nhcx/errors/payr-1241.md @@ -0,0 +1,77 @@ +--- +id: nhcx.error.payr-1241 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1241: registration date is not valid' +summary: >- + The payer refused the request because the patient's registration date was missing + or not valid. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1242 + - nhcx.error.payr-1098 +--- + +# PAYR-1241: registration date is not valid + +## In plain words + +The patient's registration date in your request is missing or not a date the payer accepts. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1241` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid registration date received for case number %s. Hence the request will not be processed. +``` + +`PAYR-1241` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The registration date for the case number in the message is not valid. +- The registration date travels in `Claim.supportingInfo`, with category `OTH` and code `EDT`, EncounterDateTime. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1241`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Send the registration date in a `supportingInfo` entry with category `OTH` and code `EDT`. +2. Send the value as `timing`, a date or a period, or as a string. +3. Use the [NRCeS](../../shared/glossary/nrces.md) date-time format, for example `2026-03-10T21:21:17+05:30`. +4. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1242.md b/catalogue/nhcx/errors/payr-1242.md new file mode 100644 index 000000000..dac4fb051 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1242.md @@ -0,0 +1,76 @@ +--- +id: nhcx.error.payr-1242 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1242: registration date format is not valid' +summary: >- + The payer refused the request because the patient's registration date was not + in an accepted format. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1241 + - nhcx.error.payr-1098 +--- + +# PAYR-1242: registration date format is not valid + +## In plain words + +The patient's registration date is present, but not in a format the payer accepts. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1242` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid registration date format received for case number %s. Hence the request will not be processed. +``` + +`PAYR-1242` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The registration date for the case number in the message is not in the accepted format. +- The registration date travels in `Claim.supportingInfo`, with category `OTH` and code `EDT`, EncounterDateTime. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1242`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Write the registration date in the [NRCeS](../../shared/glossary/nrces.md) date-time format, for example `2026-03-10T21:21:17+05:30`. +2. Send it as `timing`, a date or a period, or as a string, in the entry with category `OTH` and code `EDT`. +3. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1243.md b/catalogue/nhcx/errors/payr-1243.md new file mode 100644 index 000000000..6c9f6d21f --- /dev/null +++ b/catalogue/nhcx/errors/payr-1243.md @@ -0,0 +1,76 @@ +--- +id: nhcx.error.payr-1243 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1243: admission date is not valid' +summary: >- + The payer refused the request because the admission date was missing or not valid. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1244 + - nhcx.error.payr-1502 +--- + +# PAYR-1243: admission date is not valid + +## In plain words + +The admission date in your request is missing or not a date the payer accepts. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1243` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid admission date received for case number %s. Hence the request will not be processed. +``` + +`PAYR-1243` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The admission date for the case number in the message is not valid. +- The admission date travels in `Claim.supportingInfo`, with code `ADDD`, Admission date - Discharge date. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1243`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Send the admission date in a `supportingInfo` entry with code `ADDD`. +2. Send the value as `timing`, a date or a period, or as a string. +3. Use the [NRCeS](../../shared/glossary/nrces.md) date-time format, for example `2026-03-10T21:21:17+05:30`. +4. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1244.md b/catalogue/nhcx/errors/payr-1244.md new file mode 100644 index 000000000..89faf4745 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1244.md @@ -0,0 +1,76 @@ +--- +id: nhcx.error.payr-1244 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1244: admission date format is not valid' +summary: >- + The payer refused the request because the admission date was not in an accepted + format. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1243 + - nhcx.error.payr-1502 +--- + +# PAYR-1244: admission date format is not valid + +## In plain words + +The admission date is present, but not in a format the payer accepts. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1244` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid admission date format received for case number %s. Hence the request will not be processed. +``` + +`PAYR-1244` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The admission date for the case number in the message is not in the accepted format. +- The admission date travels in `Claim.supportingInfo`, with code `ADDD`, Admission date - Discharge date. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1244`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Write the admission date in the [NRCeS](../../shared/glossary/nrces.md) date-time format, for example `2026-03-10T21:21:17+05:30`. +2. Send it as `timing`, a date or a period, or as a string, in the entry with code `ADDD`. +3. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1245.md b/catalogue/nhcx/errors/payr-1245.md new file mode 100644 index 000000000..a64d03178 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1245.md @@ -0,0 +1,77 @@ +--- +id: nhcx.error.payr-1245 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1245: a scheme rule failed' +summary: >- + The payer refused the request because it broke one of the scheme's business rules. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1111 + - nhcx.error.payr-1354 +--- + +# PAYR-1245: a scheme rule failed + +## In plain words + +Your request broke one of the payer's scheme rules. The payer can put the rule's own text in the message in place of `Rule failure.` + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1245` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Rule failure. +``` + +`PAYR-1245` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- A business rule in the payer's system failed for your request. +- The message can name the rule. For example, `Only one conservative procedure can be booked for a case` arrives when an enhancement adds a second Conservative package. +- The same message returns [`PAYR-1111`](payr-1111.md) on a coverage eligibility check and [`PAYR-1354`](payr-1354.md) on a claim. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1245`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Read the message text you received. Correct the request against the rule it names. +2. If the message reads only `Rule failure.`, contact the support team with the case number. See [Support contacts](../sandbox/support-contacts.md). +3. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1246.md b/catalogue/nhcx/errors/payr-1246.md new file mode 100644 index 000000000..c2aaf9de9 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1246.md @@ -0,0 +1,76 @@ +--- +id: nhcx.error.payr-1246 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1246: payer id is not valid' +summary: >- + The payer refused the request because the payer identifier in it was not valid. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + - nhcx.concept.participant-code + - nhcx.concept.protocol-headers + flows: + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1247 +--- + +# PAYR-1246: payer id is not valid + +## In plain words + +The request names the payer with an identifier the payer does not accept. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1246` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid payer id received as %s. Please try again with valid payer id. +``` + +`PAYR-1246` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The payer id in the message is not valid. +- The request names the payer in two places. One is the `x-hcx-recipient_code` protected header. The other is the payer `Organization` that `Claim.insurer` references. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1246`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Set `x-hcx-recipient_code` to the payer's [participant code](../glossary/participant-code.md). +2. Give the payer `Organization` its identifier, and point `Claim.insurer` at that `Organization`. +3. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1247.md b/catalogue/nhcx/errors/payr-1247.md new file mode 100644 index 000000000..2755719a0 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1247.md @@ -0,0 +1,77 @@ +--- +id: nhcx.error.payr-1247 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1247: payer details not received from the exchange' +summary: >- + The payer refused the request because it did not receive the payer details for + the payer identifier sent. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + - nhcx.concept.participant-code + flows: + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1246 + - nhcx.error.payr-1119 +--- + +# PAYR-1247: payer details not received from the exchange + +## In plain words + +The payer could not get the details for the payer id in your request from [NHCX](../../shared/glossary/nhcx.md), so it stopped processing. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1247` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Payer details for payer id %s is not received from HCX for the request. Hence the request will not be processed. +``` + +`PAYR-1247` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The payer id in the message did not resolve to payer details for the request. +- A coverage eligibility check fails the same way with [`PAYR-1119`](payr-1119.md). + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1247`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Check the payer id as described for [`PAYR-1246`](payr-1246.md). +2. Resend the request. +3. If it repeats with a correct payer id, contact the support team. See [Support contacts](../sandbox/support-contacts.md). + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1248.md b/catalogue/nhcx/errors/payr-1248.md new file mode 100644 index 000000000..00aa24d61 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1248.md @@ -0,0 +1,78 @@ +--- +id: nhcx.error.payr-1248 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1248: item code is not valid' +summary: >- + The payer refused the request because the code on an item is not valid. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1249 + - nhcx.error.payr-1204 +--- + +# PAYR-1248: item code is not valid + +## In plain words + +An item in your request carries a code the payer does not accept. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1248` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid item code received as %s for item sequence %s case number %s. Please try again with valid data. +``` + +`PAYR-1248` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The item code in the message is not valid for the item with the sequence in the message. +- The item code is the package code in `Claim.item.productOrService`, for example `MG0111A`. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1248`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Fetch the current insurance plan for your hospital and the beneficiary's policy. See [Fetch the insurance plan](../flows/insurance-plan-request.md). +2. Copy the package code from the plan into `Claim.item.productOrService` for the named item. +3. Resend the request. + +Refresh your stored insurance plan at least weekly, and whenever the payer renews or amends the policy. Outdated tariff versions cause automatic rejection. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1249.md b/catalogue/nhcx/errors/payr-1249.md new file mode 100644 index 000000000..23afc1b1d --- /dev/null +++ b/catalogue/nhcx/errors/payr-1249.md @@ -0,0 +1,75 @@ +--- +id: nhcx.error.payr-1249 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1249: item sequence is not valid' +summary: >- + The payer refused the request because an item's sequence number is not valid. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1248 +--- + +# PAYR-1249: item sequence is not valid + +## In plain words + +An item in your request carries a sequence number the payer does not accept. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1249` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid item sequence received as %s for case number %s. Please try again with valid data. +``` + +`PAYR-1249` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The item sequence in the message is not valid. +- Each `Claim.item` carries a `sequence`. The first item's `sequence` is `1`. +- Items point at the care team, diagnoses and procedures through `careTeamSequence`, `diagnosisSequence` and `procedureSequence`. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1249`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Give every item a unique whole-number `sequence`, starting at `1`. +2. Check that each cross-reference points at a sequence that exists in the `Claim`. +3. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1250.md b/catalogue/nhcx/errors/payr-1250.md new file mode 100644 index 000000000..aecb326a7 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1250.md @@ -0,0 +1,75 @@ +--- +id: nhcx.error.payr-1250 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1250: policy is not listed' +summary: >- + The payer refused the request because the policy code sent is not one it lists. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + - nhcx.concept.coverage-eligibility-purposes + - nhcx.concept.policy-linking + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.coverage-eligibility-check + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 +--- + +# PAYR-1250: policy is not listed + +## In plain words + +The policy code in your request is not one the payer lists. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1250` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Requested policy %s is not listed. Please try again with valid policy code. +``` + +`PAYR-1250` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The policy code in the message is not listed with the payer. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1250`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Use the policy code the beneficiary holds with this payer. +2. If you do not have it, run a [coverage eligibility check](../flows/coverage-eligibility-check.md) with purpose `discovery`. It finds the active policy code. +3. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1251.md b/catalogue/nhcx/errors/payr-1251.md new file mode 100644 index 000000000..e7c445e02 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1251.md @@ -0,0 +1,76 @@ +--- +id: nhcx.error.payr-1251 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1251: no billable treatment plan' +summary: >- + The payer refused the request because it carried no billable treatment plan for + the case. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1359 + - nhcx.error.payr-1204 +--- + +# PAYR-1251: no billable treatment plan + +## In plain words + +Your request carries nothing the payer can bill against for this case. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1251` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +No billable treatment plan received for case number %s. Please try again with valid treatment plan data. +``` + +`PAYR-1251` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The request for the case number in the message carries no billable treatment plan. +- The same message returns [`PAYR-1359`](payr-1359.md) on a claim. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1251`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Add at least one item with a package code from the insurance plan, a quantity, a unit price and a net amount above `0`. +2. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1252.md b/catalogue/nhcx/errors/payr-1252.md new file mode 100644 index 000000000..ba2b12abb --- /dev/null +++ b/catalogue/nhcx/errors/payr-1252.md @@ -0,0 +1,70 @@ +--- +id: nhcx.error.payr-1252 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1252: case is not in a state that can be cancelled' +summary: >- + The payer refused a cancellation because the case is not currently submitted or + approved. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-cancel + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.task-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.task-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.preauth-cancel + errors: + - nhcx.error.payr-1253 + - nhcx.error.payr-1257 + - nhcx.error.payr-1258 +--- + +# PAYR-1252: case is not in a state that can be cancelled + +## In plain words + +You asked to cancel a preauthorisation that is not in a cancellable state. Only a submitted or approved preauthorisation can be cancelled. + +## Before you start + +- You sent a cancellation `Task` on `POST /v1/task/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Cancel a preauthorisation](../flows/preauth-cancel.md). +- The [payer](../glossary/payer.md) answered later on `/v1/task/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1252` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Case number %s is not in active preauthorization state with the current status of the case with the payer system is %s. Hence the preauthorization can not be cancelled. Only the cases with current status as preauthorization submitted or preauthorization approved can be cancelled. +``` + +`PAYR-1252` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- You sent a cancellation for the case number in the message. +- The case's current status with the payer, given in the message, is neither preauthorisation submitted nor preauthorisation approved. + +## How you know it worked + +There is no cancellation to retry. Your system records the status the message reports, and stops offering cancel for the case. + +## When it goes wrong + +1. Do not resend the cancellation. You cannot cancel this case. +2. Read the current status in the message. Continue the case from that state. diff --git a/catalogue/nhcx/errors/payr-1253.md b/catalogue/nhcx/errors/payr-1253.md new file mode 100644 index 000000000..773b57689 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1253.md @@ -0,0 +1,69 @@ +--- +id: nhcx.error.payr-1253 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1253: case is already cancelled' +summary: >- + The payer refused a cancellation because the case is already cancelled. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-cancel + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.task-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.task-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.preauth-cancel + errors: + - nhcx.error.payr-1252 + - nhcx.error.payr-1255 +--- + +# PAYR-1253: case is already cancelled + +## In plain words + +You asked to cancel a preauthorisation that is already cancelled. + +## Before you start + +- You sent a cancellation `Task` on `POST /v1/task/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Cancel a preauthorisation](../flows/preauth-cancel.md). +- The [payer](../glossary/payer.md) answered later on `/v1/task/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1253` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Case number %s is already cancelled. Hence the preauthorization can not be cancelled again. Only the cases with current status as preauthorization submitted or preauthorization approved can be cancelled. +``` + +`PAYR-1253` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- You sent a cancellation for the case number in the message. +- That case is already cancelled. + +## How you know it worked + +The case is already cancelled, so your system shows it as cancelled and sends no further cancellation. The earlier cancellation was confirmed on `/v1/task/on_submit`, by a `Task` whose `status` is `completed`. + +## When it goes wrong + +1. Do not resend the cancellation. +2. Mark the case cancelled in your system. +3. For further treatment, raise a new preauthorisation with a new case number. A cancelled case number accepts no preauthorisation. See [`PAYR-1255`](payr-1255.md). diff --git a/catalogue/nhcx/errors/payr-1254.md b/catalogue/nhcx/errors/payr-1254.md new file mode 100644 index 000000000..a42099c61 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1254.md @@ -0,0 +1,80 @@ +--- +id: nhcx.error.payr-1254 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1254: treatment guideline questionnaire response missing' +summary: >- + The payer refused the request because a procedure needs a completed treatment + guideline checklist and none was sent. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.insurance-plan-request + - nhcx.flow.coverage-eligibility-check + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1273 + - nhcx.error.payr-1365 +--- + +# PAYR-1254: treatment guideline questionnaire response missing + +## In plain words + +A procedure you requested needs a completed Standard Treatment Guideline (STG) checklist. Your request did not include the response to it. STGs are mandatory in [PMJAY](../glossary/pmjay.md). + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1254` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Response for STG Questionnaire id %s is mandatory for procedure code %s. Hence the preauthorization request will not be processed as the questionnaire response is not received for procedure code. +``` + +`PAYR-1254` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The procedure code in the message has a mandatory STG questionnaire, with the id in the message. +- The request carries no response to that questionnaire for the procedure. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1254`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Take the STG questionnaire from the insurance plan, or from the coverage eligibility `auth-requirements` response. +2. Fill a `QuestionnaireResponse`. Put the questionnaire URL from the insurance plan in `QuestionnaireResponse.questionnaire`. +3. Add a `supportingInfo` entry to the `Claim` with category `STG`. Its value is a reference to that `QuestionnaireResponse`. +4. Include the `QuestionnaireResponse` resource in the bundle at that reference. +5. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1255.md b/catalogue/nhcx/errors/payr-1255.md new file mode 100644 index 000000000..a6ca9a473 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1255.md @@ -0,0 +1,75 @@ +--- +id: nhcx.error.payr-1255 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1255: case number already cancelled' +summary: >- + The payer refused a preauthorisation because its case number belongs to a cancelled + case. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-cancel + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1253 +--- + +# PAYR-1255: case number already cancelled + +## In plain words + +The case number in your request belongs to a cancelled preauthorisation. A cancelled case number accepts no further preauthorisation. + +## Before you start + +- You sent a new preauthorisation, workflow `12`, on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1255` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Case number %s is already cancelled. Hence no preauthorization request will be accepted for this case number. New preauthorization request needs to be raised with new case/reference number to proceed further. +``` + +`PAYR-1255` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- You sent a preauthorisation request for the case number in the message. +- The preauthorisation for that case number is already cancelled. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1255`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Raise a new preauthorisation with a new case number in `Claim.identifier`. +2. Send it with workflow `12`. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1256.md b/catalogue/nhcx/errors/payr-1256.md new file mode 100644 index 000000000..2cd8d8221 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1256.md @@ -0,0 +1,84 @@ +--- +id: nhcx.error.payr-1256 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1256: no biometric authentication and no consent questionnaire' +summary: >- + The payer refused a new preauthorisation because it carried neither the patient's + biometric authentication nor the signed consent questionnaire. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + - nhcx.concept.biometric-authentication + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.biometric-fingerprint-iris + - nhcx.flow.biometric-face + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1271 + - nhcx.error.payr-1272 + - nhcx.error.payr-1363 +--- + +# PAYR-1256: no biometric authentication and no consent questionnaire + +## In plain words + +A new preauthorisation must prove the patient is present at your hospital. Your request carried neither [biometric authentication](../concepts/biometric-authentication.md) nor the Authentication Consent Questionnaire response. + +## Before you start + +- You sent a new preauthorisation, workflow `12`, on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1256` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Response for Authentication Consent Questionnaire is missing for case number %s. This must be sent if the biometric authentication for patient is not available. For new preauthorization request, either biometric authentication for patient or response for Authentication Consent questionnaire must be sent. Please check/update the insurance plan for the policy for the details of the questionnaire. Please adhere to the response of the coverage eligibility for auth-requirements purpose to check the mandatory documents to be attached with the request +``` + +`PAYR-1256` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The request is a new preauthorisation for the case number in the message. +- It carries no biometric authentication for the patient. +- It carries no response to the Authentication Consent Questionnaire. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1256`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +Send one of the two proofs: + +1. Send biometric authentication. Authenticate the patient by fingerprint, iris or face. Pass the user token from the verification as a header on the preauthorisation. The token is valid for 30 minutes. See [Fingerprint or iris authentication](../flows/biometric-fingerprint-iris.md) or [Face authentication](../flows/biometric-face.md). +2. Or send the Authentication Consent Questionnaire response. Take the questionnaire from the insurance plan for the policy. The consent document is signed by the doctor and the patient. Send the response as a `QuestionnaireResponse`, referenced from a `supportingInfo` entry with category `INF`. + +Check the coverage eligibility `auth-requirements` response for the documents the request must attach. Then resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1257.md b/catalogue/nhcx/errors/payr-1257.md new file mode 100644 index 000000000..bc5ceb05d --- /dev/null +++ b/catalogue/nhcx/errors/payr-1257.md @@ -0,0 +1,69 @@ +--- +id: nhcx.error.payr-1257 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1257: payment already initiated for the case' +summary: >- + The payer refused a cancellation because payment for the case has already started. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-cancel + - nhcx.flow.payment-notice + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.task-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.task-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.preauth-cancel + errors: + - nhcx.error.payr-1258 + - nhcx.error.payr-1252 +--- + +# PAYR-1257: payment already initiated for the case + +## In plain words + +Payment for this case has already started. A case at that stage can no longer be cancelled. + +## Before you start + +- You sent a cancellation `Task` on `POST /v1/task/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Cancel a preauthorisation](../flows/preauth-cancel.md). +- The [payer](../glossary/payer.md) answered later on `/v1/task/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1257` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Payment is initiated for case number %s. Hence the preauthorization can not be cancelled again. Only the cases with current status as preauthorization submitted or preauthorization approved can be cancelled +``` + +`PAYR-1257` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- You sent a cancellation for the case number in the message. +- Payment is initiated for that case, so its status is no longer preauthorisation submitted or approved. + +## How you know it worked + +There is no cancellation to retry. Your system records the case as in payment, and stops offering cancel for it. + +## When it goes wrong + +1. Do not resend the cancellation. You cannot cancel this case. +2. Follow the case through payment. See [Receive a payment notice](../flows/payment-notice.md). diff --git a/catalogue/nhcx/errors/payr-1258.md b/catalogue/nhcx/errors/payr-1258.md new file mode 100644 index 000000000..0db97bf18 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1258.md @@ -0,0 +1,70 @@ +--- +id: nhcx.error.payr-1258 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1258: payment already cleared for the case' +summary: >- + The payer refused a cancellation because payment for the case has already been + made. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-cancel + - nhcx.flow.payment-notice + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.task-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.task-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.preauth-cancel + errors: + - nhcx.error.payr-1257 + - nhcx.error.payr-1252 +--- + +# PAYR-1258: payment already cleared for the case + +## In plain words + +Payment for this case is already complete. A paid case can no longer be cancelled. + +## Before you start + +- You sent a cancellation `Task` on `POST /v1/task/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Cancel a preauthorisation](../flows/preauth-cancel.md). +- The [payer](../glossary/payer.md) answered later on `/v1/task/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1258` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Payment is accomplished/cleared for case number %s. Hence the preauthorization can not be cancelled again. Only the cases with current status as preauthorization submitted or preauthorization approved can be cancelled +``` + +`PAYR-1258` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- You sent a cancellation for the case number in the message. +- Payment is accomplished or cleared for that case, so its status is no longer preauthorisation submitted or approved. + +## How you know it worked + +There is no cancellation to retry. Your system records the case as paid, and stops offering cancel for it. + +## When it goes wrong + +1. Do not resend the cancellation. You cannot cancel this case. +2. Record the case as paid. See [Receive a payment notice](../flows/payment-notice.md). diff --git a/catalogue/nhcx/errors/payr-1259.md b/catalogue/nhcx/errors/payr-1259.md new file mode 100644 index 000000000..a618d8bce --- /dev/null +++ b/catalogue/nhcx/errors/payr-1259.md @@ -0,0 +1,80 @@ +--- +id: nhcx.error.payr-1259 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1259: newborn date of birth missing' +summary: >- + The payer refused a newborn case because the baby's date of birth was not sent. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1260 + - nhcx.error.payr-1261 + - nhcx.error.payr-1262 + - nhcx.error.payr-1263 + - nhcx.error.payr-1269 + - nhcx.error.payr-1507 +--- + +# PAYR-1259: newborn date of birth missing + +## In plain words + +A newborn case must carry the baby's date of birth. Your request did not. In [PMJAY](../glossary/pmjay.md), a newborn with no Member ID yet is treated on a parent's card, as a child linked to the parent. + +## Before you start + +- You sent a new preauthorisation, workflow `12`, on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1259` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +DOB is missing for new born for the case number (%s) with correlation id as (%s) at (%s) +``` + +`PAYR-1259` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The request is a newborn case. The parent is the primary `Patient`. The parent's `Patient` links the child's `Patient` through `link`, with `type` `refer`. +- The child's `Patient` carries no date of birth. +- The message gives the case number and the correlation id. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1259`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Add the baby's date of birth to the child's `Patient`. +2. Attach the proof of date of birth: category `DOB`, code `BCF` for a birth certificate, or `DCB` for a government hospital discharge card. +3. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1260.md b/catalogue/nhcx/errors/payr-1260.md new file mode 100644 index 000000000..70bea60c7 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1260.md @@ -0,0 +1,79 @@ +--- +id: nhcx.error.payr-1260 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1260: newborn date of birth is in the future' +summary: >- + The payer refused a newborn case because the baby's date of birth was later than + today. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1259 + - nhcx.error.payr-1261 + - nhcx.error.payr-1262 + - nhcx.error.payr-1263 + - nhcx.error.payr-1269 + - nhcx.error.payr-1507 +--- + +# PAYR-1260: newborn date of birth is in the future + +## In plain words + +The baby's date of birth in your request is in the future. In [PMJAY](../glossary/pmjay.md), a newborn with no Member ID yet is treated on a parent's card, as a child linked to the parent. + +## Before you start + +- You sent a new preauthorisation, workflow `12`, on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1260` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +DOB cannot be a future date for the case number (%s) with correlation id as (%s) at (%s) +``` + +`PAYR-1260` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The request is a newborn case. The parent is the primary `Patient`. The parent's `Patient` links the child's `Patient` through `link`, with `type` `refer`. +- The child's date of birth is later than the current date. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1260`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Correct the child's date of birth. Check it against the proof of date of birth you attach. +2. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1261.md b/catalogue/nhcx/errors/payr-1261.md new file mode 100644 index 000000000..b8d106cdc --- /dev/null +++ b/catalogue/nhcx/errors/payr-1261.md @@ -0,0 +1,89 @@ +--- +id: nhcx.error.payr-1261 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1261: newborn details are not valid' +summary: >- + The payer refused a newborn case because the newborn details failed its checks. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. States the message for PAYR-1261 that the error sheet does not. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1259 + - nhcx.error.payr-1260 + - nhcx.error.payr-1262 + - nhcx.error.payr-1263 + - nhcx.error.payr-1269 + - nhcx.error.payr-1508 +--- + +# PAYR-1261: newborn details are not valid + +## In plain words + +The newborn details in your request are not valid. In [PMJAY](../glossary/pmjay.md), a newborn with no Member ID yet is treated on a parent's card, as a child linked to the parent. + +## Before you start + +- You sent a new preauthorisation, workflow `12`, on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1261` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid new born details for the case number (%s) with correlation id as (%s) at (%s) +``` + +`PAYR-1261` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The request is a newborn case. +- The newborn details fail the payer's checks. The message names the case and the correlation id, not the element. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1261`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +Check every newborn element, then resend the request: + +- The parent, mother or father, is the primary `Patient`. +- The parent's `Patient` links the child's `Patient` through `link`, with `type` `refer` and `other` pointing at the child. +- The child's `Patient` carries gender, date of birth and name. +- Proof of date of birth: category `DOB`, code `BCF` for a birth certificate, or `DCB` for a government hospital discharge card. +- The bill is in the parent's name as `Baby of `, with a supporting attachment. +- Twins get two separate preauthorisations, one per child. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1262.md b/catalogue/nhcx/errors/payr-1262.md new file mode 100644 index 000000000..a82e3faad --- /dev/null +++ b/catalogue/nhcx/errors/payr-1262.md @@ -0,0 +1,78 @@ +--- +id: nhcx.error.payr-1262 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1262: newborn gender missing' +summary: >- + The payer refused a newborn case because the baby's gender was not sent. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1259 + - nhcx.error.payr-1260 + - nhcx.error.payr-1261 + - nhcx.error.payr-1263 + - nhcx.error.payr-1269 + - nhcx.error.payr-1506 +--- + +# PAYR-1262: newborn gender missing + +## In plain words + +A newborn case must carry the baby's gender. Your request did not. In [PMJAY](../glossary/pmjay.md), a newborn with no Member ID yet is treated on a parent's card, as a child linked to the parent. + +## Before you start + +- You sent a new preauthorisation, workflow `12`, on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1262` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Gender is mandatory for the new born beneficiary +``` + +`PAYR-1262` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The request is a newborn case. The parent is the primary `Patient`. The parent's `Patient` links the child's `Patient` through `link`, with `type` `refer`. +- The child's `Patient` carries no gender. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1262`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Add the gender to the child's `Patient`. Use a value from the administrative gender value set, `https://hl7.org/fhir/R4/valueset-administrative-gender.html`. +2. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1263.md b/catalogue/nhcx/errors/payr-1263.md new file mode 100644 index 000000000..b1c6b420e --- /dev/null +++ b/catalogue/nhcx/errors/payr-1263.md @@ -0,0 +1,89 @@ +--- +id: nhcx.error.payr-1263 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1263: newborn documents missing' +summary: >- + The payer refused a newborn case because a mandatory document for the baby was + not attached. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. States the message for PAYR-1263 that the error sheet does not. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1264 + - nhcx.error.payr-1265 + - nhcx.error.payr-1266 + - nhcx.error.payr-1259 + - nhcx.error.payr-1509 +--- + +# PAYR-1263: newborn documents missing + +## In plain words + +A newborn case needs supporting documents, and one is missing from your request. In [PMJAY](../glossary/pmjay.md), a newborn with no Member ID yet is treated on a parent's card, as a child linked to the parent. + +## Before you start + +- You sent a new preauthorisation, workflow `12`, on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1263` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Documents are mandatory for the new born beneficiary +``` + +`PAYR-1263` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The request is a newborn case. +- A document the payer requires for the newborn is missing. +- Four codes, `PAYR-1263` to `PAYR-1266`, carry this same message. The message does not say which document is missing. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1263`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +Attach every newborn document, then resend the request: + +- Proof of date of birth: category `DOB`, code `BCF` for a birth certificate, or `DCB` for a government hospital discharge card. +- A supporting attachment that justifies a bill in the parent's name as `Baby of `. +- Every document the coverage eligibility `auth-requirements` response lists for the procedures. + +Each attachment must be Base64 encoded and named, with an accepted content type. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1264.md b/catalogue/nhcx/errors/payr-1264.md new file mode 100644 index 000000000..89b3a3f9e --- /dev/null +++ b/catalogue/nhcx/errors/payr-1264.md @@ -0,0 +1,89 @@ +--- +id: nhcx.error.payr-1264 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1264: newborn documents missing' +summary: >- + The payer refused a newborn case because a mandatory document for the baby was + not attached. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. States the message for PAYR-1264 that the error sheet does not. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1263 + - nhcx.error.payr-1265 + - nhcx.error.payr-1266 + - nhcx.error.payr-1259 + - nhcx.error.payr-1509 +--- + +# PAYR-1264: newborn documents missing + +## In plain words + +A newborn case needs supporting documents, and one is missing from your request. In [PMJAY](../glossary/pmjay.md), a newborn with no Member ID yet is treated on a parent's card, as a child linked to the parent. + +## Before you start + +- You sent a new preauthorisation, workflow `12`, on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1264` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Documents are mandatory for the new born beneficiary +``` + +`PAYR-1264` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The request is a newborn case. +- A document the payer requires for the newborn is missing. +- Four codes, `PAYR-1263` to `PAYR-1266`, carry this same message. The message does not say which document is missing. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1264`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +Attach every newborn document, then resend the request: + +- Proof of date of birth: category `DOB`, code `BCF` for a birth certificate, or `DCB` for a government hospital discharge card. +- A supporting attachment that justifies a bill in the parent's name as `Baby of `. +- Every document the coverage eligibility `auth-requirements` response lists for the procedures. + +Each attachment must be Base64 encoded and named, with an accepted content type. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1265.md b/catalogue/nhcx/errors/payr-1265.md new file mode 100644 index 000000000..732605a66 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1265.md @@ -0,0 +1,89 @@ +--- +id: nhcx.error.payr-1265 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1265: newborn documents missing' +summary: >- + The payer refused a newborn case because a mandatory document for the baby was + not attached. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. States the message for PAYR-1265 that the error sheet does not. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1263 + - nhcx.error.payr-1264 + - nhcx.error.payr-1266 + - nhcx.error.payr-1259 + - nhcx.error.payr-1509 +--- + +# PAYR-1265: newborn documents missing + +## In plain words + +A newborn case needs supporting documents, and one is missing from your request. In [PMJAY](../glossary/pmjay.md), a newborn with no Member ID yet is treated on a parent's card, as a child linked to the parent. + +## Before you start + +- You sent a new preauthorisation, workflow `12`, on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1265` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Documents are mandatory for the new born beneficiary +``` + +`PAYR-1265` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The request is a newborn case. +- A document the payer requires for the newborn is missing. +- Four codes, `PAYR-1263` to `PAYR-1266`, carry this same message. The message does not say which document is missing. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1265`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +Attach every newborn document, then resend the request: + +- Proof of date of birth: category `DOB`, code `BCF` for a birth certificate, or `DCB` for a government hospital discharge card. +- A supporting attachment that justifies a bill in the parent's name as `Baby of `. +- Every document the coverage eligibility `auth-requirements` response lists for the procedures. + +Each attachment must be Base64 encoded and named, with an accepted content type. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1266.md b/catalogue/nhcx/errors/payr-1266.md new file mode 100644 index 000000000..908b74697 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1266.md @@ -0,0 +1,89 @@ +--- +id: nhcx.error.payr-1266 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1266: newborn documents missing' +summary: >- + The payer refused a newborn case because a mandatory document for the baby was + not attached. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. States the message for PAYR-1266 that the error sheet does not. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1263 + - nhcx.error.payr-1264 + - nhcx.error.payr-1265 + - nhcx.error.payr-1259 + - nhcx.error.payr-1509 +--- + +# PAYR-1266: newborn documents missing + +## In plain words + +A newborn case needs supporting documents, and one is missing from your request. In [PMJAY](../glossary/pmjay.md), a newborn with no Member ID yet is treated on a parent's card, as a child linked to the parent. + +## Before you start + +- You sent a new preauthorisation, workflow `12`, on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1266` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Documents are mandatory for the new born beneficiary +``` + +`PAYR-1266` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The request is a newborn case. +- A document the payer requires for the newborn is missing. +- Four codes, `PAYR-1263` to `PAYR-1266`, carry this same message. The message does not say which document is missing. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1266`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +Attach every newborn document, then resend the request: + +- Proof of date of birth: category `DOB`, code `BCF` for a birth certificate, or `DCB` for a government hospital discharge card. +- A supporting attachment that justifies a bill in the parent's name as `Baby of `. +- Every document the coverage eligibility `auth-requirements` response lists for the procedures. + +Each attachment must be Base64 encoded and named, with an accepted content type. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1267.md b/catalogue/nhcx/errors/payr-1267.md new file mode 100644 index 000000000..cf84adfc3 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1267.md @@ -0,0 +1,81 @@ +--- +id: nhcx.error.payr-1267 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1267: active newborn preauthorisation at your hospital' +summary: >- + The payer refused a newborn case because the beneficiary already has an active + newborn preauthorisation at your hospital. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-cancel + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1268 + - nhcx.error.payr-1238 +--- + +# PAYR-1267: active newborn preauthorisation at your hospital + +## In plain words + +The beneficiary already has an active preauthorisation for a newborn case at your hospital. Close it before you open another. + +## Before you start + +- You sent a new preauthorisation, workflow `12`, on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1267` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Beneficiary is having an active preauthorization request for new born case at this hospital with reference number %s. Hence the request will not be processed. Kindly cancel the active preauthorization request or raise a claim to proceed with current preauthorization +``` + +`PAYR-1267` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The beneficiary in your request has an active newborn preauthorisation at your hospital. +- The message gives its reference number. +- That preauthorisation is neither cancelled nor claimed. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1267`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Find the active preauthorisation by the reference number in the message. +2. Cancel it, or raise its claim. See [Cancel a preauthorisation](../flows/preauth-cancel.md) and [Submit a claim](../flows/claim-submit.md). +3. Resend your request. + +Twins are two children with two treatments. Raise one preauthorisation per child, each with its own linked child `Patient`. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1268.md b/catalogue/nhcx/errors/payr-1268.md new file mode 100644 index 000000000..5f0c0b409 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1268.md @@ -0,0 +1,76 @@ +--- +id: nhcx.error.payr-1268 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1268: active newborn preauthorisation at another hospital' +summary: >- + The payer refused a newborn case because the beneficiary already has an active + newborn preauthorisation at another hospital. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-cancel + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1267 + - nhcx.error.payr-1237 +--- + +# PAYR-1268: active newborn preauthorisation at another hospital + +## In plain words + +The beneficiary already has an active preauthorisation for a newborn case at another hospital. The payer refuses a second one while that stays active. + +## Before you start + +- You sent a new preauthorisation, workflow `12`, on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1268` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Beneficiary is having an active preauthorization request for new born case at %s. Hence the request will not be processed. Kindly inform %s to cancel the active preauthorization request or raise a claim to proceed with current preauthorization +``` + +`PAYR-1268` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The beneficiary in your request has an active newborn preauthorisation at the hospital named in the message. +- That preauthorisation is neither cancelled nor claimed. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1268`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Ask the hospital named in the message to cancel its active preauthorisation, or to raise its claim. +2. Resend your request once that hospital confirms. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1269.md b/catalogue/nhcx/errors/payr-1269.md new file mode 100644 index 000000000..cbb80a9af --- /dev/null +++ b/catalogue/nhcx/errors/payr-1269.md @@ -0,0 +1,79 @@ +--- +id: nhcx.error.payr-1269 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1269: newborn is older than 6 years' +summary: >- + The payer refused a newborn case because the child's date of birth is more than + 6 years ago. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1259 + - nhcx.error.payr-1260 + - nhcx.error.payr-1261 + - nhcx.error.payr-1262 + - nhcx.error.payr-1263 +--- + +# PAYR-1269: newborn is older than 6 years + +## In plain words + +A newborn case is only for a child aged 6 years or under. The date of birth you sent is more than 6 years ago. + +## Before you start + +- You sent a new preauthorisation, workflow `12`, on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1269` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Date of birth received for new born beneficiary exceeds 6 years before the current date. New born cases can be raised only for the beneficiary whose date of birth is within 6 years of current date +``` + +`PAYR-1269` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The request is a newborn case. +- The child's date of birth is more than 6 years before the current date. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1269`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Check the date of birth against the proof you attach. Correct it if it is wrong. +2. A newborn case is for a child aged 6 or under who has no Member ID yet. If the child is older than 6 years, do not send the case as a newborn case. +3. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1270.md b/catalogue/nhcx/errors/payr-1270.md new file mode 100644 index 000000000..f0f6abb21 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1270.md @@ -0,0 +1,76 @@ +--- +id: nhcx.error.payr-1270 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1270: item LM100 sent on a preauthorisation' +summary: >- + The payer refused the preauthorisation because it included item LM100, which belongs + only on a claim. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1362 +--- + +# PAYR-1270: item LM100 sent on a preauthorisation + +## In plain words + +Your preauthorisation includes item `LM100`. `LM100` belongs only on a claim, for a patient who leaves against medical advice. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1270` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Item LM100 is not applicable for preauthorization request. This item is expected/mandated only during claim submission if the patient is discharged after/during surgery under LAMA/DAMA category for PMJAY cases. +``` + +`PAYR-1270` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The request carries an item with code `LM100`. +- `LM100` is a claim-only package for [PMJAY](../glossary/pmjay.md) cases discharged under LAMA or DAMA, leaving or discharged against medical advice. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1270`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Remove the `LM100` item from the preauthorisation. +2. Send `LM100` only on the claim, when the discharge qualifies. See [Submit a claim](../flows/claim-submit.md). +3. Resend the preauthorisation. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1271.md b/catalogue/nhcx/errors/payr-1271.md new file mode 100644 index 000000000..0c8bb6d4a --- /dev/null +++ b/catalogue/nhcx/errors/payr-1271.md @@ -0,0 +1,80 @@ +--- +id: nhcx.error.payr-1271 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1271: consent questionnaire answer missing' +summary: >- + The payer refused a new preauthorisation because a question in the consent questionnaire + had no answer. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + - nhcx.concept.biometric-authentication + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.biometric-fingerprint-iris + - nhcx.flow.biometric-face + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1256 + - nhcx.error.payr-1272 + - nhcx.error.payr-1364 +--- + +# PAYR-1271: consent questionnaire answer missing + +## In plain words + +Your request used the Authentication Consent Questionnaire in place of biometrics, but one of its questions has no answer. + +## Before you start + +- You sent a new preauthorisation, workflow `12`, on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1271` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +No value received for link id %s for Authentication Consent Questionnaire for preauthorization request. This must be sent if the biometric authentication for patient is not available. For new preauthorization request, either biometric authentication for patient or response for Authentication Consent questionnaire must be sent. Please check/update the insurance plan for the policy for the details of the questionnaire. Please adhere to the response of the coverage eligibility for auth-requirements purpose to check the mandatory documents to be attached with the request. +``` + +`PAYR-1271` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The request carries the Authentication Consent Questionnaire response instead of biometric authentication. +- The question with the link id in the message has no value. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1271`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Answer every question in the questionnaire, as the insurance plan for the policy defines it. +2. Or send biometric authentication. Authenticate the patient by fingerprint, iris or face. Pass the user token from the verification as a header on the preauthorisation. The token is valid for 30 minutes. See [Fingerprint or iris authentication](../flows/biometric-fingerprint-iris.md) or [Face authentication](../flows/biometric-face.md). +3. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1272.md b/catalogue/nhcx/errors/payr-1272.md new file mode 100644 index 000000000..c76879252 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1272.md @@ -0,0 +1,80 @@ +--- +id: nhcx.error.payr-1272 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1272: biometric user token is not valid' +summary: >- + The payer refused the request because the patient's biometric user token was not + valid. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + - nhcx.concept.biometric-authentication + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.biometric-fingerprint-iris + - nhcx.flow.biometric-face + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1256 + - nhcx.error.payr-1271 + - nhcx.error.payr-1366 +--- + +# PAYR-1272: biometric user token is not valid + +## In plain words + +The token that proves the patient's [biometric authentication](../concepts/biometric-authentication.md) is not valid. A user token lasts 30 minutes after verification. + +## Before you start + +- You sent a new preauthorisation, workflow `12`, on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1272` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +Invalid biometric user token received. Please try again with valid valid biometric details of the beneficiary. For any issues with biometric, please try with Authentication Consent Questionnaire, details for which has been received in response for coverage eligibliity auth-requirements. +``` + +`PAYR-1272` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- The biometric user token in the request is not valid. +- A user token is valid for 30 minutes after biometric verification. After that, a fresh authentication is mandatory. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1272`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Authenticate the patient again by fingerprint, iris or face. See [Fingerprint or iris authentication](../flows/biometric-fingerprint-iris.md) or [Face authentication](../flows/biometric-face.md). +2. Send the new user token with the preauthorisation. +3. If biometric capture keeps failing, send the Authentication Consent Questionnaire response instead. See [`PAYR-1256`](payr-1256.md). + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1273.md b/catalogue/nhcx/errors/payr-1273.md new file mode 100644 index 000000000..15e1e9608 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1273.md @@ -0,0 +1,77 @@ +--- +id: nhcx.error.payr-1273 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1273: questionnaire not found for the selection' +summary: >- + The payer refused the request because a questionnaire response pointed at a questionnaire + it could not find. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.insurance-plan-request + - nhcx.flow.coverage-eligibility-check + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1254 + - nhcx.error.payr-1256 +--- + +# PAYR-1273: questionnaire not found for the selection + +## In plain words + +A questionnaire response in your request points at a questionnaire the payer cannot find. + +## Before you start + +- You sent a preauthorisation request on `POST /v1/preauth/submit`, and [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md). +- The [payer](../glossary/payer.md) answered later on `/v1/preauth/on_submit`. You decrypted the sealed [JWE](../glossary/jwe.md) payload. See [The sealed envelope](../concepts/jwe-envelope.md). +- The decrypted response carries `PAYR-1273` with the message below. The payer fills each `%s` placeholder when it sends it. + +```text +No questionnaire found for the received selection. Please validate the questionnaire url from insurance plan/coverage auth-requirements response. +``` + +`PAYR-1273` is a reference payer code. A payer running the [PMJAY](../glossary/pmjay.md) reference implementation sends it. See [Error code spaces](../concepts/error-code-spaces.md). + +## What happens + +- A `QuestionnaireResponse` in the request points at a questionnaire the payer cannot find for the selection. + +## How you know it worked + +Send the corrected request on `/v1/preauth/submit` with a new `x-hcx-correlation_id`. NHCX answers `202 Accepted`. + +The fix worked when the next `/v1/preauth/on_submit` for the case carries no `PAYR-1273`. It carries the payer's decision in a `ClaimResponse` instead: + +- Approved: workflow `21`, `outcome` `complete`, and a `preAuthRef` you cite on the claim. A partial approval carries `outcome` `partial`. +- Queried: workflow `24`, with adjudication reason `queried`. +- Rejected: workflow `23`, with adjudication reason `cancelled` and the reason in `disposition`. + +## When it goes wrong + +1. Put the exact questionnaire URL in `QuestionnaireResponse.questionnaire`. Take it from the insurance plan or the coverage eligibility `auth-requirements` response. +2. Refresh your stored insurance plan if it is out of date. +3. Resend the request. + +Use a new [`x-hcx-correlation_id`](../glossary/correlation-id.md) for every resend. A correlation id is retired once its request fails, and reusing it returns [`NHCX-1006`](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1301.md b/catalogue/nhcx/errors/payr-1301.md new file mode 100644 index 000000000..a0b2c7be1 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1301.md @@ -0,0 +1,91 @@ +--- +id: nhcx.error.payr-1301 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1301: a claim already exists for this case' +summary: >- + The payer refused a new claim because a claim has already been raised for the + same case. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + - nhcx.flow.claim-reprocess + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1016 + - nhcx.error.payr-1322 + - nhcx.error.payr-1342 +--- + +# PAYR-1301: a claim already exists for this case + +## In plain words + +The case you named already has a claim, so the payer will not accept a new claim for it. You receive this code when your system sends a second new claim for one case. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1301`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Claim has already been raised for case number `%s`. Hence new claim request will not be accepted. + +`%s` is the case number you sent. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- A claim has already been raised for the case number in your request. +- Your request asked for a new claim rather than an update to the existing one. +- A claim cannot be cancelled once submitted. After the payer sends `response.complete`, it accepts no further submissions against that claim identifier. + +## How you know it worked + +Do not send the claim again. Follow the first claim for the case to its response. Any later request on the case goes out as a fresh request, with a new `x-hcx-correlation_id`. Reusing an inactive correlation id returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1301`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Do not raise a second claim for the case. Wait for the payer's response to the first claim on `/v1/claim/on_submit`. +2. If the payer queried the first claim, answer the query on the same claim. Follow [answer a payer query on a claim](../flows/claim-query-response.md). +3. If the payer rejected the claim and you dispute the decision, follow [ask the payer to reprocess a claim](../flows/claim-reprocess.md). +4. If your records show no earlier claim, search your submission log for an earlier `202 Accepted` on the same case number. diff --git a/catalogue/nhcx/errors/payr-1302.md b/catalogue/nhcx/errors/payr-1302.md new file mode 100644 index 000000000..54626a1cf --- /dev/null +++ b/catalogue/nhcx/errors/payr-1302.md @@ -0,0 +1,89 @@ +--- +id: nhcx.error.payr-1302 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1302: no approved preauthorisation for this case' +summary: >- + The payer refused a new claim because it found no approved preauthorisation for + the case. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.claim-submit + - nhcx.endpoint.participant-get-policies + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1010 + - nhcx.error.payr-1013 +--- + +# PAYR-1302: no approved preauthorisation for this case + +## In plain words + +A claim is paid against an approved preauthorisation. The payer found none for the case your claim names, so it will not accept the claim. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1302`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> No preauthorization approved record found for case number `%s`. Hence new claim request will not be accepted. + +`%s` is the case number you sent. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The payer has approved no preauthorisation for the case number in your claim. +- The preauthorisation exists but is not approved yet. It may still be under review or under query. +- Your claim carries a new identifier instead of the identifier of the approved preauthorisation. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1302`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Put the identifier of the approved preauthorisation in `Claim.identifier`, or reference the `preAuthRef` from its ClaimResponse. +2. Submit the claim only after the preauthorisation is approved and treatment is complete. Follow [submit a preauthorisation](../flows/preauth-submit.md) first. +3. Set `x-hcx-recipient_code` to the `processingID` from the [get policies](../endpoints/participant-get-policies.md) response, not the `PayerID`. diff --git a/catalogue/nhcx/errors/payr-1303.md b/catalogue/nhcx/errors/payr-1303.md new file mode 100644 index 000000000..bde7b304c --- /dev/null +++ b/catalogue/nhcx/errors/payr-1303.md @@ -0,0 +1,91 @@ +--- +id: nhcx.error.payr-1303 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1303: no active claim to update for this case' +summary: >- + The payer refused your query response because the case has no open claim to update. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + - nhcx.concept.queries-and-communication + flows: + - nhcx.flow.claim-query-response + - nhcx.flow.claim-submit + - nhcx.flow.claim-reprocess + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1304 + - nhcx.error.payr-1322 +--- + +# PAYR-1303: no active claim to update for this case + +## In plain words + +A query response updates a claim that is still open. The payer found no active claim for the case you named, so it refused the update. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- The payer queried your claim, and you answered with a query response on [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [answer a payer query on a claim](../flows/claim-query-response.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1303`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> No active claim record found for case number `%s`. Hence query updation request will not be accepted. + +`%s` is the case number you sent. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- No claim has been raised for the case number in your request. +- The claim for the case is closed. After the payer sends `response.complete`, it accepts no further submissions against that claim identifier. +- Your query response carries a different identifier from the claim it answers. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The query response step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries the payer's decision on your answered query: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1303`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Reuse the original `Claim.identifier` in the query response. +2. Check the payer's last response on the claim. If it was `response.complete`, the claim is closed and a query response will not be accepted. +3. To dispute a closed claim that was rejected, follow [ask the payer to reprocess a claim](../flows/claim-reprocess.md). +4. If no claim exists yet, submit one first. Follow [submit a claim after discharge](../flows/claim-submit.md). diff --git a/catalogue/nhcx/errors/payr-1304.md b/catalogue/nhcx/errors/payr-1304.md new file mode 100644 index 000000000..a4ee7743e --- /dev/null +++ b/catalogue/nhcx/errors/payr-1304.md @@ -0,0 +1,91 @@ +--- +id: nhcx.error.payr-1304 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1304: the claim for this case is not under query' +summary: >- + The payer refused your query response because it has not queried the claim for + this case. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + - nhcx.concept.queries-and-communication + - nhcx.concept.workflow-codes + flows: + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + - nhcx.fhir.claim-response + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1303 + - nhcx.error.payr-1321 +--- + +# PAYR-1304: the claim for this case is not under query + +## In plain words + +You can answer a query only while the payer is waiting for your answer. The payer holds no queried claim for the case you named. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- The payer queried your claim, and you answered with a query response on [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [answer a payer query on a claim](../flows/claim-query-response.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1304`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> No claim queried record found for case number `%s`. Hence query updation request will not be accepted. + +`%s` is the case number you sent. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The payer never queried the claim for the case number. +- Your system sent a query response without receiving a query. A query arrives on `/v1/claim/on_submit` as a ClaimResponse with `outcome` `partial` and adjudication reason `queried`. +- Your query response names a different case number from the queried claim. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The query response step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries the payer's decision on your answered query: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1304`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Send a query response only after a query arrives. Read `outcome` and the adjudication reason code together: `partial` with `queried` is a query. +2. Reuse the `Claim.identifier` of the queried claim. +3. Set `x-hcx-workflow_id` to the claim query response code from [workflow codes](../concepts/workflow-codes.md), not a preauthorisation code. diff --git a/catalogue/nhcx/errors/payr-1305.md b/catalogue/nhcx/errors/payr-1305.md new file mode 100644 index 000000000..557912d32 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1305.md @@ -0,0 +1,86 @@ +--- +id: nhcx.error.payr-1305 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1305: the use case is not valid for this case' +summary: >- + The payer refused the request because the use case it declares is not valid for + the case. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1321 +--- + +# PAYR-1305: the use case is not valid for this case + +## In plain words + +Every claim request declares what it is: a new claim or a resubmission. The payer did not accept the use case your request declared for this case. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1305`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid usecase requested for case number `%s`. Please try again with valid usecase. + +`%s` is the case number you sent. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The use case in your request is not a claim use case. The claim use cases are `Claim New` and `Claim Resubmit`. +- `Claim.use` is not `claim`. The value `preauthorization` marks the preauthorisation stage. +- The use case does not match the state of the case. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1305`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Set `Claim.use` to `claim` on every claim bundle. +2. If you send `x-hcx-use_case`, use the claim value for the step: `New` for a first claim, `Resubmit` for a resubmission. +3. Declare a resubmission only for a case that already has a claim. diff --git a/catalogue/nhcx/errors/payr-1306.md b/catalogue/nhcx/errors/payr-1306.md new file mode 100644 index 000000000..4743b6066 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1306.md @@ -0,0 +1,87 @@ +--- +id: nhcx.error.payr-1306 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1306: the procedure is not in the preauthorisation request' +summary: >- + The claim bills a procedure that the preauthorisation for the case never requested. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + - nhcx.flow.preauth-enhancement + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1308 + - nhcx.error.payr-1315 + - nhcx.error.payr-1013 +--- + +# PAYR-1306: the procedure is not in the preauthorisation request + +## In plain words + +A claim is checked item by item against the preauthorisation for the case. Your claim bills a procedure that the preauthorisation request did not contain. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1306`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> No item found in preauthorization request for procedure `%s` with item sequence `%s` for case number `%s`. Please try again with valid items. + +The three `%s` values are, in order, the procedure code, the item sequence and the case number. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The procedure code at the named item sequence does not appear in the preauthorisation request for the case. +- The payer matches the procedure code and the item sequence together. The right code under a different sequence does not match. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1306`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Claim only the procedures the preauthorisation requested. Reuse its procedure entries instead of rebuilding them. +2. Keep each item's `Claim.item[].sequence` as it was in the preauthorisation. +3. If treatment needed a procedure the preauthorisation did not cover, request an enhancement before discharge. Follow [request a preauthorisation enhancement](../flows/preauth-enhancement.md). diff --git a/catalogue/nhcx/errors/payr-1307.md b/catalogue/nhcx/errors/payr-1307.md new file mode 100644 index 000000000..c33f638b2 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1307.md @@ -0,0 +1,90 @@ +--- +id: nhcx.error.payr-1307 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1307: the procedure quantity is not valid' +summary: >- + The claim carries a quantity for a procedure that the payer does not accept for + the case. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1349 + - nhcx.error.payr-1306 + - nhcx.error.payr-1368 + - nhcx.error.payr-1362 +--- + +# PAYR-1307: the procedure quantity is not valid + +## In plain words + +The payer checked the quantity on a claimed procedure and did not accept it for this case. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1307`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid quantity requested for procedure `%s` with item sequence `%s` for case number `%s`. Please try again with valid quantity. + +The three `%s` values are, in order, the procedure code, the item sequence and the case number. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The quantity on the procedure at the named item sequence is not valid for the case. +- The payer checks every claim item against the approved preauthorisation for the case. +- For a cyclic procedure, the maximum number of cycles comes from the claim condition in the insurance plan. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1307`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Compare `Claim.item[].quantity` with the item at the same sequence in the approved preauthorisation. +2. Send the quantity of the procedure actually delivered to the patient. +3. On the LM100 item, send the number of days the patient was admitted. See [`PAYR-1362`](./payr-1362.md). +4. For a cyclic procedure, stay within the cycles the insurance plan allows. Payment covers only cycles with a biometric capture. diff --git a/catalogue/nhcx/errors/payr-1308.md b/catalogue/nhcx/errors/payr-1308.md new file mode 100644 index 000000000..f451281c9 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1308.md @@ -0,0 +1,86 @@ +--- +id: nhcx.error.payr-1308 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1308: the procedure is not in the active claim' +summary: >- + The update names a procedure that the claim now open for the case does not contain. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + - nhcx.concept.queries-and-communication + flows: + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1306 + - nhcx.error.payr-1303 +--- + +# PAYR-1308: the procedure is not in the active claim + +## In plain words + +An update to an open claim, such as a query response, must refer to items already in that claim. Your request names a procedure the active claim does not contain. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- The payer queried your claim, and you answered with a query response on [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [answer a payer query on a claim](../flows/claim-query-response.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1308`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> No item found in active claim request for procedure `%s` with item sequence `%s` for case number `%s`. Please try again with valid items. + +The three `%s` values are, in order, the procedure code, the item sequence and the case number. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The procedure code at the named item sequence is not in the active claim for the case. +- The payer matches the code and the item sequence together. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The query response step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries the payer's decision on your answered query: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1308`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Keep the items of the submitted claim when you answer a query. Change what the query asked for, such as supporting documents. +2. Reuse the original `Claim.identifier` and each item's `sequence`. diff --git a/catalogue/nhcx/errors/payr-1309.md b/catalogue/nhcx/errors/payr-1309.md new file mode 100644 index 000000000..fd9cd1010 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1309.md @@ -0,0 +1,87 @@ +--- +id: nhcx.error.payr-1309 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1309: the implant is not in the preauthorisation request' +summary: >- + The claim bills an implant that the preauthorisation for the case never requested. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + - nhcx.flow.preauth-enhancement + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1311 + - nhcx.error.payr-1317 + - nhcx.error.payr-1013 +--- + +# PAYR-1309: the implant is not in the preauthorisation request + +## In plain words + +A claim is checked item by item against the preauthorisation for the case. Your claim bills an implant that the preauthorisation request did not contain. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1309`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> No item found in preauthorization request for implant `%s` with item sequence `%s` for case number `%s`. Please try again with valid items. + +The three `%s` values are, in order, the implant code, the item sequence and the case number. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The implant code at the named item sequence does not appear in the preauthorisation request for the case. +- The payer matches the implant code and the item sequence together. The right code under a different sequence does not match. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1309`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Claim only the implants the preauthorisation requested. Reuse its implant entries instead of rebuilding them. +2. Keep each item's `Claim.item[].sequence` as it was in the preauthorisation. +3. If treatment needed an implant the preauthorisation did not cover, request an enhancement before discharge. Follow [request a preauthorisation enhancement](../flows/preauth-enhancement.md). diff --git a/catalogue/nhcx/errors/payr-1310.md b/catalogue/nhcx/errors/payr-1310.md new file mode 100644 index 000000000..61fb43ce9 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1310.md @@ -0,0 +1,85 @@ +--- +id: nhcx.error.payr-1310 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1310: the implant quantity is not valid' +summary: >- + The claim carries a quantity for an implant that the payer does not accept for + the case. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1335 + - nhcx.error.payr-1309 +--- + +# PAYR-1310: the implant quantity is not valid + +## In plain words + +The payer checked the quantity on a claimed implant and did not accept it for this case. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1310`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid quantity requested for implant `%s` with item sequence `%s` for case number `%s`. Please try again with valid quantity. + +The three `%s` values are, in order, the implant code, the item sequence and the case number. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The quantity on the implant at the named item sequence is not valid for the case. +- The payer checks every claim item against the approved preauthorisation for the case. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1310`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Compare `Claim.item[].quantity` with the item at the same sequence in the approved preauthorisation. +2. Send the quantity of the implant actually delivered to the patient. diff --git a/catalogue/nhcx/errors/payr-1311.md b/catalogue/nhcx/errors/payr-1311.md new file mode 100644 index 000000000..327934fa9 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1311.md @@ -0,0 +1,86 @@ +--- +id: nhcx.error.payr-1311 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1311: the implant is not in the active claim' +summary: >- + The update names an implant that the claim now open for the case does not contain. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + - nhcx.concept.queries-and-communication + flows: + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1309 + - nhcx.error.payr-1303 +--- + +# PAYR-1311: the implant is not in the active claim + +## In plain words + +An update to an open claim, such as a query response, must refer to items already in that claim. Your request names an implant the active claim does not contain. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- The payer queried your claim, and you answered with a query response on [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [answer a payer query on a claim](../flows/claim-query-response.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1311`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> No item found in active claim request for implant `%s` with item sequence `%s` for case number `%s`. Please try again with valid items. + +The three `%s` values are, in order, the implant code, the item sequence and the case number. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The implant code at the named item sequence is not in the active claim for the case. +- The payer matches the code and the item sequence together. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The query response step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries the payer's decision on your answered query: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1311`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Keep the items of the submitted claim when you answer a query. Change what the query asked for, such as supporting documents. +2. Reuse the original `Claim.identifier` and each item's `sequence`. diff --git a/catalogue/nhcx/errors/payr-1312.md b/catalogue/nhcx/errors/payr-1312.md new file mode 100644 index 000000000..b12285a1d --- /dev/null +++ b/catalogue/nhcx/errors/payr-1312.md @@ -0,0 +1,88 @@ +--- +id: nhcx.error.payr-1312 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1312: the investigation is not in the preauthorisation request' +summary: >- + The claim bills an investigation that the preauthorisation for the case never + requested. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + - nhcx.flow.preauth-enhancement + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1314 + - nhcx.error.payr-1316 + - nhcx.error.payr-1013 +--- + +# PAYR-1312: the investigation is not in the preauthorisation request + +## In plain words + +A claim is checked item by item against the preauthorisation for the case. Your claim bills an investigation that the preauthorisation request did not contain. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1312`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> No item found in preauthorization request for investigation `%s` with item sequence `%s` for case number `%s`. Please try again with valid items. + +The three `%s` values are, in order, the investigation code, the item sequence and the case number. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The investigation code at the named item sequence does not appear in the preauthorisation request for the case. +- The payer matches the investigation code and the item sequence together. The right code under a different sequence does not match. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1312`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Claim only the investigations the preauthorisation requested. Reuse its investigation entries instead of rebuilding them. +2. Keep each item's `Claim.item[].sequence` as it was in the preauthorisation. +3. If treatment needed an investigation the preauthorisation did not cover, request an enhancement before discharge. Follow [request a preauthorisation enhancement](../flows/preauth-enhancement.md). diff --git a/catalogue/nhcx/errors/payr-1313.md b/catalogue/nhcx/errors/payr-1313.md new file mode 100644 index 000000000..c914aaae0 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1313.md @@ -0,0 +1,84 @@ +--- +id: nhcx.error.payr-1313 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1313: the investigation quantity is not valid' +summary: >- + The claim carries a quantity for an investigation that the payer does not accept + for the case. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1312 +--- + +# PAYR-1313: the investigation quantity is not valid + +## In plain words + +The payer checked the quantity on a claimed investigation and did not accept it for this case. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1313`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid quantity requested for investigation `%s` with item sequence `%s` for case number `%s`. Please try again with valid quantity. + +The three `%s` values are, in order, the investigation code, the item sequence and the case number. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The quantity on the investigation at the named item sequence is not valid for the case. +- The payer checks every claim item against the approved preauthorisation for the case. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1313`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Compare `Claim.item[].quantity` with the item at the same sequence in the approved preauthorisation. +2. Send the quantity of the investigation actually delivered to the patient. diff --git a/catalogue/nhcx/errors/payr-1314.md b/catalogue/nhcx/errors/payr-1314.md new file mode 100644 index 000000000..0ef30d8bd --- /dev/null +++ b/catalogue/nhcx/errors/payr-1314.md @@ -0,0 +1,87 @@ +--- +id: nhcx.error.payr-1314 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1314: the investigation is not in the active claim' +summary: >- + The update names an investigation that the claim now open for the case does not + contain. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + - nhcx.concept.queries-and-communication + flows: + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1312 + - nhcx.error.payr-1303 +--- + +# PAYR-1314: the investigation is not in the active claim + +## In plain words + +An update to an open claim, such as a query response, must refer to items already in that claim. Your request names an investigation the active claim does not contain. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- The payer queried your claim, and you answered with a query response on [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [answer a payer query on a claim](../flows/claim-query-response.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1314`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> No item found in active claim request for investigation `%s` with item sequence `%s` for case number `%s`. Please try again with valid items. + +The three `%s` values are, in order, the investigation code, the item sequence and the case number. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The investigation code at the named item sequence is not in the active claim for the case. +- The payer matches the code and the item sequence together. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The query response step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries the payer's decision on your answered query: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1314`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Keep the items of the submitted claim when you answer a query. Change what the query asked for, such as supporting documents. +2. Reuse the original `Claim.identifier` and each item's `sequence`. diff --git a/catalogue/nhcx/errors/payr-1315.md b/catalogue/nhcx/errors/payr-1315.md new file mode 100644 index 000000000..3dc1cab12 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1315.md @@ -0,0 +1,85 @@ +--- +id: nhcx.error.payr-1315 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1315: the procedure was rejected at preauthorisation' +summary: >- + The claim bills a procedure that the payer rejected when it decided the preauthorisation. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + - nhcx.fhir.preauth-response + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1306 +--- + +# PAYR-1315: the procedure was rejected at preauthorisation + +## In plain words + +When the payer decided the preauthorisation, it rejected one of the procedures. Your claim bills that procedure anyway, so the payer refused the claim. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1315`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Rejected item found for preauthorization for procedure `%s` with item sequence `%s` for case number `%s`. Please try again with valid items. + +The three `%s` values are, in order, the procedure code, the item sequence and the case number. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The preauthorisation response rejected the procedure at the named item sequence. +- Your claim includes that item. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1315`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Remove the rejected item from the claim. +2. Read the item adjudication in the preauthorisation's ClaimResponse before you build the claim. The adjudication with category `status` gives each item's decision. +3. Build claim items from the approved items only. diff --git a/catalogue/nhcx/errors/payr-1316.md b/catalogue/nhcx/errors/payr-1316.md new file mode 100644 index 000000000..d7a93953a --- /dev/null +++ b/catalogue/nhcx/errors/payr-1316.md @@ -0,0 +1,85 @@ +--- +id: nhcx.error.payr-1316 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1316: the investigation was rejected at preauthorisation' +summary: >- + The claim bills an investigation that the payer rejected when it decided the preauthorisation. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + - nhcx.fhir.preauth-response + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1312 +--- + +# PAYR-1316: the investigation was rejected at preauthorisation + +## In plain words + +When the payer decided the preauthorisation, it rejected one of the investigations. Your claim bills that investigation anyway, so the payer refused the claim. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1316`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Rejected item found for preauthorization for investigation `%s` with item sequence `%s` for case number `%s`. Please try again with valid items. + +The three `%s` values are, in order, the investigation code, the item sequence and the case number. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The preauthorisation response rejected the investigation at the named item sequence. +- Your claim includes that item. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1316`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Remove the rejected item from the claim. +2. Read the item adjudication in the preauthorisation's ClaimResponse before you build the claim. The adjudication with category `status` gives each item's decision. +3. Build claim items from the approved items only. diff --git a/catalogue/nhcx/errors/payr-1317.md b/catalogue/nhcx/errors/payr-1317.md new file mode 100644 index 000000000..b16b5cebb --- /dev/null +++ b/catalogue/nhcx/errors/payr-1317.md @@ -0,0 +1,85 @@ +--- +id: nhcx.error.payr-1317 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1317: the implant was rejected at preauthorisation' +summary: >- + The claim bills an implant that the payer rejected when it decided the preauthorisation. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + - nhcx.fhir.preauth-response + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1309 +--- + +# PAYR-1317: the implant was rejected at preauthorisation + +## In plain words + +When the payer decided the preauthorisation, it rejected one of the implants. Your claim bills that implant anyway, so the payer refused the claim. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1317`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Rejected item found for preauthorization for implant `%s` with item sequence `%s` for case number `%s`. Please try again with valid items. + +The three `%s` values are, in order, the implant code, the item sequence and the case number. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The preauthorisation response rejected the implant at the named item sequence. +- Your claim includes that item. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1317`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Remove the rejected item from the claim. +2. Read the item adjudication in the preauthorisation's ClaimResponse before you build the claim. The adjudication with category `status` gives each item's decision. +3. Build claim items from the approved items only. diff --git a/catalogue/nhcx/errors/payr-1318.md b/catalogue/nhcx/errors/payr-1318.md new file mode 100644 index 000000000..d1cd7ebfa --- /dev/null +++ b/catalogue/nhcx/errors/payr-1318.md @@ -0,0 +1,86 @@ +--- +id: nhcx.error.payr-1318 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1318: the claim has no requested treatment plan' +summary: >- + The claim carries no requested treatment plan for the case, so the payer cannot + check it. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1319 + - nhcx.error.payr-1359 + - nhcx.error.payr-1306 +--- + +# PAYR-1318: the claim has no requested treatment plan + +## In plain words + +The payer looks for the treatment your hospital requested for the case. It found none in the claim. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1318`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> No requested treatment plan found for case number `%s`. Please try again with valid items. + +`%s` is the case number you sent. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The claim carries no treatment item the payer can match for the case. +- The payer checks the claim against the approved preauthorisation. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1318`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Include the treatment items in `Claim.item`, each with its procedure code, category and amounts. +2. Reuse the procedure entries from the approved preauthorisation. diff --git a/catalogue/nhcx/errors/payr-1319.md b/catalogue/nhcx/errors/payr-1319.md new file mode 100644 index 000000000..e6018cb96 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1319.md @@ -0,0 +1,85 @@ +--- +id: nhcx.error.payr-1319 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1319: the claim has no requested investigation plan' +summary: >- + The claim carries no requested investigation plan for the case, so the payer cannot + check it. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1318 + - nhcx.error.payr-1312 +--- + +# PAYR-1319: the claim has no requested investigation plan + +## In plain words + +The payer looks for the investigations your hospital requested for the case. It found none in the claim. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1319`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> No requested investigation plan found for case number `%s`. Please try again with valid items. + +`%s` is the case number you sent. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The claim carries no investigation item the payer can match for the case. +- The payer checks the claim against the approved preauthorisation. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1319`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Include the investigation items the preauthorisation requested, each with its investigation code and amounts. +2. Reuse the investigation entries from the approved preauthorisation. diff --git a/catalogue/nhcx/errors/payr-1320.md b/catalogue/nhcx/errors/payr-1320.md new file mode 100644 index 000000000..0aa583efd --- /dev/null +++ b/catalogue/nhcx/errors/payr-1320.md @@ -0,0 +1,87 @@ +--- +id: nhcx.error.payr-1320 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1320: the payer has no details for the requested investigations' +summary: >- + The payer's system holds no details for the investigations the claim requests. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + - nhcx.concept.insurance-plan + flows: + - nhcx.flow.claim-submit + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1221 +--- + +# PAYR-1320: the payer has no details for the requested investigations + +## In plain words + +The payer looked up the investigations in your claim and found no details for them in its system. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1320`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> No details found for the requested investigations in the system. Hence request will not be processed. + +The message has no placeholder. + +The payer returns this code when: + +- A code for one of the investigations is not in the payer's master data for your hospital. +- Your system took the code from an outdated copy of the insurance plan. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1320`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Take codes from the current insurance plan for your hospital. Follow [request the insurance plan](../flows/insurance-plan-request.md). +2. Refresh the insurance plan at least weekly, and at once when the policy is renewed or amended. +3. Outdated tariff versions cause rate mismatches and automatic claim rejection. Record which plan version each claim used. +4. Check each code against the insurance plan. A code the plan does not list also returns [`PAYR-1221`](./payr-1221.md). diff --git a/catalogue/nhcx/errors/payr-1321.md b/catalogue/nhcx/errors/payr-1321.md new file mode 100644 index 000000000..285270a37 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1321.md @@ -0,0 +1,88 @@ +--- +id: nhcx.error.payr-1321 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1321: the workflow id is not valid for this step' +summary: >- + The payer could not process the request because the workflow id it carries is + not valid. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + - nhcx.concept.workflow-codes + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1003 + - nhcx.error.payr-1305 +--- + +# PAYR-1321: the workflow id is not valid for this step + +## In plain words + +Every request names its step in the claim cycle with a workflow id. The payer could not process the workflow id your request carried. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1321`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Error occurred while processing the request due to invalid workflow id as (`%s`) + +`%s` is the workflow id you sent in `x-hcx-workflow_id`. + +The payer returns this code when: + +- `x-hcx-workflow_id` carries a code that is not a claim workflow code. +- The code belongs to a different step, for example a preauthorisation or discharge code on a claim. +- The code does not fit the current state of the case. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1321`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Set `x-hcx-workflow_id` to the code for the claim step you are taking. A new claim is `15`, Claim Request Initiated. +2. For a query response and every other step, take the code from [workflow codes](../concepts/workflow-codes.md). +3. In PMJAY there is no separate discharge workflow. Submit the claim with the Claim Submitted workflow id, not a discharge code. diff --git a/catalogue/nhcx/errors/payr-1322.md b/catalogue/nhcx/errors/payr-1322.md new file mode 100644 index 000000000..9b605d6d6 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1322.md @@ -0,0 +1,87 @@ +--- +id: nhcx.error.payr-1322 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1322: the case is not in a state that accepts this request' +summary: >- + The payer refused the request because of the current state of the case it names. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1301 + - nhcx.error.payr-1342 +--- + +# PAYR-1322: the case is not in a state that accepts this request + +## In plain words + +The payer refused your request because of the state of the case. You receive this code in two situations, and the message tells them apart. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1322`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> No active case found for the given case number. + +On a case that is busy, the message reads `Active instance found for case number` instead. + +The message has no placeholder. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- Message `No active case found for the given case number.`: the payer holds no open case for that number. +- Message `Active instance found for case number`: you sent a second request on the case while the first was still queued with the payer. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1322`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. For no active case, check that the case number is the identifier of the approved preauthorisation. A closed claim does not reopen. +2. For an active instance, wait for the payer's response to the first request on `/v1/claim/on_submit`. Send the next request on the case after it arrives. +3. Send every request on a case one at a time. Queue the next request in your system until the previous response arrives. diff --git a/catalogue/nhcx/errors/payr-1323.md b/catalogue/nhcx/errors/payr-1323.md new file mode 100644 index 000000000..57f770fc6 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1323.md @@ -0,0 +1,89 @@ +--- +id: nhcx.error.payr-1323 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1323: the beneficiary''s wallet balance is too low' +summary: >- + The payer refused the claim because the beneficiary does not have enough scheme + balance left. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + - nhcx.concept.coverage-eligibility-purposes + flows: + - nhcx.flow.claim-submit + - nhcx.flow.coverage-eligibility-check + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1356 + - nhcx.error.payr-1201 + - nhcx.error.payr-1008 +--- + +# PAYR-1323: the beneficiary's wallet balance is too low + +## In plain words + +Each beneficiary has a wallet: the amount the scheme will still pay for them. The wallet does not hold enough to pay this claim. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1323`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Insufficient wallet balance. Hence the request will not be processed. + +The message has no placeholder. + +The payer returns this code when: + +- The amount claimed is more than the beneficiary's available wallet balance. +- The claimed amount must be greater than zero and not more than the balance wallet amount. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1323`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Check the balance with a [coverage eligibility check](../flows/coverage-eligibility-check.md) of purpose `validation`. It returns the used amount, the available balance and the wallet liability. +2. Keep the claimed amount at or below the available balance. +3. If the patient must pay the difference, check that patient liability applies at your hospital. See [`PAYR-1356`](./payr-1356.md). diff --git a/catalogue/nhcx/errors/payr-1324.md b/catalogue/nhcx/errors/payr-1324.md new file mode 100644 index 000000000..0397e591f --- /dev/null +++ b/catalogue/nhcx/errors/payr-1324.md @@ -0,0 +1,86 @@ +--- +id: nhcx.error.payr-1324 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1324: the discharge stage is not valid' +summary: >- + The claim carries a discharge stage that the payer does not accept. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1095 + - nhcx.error.payr-1514 + - nhcx.error.payr-1362 +--- + +# PAYR-1324: the discharge stage is not valid + +## In plain words + +Every claim says at what stage the patient was discharged, relative to surgery. The stage in your claim is not a value the payer accepts. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1324`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid discharge stage received for case number `%s`. Hence the request will not be processed. + +`%s` is the case number you sent. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The discharge entry in `Claim.supportingInfo` carries a stage value the payer does not recognise. +- The accepted stage values are `Before Surgery`, `During Surgery` and `After Surgery`. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1324`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Send one `Claim.supportingInfo` entry with category `DIS` and code `DTH`, `DTM`, `LAMA` or `DAMA`. +2. Put the stage in `valueString`, spelled exactly as one of the accepted values. +3. Send the entry on every claim, surgical or medical. diff --git a/catalogue/nhcx/errors/payr-1325.md b/catalogue/nhcx/errors/payr-1325.md new file mode 100644 index 000000000..e1ab721b1 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1325.md @@ -0,0 +1,88 @@ +--- +id: nhcx.error.payr-1325 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1325: the admission date is not valid' +summary: >- + The payer read the admission date in the claim but does not accept it for the + case. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1327 + - nhcx.error.payr-1357 + - nhcx.error.payr-1502 +--- + +# PAYR-1325: the admission date is not valid + +## In plain words + +The payer read the admission date in your claim but does not accept it for this case. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1325`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid admission date received for case number `%s`. Hence the request will not be processed. + +`%s` is the case number you sent. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The admission date is not a valid date for the case. +- The admission date does not match the patient's record of the admission. +- An admission date later than the discharge date has its own code, [`PAYR-1357`](./payr-1357.md). + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1325`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Carry each date in its own `Claim.supportingInfo` entry, built as the [claim request bundle](../fhir/claim-request.md) shows it. +2. Use the actual admission date and time from the patient's record. +3. Send the date as a string value or as timing, in the [NRCeS](../../shared/glossary/nrces.md) date-time format. Use a full date-time with the offset, in the form `YYYY-MM-DDThh:mm:ss+05:30`. diff --git a/catalogue/nhcx/errors/payr-1326.md b/catalogue/nhcx/errors/payr-1326.md new file mode 100644 index 000000000..67bda6caa --- /dev/null +++ b/catalogue/nhcx/errors/payr-1326.md @@ -0,0 +1,88 @@ +--- +id: nhcx.error.payr-1326 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1326: the discharge date is not valid' +summary: >- + The payer read the discharge date in the claim but does not accept it for the + case. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1328 + - nhcx.error.payr-1357 + - nhcx.error.payr-1099 +--- + +# PAYR-1326: the discharge date is not valid + +## In plain words + +The payer read the discharge date in your claim but does not accept it for this case. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1326`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid discharge date received for case number `%s`. Hence the request will not be processed. + +`%s` is the case number you sent. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The discharge date is not a valid date for the case. +- The discharge date does not match the patient's record of the admission. +- An admission date later than the discharge date has its own code, [`PAYR-1357`](./payr-1357.md). + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1326`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Carry each date in its own `Claim.supportingInfo` entry, built as the [claim request bundle](../fhir/claim-request.md) shows it. +2. Use the actual discharge date and time from the patient's record. +3. Send the date as a string value or as timing, in the [NRCeS](../../shared/glossary/nrces.md) date-time format. Use a full date-time with the offset, in the form `YYYY-MM-DDThh:mm:ss+05:30`. diff --git a/catalogue/nhcx/errors/payr-1327.md b/catalogue/nhcx/errors/payr-1327.md new file mode 100644 index 000000000..29aa01ae3 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1327.md @@ -0,0 +1,86 @@ +--- +id: nhcx.error.payr-1327 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1327: the admission date is in the wrong format' +summary: >- + The payer could not read the admission date in the claim because of its format. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1325 + - nhcx.error.payr-1357 + - nhcx.error.payr-1502 +--- + +# PAYR-1327: the admission date is in the wrong format + +## In plain words + +The payer could not read the admission date in your claim. The date is not in the format it expects. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1327`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid admission date format received for case number `%s`. Hence the request will not be processed. + +`%s` is the case number you sent. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The admission date is not a valid [NRCeS](../../shared/glossary/nrces.md) date-time. +- The admission date is sent with a value type the payer does not read for that entry. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1327`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Carry each date in its own `Claim.supportingInfo` entry, built as the [claim request bundle](../fhir/claim-request.md) shows it. +2. Send the date as a string value or as timing, in the NRCeS date-time format. Use a full date-time with the offset, in the form `YYYY-MM-DDThh:mm:ss+05:30`. +3. Use the same offset on every date in the claim. diff --git a/catalogue/nhcx/errors/payr-1328.md b/catalogue/nhcx/errors/payr-1328.md new file mode 100644 index 000000000..509396b4c --- /dev/null +++ b/catalogue/nhcx/errors/payr-1328.md @@ -0,0 +1,86 @@ +--- +id: nhcx.error.payr-1328 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1328: the discharge date is in the wrong format' +summary: >- + The payer could not read the discharge date in the claim because of its format. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1326 + - nhcx.error.payr-1357 + - nhcx.error.payr-1099 +--- + +# PAYR-1328: the discharge date is in the wrong format + +## In plain words + +The payer could not read the discharge date in your claim. The date is not in the format it expects. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1328`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid discharge date format received for case number `%s`. Hence the request will not be processed. + +`%s` is the case number you sent. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The discharge date is not a valid [NRCeS](../../shared/glossary/nrces.md) date-time. +- The discharge date is sent with a value type the payer does not read for that entry. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1328`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Carry each date in its own `Claim.supportingInfo` entry, built as the [claim request bundle](../fhir/claim-request.md) shows it. +2. Send the date as a string value or as timing, in the NRCeS date-time format. Use a full date-time with the offset, in the form `YYYY-MM-DDThh:mm:ss+05:30`. +3. Use the same offset on every date in the claim. diff --git a/catalogue/nhcx/errors/payr-1329.md b/catalogue/nhcx/errors/payr-1329.md new file mode 100644 index 000000000..ff14cf292 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1329.md @@ -0,0 +1,88 @@ +--- +id: nhcx.error.payr-1329 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1329: the registration date is not valid' +summary: >- + The payer read the registration date in the claim but does not accept it for the + case. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1330 + - nhcx.error.payr-1358 + - nhcx.error.payr-1098 +--- + +# PAYR-1329: the registration date is not valid + +## In plain words + +The payer read the registration date in your claim but does not accept it for this case. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1329`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid registration date received for case number `%s`. Hence the request will not be processed. + +`%s` is the case number you sent. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The registration date is not a valid date for the case. +- The registration date does not match the patient's record of the admission. +- A registration date too long after admission has its own code, [`PAYR-1358`](./payr-1358.md). + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1329`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Send the registration date in the `Claim.supportingInfo` entry with category `OTH` and code `EDT`. +2. Use the actual registration date and time from the patient's record. +3. Send the date as a string value or as timing, in the [NRCeS](../../shared/glossary/nrces.md) date-time format. Use a full date-time with the offset, in the form `YYYY-MM-DDThh:mm:ss+05:30`. diff --git a/catalogue/nhcx/errors/payr-1330.md b/catalogue/nhcx/errors/payr-1330.md new file mode 100644 index 000000000..976655f7e --- /dev/null +++ b/catalogue/nhcx/errors/payr-1330.md @@ -0,0 +1,86 @@ +--- +id: nhcx.error.payr-1330 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1330: the registration date is in the wrong format' +summary: >- + The payer could not read the registration date in the claim because of its format. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1329 + - nhcx.error.payr-1358 + - nhcx.error.payr-1098 +--- + +# PAYR-1330: the registration date is in the wrong format + +## In plain words + +The payer could not read the registration date in your claim. The date is not in the format it expects. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1330`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid registration date format received for case number `%s`. Hence the request will not be processed. + +`%s` is the case number you sent. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The registration date is not a valid [NRCeS](../../shared/glossary/nrces.md) date-time. +- The registration date is sent with a value type the payer does not read for that entry. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1330`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Send the registration date in the `Claim.supportingInfo` entry with category `OTH` and code `EDT`. +2. Send the date as a string value or as timing, in the NRCeS date-time format. Use a full date-time with the offset, in the form `YYYY-MM-DDThh:mm:ss+05:30`. +3. Use the same offset on every date in the claim. diff --git a/catalogue/nhcx/errors/payr-1331.md b/catalogue/nhcx/errors/payr-1331.md new file mode 100644 index 000000000..48d9c0b45 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1331.md @@ -0,0 +1,86 @@ +--- +id: nhcx.error.payr-1331 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1331: the receiver is not registered in NHCX' +summary: >- + The payer found that the receiver named in the claim is not a registered participant. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + - nhcx.concept.participant-code + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + - nhcx.endpoint.participant-get-policies + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1003 +--- + +# PAYR-1331: the receiver is not registered in NHCX + +## In plain words + +Every request names the participant that should receive it. The receiver in your request is not a registered [NHCX](../../shared/glossary/nhcx.md) participant. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- NHCX answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1331`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Receiver not registered in NHCX. Please try again with valid receiver details. + +The message has no placeholder. + +The payer returns this code when: + +- `x-hcx-recipient_code` carries a code that is not a registered participant code. +- Your system used the payer's `PayerID` instead of its `processingID`. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1331`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Set `x-hcx-recipient_code` to the `processingID` from the [get policies](../endpoints/participant-get-policies.md) response. +2. Check the code is a registered [participant code](../concepts/participant-code.md) before you send. +3. The same condition at the exchange returns [`NHCX-1003`](./nhcx-1003.md). diff --git a/catalogue/nhcx/errors/payr-1332.md b/catalogue/nhcx/errors/payr-1332.md new file mode 100644 index 000000000..3830ecbb7 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1332.md @@ -0,0 +1,84 @@ +--- +id: nhcx.error.payr-1332 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1332: the Claim Review Committee request is not valid' +summary: >- + The payer refused a request meant for review of a claim decision. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + - nhcx.concept.reprocess-and-cancel + flows: + - nhcx.flow.claim-reprocess + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1343 +--- + +# PAYR-1332: the Claim Review Committee request is not valid + +## In plain words + +A rejected claim can be sent for review by the Claim Review Committee ([CRC](../glossary/crc.md)). The payer did not accept your request for that review. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- The payer decided your claim, and you asked for a review of that decision. You followed [ask the payer to reprocess a claim](../flows/claim-reprocess.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1332`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid CRC request. + +The message has no placeholder. + +The payer returns this code when: + +- The payer does not accept the request as a CRC review for the case. The message gives no further detail. +- The CRC decision on a case is final. No further erroneous claim can be raised against it. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The review step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries the payer's decision on your request: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1332`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Check whether the CRC has already decided the case. If it has, the decision stands. +2. Build the request as [ask the payer to reprocess a claim](../flows/claim-reprocess.md) describes. diff --git a/catalogue/nhcx/errors/payr-1333.md b/catalogue/nhcx/errors/payr-1333.md new file mode 100644 index 000000000..cd6e704f6 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1333.md @@ -0,0 +1,82 @@ +--- +id: nhcx.error.payr-1333 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1333: the claim type is not valid' +summary: >- + The claim says in-patient or out-patient in a way the payer does not accept. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 +--- + +# PAYR-1333: the claim type is not valid + +## In plain words + +Every claim says whether the care was in-patient or out-patient. The payer did not accept the claim type in your claim. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1333`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid claim type (in-patient/out-patient) received. Hence the request will not be processed. + +The message has no placeholder. + +The payer returns this code when: + +- `Claim.type` carries a code the payer does not accept as in-patient or out-patient. +- The claim type differs from the care the case was approved for. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1333`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Set `Claim.type` to the care type of the case. For in-patient care, use [SNOMED CT](../../shared/glossary/snomed-ct.md) `737481003`, Inpatient care management. +2. Keep the claim type the same as in the approved preauthorisation. diff --git a/catalogue/nhcx/errors/payr-1334.md b/catalogue/nhcx/errors/payr-1334.md new file mode 100644 index 000000000..a7d33e05b --- /dev/null +++ b/catalogue/nhcx/errors/payr-1334.md @@ -0,0 +1,85 @@ +--- +id: nhcx.error.payr-1334 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1334: the payer has no configuration for your hospital' +summary: >- + The payer's system holds no configuration for the hospital that sent the claim. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1105 + - nhcx.error.payr-1239 +--- + +# PAYR-1334: the payer has no configuration for your hospital + +## In plain words + +The payer could not find a configuration for your hospital in its system. The fix is on the payer's side. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1334`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Hospital configuration not found. Please contact support team. + +The message has no placeholder. + +The payer returns this code when: + +- The payer's system holds no configuration for your hospital. +- Your request identifies the hospital in a way the payer cannot match. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1334`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Check that `x-hcx-sender_code` is your own registered participant code. +2. Check the provider Organization carries the hospital's [HFR](../../shared/glossary/hfr.md) id as an identifier with type code `NPI`. It must match the id recorded in NHCX for your participant code. +3. If both are right, contact the support team with the case number and your `x-hcx-correlation_id`. diff --git a/catalogue/nhcx/errors/payr-1335.md b/catalogue/nhcx/errors/payr-1335.md new file mode 100644 index 000000000..0b859d520 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1335.md @@ -0,0 +1,83 @@ +--- +id: nhcx.error.payr-1335 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1335: the implant quantity is not valid' +summary: >- + The claim carries an implant quantity that the payer does not accept. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1310 + - nhcx.error.payr-1336 +--- + +# PAYR-1335: the implant quantity is not valid + +## In plain words + +The payer checked the quantity on an implant in your claim and did not accept it. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1335`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid implant quantity received as `%s` for implant `%s` for case number `%s`. Please try again with valid data. + +The three `%s` values are, in order, the quantity you sent, the implant code and the case number. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The quantity on the implant is not valid for the case. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1335`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Send the number of implants actually used. +2. Compare the quantity with the implant at the same sequence in the approved preauthorisation. diff --git a/catalogue/nhcx/errors/payr-1336.md b/catalogue/nhcx/errors/payr-1336.md new file mode 100644 index 000000000..9275deb35 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1336.md @@ -0,0 +1,84 @@ +--- +id: nhcx.error.payr-1336 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1336: the implant unit price is not valid' +summary: >- + The claim carries an implant unit price that the payer does not accept. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1337 + - nhcx.error.payr-1017 +--- + +# PAYR-1336: the implant unit price is not valid + +## In plain words + +The payer checked the unit price on an implant in your claim and did not accept it. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1336`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid implant unit price received as INR `%s` for implant `%s` for case number `%s`. Please try again with valid data. + +The three `%s` values are, in order, the unit price in rupees you sent, the implant code and the case number. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The unit price on the implant is not valid for the case. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1336`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Take the implant price from the current insurance plan for your hospital. +2. Refresh the insurance plan at least weekly, and at once when the policy is renewed or amended. +3. Outdated tariff versions cause rate mismatches and automatic claim rejection. Record which plan version each claim used. diff --git a/catalogue/nhcx/errors/payr-1337.md b/catalogue/nhcx/errors/payr-1337.md new file mode 100644 index 000000000..c8f692183 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1337.md @@ -0,0 +1,84 @@ +--- +id: nhcx.error.payr-1337 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1337: the implant net amount is not valid' +summary: >- + The claim carries an implant net amount that the payer does not accept. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1336 + - nhcx.error.payr-1017 +--- + +# PAYR-1337: the implant net amount is not valid + +## In plain words + +The payer checked the net amount on an implant in your claim and did not accept it. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1337`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid implant net amount received as INR `%s` for implant `%s` for case number `%s`. Please try again with valid data. + +The three `%s` values are, in order, the net amount in rupees you sent, the implant code and the case number. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The net amount on the implant is not valid for the case. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1337`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Recalculate `net` from the quantity and unit price you send for the implant. +2. Take the implant price from the current insurance plan for your hospital. +3. Amount calculations that do not add up also return [`PAYR-1017`](./payr-1017.md). diff --git a/catalogue/nhcx/errors/payr-1338.md b/catalogue/nhcx/errors/payr-1338.md new file mode 100644 index 000000000..978f8d2cc --- /dev/null +++ b/catalogue/nhcx/errors/payr-1338.md @@ -0,0 +1,86 @@ +--- +id: nhcx.error.payr-1338 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1338: the implant attachment is not valid' +summary: >- + The claim carries an implant attachment that the payer does not accept. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1341 +--- + +# PAYR-1338: the implant attachment is not valid + +## In plain words + +The payer checked the attachment on an implant in your claim and did not accept it. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1338`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid implant attachment received for investigation `%s` for case number `%s`. Please try again with valid data. + +The two `%s` values are the item code and the case number. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The attachment linked to the item is not valid. +- The message names the item as an investigation, even on an implant. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1338`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Encode the attachment value as Base64. +2. Give the attachment a name. The name cannot be empty. +3. Use one of the allowed content types: `application/pdf`, `application/jpg`, `application/jpeg`, `application/png` or `application/fhir+json`. +4. Keep each document under 2 MB. The whole bundle can be 20 MB at most. +5. Link one document per item. Merge several documents for one item into one file. diff --git a/catalogue/nhcx/errors/payr-1339.md b/catalogue/nhcx/errors/payr-1339.md new file mode 100644 index 000000000..fd324ba62 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1339.md @@ -0,0 +1,85 @@ +--- +id: nhcx.error.payr-1339 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1339: the implant status is not valid' +summary: >- + The claim carries an implant status that the payer does not accept. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1340 + - nhcx.error.payr-1345 +--- + +# PAYR-1339: the implant status is not valid + +## In plain words + +The payer checked the status on an implant in your claim and did not accept it. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1339`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid implant status received as `%s` for investigation `%s` for case number `%s`. Please try again with valid data. + +The three `%s` values are, in order, the status you sent, the item code and the case number. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The status on the implant is not a value the payer accepts. +- The message names the item as an investigation, even on an implant. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1339`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Compare the status on the implant with the item at the same sequence in the approved preauthorisation. +2. Send `Requested` as the status on a requested item. The payer requires that value on the LM100 item. +3. The full list of accepted status values is not yet published. diff --git a/catalogue/nhcx/errors/payr-1340.md b/catalogue/nhcx/errors/payr-1340.md new file mode 100644 index 000000000..d70fcaf82 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1340.md @@ -0,0 +1,84 @@ +--- +id: nhcx.error.payr-1340 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1340: the investigation status is not valid' +summary: >- + The claim carries an investigation status that the payer does not accept. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1339 + - nhcx.error.payr-1345 +--- + +# PAYR-1340: the investigation status is not valid + +## In plain words + +The payer checked the status on an investigation in your claim and did not accept it. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1340`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid investigation status received as `%s` for investigation `%s` for case number `%s`. Please try again with valid data. + +The three `%s` values are, in order, the status you sent, the investigation code and the case number. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The status on the investigation is not a value the payer accepts. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1340`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Compare the status on the investigation with the item at the same sequence in the approved preauthorisation. +2. Send `Requested` as the status on a requested item. The payer requires that value on the LM100 item. +3. The full list of accepted status values is not yet published. diff --git a/catalogue/nhcx/errors/payr-1341.md b/catalogue/nhcx/errors/payr-1341.md new file mode 100644 index 000000000..f3ab17cf5 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1341.md @@ -0,0 +1,85 @@ +--- +id: nhcx.error.payr-1341 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1341: the investigation attachment is not valid' +summary: >- + The claim carries an investigation attachment that the payer does not accept. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1338 +--- + +# PAYR-1341: the investigation attachment is not valid + +## In plain words + +The payer checked the attachment on an investigation in your claim and did not accept it. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1341`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid investigation attachment received for investigation `%s` for case number `%s`. Please try again with valid data. + +The two `%s` values are the investigation code and the case number. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The attachment linked to the investigation is not valid. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1341`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Encode the attachment value as Base64. +2. Give the attachment a name. The name cannot be empty. +3. Use one of the allowed content types: `application/pdf`, `application/jpg`, `application/jpeg`, `application/png` or `application/fhir+json`. +4. Keep each document under 2 MB. The whole bundle can be 20 MB at most. +5. Link one document per item. Merge several documents for one item into one file. diff --git a/catalogue/nhcx/errors/payr-1342.md b/catalogue/nhcx/errors/payr-1342.md new file mode 100644 index 000000000..e3bae6fd3 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1342.md @@ -0,0 +1,89 @@ +--- +id: nhcx.error.payr-1342 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1342: a case in progress blocks a new reimbursement request' +summary: >- + The payer refused a new reimbursement request because an earlier request on the + same case is still in progress. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + - nhcx.concept.workflow-codes + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1343 + - nhcx.error.payr-1213 + - nhcx.error.payr-1322 +--- + +# PAYR-1342: a case in progress blocks a new reimbursement request + +## In plain words + +A reimbursement claim is paid back to the hospital after treatment. The payer is still processing an earlier request on this case, so it refused the new one. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1342`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Existing case in progress found for case number `%s`. Hence new reimbursement request will not be accepted. + +`%s` is the case number you sent. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- An earlier request on the case number is still in progress with the payer. +- Your system sent a new reimbursement request before the payer finished the earlier one. +- Reimbursement claims use their own workflow ids, such as `R15` for a submitted reimbursement claim. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1342`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Wait for the payer's response to the earlier request before you send a new one. +2. Check that `x-hcx-workflow_id` is the reimbursement code for the step. Take it from [workflow codes](../concepts/workflow-codes.md). +3. Send the new request with a new `x-hcx-correlation_id` once the earlier request is finished. diff --git a/catalogue/nhcx/errors/payr-1343.md b/catalogue/nhcx/errors/payr-1343.md new file mode 100644 index 000000000..e91f3be99 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1343.md @@ -0,0 +1,88 @@ +--- +id: nhcx.error.payr-1343 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1343: a reimbursement was already approved for this case' +summary: >- + The payer refused a new reimbursement request because it has already approved + one for the same case. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + - nhcx.concept.workflow-codes + flows: + - nhcx.flow.claim-submit + - nhcx.flow.claim-reprocess + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1342 + - nhcx.error.payr-1301 +--- + +# PAYR-1343: a reimbursement was already approved for this case + +## In plain words + +The payer already approved a reimbursement for this case. It will not process a second reimbursement request for the same case. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1343`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Previous reimbursement approved record found for the new reimbursement request for case number `%s`. Hence request will not be processed further. + +`%s` is the case number you sent. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- An approved reimbursement already exists for the case number. +- Your request is a new reimbursement request, not a dispute of the approved one. + +## How you know it worked + +Do not resend the reimbursement request. Send any reprocess as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. Reusing an inactive correlation id returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1343`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Do not resend the reimbursement request for the case. +2. To dispute the approved amount, raise a reprocess request instead. A reimbursement reprocess uses its own workflow id, `R122`. +3. Follow [ask the payer to reprocess a claim](../flows/claim-reprocess.md) for the request itself. diff --git a/catalogue/nhcx/errors/payr-1344.md b/catalogue/nhcx/errors/payr-1344.md new file mode 100644 index 000000000..4020c9cc3 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1344.md @@ -0,0 +1,89 @@ +--- +id: nhcx.error.payr-1344 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1344: the payer has no details for the requested procedures' +summary: >- + The payer's system holds no details for the procedures the claim requests. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + - nhcx.concept.insurance-plan + flows: + - nhcx.flow.claim-submit + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1204 + - nhcx.error.payr-1106 + - nhcx.error.payr-1240 +--- + +# PAYR-1344: the payer has no details for the requested procedures + +## In plain words + +The payer looked up the procedures in your claim and found no details for them in its system. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1344`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> No details found for the requested procedures in the system. + +The message has no placeholder. + +The payer returns this code when: + +- A code for one of the procedures is not in the payer's master data for your hospital. +- Your system took the code from an outdated copy of the insurance plan. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1344`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Take codes from the current insurance plan for your hospital. Follow [request the insurance plan](../flows/insurance-plan-request.md). +2. Refresh the insurance plan at least weekly, and at once when the policy is renewed or amended. +3. Outdated tariff versions cause rate mismatches and automatic claim rejection. Record which plan version each claim used. +4. Check each code against the insurance plan. A code the plan does not list also returns [`PAYR-1204`](./payr-1204.md). diff --git a/catalogue/nhcx/errors/payr-1345.md b/catalogue/nhcx/errors/payr-1345.md new file mode 100644 index 000000000..8be64456a --- /dev/null +++ b/catalogue/nhcx/errors/payr-1345.md @@ -0,0 +1,84 @@ +--- +id: nhcx.error.payr-1345 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1345: the procedure status is not valid' +summary: >- + The claim carries a procedure status that the payer does not accept. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1362 + - nhcx.error.payr-1340 +--- + +# PAYR-1345: the procedure status is not valid + +## In plain words + +The payer checked the status on a procedure in your claim and did not accept it. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1345`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid procedure status received as `%s` for procedure `%s` for case number `%s`. Please try again with valid data. + +The three `%s` values are, in order, the status you sent, the procedure code and the case number. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The status on the procedure is not a value the payer accepts. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1345`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Compare the status on the procedure with the item at the same sequence in the approved preauthorisation. +2. Send `Requested` as the status on a requested item. The payer requires that value on the LM100 item. +3. The full list of accepted status values is not yet published. diff --git a/catalogue/nhcx/errors/payr-1346.md b/catalogue/nhcx/errors/payr-1346.md new file mode 100644 index 000000000..c2a2b1f05 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1346.md @@ -0,0 +1,83 @@ +--- +id: nhcx.error.payr-1346 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1346: the procedure description is not valid' +summary: >- + The claim carries a procedure description that the payer does not accept. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1204 + - nhcx.error.payr-1203 +--- + +# PAYR-1346: the procedure description is not valid + +## In plain words + +The payer checked the description on a procedure in your claim and did not accept it. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1346`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid procedure description received as `%s` for procedure `%s` for case number `%s`. Please try again with valid data. + +The three `%s` values are, in order, the description you sent, the procedure code and the case number. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The description on the procedure does not match what the payer holds for the procedure code. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1346`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Send the procedure description exactly as the insurance plan gives it for that procedure code. +2. Refresh the insurance plan at least weekly, and at once when the policy is renewed or amended. diff --git a/catalogue/nhcx/errors/payr-1347.md b/catalogue/nhcx/errors/payr-1347.md new file mode 100644 index 000000000..7d1ff0113 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1347.md @@ -0,0 +1,82 @@ +--- +id: nhcx.error.payr-1347 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1347: the procedure type is not valid' +summary: >- + The claim carries a procedure type that the payer does not accept. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1346 +--- + +# PAYR-1347: the procedure type is not valid + +## In plain words + +The payer checked the type on a procedure in your claim and did not accept it. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1347`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid procedure type received as `%s` for procedure `%s` for case number `%s`. Please try again with valid data. + +The three `%s` values are, in order, the type you sent, the procedure code and the case number. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The type on the procedure does not match what the payer holds for the procedure code. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1347`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Send the procedure type the insurance plan gives for the procedure code. +2. Compare the type with the procedure in the approved preauthorisation. diff --git a/catalogue/nhcx/errors/payr-1348.md b/catalogue/nhcx/errors/payr-1348.md new file mode 100644 index 000000000..e19135348 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1348.md @@ -0,0 +1,82 @@ +--- +id: nhcx.error.payr-1348 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1348: the procedure factor is not valid' +summary: >- + The claim carries a procedure factor that the payer does not accept. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1350 +--- + +# PAYR-1348: the procedure factor is not valid + +## In plain words + +The payer checked the factor on a procedure in your claim and did not accept it. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1348`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid procedure factor received as `%s` for procedure `%s` for case number `%s`. Please try again with valid data. + +The three `%s` values are, in order, the factor you sent, the procedure code and the case number. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- `Claim.item[].factor` on the procedure is not a value the payer accepts for the case. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1348`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Compare the factor with the procedure at the same sequence in the approved preauthorisation. +2. Do not recompute the factor on your side between preauthorisation and claim. diff --git a/catalogue/nhcx/errors/payr-1349.md b/catalogue/nhcx/errors/payr-1349.md new file mode 100644 index 000000000..e0d36fa3f --- /dev/null +++ b/catalogue/nhcx/errors/payr-1349.md @@ -0,0 +1,84 @@ +--- +id: nhcx.error.payr-1349 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1349: the procedure quantity is not valid' +summary: >- + The claim carries a procedure quantity that the payer does not accept. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1307 + - nhcx.error.payr-1368 +--- + +# PAYR-1349: the procedure quantity is not valid + +## In plain words + +The payer checked the quantity on a procedure in your claim and did not accept it. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1349`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid procedure quantity received as `%s` for procedure `%s` for case number `%s`. Please try again with valid data. + +The three `%s` values are, in order, the quantity you sent, the procedure code and the case number. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- `Claim.item[].quantity` on the procedure is not valid for the case. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1349`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Send the quantity actually delivered, compared with the approved preauthorisation. +2. On the LM100 item, send the number of days the patient was admitted. +3. For a cyclic procedure, stay within the cycles the insurance plan allows. diff --git a/catalogue/nhcx/errors/payr-1350.md b/catalogue/nhcx/errors/payr-1350.md new file mode 100644 index 000000000..ada0dd0de --- /dev/null +++ b/catalogue/nhcx/errors/payr-1350.md @@ -0,0 +1,85 @@ +--- +id: nhcx.error.payr-1350 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1350: the procedure net amount is not valid' +summary: >- + The claim carries a procedure net amount that the payer does not accept. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1017 + - nhcx.error.payr-1348 +--- + +# PAYR-1350: the procedure net amount is not valid + +## In plain words + +The payer checked the net amount on a procedure in your claim and did not accept it. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1350`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid procedure net amount received as INR `%s` for procedure `%s` for case number `%s`. Please try again with valid data. + +The three `%s` values are, in order, the net amount in rupees you sent, the procedure code and the case number. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- `Claim.item[].net` on the procedure is not valid for the case. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1350`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Take the package cost from the current insurance plan for your hospital. +2. Recalculate `net` from the `quantity`, `factor` and `unitPrice` you send. +3. Amount calculations that do not add up also return [`PAYR-1017`](./payr-1017.md). +4. Outdated tariff versions cause rate mismatches and automatic claim rejection. Record which plan version each claim used. diff --git a/catalogue/nhcx/errors/payr-1351.md b/catalogue/nhcx/errors/payr-1351.md new file mode 100644 index 000000000..d3f77cc05 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1351.md @@ -0,0 +1,84 @@ +--- +id: nhcx.error.payr-1351 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1351: the procedure speciality code is not valid' +summary: >- + The claim carries a procedure speciality code that the payer does not accept. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1203 + - nhcx.error.payr-1202 +--- + +# PAYR-1351: the procedure speciality code is not valid + +## In plain words + +The payer checked the speciality code on a procedure in your claim and did not accept it. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1351`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid speciality code received as `%s` for procedure `%s` for case number `%s`. Please try again with valid data. + +The three `%s` values are, in order, the speciality code you sent, the procedure code and the case number. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The speciality code in `Claim.item[].category` does not match the procedure in the insurance plan. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1351`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Send the category code of the specific cost of the plan in the insurance plan, for example `MG` for General Medicine. +2. Take the procedure and its speciality from the same entry in the insurance plan. +3. Refresh the insurance plan at least weekly, and at once when the policy is renewed or amended. diff --git a/catalogue/nhcx/errors/payr-1352.md b/catalogue/nhcx/errors/payr-1352.md new file mode 100644 index 000000000..6f61a94f4 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1352.md @@ -0,0 +1,86 @@ +--- +id: nhcx.error.payr-1352 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1352: the beneficiary and care plan do not fit this hospital' +summary: >- + The beneficiary and care plan in the claim match no rule for handling the case + at this hospital. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + - nhcx.concept.insurance-plan + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1353 +--- + +# PAYR-1352: the beneficiary and care plan do not fit this hospital + +## In plain words + +The payer checked the beneficiary and the care plan together for your hospital. The combination matches no criteria for handling the case there. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1352`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Requested beneficary details and careplan details does not match any criteria for processing the case at this hospital. Please try again with valid data. + +The message has no placeholder. + +The payer returns this code when: + +- The beneficiary details and care plan details in the claim do not match any criteria for your hospital. +- The insurance plan lists only the specialities relevant to your hospital. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1352`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Use the same beneficiary and care plan details as the approved preauthorisation. +2. Take the treatment from the insurance plan for your hospital. +3. Refresh the insurance plan at least weekly, and at once when the policy is renewed or amended. diff --git a/catalogue/nhcx/errors/payr-1353.md b/catalogue/nhcx/errors/payr-1353.md new file mode 100644 index 000000000..87261f77a --- /dev/null +++ b/catalogue/nhcx/errors/payr-1353.md @@ -0,0 +1,83 @@ +--- +id: nhcx.error.payr-1353 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1353: the care plan id is not valid' +summary: >- + The claim carries a care plan id the payer does not accept. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1103 + - nhcx.error.payr-1352 +--- + +# PAYR-1353: the care plan id is not valid + +## In plain words + +The care plan id in your claim is not one the payer accepts. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1353`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid careplan id received. Please try again with valid careplan id. + +The message has no placeholder. + +The payer returns this code when: + +- The care plan id in the claim is not valid for the beneficiary or the case. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1353`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Use the care plan recorded when the beneficiary was registered. +2. Keep the care plan id the same as in the approved preauthorisation. diff --git a/catalogue/nhcx/errors/payr-1354.md b/catalogue/nhcx/errors/payr-1354.md new file mode 100644 index 000000000..ef665311c --- /dev/null +++ b/catalogue/nhcx/errors/payr-1354.md @@ -0,0 +1,86 @@ +--- +id: nhcx.error.payr-1354 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1354: the claim failed a payer rule' +summary: >- + The claim failed one of the payer's rules, and the message does not name the rule. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + - nhcx.concept.insurance-plan + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1111 + - nhcx.error.payr-1245 +--- + +# PAYR-1354: the claim failed a payer rule + +## In plain words + +The claim broke one of the payer's rules. The message does not say which rule. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1354`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Rule failure. + +The message has no placeholder. + +The payer returns this code when: + +- The claim fails a rule the payer applies to the case. +- Scheme rules for each package sit in the claim conditions of the insurance plan. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1354`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Recheck each package in the claim against the claim conditions in the insurance plan. +2. Compare the claim with the approved preauthorisation, item by item. +3. If you find nothing, contact the support team with the case number and your `x-hcx-correlation_id`. diff --git a/catalogue/nhcx/errors/payr-1355.md b/catalogue/nhcx/errors/payr-1355.md new file mode 100644 index 000000000..b130a28dc --- /dev/null +++ b/catalogue/nhcx/errors/payr-1355.md @@ -0,0 +1,87 @@ +--- +id: nhcx.error.payr-1355 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1355: the payer has no details for the requested implants' +summary: >- + The payer's system holds no details for the implants the claim requests. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + - nhcx.concept.insurance-plan + flows: + - nhcx.flow.claim-submit + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1225 +--- + +# PAYR-1355: the payer has no details for the requested implants + +## In plain words + +The payer looked up the implants in your claim and found no details for them in its system. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1355`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> No details found for the requested implants in the system. Hence request will not be processed. + +The message has no placeholder. + +The payer returns this code when: + +- A code for one of the implants is not in the payer's master data for your hospital. +- Your system took the code from an outdated copy of the insurance plan. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1355`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Take codes from the current insurance plan for your hospital. Follow [request the insurance plan](../flows/insurance-plan-request.md). +2. Refresh the insurance plan at least weekly, and at once when the policy is renewed or amended. +3. Outdated tariff versions cause rate mismatches and automatic claim rejection. Record which plan version each claim used. +4. Check each code against the insurance plan. A code the plan does not list also returns [`PAYR-1225`](./payr-1225.md). diff --git a/catalogue/nhcx/errors/payr-1356.md b/catalogue/nhcx/errors/payr-1356.md new file mode 100644 index 000000000..df5fa5573 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1356.md @@ -0,0 +1,87 @@ +--- +id: nhcx.error.payr-1356 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1356: the wallet is short and the patient cannot pay the difference' +summary: >- + The beneficiary's scheme balance does not cover the amount, and the hospital may + not charge the patient the rest. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + - nhcx.concept.coverage-eligibility-purposes + flows: + - nhcx.flow.claim-submit + - nhcx.flow.coverage-eligibility-check + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1323 + - nhcx.error.payr-1201 +--- + +# PAYR-1356: the wallet is short and the patient cannot pay the difference + +## In plain words + +The beneficiary's wallet does not cover the amount you claimed. Your hospital is not allowed to charge the patient the difference, so the payer refused the claim. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1356`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Patient liability is not aplicable for the hospital and beneficiary do not have enough wallet balance with deficit amount INR `%s` for the requested preauthorization for case number `%s`. + +The two `%s` values are the deficit in rupees and the case number. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The claimed amount is more than the beneficiary's available wallet balance. +- Patient liability is not applicable for your hospital, so the patient cannot cover the deficit. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1356`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Check the balance with a [coverage eligibility check](../flows/coverage-eligibility-check.md) of purpose `validation`. It returns the available balance and the wallet liability. +2. Reduce the claimed amount by the deficit in the message, so it stays within the available balance. diff --git a/catalogue/nhcx/errors/payr-1357.md b/catalogue/nhcx/errors/payr-1357.md new file mode 100644 index 000000000..5cecd7de3 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1357.md @@ -0,0 +1,85 @@ +--- +id: nhcx.error.payr-1357 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1357: the admission date is after the discharge date' +summary: >- + The claim gives an admission date later than its discharge date. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1325 + - nhcx.error.payr-1326 +--- + +# PAYR-1357: the admission date is after the discharge date + +## In plain words + +Your claim says the patient was admitted after they were discharged. The payer refused it. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1357`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Admission date cannot be after the discharge date. Hence request will not be processed. Please correct the data and try again. + +The message has no placeholder. + +The payer returns this code when: + +- The admission date in `Claim.supportingInfo` is later than the discharge date. +- Dates with different offsets can reverse their order once the payer compares them. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1357`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Correct whichever date is wrong, using the patient's record. +2. Use the same offset, `+05:30`, on the admission and discharge dates. +3. Carry each date in its own `Claim.supportingInfo` entry, built as the [claim request bundle](../fhir/claim-request.md) shows it. diff --git a/catalogue/nhcx/errors/payr-1358.md b/catalogue/nhcx/errors/payr-1358.md new file mode 100644 index 000000000..f54c5a3da --- /dev/null +++ b/catalogue/nhcx/errors/payr-1358.md @@ -0,0 +1,84 @@ +--- +id: nhcx.error.payr-1358 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1358: the patient was registered too long after admission' +summary: >- + The registration date in the claim is later after admission than the scheme allows. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1329 + - nhcx.error.payr-1325 +--- + +# PAYR-1358: the patient was registered too long after admission + +## In plain words + +The scheme allows a patient to be registered only within a set number of days after admission. Your claim gives a registration date outside that window. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1358`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Registration of the patient is allowed maximum upto `%s` days after admission. Hence request will not be processed. Please correct the data and try again. + +`%s` is the maximum number of days after admission that applies to your case. + +The payer returns this code when: + +- The registration date, in the entry with category `OTH` and code `EDT`, is more than the allowed days after the admission date. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1358`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Check the registration date against the patient's record and correct it if it is wrong. +2. Check the admission date as well. A wrong admission date moves the window. +3. Use the same offset, `+05:30`, on both dates. diff --git a/catalogue/nhcx/errors/payr-1359.md b/catalogue/nhcx/errors/payr-1359.md new file mode 100644 index 000000000..b913d24bb --- /dev/null +++ b/catalogue/nhcx/errors/payr-1359.md @@ -0,0 +1,84 @@ +--- +id: nhcx.error.payr-1359 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1359: the claim has no billable treatment plan' +summary: >- + The treatment plan in the claim has nothing the payer can bill for the case. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1318 + - nhcx.error.payr-1362 +--- + +# PAYR-1359: the claim has no billable treatment plan + +## In plain words + +The payer found no treatment item it can bill in your claim for this case. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1359`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> No billable treatment plan received for case number `%s`. Please try again with valid treatment plan data. + +`%s` is the case number you sent. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The claim carries no treatment item with a billable amount for the case. +- In a discharge against medical advice before or during surgery, LM100 replaces every other preauthorisation item. Without LM100, nothing billable remains. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1359`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Send at least one treatment item with its code, `quantity`, `unitPrice` and `net`. +2. For a discharge against medical advice before or during surgery, add the LM100 item. See [`PAYR-1362`](./payr-1362.md). diff --git a/catalogue/nhcx/errors/payr-1360.md b/catalogue/nhcx/errors/payr-1360.md new file mode 100644 index 000000000..63736f9be --- /dev/null +++ b/catalogue/nhcx/errors/payr-1360.md @@ -0,0 +1,86 @@ +--- +id: nhcx.error.payr-1360 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1360: an item code is not valid' +summary: >- + The claim carries an item code the payer does not accept at the named item sequence. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + - nhcx.concept.insurance-plan + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1204 + - nhcx.error.payr-1361 +--- + +# PAYR-1360: an item code is not valid + +## In plain words + +The payer did not accept the code on one of the items in your claim. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1360`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid item code received as `%s` for item sequence `%s` case number `%s`. Please try again with valid data. + +The three `%s` values are, in order, the item code you sent, the item sequence and the case number. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- `Claim.item[].productOrService` at the named sequence carries a code the payer does not accept. +- Procedure codes come from the code of the type of the benefit component, of the specific cost, of the plan in the insurance plan. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1360`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Take each item code from the current insurance plan for your hospital. +2. Compare the code with the item at the same sequence in the approved preauthorisation. +3. Refresh the insurance plan at least weekly, and at once when the policy is renewed or amended. diff --git a/catalogue/nhcx/errors/payr-1361.md b/catalogue/nhcx/errors/payr-1361.md new file mode 100644 index 000000000..75204cd97 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1361.md @@ -0,0 +1,85 @@ +--- +id: nhcx.error.payr-1361 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1361: an item sequence is not valid' +summary: >- + The claim carries an item sequence number the payer does not accept. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1360 + - nhcx.error.payr-1306 +--- + +# PAYR-1361: an item sequence is not valid + +## In plain words + +Each item in a claim has a sequence number. The payer did not accept one of yours. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1361`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid item sequence received as `%s` for case number `%s`. Please try again with valid data. + +The two `%s` values are the item sequence you sent and the case number. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- `Claim.item[].sequence` carries a number the payer does not accept for the case. +- The payer matches claim items to the preauthorisation by code and sequence. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1361`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Keep the sequence each item had in the approved preauthorisation. +2. Give every item its own sequence number. +3. Check that `careTeamSequence`, `diagnosisSequence`, `procedureSequence` and `informationSequence` point at entries in the claim. diff --git a/catalogue/nhcx/errors/payr-1362.md b/catalogue/nhcx/errors/payr-1362.md new file mode 100644 index 000000000..126dbd2f1 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1362.md @@ -0,0 +1,93 @@ +--- +id: nhcx.error.payr-1362 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1362: a discharge against medical advice needs the LM100 procedure' +summary: >- + The patient left against medical advice before or during surgery, and the claim + lacks the special procedure for that case. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1270 + - nhcx.error.payr-1324 + - nhcx.error.payr-1095 +--- + +# PAYR-1362: a discharge against medical advice needs the LM100 procedure + +## In plain words + +Sometimes a patient leaves before or during surgery against medical advice. For [PMJAY](../glossary/pmjay.md) claims, the claim must then carry the LM100 procedure, and your claim did not. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A PMJAY payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1362`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> No procedure with code LM100 received with 'Requested' status for case number `%s`. Please try again with valid data. For PMJAY claims, if case comes under LAMA/DAMA scenario with beneficiary being discharged before surgery or during surgery, procedure with code LM100 is mandatory. Only this procedure code will be accepted for LAMA/DAMA case, and all other previous preauthorization approved items will get disqualified for the claim submission + +`%s` is the case number you sent. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The discharge entry has code `LAMA` (Left Against Medical Advice) or `DAMA` (Discharged Against Medical Advice). +- The discharge stage is before surgery or during surgery. +- The claim has no procedure with code `LM100` and status `Requested`. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1362`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Add an item with procedure code `LM100` and status `Requested`. +2. Set its quantity to the number of days the patient was admitted. +3. Remove the other preauthorisation items. LM100 is the only procedure accepted, and only the actual stay is payable. +4. Keep the discharge entry: category `DIS`, code `LAMA` or `DAMA`, and the stage as its value. +5. If the patient left after surgery, LM100 does not apply. Record the stage as `After Surgery` and claim the surgical package. +6. Whether a procedure qualifies comes from the LAMA-DAMA claim condition in the insurance plan. +7. Do not send LM100 at preauthorisation. That returns [`PAYR-1270`](./payr-1270.md). diff --git a/catalogue/nhcx/errors/payr-1363.md b/catalogue/nhcx/errors/payr-1363.md new file mode 100644 index 000000000..0e4ca82ee --- /dev/null +++ b/catalogue/nhcx/errors/payr-1363.md @@ -0,0 +1,93 @@ +--- +id: nhcx.error.payr-1363 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1363: no biometric authentication and no consent questionnaire at discharge' +summary: >- + The claim carries neither proof that the patient was present at discharge nor + the consent questionnaire that replaces it. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + - nhcx.concept.biometric-authentication + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.claim-submit + - nhcx.flow.biometric-fingerprint-iris + - nhcx.flow.biometric-face + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1364 + - nhcx.error.payr-1366 + - nhcx.error.payr-1256 + - nhcx.error.payr-1271 +--- + +# PAYR-1363: no biometric authentication and no consent questionnaire at discharge + +## In plain words + +A new claim needs proof that the patient was present at discharge. That proof is biometric authentication, or a response to the Authentication Consent Questionnaire. Your claim had neither. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1363`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Response for Authentication Consent Questionnaire is missing for case number `%s`. This must be sent if the biometric authentication for patient is not available during discharge. For new claim request, either biometric authentication for patient during discharge, or response for Authentication Consent questionnaire must be sent. Please check/update the insurance plan for the policy for the details of the questionnaire. + +`%s` is the case number you sent. The case number is the reference number in `Claim.identifier`. On a claim, reuse the identifier of the approved preauthorisation. + +The payer returns this code when: + +- The claim carries no biometric authentication of the patient during discharge. +- The claim carries no Authentication Consent Questionnaire response either. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1363`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Authenticate the patient by [fingerprint or iris](../flows/biometric-fingerprint-iris.md) or [face](../flows/biometric-face.md) at discharge. Pass the user token as a header parameter on the claim submission. +2. If biometric authentication is not possible, send the Authentication Consent Questionnaire response. Take the questionnaire for the policy from the insurance plan. +3. Add the response as a QuestionnaireResponse in the bundle. Reference it from `Claim.supportingInfo` with category `INF`, as the [claim request bundle](../fhir/claim-request.md) shows. +4. A cyclic package cannot use the consent form. Biometric authentication is mandatory at its discharge. diff --git a/catalogue/nhcx/errors/payr-1364.md b/catalogue/nhcx/errors/payr-1364.md new file mode 100644 index 000000000..3662fadeb --- /dev/null +++ b/catalogue/nhcx/errors/payr-1364.md @@ -0,0 +1,89 @@ +--- +id: nhcx.error.payr-1364 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1364: a consent questionnaire answer is empty' +summary: >- + The consent questionnaire response in the claim leaves one of its questions unanswered. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + - nhcx.concept.biometric-authentication + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.claim-submit + - nhcx.flow.biometric-fingerprint-iris + - nhcx.flow.biometric-face + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1363 + - nhcx.error.payr-1271 +--- + +# PAYR-1364: a consent questionnaire answer is empty + +## In plain words + +Your claim carries an Authentication Consent Questionnaire response, but one question in it has no answer. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1364`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> No value received for link id `%s` for Authentication Consent Questionnaire for claim request. This must be sent if the biometric authentication for patient is not available during discharge. For new claim request, either biometric authentication for patient during discharge, or response for Authentication Consent questionnaire must be sent. Please check/update the insurance plan for the policy for the details of the questionnaire. + +`%s` is the link id of the unanswered question. + +The payer returns this code when: + +- The claim relies on the Authentication Consent Questionnaire instead of biometric authentication at discharge. +- The response gives no value for the question with the named link id. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1364`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Answer every question in the questionnaire. Give the item with the named link id a value. +2. Take the questions from the insurance plan for the policy, and refresh it when the policy changes. +3. Authenticate the patient by [fingerprint or iris](../flows/biometric-fingerprint-iris.md) or [face](../flows/biometric-face.md) at discharge. Pass the user token as a header parameter on the claim submission. diff --git a/catalogue/nhcx/errors/payr-1365.md b/catalogue/nhcx/errors/payr-1365.md new file mode 100644 index 000000000..159552d49 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1365.md @@ -0,0 +1,88 @@ +--- +id: nhcx.error.payr-1365 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1365: the standard treatment guideline response is missing' +summary: >- + A procedure in the claim needs its treatment guideline questionnaire answered, + and the claim does not include the answer. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + - nhcx.concept.insurance-plan + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1254 + - nhcx.error.payr-1505 +--- + +# PAYR-1365: the standard treatment guideline response is missing + +## In plain words + +Some procedures come with a standard treatment guideline (STG) questionnaire. A procedure in your claim needs one, and the claim did not include the response. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1365`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Response for STG Questionnaire id `%s` is mandatory for procedure code `%s`. Hence the preauthorization request will not be processed as the questionnaire response is not received for procedure code. + +The two `%s` values are the STG questionnaire id and the procedure code. + +The payer returns this code when: + +- The procedure requires a response to the named STG questionnaire. +- The claim carries no response for that questionnaire. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1365`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Take the STG questionnaire for the procedure from the insurance plan. +2. Send the questionnaire URL from the insurance plan back in the questionnaire response. +3. Reference the response from `Claim.supportingInfo` with category `STG` and the value as a reference. diff --git a/catalogue/nhcx/errors/payr-1366.md b/catalogue/nhcx/errors/payr-1366.md new file mode 100644 index 000000000..a50304e70 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1366.md @@ -0,0 +1,90 @@ +--- +id: nhcx.error.payr-1366 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1366: the biometric user token is not valid' +summary: >- + The token from the patient's biometric authentication is not valid for this claim. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + - nhcx.concept.biometric-authentication + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.claim-submit + - nhcx.flow.biometric-fingerprint-iris + - nhcx.flow.biometric-face + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1272 + - nhcx.error.payr-1363 +--- + +# PAYR-1366: the biometric user token is not valid + +## In plain words + +Biometric authentication gives your system a user token for the patient. The token sent with your claim is not valid. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1366`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Invalid biometric user token received. Please try again with valid biometric details of the beneficiary. For any issues with biometric, please try with Authentication Consent Questionnaire for discharge, details for which has been received in insurance plan. + +The message has no placeholder. + +The payer returns this code when: + +- The user token has expired. It is valid for 30 minutes. +- The token does not belong to the beneficiary of the case. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1366`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Authenticate the patient again at discharge and send the new token with the claim. +2. Refresh the token automatically until the transaction cycle completes. If it expires, start a fresh biometric authentication. +3. For a cyclic procedure's claim, a still-valid refresh token from the last cycle is allowed. A new token is preferred. +4. If biometric authentication keeps failing, use the Authentication Consent Questionnaire for discharge instead. See [`PAYR-1363`](./payr-1363.md). diff --git a/catalogue/nhcx/errors/payr-1367.md b/catalogue/nhcx/errors/payr-1367.md new file mode 100644 index 000000000..fc8775a93 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1367.md @@ -0,0 +1,89 @@ +--- +id: nhcx.error.payr-1367 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1367: no biometric record for a cycle date' +summary: >- + The payer found no biometric authentication of the beneficiary for a date the + claim gives for a treatment cycle. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + - nhcx.concept.biometric-authentication + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1368 + - nhcx.error.payr-1369 + - nhcx.error.payr-1370 +--- + +# PAYR-1367: no biometric record for a cycle date + +## In plain words + +A cyclic procedure, such as dialysis, is given in repeated cycles. Each cycle needs its own biometric authentication, and the payer found none for one of your dates. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1367`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> No biometric records found for the beneficiary for `%s`. Please ensure correctness of biometric authentication date for the day for cyclic procedure `%s`. + +The two `%s` values are the date and the cyclic procedure code. + +The payer returns this code when: + +- No biometric authentication of the beneficiary exists for the named date. +- The cycle date in the claim does not match the date of the biometric capture. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1367`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Capture a live biometric authentication at every cycle, with process type `Discharge`. A refresh token is not allowed for a cycle. +2. Set each cycle's `timingPeriod` start and end to its biometric capture times. +3. Claim only the cycles that have a biometric capture. Payment covers only those. diff --git a/catalogue/nhcx/errors/payr-1368.md b/catalogue/nhcx/errors/payr-1368.md new file mode 100644 index 000000000..ebb4d7060 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1368.md @@ -0,0 +1,89 @@ +--- +id: nhcx.error.payr-1368 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1368: cycle information is missing for some cycles' +summary: >- + The claim for a cyclic procedure does not carry information for every cycle it + requests. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + - nhcx.concept.biometric-authentication + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1367 + - nhcx.error.payr-1349 + - nhcx.error.payr-1370 +--- + +# PAYR-1368: cycle information is missing for some cycles + +## In plain words + +A cyclic procedure is claimed once, after the last cycle. The claim must describe every cycle, and yours describes fewer than it requests. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1368`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> `%s` units of cycle information received for procedure code `%s` with item sequence `%s`. Cycle information should be sent for all the requested/processed cycles. + +The three `%s` values are, in order, the number of cycle entries received, the procedure code and the item sequence. + +The payer returns this code when: + +- The number of cycle entries differs from the cycles requested or processed on the item. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1368`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Send one `Claim.supportingInfo` entry per cycle, with category `CD` and code `TD`. +2. Give each entry a `timingPeriod` start and end that match that cycle's biometric capture. +3. List every cycle entry's sequence in the item's `informationSequence`. +4. Set the item quantity to the cycles actually given. diff --git a/catalogue/nhcx/errors/payr-1369.md b/catalogue/nhcx/errors/payr-1369.md new file mode 100644 index 000000000..49167d816 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1369.md @@ -0,0 +1,88 @@ +--- +id: nhcx.error.payr-1369 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1369: two biometric authentications on one date for a cyclic procedure' +summary: >- + The claim gives more than one biometric authentication on the same date for a + cyclic procedure. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + - nhcx.concept.biometric-authentication + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1367 + - nhcx.error.payr-1368 +--- + +# PAYR-1369: two biometric authentications on one date for a cyclic procedure + +## In plain words + +A cyclic procedure allows one cycle per day. Your claim gives two or more biometric authentications on the same date for one procedure. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1369`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Biometric authentication cannot be performed more than once on the same date. Multiple biometric authentication information has been provided for same date for cyclic procedure `%s`. Hence case will not be processed. Please check and update biometric authentication execution dates and try again. + +`%s` is the cyclic procedure code. + +The payer returns this code when: + +- Two or more cycle entries for the procedure carry biometric authentication on the same date. +- Two cycles of one procedure cannot be taken within 24 hours. The window runs from capture to capture, not by calendar date. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1369`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Correct the biometric authentication dates for each cycle, using your capture records. +2. Space cycles at least 24 hours apart from capture to capture. That also keeps them on different dates. +3. Disable biometric capture for the procedure for 24 hours after each capture in your system. diff --git a/catalogue/nhcx/errors/payr-1370.md b/catalogue/nhcx/errors/payr-1370.md new file mode 100644 index 000000000..85451779b --- /dev/null +++ b/catalogue/nhcx/errors/payr-1370.md @@ -0,0 +1,88 @@ +--- +id: nhcx.error.payr-1370 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1370: a supporting detail has an invalid start date' +summary: >- + An entry in the claim's supporting information carries a start date the payer + does not accept. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Claim Error Codes. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.claim-cycle + - nhcx.concept.biometric-authentication + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1367 + - nhcx.error.payr-1368 + - nhcx.error.payr-1369 +--- + +# PAYR-1370: a supporting detail has an invalid start date + +## In plain words + +One entry in your claim's supporting information has a start date the payer does not accept. + +Codes from `PAYR-1301` to `PAYR-1370` are [reference payer codes](../concepts/error-code-spaces.md). A [PMJAY](../glossary/pmjay.md) payer sends them when it checks a claim against the approved preauthorisation. + +## Before you start + +- You submitted a claim with [`POST /v1/claim/submit`](../endpoints/claim-submit.md). You followed [submit a claim after discharge](../flows/claim-submit.md). +- [NHCX](../../shared/glossary/nhcx.md) answered your request with `202 Accepted`. +- The payer's response reached your registered endpoint as [`/v1/claim/on_submit`](../callbacks/claim-on-submit.md). +- You decrypted its [JWE](../glossary/jwe.md) payload with your private key and found `PAYR-1370`. + +The payer sends this code inside its sealed response on `/v1/claim/on_submit`. Clinical, patient and business errors are not shared with NHCX. The payer embeds them in the encrypted ClaimResponse. + +## What happens + +The message you receive reads: + +> Received invalid start date as `%s` for supporting details with item sequence `%s`. Please try again with valid start date. + +The two `%s` values are the start date you sent and the sequence of the supporting information entry. + +The payer returns this code when: + +- `timingPeriod.start` on the named `Claim.supportingInfo` entry is not a valid date-time. +- For a cyclic procedure, the payer checks each cycle's period against the actual biometric capture time. + +## How you know it worked + +Resend the corrected request as a fresh request, with a new `x-hcx-correlation_id` and a new `x-hcx-api_call_id`. After an error the old correlation id is inactive, and reusing it returns [`NHCX-1006`](./nhcx-1006.md). + +The claim step is complete when you observe all four: + +1. NHCX answers your request with `202 Accepted`. +2. The payer's sealed response arrives on `/v1/claim/on_submit` with the `x-hcx-correlation_id` you sent. +3. The decrypted ClaimResponse carries an adjudication decision: an `outcome` and an adjudication reason code such as `approved` or `queried`. +4. The response carries no `PAYR-1370`. + +If `outcome` is `partial`, the claim is still open. Keep listening for further responses on the same correlation id. + +## When it goes wrong + +Work through these fixes in order: + +1. Send `timingPeriod.start` as a full date-time with offset, for example `2026-08-05T13:01:33+05:30`. +2. For each cycle of a cyclic procedure, set the start and end to the biometric capture times for that cycle. +3. Keep the entry's `sequence` and the item's `informationSequence` pointing at each other. diff --git a/catalogue/nhcx/errors/payr-1401.md b/catalogue/nhcx/errors/payr-1401.md new file mode 100644 index 000000000..9563fee30 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1401.md @@ -0,0 +1,80 @@ +--- +id: nhcx.error.payr-1401 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1401: the policy is not allowed for your hospital' +summary: >- + The payer will not give your hospital the plan for this policy, and only the technical + support team can change that. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Insurance Plan Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.insurance-plan + flows: + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.insuranceplan-request + callbacks: + - nhcx.callback.insuranceplan-on-request + fhir: + - nhcx.fhir.insurance-plan-bundle + errors: + - nhcx.error.nhcx-1006 +--- + +# PAYR-1401: the policy is not allowed for your hospital + +## In plain words + +You asked a [payer](../glossary/payer.md), through [NHCX](../../shared/glossary/nhcx.md), for the [insurance plan](../glossary/insurance-plan.md) of a policy. The policy is not applicable to your hospital, so the payer returns no plan. + +Your system cannot fix this by changing the request. The technical support team has to act. + +## Before you start + +- Your system sent `POST /v1/insuranceplan/request` through [NHCX](../../shared/glossary/nhcx.md), and NHCX answered `202 Accepted`. See [POST /v1/insuranceplan/request](../endpoints/insuranceplan-request.md). +- Your system receives `/v1/insuranceplan/on_request`. See [Receiving POST /v1/insuranceplan/on_request](../callbacks/insuranceplan-on-request.md). + +The payer's answer arrived on `/v1/insuranceplan/on_request` in place of an insurance plan. The code is in `x-hcx-error_details.code`, and the full text is in `x-hcx-error_details.message`. + +Your callback tells an error from a decision by the `type` field of what arrives. An encrypted payload comes only when the payer processed your request. A `ProtocolResponse` comes when it could not, and carries the error details in clear headers. + +`PAYR-14xx` codes come from the [PMJAY](../glossary/pmjay.md) payer, not from the exchange. [Error code spaces](../concepts/error-code-spaces.md) explains the difference. + +## What happens + +The payer returns `PAYR-1401` when the policy in your request is not applicable to the hospital that sent it. + +The payer reads the policy from the `policyNumber` input of your `Task`. It knows your hospital from your [participant code](../glossary/participant-code.md) and your [HFR](../../shared/glossary/hfr.md) id. Each hospital receives a plan for the specialities and treatments it is authorised for. + +The message names the policy it refused: + +```text + policy not allowed for the hospital. Please reach out to technical support team. +``` + +`` is replaced by the policy code from your request. + +## How you know it worked + +You send a new `POST /v1/insuranceplan/request` with a new `x-hcx-correlation_id`, and receive `202 Accepted`. + +Then `/v1/insuranceplan/on_request` delivers an encrypted payload, and `PAYR-1401` does not come back. After you decrypt it, the payload is a `Bundle` of type `collection`. It holds an `InsurancePlan`, an `Organization` and `Questionnaire` resources. + +## When it goes wrong + +1. Confirm that `` in the message is the policy you meant to request. +2. Contact the technical support team. Give them the full message, ``, your participant code, your HFR id and the `x-hcx-correlation_id` of the refused request. +3. After support resolves it, send a new request. + +Send every retry as a new request with a new `x-hcx-correlation_id`. A correlation id that ended in an error is inactive. A correlation id that already exists is refused with [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1402.md b/catalogue/nhcx/errors/payr-1402.md new file mode 100644 index 000000000..5452b2252 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1402.md @@ -0,0 +1,92 @@ +--- +id: nhcx.error.payr-1402 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1402: the payer has no policy with the code you requested' +summary: >- + The payer could not find the policy code in your insurance plan request, so it + returned no plan. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Insurance Plan Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.insurance-plan + flows: + - nhcx.flow.insurance-plan-request + - nhcx.flow.coverage-eligibility-check + endpoints: + - nhcx.endpoint.insuranceplan-request + callbacks: + - nhcx.callback.insuranceplan-on-request + fhir: + - nhcx.fhir.insurance-plan-bundle + errors: + - nhcx.error.nhcx-1006 +--- + +# PAYR-1402: the payer has no policy with the code you requested + +## In plain words + +You asked a [payer](../glossary/payer.md), through [NHCX](../../shared/glossary/nhcx.md), for the [insurance plan](../glossary/insurance-plan.md) of a policy. The payer found no policy with that code in its system. It stops processing the request. + +Check the policy code first. If it is correct, the technical support team has to act. + +## Before you start + +- Your system sent `POST /v1/insuranceplan/request` through [NHCX](../../shared/glossary/nhcx.md), and NHCX answered `202 Accepted`. See [POST /v1/insuranceplan/request](../endpoints/insuranceplan-request.md). +- Your system receives `/v1/insuranceplan/on_request`. See [Receiving POST /v1/insuranceplan/on_request](../callbacks/insuranceplan-on-request.md). + +The payer's answer arrived on `/v1/insuranceplan/on_request` in place of an insurance plan. The code is in `x-hcx-error_details.code`, and the full text is in `x-hcx-error_details.message`. + +Your callback tells an error from a decision by the `type` field of what arrives. An encrypted payload comes only when the payer processed your request. A `ProtocolResponse` comes when it could not, and carries the error details in clear headers. + +`PAYR-14xx` codes come from the [PMJAY](../glossary/pmjay.md) payer, not from the exchange. [Error code spaces](../concepts/error-code-spaces.md) explains the difference. + +## What happens + +The payer returns `PAYR-1402` when the policy requested for the insurance plan does not exist in its system. + +The payer reads the policy from the `policyNumber` input of your `Task`: + +```json +"input": [ + { + "type": { + "coding": [ + { "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code", "code": "policyNumber" } + ] + }, + "valueString": "" + } +] +``` + +The message names the policy it looked for: + +```text +Requested policy found not be associated with any payer for insurance plan request. Hence request will not be processed. +``` + +## How you know it worked + +You send a new `POST /v1/insuranceplan/request` with a new `x-hcx-correlation_id`, and receive `202 Accepted`. + +Then `/v1/insuranceplan/on_request` delivers an encrypted payload, and `PAYR-1402` does not come back. After you decrypt it, the payload is a `Bundle` of type `collection`. It holds an `InsurancePlan`, an `Organization` and `Questionnaire` resources. + +## When it goes wrong + +1. Compare `` in the message with the `policyNumber` value you sent. Look for a typing error, a space or a wrong segment. The sample policy codes are `PMJAY/HP/S/G` and `PMJAY/CH/S/G`. +2. Take the policy code from your coverage eligibility result, not from free text. See [Check coverage eligibility](../flows/coverage-eligibility-check.md). +3. If the code is correct, contact the technical support team. Give them the full message and the `x-hcx-correlation_id` of the refused request. + +Send every retry as a new request with a new `x-hcx-correlation_id`. A correlation id that ended in an error is inactive. A correlation id that already exists is refused with [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1403.md b/catalogue/nhcx/errors/payr-1403.md new file mode 100644 index 000000000..eefdff16a --- /dev/null +++ b/catalogue/nhcx/errors/payr-1403.md @@ -0,0 +1,78 @@ +--- +id: nhcx.error.payr-1403 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1403: the renewal does not belong to the requested policy' +summary: >- + The payer knows the policy you asked about but not the renewal you named under + it, so it returned no plan. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Insurance Plan Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.insurance-plan + flows: + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.insuranceplan-request + callbacks: + - nhcx.callback.insuranceplan-on-request + fhir: + - nhcx.fhir.insurance-plan-bundle + errors: + - nhcx.error.payr-1402 + - nhcx.error.nhcx-1006 +--- + +# PAYR-1403: the renewal does not belong to the requested policy + +## In plain words + +You asked a [payer](../glossary/payer.md), through [NHCX](../../shared/glossary/nhcx.md), for the [insurance plan](../glossary/insurance-plan.md) of a policy and a renewal of it. The payer found no such renewal under that policy. It stops processing the request. + +## Before you start + +- Your system sent `POST /v1/insuranceplan/request` through [NHCX](../../shared/glossary/nhcx.md), and NHCX answered `202 Accepted`. See [POST /v1/insuranceplan/request](../endpoints/insuranceplan-request.md). +- Your system receives `/v1/insuranceplan/on_request`. See [Receiving POST /v1/insuranceplan/on_request](../callbacks/insuranceplan-on-request.md). + +The payer's answer arrived on `/v1/insuranceplan/on_request` in place of an insurance plan. The code is in `x-hcx-error_details.code`, and the full text is in `x-hcx-error_details.message`. + +Your callback tells an error from a decision by the `type` field of what arrives. An encrypted payload comes only when the payer processed your request. A `ProtocolResponse` comes when it could not, and carries the error details in clear headers. + +`PAYR-14xx` codes come from the [PMJAY](../glossary/pmjay.md) payer, not from the exchange. [Error code spaces](../concepts/error-code-spaces.md) explains the difference. + +## What happens + +The payer returns `PAYR-1403` when it cannot find the renewal from your request under the policy from your request. + +The message names both values it read: + +```text +Requested renewal found not be associated with requested policy for insurance plan request. Hence request will not be processed. +``` + +`` and `` are replaced by the values the payer read from your request. + +## How you know it worked + +You send a new `POST /v1/insuranceplan/request` with a new `x-hcx-correlation_id`, and receive `202 Accepted`. + +Then `/v1/insuranceplan/on_request` delivers an encrypted payload, and `PAYR-1403` does not come back. After you decrypt it, the payload is a `Bundle` of type `collection`. It holds an `InsurancePlan`, an `Organization` and `Questionnaire` resources. + +## When it goes wrong + +1. Compare `` and `` in the message with the values your system sent. Correct whichever is wrong. +2. If both are correct, contact the technical support team. Give them the full message and the `x-hcx-correlation_id` of the refused request. + +A policy code that the payer does not hold at all returns [PAYR-1402](payr-1402.md) instead. + +Send every retry as a new request with a new `x-hcx-correlation_id`. A correlation id that ended in an error is inactive. A correlation id that already exists is refused with [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1404.md b/catalogue/nhcx/errors/payr-1404.md new file mode 100644 index 000000000..4d07d6856 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1404.md @@ -0,0 +1,80 @@ +--- +id: nhcx.error.payr-1404 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1404: no treatment is configured for the policy under any speciality' +summary: >- + The payer has the policy you asked about but no speciality or treatment set up + under it, so there is no plan to return. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Insurance Plan Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.insurance-plan + flows: + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.insuranceplan-request + callbacks: + - nhcx.callback.insuranceplan-on-request + fhir: + - nhcx.fhir.insurance-plan-bundle + errors: + - nhcx.error.payr-1402 + - nhcx.error.nhcx-1006 +--- + +# PAYR-1404: no treatment is configured for the policy under any speciality + +## In plain words + +You asked a [payer](../glossary/payer.md), through [NHCX](../../shared/glossary/nhcx.md), for the [insurance plan](../glossary/insurance-plan.md) of a policy. The payer has no speciality configured for that policy. With no speciality there is no treatment to list, so it returns no plan. + +The configuration lives on the payer's side. Check your policy code, then contact the technical support team. + +## Before you start + +- Your system sent `POST /v1/insuranceplan/request` through [NHCX](../../shared/glossary/nhcx.md), and NHCX answered `202 Accepted`. See [POST /v1/insuranceplan/request](../endpoints/insuranceplan-request.md). +- Your system receives `/v1/insuranceplan/on_request`. See [Receiving POST /v1/insuranceplan/on_request](../callbacks/insuranceplan-on-request.md). + +The payer's answer arrived on `/v1/insuranceplan/on_request` in place of an insurance plan. The code is in `x-hcx-error_details.code`, and the full text is in `x-hcx-error_details.message`. + +Your callback tells an error from a decision by the `type` field of what arrives. An encrypted payload comes only when the payer processed your request. A `ProtocolResponse` comes when it could not, and carries the error details in clear headers. + +`PAYR-14xx` codes come from the [PMJAY](../glossary/pmjay.md) payer, not from the exchange. [Error code spaces](../concepts/error-code-spaces.md) explains the difference. + +## What happens + +The payer returns `PAYR-1404` when no speciality is configured for the policy in your request. + +In an insurance plan, each speciality is the category of a specific cost. Each treatment package sits under a speciality as a benefit. + +```text +No treatment provided for policy under any speciality. Please reach out to technical support team. +``` + +`` is replaced by the policy code from your request. + +## How you know it worked + +You send a new `POST /v1/insuranceplan/request` with a new `x-hcx-correlation_id`, and receive `202 Accepted`. + +Then `/v1/insuranceplan/on_request` delivers an encrypted payload, and `PAYR-1404` does not come back. After you decrypt it, the payload is a `Bundle` of type `collection`. It holds an `InsurancePlan`, an `Organization` and `Questionnaire` resources. + +The `InsurancePlan` lists at least one speciality, with treatment packages under it. + +## When it goes wrong + +1. Compare `` in the message with the `policyNumber` value you sent. Correct it if it is not the policy you meant. +2. If the policy code is correct, contact the technical support team. The payer has to configure a speciality for the policy. Give them the full message and the `x-hcx-correlation_id`. + +Send every retry as a new request with a new `x-hcx-correlation_id`. A correlation id that ended in an error is inactive. A correlation id that already exists is refused with [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1405.md b/catalogue/nhcx/errors/payr-1405.md new file mode 100644 index 000000000..e18c74a44 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1405.md @@ -0,0 +1,82 @@ +--- +id: nhcx.error.payr-1405 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1405: the payer has no enrolled hospital for your HFR id or sender + code' +summary: >- + The payer could not find your hospital in its records from the facility registry + id or sender code you sent, so it returned no plan. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Insurance Plan Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.insurance-plan + - nhcx.concept.participant-code + flows: + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.insuranceplan-request + callbacks: + - nhcx.callback.insuranceplan-on-request + fhir: + - nhcx.fhir.insurance-plan-bundle + errors: + - nhcx.error.nhcx-1006 +--- + +# PAYR-1405: the payer has no enrolled hospital for your HFR id or sender code + +## In plain words + +You asked a [payer](../glossary/payer.md), through [NHCX](../../shared/glossary/nhcx.md), for an [insurance plan](../glossary/insurance-plan.md). The payer looked your hospital up and found no enrolled hospital. It checked your [HFR](../../shared/glossary/hfr.md) id and your sender code. With no hospital record, it cannot build a plan for you. + +## Before you start + +- Your system sent `POST /v1/insuranceplan/request` through [NHCX](../../shared/glossary/nhcx.md), and NHCX answered `202 Accepted`. See [POST /v1/insuranceplan/request](../endpoints/insuranceplan-request.md). +- Your system receives `/v1/insuranceplan/on_request`. See [Receiving POST /v1/insuranceplan/on_request](../callbacks/insuranceplan-on-request.md). + +The payer's answer arrived on `/v1/insuranceplan/on_request` in place of an insurance plan. The code is in `x-hcx-error_details.code`, and the full text is in `x-hcx-error_details.message`. + +Your callback tells an error from a decision by the `type` field of what arrives. An encrypted payload comes only when the payer processed your request. A `ProtocolResponse` comes when it could not, and carries the error details in clear headers. + +`PAYR-14xx` codes come from the [PMJAY](../glossary/pmjay.md) payer, not from the exchange. [Error code spaces](../concepts/error-code-spaces.md) explains the difference. + +## What happens + +The payer returns `PAYR-1405` when it finds no data for your hospital in its system. + +It looks the hospital up by two values: + +| Value in the message | Where it comes from | +|---|---| +| `` | The `providerId` input of your `Task`, which carries your HFR id | +| `` | `x-hcx-sender_code` in your [protected header](../glossary/protected-header.md), which is your [participant code](../glossary/participant-code.md) | + +```text +No enrolled hospital found for HFR id or sender id . Please reach out to technical support team. +``` + +## How you know it worked + +You send a new `POST /v1/insuranceplan/request` with a new `x-hcx-correlation_id`, and receive `202 Accepted`. + +Then `/v1/insuranceplan/on_request` delivers an encrypted payload, and `PAYR-1405` does not come back. After you decrypt it, the payload is a `Bundle` of type `collection`. It holds an `InsurancePlan`, an `Organization` and `Questionnaire` resources. + +## When it goes wrong + +1. Compare `` in the message with your facility's HFR id. Correct the `providerId` value if it differs. +2. Send the HFR id that matches the registry id recorded for your participant in NHCX. +3. Check that `` is your own participant code. +4. If both values are correct, contact the technical support team. Your hospital's enrolment with the payer has to be checked. Give them the full message and the `x-hcx-correlation_id`. + +Send every retry as a new request with a new `x-hcx-correlation_id`. A correlation id that ended in an error is inactive. A correlation id that already exists is refused with [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1406.md b/catalogue/nhcx/errors/payr-1406.md new file mode 100644 index 000000000..c8eb86552 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1406.md @@ -0,0 +1,85 @@ +--- +id: nhcx.error.payr-1406 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1406: an earlier insurance plan request for the same policy is still + running' +summary: >- + The payer is still working on an earlier plan request from your hospital for the + same policy, so wait before asking again. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Insurance Plan Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.insurance-plan + - nhcx.concept.message-identifiers + flows: + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.insuranceplan-request + callbacks: + - nhcx.callback.insuranceplan-on-request + fhir: + - nhcx.fhir.insurance-plan-bundle + errors: + - nhcx.error.nhcx-1006 +--- + +# PAYR-1406: an earlier insurance plan request for the same policy is still running + +## In plain words + +Your hospital asked a [payer](../glossary/payer.md), through [NHCX](../../shared/glossary/nhcx.md), for the [insurance plan](../glossary/insurance-plan.md) of a policy. An earlier request from your hospital for the same policy is still in progress. The payer refuses the new one until the earlier one finishes. + +The fix is to wait, not to change the request. + +## Before you start + +- Your system sent `POST /v1/insuranceplan/request` through [NHCX](../../shared/glossary/nhcx.md), and NHCX answered `202 Accepted`. See [POST /v1/insuranceplan/request](../endpoints/insuranceplan-request.md). +- Your system receives `/v1/insuranceplan/on_request`. See [Receiving POST /v1/insuranceplan/on_request](../callbacks/insuranceplan-on-request.md). + +The payer's answer arrived on `/v1/insuranceplan/on_request` in place of an insurance plan. The code is in `x-hcx-error_details.code`, and the full text is in `x-hcx-error_details.message`. + +Your callback tells an error from a decision by the `type` field of what arrives. An encrypted payload comes only when the payer processed your request. A `ProtocolResponse` comes when it could not, and carries the error details in clear headers. + +`PAYR-14xx` codes come from the [PMJAY](../glossary/pmjay.md) payer, not from the exchange. [Error code spaces](../concepts/error-code-spaces.md) explains the difference. + +## What happens + +The payer returns `PAYR-1406` when both of these hold: + +- a new insurance plan request arrives from your hospital for a policy; and +- the payer is still executing an earlier request from your hospital for the same policy. + +The message names the earlier request by its [correlation id](../glossary/correlation-id.md): + +```text +Existing request with correlation id %s is in progress with the payer. Hence this request will not be accepted until the execution for previous request is complete. Please wait for 15 - 60 minutes to allow the execution of previous requests. For further assistance, please reach out to technical support team. +``` + +`%s` is replaced by the correlation id of the earlier request. + +## How you know it worked + +The answer to the earlier request arrives on `/v1/insuranceplan/on_request`. Match it to the earlier request by its protected header identifiers, as [Correlation id, API call id and workflow id](../concepts/message-identifiers.md) describes. It holds the insurance plan you need. + +If you send a new request after the wait, `/v1/insuranceplan/on_request` delivers an insurance plan bundle, and `PAYR-1406` does not come back. + +## When it goes wrong + +1. Do not send another request for the same policy. Each one is refused while the earlier one runs. +2. Wait 15 to 60 minutes. Watch `/v1/insuranceplan/on_request` for the answer to the earlier request. +3. If no answer arrives after 60 minutes, contact the technical support team. Give them the correlation id from the message. + +To avoid it, allow one insurance plan request at a time per hospital and policy. Store the plan you receive and reuse it. Refresh it weekly, and at once when a policy is renewed or amended. + +Send every retry as a new request with a new `x-hcx-correlation_id`. A correlation id that ended in an error is inactive. A correlation id that already exists is refused with [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1501.md b/catalogue/nhcx/errors/payr-1501.md new file mode 100644 index 000000000..b249ee968 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1501.md @@ -0,0 +1,100 @@ +--- +id: nhcx.error.payr-1501 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1501: the surgery date entry carries the wrong kind of value' +summary: >- + The scheme payer rejected your preauthorisation or claim because the surgery date + entry holds a value that is not a date, a period or text. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + errors: + - nhcx.error.payr-1043 + - nhcx.error.payr-1044 + - nhcx.error.nhcx-1006 +--- + +# PAYR-1501: the surgery date entry carries the wrong kind of value + +## In plain words + +Your preauthorisation or claim lists the surgery date as a supporting information entry. The [PMJAY](../glossary/pmjay.md) payer found that entry holding the wrong kind of value. It reads the surgery date only from a timing, meaning a date or a period, or from a string. It refused the request. + +## Before you start + +- Your system sent a [preauthorisation](../glossary/preauthorisation.md) or a [claim](../glossary/claim.md) through [NHCX](../../shared/glossary/nhcx.md), and NHCX answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md) and [Submit a claim after discharge](../flows/claim-submit.md). +- Both bundles carry a `Claim` resource. `Claim.use` is `preauthorization` for a preauthorisation and `claim` for a claim. + +The [PMJAY](../glossary/pmjay.md) payer checked the `Claim` resource and refused it. Its answer arrived on the callback for your request: `/v1/preauth/on_submit` or `/v1/claim/on_submit`. The code is in `x-hcx-error_details.code`, and the full text is in `x-hcx-error_details.message`. + +Your callback tells an error from a decision by the `type` field of what arrives. An encrypted payload comes only when the payer processed your request. A `ProtocolResponse` comes when it could not, and carries the error details in clear headers. + +[Error code spaces](../concepts/error-code-spaces.md) explains where `PAYR-15xx` codes come from. + +## What happens + +The payer reads the surgery date from the `Claim.supportingInfo` entry with category `ONS` and code `PSP`. It returns `PAYR-1501` when that entry's value is neither a timing nor a string. + +```text +Value type received as %s for category - ONS and code - PSP for item with sequence %s in supporting info in claim resource. In supporting info list, item with category - ONS and code - PSP combination is used to get the surgery date. So the surgery date should be sent as timing (date or period) or as a string value, adhering to the NRCES standards, with the category - ONS and code - PSP. +``` + +The first `%s` is the value type you sent. The second is the entry's `sequence`. + +## How you know it worked + +You send the corrected bundle as a new request and receive `202 Accepted`. + +The answer on `/v1/preauth/on_submit` or `/v1/claim/on_submit` is an encrypted payload, and `PAYR-1501` does not come back. After you decrypt it, the payload is a `ClaimResponse` bundle carrying the payer's decision on the case. + +## When it goes wrong + +1. Find the `supportingInfo` entry whose `sequence` matches the message. +2. Send the surgery date in that entry as a string in the [NRCeS](../../shared/glossary/nrces.md) date-time format. Keep category `ONS` and code `PSP`. +3. Replace the value. Do not send an attachment or a reference in this entry. + +```json +{ + "sequence": 3, + "category": { + "coding": [ + { "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category", "code": "ONS" } + ] + }, + "code": { + "coding": [ + { "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-code", "code": "PSP" } + ] + }, + "valueString": "" +} +``` + +A date-time in this format looks like `2026-03-10T21:21:17+05:30`. A string in the wrong date format is refused with [PAYR-1043](payr-1043.md) or [PAYR-1044](payr-1044.md). + +Send every retry as a new request with a new `x-hcx-correlation_id`. A correlation id that ended in an error is inactive. A correlation id that already exists is refused with [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1502.md b/catalogue/nhcx/errors/payr-1502.md new file mode 100644 index 000000000..0a7b2e087 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1502.md @@ -0,0 +1,107 @@ +--- +id: nhcx.error.payr-1502 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1502: the admission date entry carries the wrong kind of value' +summary: >- + The scheme payer rejected your preauthorisation or claim because the admission + date entry holds a value that is not a date, a period or text. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + errors: + - nhcx.error.payr-1043 + - nhcx.error.payr-1044 + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1243 + - nhcx.error.payr-1244 + - nhcx.error.payr-1325 + - nhcx.error.payr-1327 + - nhcx.error.payr-1357 +--- + +# PAYR-1502: the admission date entry carries the wrong kind of value + +## In plain words + +Your preauthorisation or claim lists the admission date as a supporting information entry. The [PMJAY](../glossary/pmjay.md) payer found that entry holding the wrong kind of value. It reads the admission date only from a timing, meaning a date or a period, or from a string. It refused the request. + +## Before you start + +- Your system sent a [preauthorisation](../glossary/preauthorisation.md) or a [claim](../glossary/claim.md) through [NHCX](../../shared/glossary/nhcx.md), and NHCX answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md) and [Submit a claim after discharge](../flows/claim-submit.md). +- Both bundles carry a `Claim` resource. `Claim.use` is `preauthorization` for a preauthorisation and `claim` for a claim. + +The [PMJAY](../glossary/pmjay.md) payer checked the `Claim` resource and refused it. Its answer arrived on the callback for your request: `/v1/preauth/on_submit` or `/v1/claim/on_submit`. The code is in `x-hcx-error_details.code`, and the full text is in `x-hcx-error_details.message`. + +Your callback tells an error from a decision by the `type` field of what arrives. An encrypted payload comes only when the payer processed your request. A `ProtocolResponse` comes when it could not, and carries the error details in clear headers. + +[Error code spaces](../concepts/error-code-spaces.md) explains where `PAYR-15xx` codes come from. + +## What happens + +The payer reads the admission date from the `Claim.supportingInfo` entry with category `ONS` and code `ADDD`. It returns `PAYR-1502` when that entry's value is neither a timing nor a string. + +```text +Value type received as %s for category - ONS and code - ADDD for item with sequence %s in supporting info in claim resource. In supporting info list, item with category - ONS and code - ADDD combination is used to get the admission date. So the admission date should be sent as timing (date or period) or as a string value, adhering to the NRCES standards, with the category - ONS and code - ADDD. +``` + +The first `%s` is the value type you sent. The second is the entry's `sequence`. + +## How you know it worked + +You send the corrected bundle as a new request and receive `202 Accepted`. + +The answer on `/v1/preauth/on_submit` or `/v1/claim/on_submit` is an encrypted payload, and `PAYR-1502` does not come back. After you decrypt it, the payload is a `ClaimResponse` bundle carrying the payer's decision on the case. + +## When it goes wrong + +1. Find the `supportingInfo` entry whose `sequence` matches the message. +2. Send the admission date in that entry as a string in the [NRCeS](../../shared/glossary/nrces.md) date-time format. Keep category `ONS` and code `ADDD`. +3. Replace the value. Do not send an attachment or a reference in this entry. + +```json +{ + "sequence": 3, + "category": { + "coding": [ + { "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category", "code": "ONS" } + ] + }, + "code": { + "coding": [ + { "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-code", "code": "ADDD" } + ] + }, + "valueString": "" +} +``` + +A date-time in this format looks like `2026-03-10T21:21:17+05:30`. A string in the wrong date format is refused with [PAYR-1043](payr-1043.md) or [PAYR-1044](payr-1044.md). + +The admission date is mandatory on a preauthorisation and on a claim. A missing or unusable admission date on a preauthorisation returns [PAYR-1243](payr-1243.md) or [PAYR-1244](payr-1244.md). On a claim it returns [PAYR-1325](payr-1325.md) or [PAYR-1327](payr-1327.md). + +Send every retry as a new request with a new `x-hcx-correlation_id`. A correlation id that ended in an error is inactive. A correlation id that already exists is refused with [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1503.md b/catalogue/nhcx/errors/payr-1503.md new file mode 100644 index 000000000..f813b2d43 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1503.md @@ -0,0 +1,103 @@ +--- +id: nhcx.error.payr-1503 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1503: the death date entry carries the wrong kind of value' +summary: >- + The scheme payer rejected your claim because the death date entry holds a value + that is not a date, a period or text. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + errors: + - nhcx.error.payr-1043 + - nhcx.error.payr-1044 + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1095 + - nhcx.error.payr-1096 + - nhcx.error.payr-1514 +--- + +# PAYR-1503: the death date entry carries the wrong kind of value + +## In plain words + +Your claim lists the death date as a supporting information entry. The [PMJAY](../glossary/pmjay.md) payer found that entry holding the wrong kind of value. It reads the death date only from a timing, meaning a date or a period, or from a string. It refused the request. + +## Before you start + +- Your system sent a [claim](../glossary/claim.md) through [NHCX](../../shared/glossary/nhcx.md), and NHCX answered `202 Accepted`. See [Submit a claim after discharge](../flows/claim-submit.md). +- The claim bundle carries a `Claim` resource with `Claim.use` set to `claim`. + +The [PMJAY](../glossary/pmjay.md) payer checked the `Claim` resource and refused it. Its answer arrived on `/v1/claim/on_submit`. The code is in `x-hcx-error_details.code`, and the full text is in `x-hcx-error_details.message`. + +Your callback tells an error from a decision by the `type` field of what arrives. An encrypted payload comes only when the payer processed your request. A `ProtocolResponse` comes when it could not, and carries the error details in clear headers. + +[Error code spaces](../concepts/error-code-spaces.md) explains where `PAYR-15xx` codes come from. + +## What happens + +The payer reads the death date from the `Claim.supportingInfo` entry with category `ONS` and code `DTM`. It returns `PAYR-1503` when that entry's value is neither a timing nor a string. + +```text +Value type received as %s for category - ONS and code - DTM for item with sequence %s in supporting info in claim resource. In supporting info list, item with category - ONS and code - DTM combination is used to get the death date. So the death date should be sent as timing (date or period) or as a string value, adhering to the NRCES standards, with the category - ONS and code - DTM. +``` + +The first `%s` is the value type you sent. The second is the entry's `sequence`. + +When the discharge type is death, the death date is mandatory on the claim. A claim with no death date for a death discharge returns [PAYR-1096](payr-1096.md) instead. + +## How you know it worked + +You send the corrected bundle as a new request and receive `202 Accepted`. + +The answer on `/v1/claim/on_submit` is an encrypted payload, and `PAYR-1503` does not come back. After you decrypt it, the payload is a `ClaimResponse` bundle carrying the payer's decision on the case. + +## When it goes wrong + +1. Find the `supportingInfo` entry whose `sequence` matches the message. +2. Send the death date in that entry as a string in the [NRCeS](../../shared/glossary/nrces.md) date-time format. Keep category `ONS` and code `DTM`. +3. Replace the value. Do not send an attachment or a reference in this entry. + +```json +{ + "sequence": 3, + "category": { + "coding": [ + { "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category", "code": "ONS" } + ] + }, + "code": { + "coding": [ + { "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-code", "code": "DTM" } + ] + }, + "valueString": "" +} +``` + +A date-time in this format looks like `2026-03-10T21:21:17+05:30`. A string in the wrong date format is refused with [PAYR-1043](payr-1043.md) or [PAYR-1044](payr-1044.md). + +The discharge information itself goes in a separate entry with category `DIS`. See [PAYR-1514](payr-1514.md). + +Send every retry as a new request with a new `x-hcx-correlation_id`. A correlation id that ended in an error is inactive. A correlation id that already exists is refused with [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1504.md b/catalogue/nhcx/errors/payr-1504.md new file mode 100644 index 000000000..2a3059788 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1504.md @@ -0,0 +1,94 @@ +--- +id: nhcx.error.payr-1504 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1504: the case remarks in your query response are not text' +summary: >- + The scheme payer rejected your answer to its query because the overall case remarks + were not sent as text. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.queries-and-communication + flows: + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-query-response + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.query-update + errors: + - nhcx.error.nhcx-1006 +--- + +# PAYR-1504: the case remarks in your query response are not text + +## In plain words + +The payer queried your [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md), and your system answered. Your answer carries overall case remarks as a supporting information entry. The [PMJAY](../glossary/pmjay.md) payer reads those remarks only as a string. Your entry held another kind of value, so it refused the answer. + +## Before you start + +- The payer raised a query on a preauthorisation or a claim. See [Answer a payer query on a preauthorisation](../flows/preauth-query-response.md) and [Answer a payer query on a claim](../flows/claim-query-response.md). +- Your system sent its query response through [NHCX](../../shared/glossary/nhcx.md), and NHCX answered `202 Accepted`. + +The payer's answer to your query response carries this code in `x-hcx-error_details.code`. The full text is in `x-hcx-error_details.message`. + +Your callback tells an error from a decision by the `type` field of what arrives. An encrypted payload comes only when the payer processed your request. A `ProtocolResponse` comes when it could not, and carries the error details in clear headers. + +[Error code spaces](../concepts/error-code-spaces.md) explains where `PAYR-15xx` codes come from. + +## What happens + +The payer reads the case remarks from the `Claim.supportingInfo` entry with category `NMI` and code `CQD`. It returns `PAYR-1504` when that entry's value is not a string. + +```text +Value type received as %s for category - NMI and code - CQD for item with sequence %s in supporting info in claim resource. In supporting info list, item with category - NMI and code - CQD combination is used to get the overall case remarks for query response. So the case remarks for query response should be sent as a string value, adhering to the NRCES standards, with the category - NMI and code - CQD. +``` + +The first `%s` is the value type you sent. The second is the entry's `sequence`. + +## How you know it worked + +You send the corrected query response as a new request and receive `202 Accepted`. + +The payer's answer is an encrypted payload, and `PAYR-1504` does not come back. After you decrypt it, the payload is a `ClaimResponse` bundle carrying the payer's decision on the case. + +## When it goes wrong + +1. Find the `supportingInfo` entry whose `sequence` matches the message. +2. Put the remarks in that entry as a string, with category `NMI` and code `CQD`. +3. Replace any attachment or reference in this entry with the text itself. + +```json +{ + "sequence": 6, + "category": { + "coding": [ + { "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category", "code": "NMI" } + ] + }, + "code": { + "coding": [ + { "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-code", "code": "CQD" } + ] + }, + "valueString": "" +} +``` + +Send every retry as a new request with a new `x-hcx-correlation_id`. A correlation id that ended in an error is inactive. A correlation id that already exists is refused with [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1505.md b/catalogue/nhcx/errors/payr-1505.md new file mode 100644 index 000000000..c11997967 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1505.md @@ -0,0 +1,108 @@ +--- +id: nhcx.error.payr-1505 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1505: a questionnaire response is attached under the wrong category + or code' +summary: >- + The scheme payer rejected your preauthorisation or claim because a questionnaire + answer is attached under a category and code it does not accept. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.insurance-plan + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + errors: + - nhcx.error.payr-1254 + - nhcx.error.payr-1365 + - nhcx.error.payr-1084 + - nhcx.error.nhcx-1006 +--- + +# PAYR-1505: a questionnaire response is attached under the wrong category or code + +## In plain words + +Your [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) attaches a questionnaire response through a supporting information entry. The entry points at a `QuestionnaireResponse` resource in your bundle. The [PMJAY](../glossary/pmjay.md) payer accepts that link only under two category and code pairs. Yours used another pair, so it refused the request. + +## Before you start + +- Your system sent a [preauthorisation](../glossary/preauthorisation.md) or a [claim](../glossary/claim.md) through [NHCX](../../shared/glossary/nhcx.md), and NHCX answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md) and [Submit a claim after discharge](../flows/claim-submit.md). +- Both bundles carry a `Claim` resource. `Claim.use` is `preauthorization` for a preauthorisation and `claim` for a claim. + +The [PMJAY](../glossary/pmjay.md) payer checked the `Claim` resource and refused it. Its answer arrived on the callback for your request: `/v1/preauth/on_submit` or `/v1/claim/on_submit`. The code is in `x-hcx-error_details.code`, and the full text is in `x-hcx-error_details.message`. + +Your callback tells an error from a decision by the `type` field of what arrives. An encrypted payload comes only when the payer processed your request. A `ProtocolResponse` comes when it could not, and carries the error details in clear headers. + +[Error code spaces](../concepts/error-code-spaces.md) explains where `PAYR-15xx` codes come from. + +## What happens + +The payer returns `PAYR-1505` when a `Claim.supportingInfo` entry references a `QuestionnaireResponse` under any category and code other than these: + +| You are attaching | Category | Code | Value | +|---|---|---|---| +| A policy or case level questionnaire response | `INF` | `ODN` | A reference to a `QuestionnaireResponse` in the bundle | +| A response to a standard treatment guideline questionnaire | `STG` | Not specified | A reference to a `QuestionnaireResponse` in the bundle | + +```text +Category received as %s and code received as %s for item with sequence %s in supporting info in claim resource, where the reference value redirects to Questionnaire Response resource in the FHIR bundle. To include a policy/case level Questionnaire Response, in supporting info list there should be an entry with category - INF and code - ODN , and the value as reference. This reference value should refer to a resource of Questionnaire Response in the FHIR bundle. To include response for any STG questionnaire, in supporting info list there should be an entry with category - STG, and the value as reference +``` + +The three `%s` values are the category, the code and the entry's `sequence`. The questionnaires come from the insurance plan for the policy. See [The insurance plan](../concepts/insurance-plan.md). + +## How you know it worked + +You send the corrected bundle as a new request and receive `202 Accepted`. + +The answer on `/v1/preauth/on_submit` or `/v1/claim/on_submit` is an encrypted payload, and `PAYR-1505` does not come back. After you decrypt it, the payload is a `ClaimResponse` bundle carrying the payer's decision on the case. + +## When it goes wrong + +1. Find the `supportingInfo` entry whose `sequence` matches the message. +2. Set its category and code to the pair for what it attaches, as in the table. +3. Point its `valueReference` at a `QuestionnaireResponse` resource included in the same bundle. + +```json +{ + "sequence": 8, + "category": { + "coding": [ + { "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category", "code": "INF" } + ] + }, + "code": { + "coding": [ + { "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-code", "code": "ODN" } + ] + }, + "valueReference": { "reference": "" } +} +``` + +A reference with no matching resource in the bundle returns [PAYR-1084](payr-1084.md). A procedure that needs a standard treatment guideline response and has none returns [PAYR-1254](payr-1254.md) on a preauthorisation, or [PAYR-1365](payr-1365.md) on a claim. + +Send every retry as a new request with a new `x-hcx-correlation_id`. A correlation id that ended in an error is inactive. A correlation id that already exists is refused with [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1506.md b/catalogue/nhcx/errors/payr-1506.md new file mode 100644 index 000000000..e9d1b7888 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1506.md @@ -0,0 +1,99 @@ +--- +id: nhcx.error.payr-1506 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1506: the newborn''s gender is not valid' +summary: >- + The scheme payer rejected your newborn case because the child's record has no + valid gender. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + errors: + - nhcx.error.payr-1262 + - nhcx.error.payr-1507 + - nhcx.error.payr-1508 + - nhcx.error.payr-1509 + - nhcx.error.nhcx-1006 +--- + +# PAYR-1506: the newborn's gender is not valid + +## In plain words + +Your [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) is for a newborn under [PMJAY](../glossary/pmjay.md). The newborn has no scheme membership of its own yet. The parent is the main patient, and the child is a separate, linked patient. + +The PMJAY payer requires a valid gender on the child's record. Yours was not a valid value, so it refused the request. + +## Before you start + +- Your system sent a [preauthorisation](../glossary/preauthorisation.md) or a [claim](../glossary/claim.md) through [NHCX](../../shared/glossary/nhcx.md), and NHCX answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md) and [Submit a claim after discharge](../flows/claim-submit.md). +- Both bundles carry a `Claim` resource. `Claim.use` is `preauthorization` for a preauthorisation and `claim` for a claim. + +The [PMJAY](../glossary/pmjay.md) payer checked the `Claim` resource and refused it. Its answer arrived on the callback for your request: `/v1/preauth/on_submit` or `/v1/claim/on_submit`. The code is in `x-hcx-error_details.code`, and the full text is in `x-hcx-error_details.message`. + +Your callback tells an error from a decision by the `type` field of what arrives. An encrypted payload comes only when the payer processed your request. A `ProtocolResponse` comes when it could not, and carries the error details in clear headers. + +[Error code spaces](../concepts/error-code-spaces.md) explains where `PAYR-15xx` codes come from. + +Your bundle carries a newborn: the parent's `Patient` resource links to a child `Patient` resource. + +## What happens + +The payer checks the child `Patient` resource that the parent's `link` points to. It returns `PAYR-1506` when that resource has no valid gender. Gender is mandatory for a PMJAY newborn case. + +Valid values are the administrative gender codes at https://hl7.org/fhir/R4/valueset-administrative-gender.html. + +```text +Invalid gender received for new born patient. Please try agian with valid gender data as it is mandatory for PMJAY in new born case. Please refer to the valid gender values at https://hl7.org/fhir/R4/valueset-administrative-gender.html +``` + +The newborn construct applies when the baby has no member id yet and is 6 years old or younger. + +## How you know it worked + +You send the corrected bundle as a new request and receive `202 Accepted`. + +The answer on `/v1/preauth/on_submit` or `/v1/claim/on_submit` is an encrypted payload, and `PAYR-1506` does not come back. After you decrypt it, the payload is a `ClaimResponse` bundle carrying the payer's decision on the case. + +## When it goes wrong + +1. Find the child `Patient` resource that the parent's `link` points to. +2. Set `gender` to a code from the value set above. + +```json +{ + "resourceType": "Patient", + "gender": "", + "birthDate": "" +} +``` + +The child's record also needs a date of birth and a proof of birth document. See [PAYR-1507](payr-1507.md) and [PAYR-1509](payr-1509.md). A preauthorisation with no gender for the newborn returns [PAYR-1262](payr-1262.md). + +Send every retry as a new request with a new `x-hcx-correlation_id`. A correlation id that ended in an error is inactive. A correlation id that already exists is refused with [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1507.md b/catalogue/nhcx/errors/payr-1507.md new file mode 100644 index 000000000..3ee0aaf23 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1507.md @@ -0,0 +1,93 @@ +--- +id: nhcx.error.payr-1507 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1507: the newborn''s date of birth is not valid' +summary: >- + The scheme payer rejected your newborn case because the child's record has no + valid date of birth. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + errors: + - nhcx.error.payr-1259 + - nhcx.error.payr-1260 + - nhcx.error.payr-1269 + - nhcx.error.payr-1506 + - nhcx.error.payr-1509 + - nhcx.error.nhcx-1006 +--- + +# PAYR-1507: the newborn's date of birth is not valid + +## In plain words + +Your [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) is for a newborn under [PMJAY](../glossary/pmjay.md). The newborn has no scheme membership of its own yet. The parent is the main patient, and the child is a separate, linked patient. + +The PMJAY payer requires a valid date of birth on the child's record. Yours was not valid, so it refused the request. + +## Before you start + +- Your system sent a [preauthorisation](../glossary/preauthorisation.md) or a [claim](../glossary/claim.md) through [NHCX](../../shared/glossary/nhcx.md), and NHCX answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md) and [Submit a claim after discharge](../flows/claim-submit.md). +- Both bundles carry a `Claim` resource. `Claim.use` is `preauthorization` for a preauthorisation and `claim` for a claim. + +The [PMJAY](../glossary/pmjay.md) payer checked the `Claim` resource and refused it. Its answer arrived on the callback for your request: `/v1/preauth/on_submit` or `/v1/claim/on_submit`. The code is in `x-hcx-error_details.code`, and the full text is in `x-hcx-error_details.message`. + +Your callback tells an error from a decision by the `type` field of what arrives. An encrypted payload comes only when the payer processed your request. A `ProtocolResponse` comes when it could not, and carries the error details in clear headers. + +[Error code spaces](../concepts/error-code-spaces.md) explains where `PAYR-15xx` codes come from. + +Your bundle carries a newborn: the parent's `Patient` resource links to a child `Patient` resource. + +## What happens + +The payer checks the child `Patient` resource that the parent's `link` points to. It returns `PAYR-1507` when that resource has no valid date of birth. The date of birth is mandatory for a PMJAY newborn case. + +```text +Invalid date of birth received for new born patient. Please try agian with valid date of birth as it is mandatory for PMJAY in new born case. +``` + +The newborn construct applies when the baby has no member id yet and is 6 years old or younger. + +## How you know it worked + +You send the corrected bundle as a new request and receive `202 Accepted`. + +The answer on `/v1/preauth/on_submit` or `/v1/claim/on_submit` is an encrypted payload, and `PAYR-1507` does not come back. After you decrypt it, the payload is a `ClaimResponse` bundle carrying the payer's decision on the case. + +## When it goes wrong + +1. Find the child `Patient` resource that the parent's `link` points to. +2. Set `birthDate` to the child's date of birth, in the form `YYYY-MM-DD`. +3. Check the date is not in the future and is within 6 years of the current date. + +A preauthorisation checks the same date in more detail. A missing date returns [PAYR-1259](payr-1259.md). A future date returns [PAYR-1260](payr-1260.md). A date more than 6 years back returns [PAYR-1269](payr-1269.md). + +The date of birth also needs a proof of birth document. See [PAYR-1509](payr-1509.md). + +Send every retry as a new request with a new `x-hcx-correlation_id`. A correlation id that ended in an error is inactive. A correlation id that already exists is refused with [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1508.md b/catalogue/nhcx/errors/payr-1508.md new file mode 100644 index 000000000..35d7dfd5e --- /dev/null +++ b/catalogue/nhcx/errors/payr-1508.md @@ -0,0 +1,103 @@ +--- +id: nhcx.error.payr-1508 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1508: the newborn link does not lead to a Patient resource' +summary: >- + The scheme payer rejected your newborn case because the parent's link to the child + does not lead to a valid patient record. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + errors: + - nhcx.error.payr-1506 + - nhcx.error.payr-1507 + - nhcx.error.payr-1512 + - nhcx.error.nhcx-1006 +--- + +# PAYR-1508: the newborn link does not lead to a Patient resource + +## In plain words + +Your [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) is for a newborn under [PMJAY](../glossary/pmjay.md). The newborn has no scheme membership of its own yet. The parent is the main patient, and the child is a separate, linked patient. + +The PMJAY payer followed the parent's link to the child and did not find a valid `Patient` resource. The linked child record is mandatory for a newborn case, so it refused the request. + +## Before you start + +- Your system sent a [preauthorisation](../glossary/preauthorisation.md) or a [claim](../glossary/claim.md) through [NHCX](../../shared/glossary/nhcx.md), and NHCX answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md) and [Submit a claim after discharge](../flows/claim-submit.md). +- Both bundles carry a `Claim` resource. `Claim.use` is `preauthorization` for a preauthorisation and `claim` for a claim. + +The [PMJAY](../glossary/pmjay.md) payer checked the `Claim` resource and refused it. Its answer arrived on the callback for your request: `/v1/preauth/on_submit` or `/v1/claim/on_submit`. The code is in `x-hcx-error_details.code`, and the full text is in `x-hcx-error_details.message`. + +Your callback tells an error from a decision by the `type` field of what arrives. An encrypted payload comes only when the payer processed your request. A `ProtocolResponse` comes when it could not, and carries the error details in clear headers. + +[Error code spaces](../concepts/error-code-spaces.md) explains where `PAYR-15xx` codes come from. + +Your bundle carries a newborn: the parent's `Patient` resource links to a child `Patient` resource. + +## What happens + +The parent's `Patient` resource carries a `link` entry of type `refer`. Its `other.reference` points to the child's `Patient` resource: + +```json +"link": [ + { + "other": { + "reference": "urn:uuid:", + "type": "Patient" + }, + "type": "refer" + } +] +``` + +The payer returns `PAYR-1508` when the resource at that reference is missing or is not a valid `Patient`. The `%s` in the message is the reference it followed. + +```text +Invalid resource received for new born patient for url %s. Please try agian with valid Patient resource for the link reference as linked Patient resource is mandatory for PMJAY in new born case +``` + +The newborn construct applies when the baby has no member id yet and is 6 years old or younger. + +## How you know it worked + +You send the corrected bundle as a new request and receive `202 Accepted`. + +The answer on `/v1/preauth/on_submit` or `/v1/claim/on_submit` is an encrypted payload, and `PAYR-1508` does not come back. After you decrypt it, the payload is a `ClaimResponse` bundle carrying the payer's decision on the case. + +## When it goes wrong + +1. Find the reference from the message in your bundle. +2. Make sure one bundle entry has that reference as its `fullUrl`, and that its resource is a `Patient`. +3. Put the child's details in that resource: gender, date of birth and name. + +A patient reference that fails outside the newborn link returns [PAYR-1512](payr-1512.md). + +Send every retry as a new request with a new `x-hcx-correlation_id`. A correlation id that ended in an error is inactive. A correlation id that already exists is refused with [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1509.md b/catalogue/nhcx/errors/payr-1509.md new file mode 100644 index 000000000..9f6860d3d --- /dev/null +++ b/catalogue/nhcx/errors/payr-1509.md @@ -0,0 +1,112 @@ +--- +id: nhcx.error.payr-1509 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1509: the newborn''s proof of birth attachment is not valid' +summary: >- + The scheme payer rejected your newborn case because the proof of birth document + is missing or unusable. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + errors: + - nhcx.error.payr-1263 + - nhcx.error.payr-1507 + - nhcx.error.nhcx-1006 +--- + +# PAYR-1509: the newborn's proof of birth attachment is not valid + +## In plain words + +Your [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) is for a newborn under [PMJAY](../glossary/pmjay.md). The newborn has no scheme membership of its own yet. The parent is the main patient, and the child is a separate, linked patient. + +A document proving the child's date of birth is mandatory. The PMJAY payer found that attachment missing or invalid, so it refused the request. + +## Before you start + +- Your system sent a [preauthorisation](../glossary/preauthorisation.md) or a [claim](../glossary/claim.md) through [NHCX](../../shared/glossary/nhcx.md), and NHCX answered `202 Accepted`. See [Submit a preauthorisation](../flows/preauth-submit.md) and [Submit a claim after discharge](../flows/claim-submit.md). +- Both bundles carry a `Claim` resource. `Claim.use` is `preauthorization` for a preauthorisation and `claim` for a claim. + +The [PMJAY](../glossary/pmjay.md) payer checked the `Claim` resource and refused it. Its answer arrived on the callback for your request: `/v1/preauth/on_submit` or `/v1/claim/on_submit`. The code is in `x-hcx-error_details.code`, and the full text is in `x-hcx-error_details.message`. + +Your callback tells an error from a decision by the `type` field of what arrives. An encrypted payload comes only when the payer processed your request. A `ProtocolResponse` comes when it could not, and carries the error details in clear headers. + +[Error code spaces](../concepts/error-code-spaces.md) explains where `PAYR-15xx` codes come from. + +Your bundle carries a newborn: the parent's `Patient` resource links to a child `Patient` resource. + +## What happens + +The payer returns `PAYR-1509` when the newborn case carries no valid attachment. + +The document is proof of date of birth. It is a supporting information entry with category `DOB`. Its code is `BCF` for a birth certificate, or `DCB` for a government hospital discharge card or slip. + +An attachment is valid when: + +- its data is a Base64 encoded string, as https://hl7.org/fhir/R4/datatypes.html#Attachment defines; +- it has a name that is not empty; and +- its content type is one of `application/pdf`, `application/jpg`, `application/jpeg`, `application/png` or `application/fhir+json`. + +```text +Invalid attachment received for new born patient. Please try agian with valid attachment as attachment is mandatory for PMJAY in new born case +``` + +The newborn construct applies when the baby has no member id yet and is 6 years old or younger. + +## How you know it worked + +You send the corrected bundle as a new request and receive `202 Accepted`. + +The answer on `/v1/preauth/on_submit` or `/v1/claim/on_submit` is an encrypted payload, and `PAYR-1509` does not come back. After you decrypt it, the payload is a `ClaimResponse` bundle carrying the payer's decision on the case. + +## When it goes wrong + +1. Add or correct the proof of birth entry. Use category `DOB` and code `BCF` or `DCB`. +2. Encode the document as Base64, give it a name and set an accepted content type. + +```json +{ + "sequence": 9, + "category": { + "coding": [ + { "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category", "code": "DOB" } + ] + }, + "code": { + "coding": [ + { "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-code", "code": "BCF" } + ] + }, + "valueAttachment": { "contentType": "application/pdf", "title": "", "data": "" } +} +``` + +A preauthorisation for a newborn with no documents returns [PAYR-1263](payr-1263.md). + +Send every retry as a new request with a new `x-hcx-correlation_id`. A correlation id that ended in an error is inactive. A correlation id that already exists is refused with [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1510.md b/catalogue/nhcx/errors/payr-1510.md new file mode 100644 index 000000000..191666094 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1510.md @@ -0,0 +1,90 @@ +--- +id: nhcx.error.payr-1510 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1510: a parameter code in your request is not valid' +summary: >- + The scheme payer rejected your request because one of its parameter codes is not + a code it accepts. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + flows: + - nhcx.flow.insurance-plan-request + - nhcx.flow.claim-reprocess + - nhcx.flow.preauth-cancel + endpoints: + - nhcx.endpoint.insuranceplan-request + - nhcx.endpoint.task-submit + callbacks: + - nhcx.callback.insuranceplan-on-request + - nhcx.callback.task-on-submit + fhir: + - nhcx.fhir.task + - nhcx.fhir.insurance-plan-bundle + errors: + - nhcx.error.payr-1511 + - nhcx.error.payr-1518 + - nhcx.error.payr-1519 + - nhcx.error.nhcx-1006 +--- + +# PAYR-1510: a parameter code in your request is not valid + +## In plain words + +The [PMJAY](../glossary/pmjay.md) payer checked the parameters in your request and found a code it does not accept. The message does not say which parameter. Your system has to find it before it resends. + +## Before you start + +- Your system sent a request whose bundle holds a `Task` resource. That is an insurance plan request, or a task request such as a reprocess or a cancellation. See [Request a patient's insurance plan](../flows/insurance-plan-request.md) and [Ask the payer to reprocess a claim](../flows/claim-reprocess.md). +- [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. + +The [PMJAY](../glossary/pmjay.md) payer's answer arrived on the callback for that request: `/v1/insuranceplan/on_request` or `/v1/task/on_submit`. The code is in `x-hcx-error_details.code`, and the full text is in `x-hcx-error_details.message`. + +Your callback tells an error from a decision by the `type` field of what arrives. An encrypted payload comes only when the payer processed your request. A `ProtocolResponse` comes when it could not, and carries the error details in clear headers. + +[Error code spaces](../concepts/error-code-spaces.md) explains where `PAYR-15xx` codes come from. + +## What happens + +The payer returns `PAYR-1510` when a parameter code in your request is not a valid code. + +```text +Invalid parameter code received. Please check and try again with a valid parameter code +``` + +In a `Task` resource, the input parameters are the `Task.input` entries. [PAYR-1518](payr-1518.md) and [PAYR-1519](payr-1519.md) use the term the same way. Each entry has a type code and a value. The documented type codes use the system `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code`: + +| Request | Inputs the `Task` carries | +|---|---| +| Insurance plan request | `policyNumber`, `providerId`, or both. At least one is mandatory. | +| Task request on a claim | `claimNumber` | +| Task request on a preauthorisation | `initimationNumber`, spelled as shown | +| Answer to a communication request | An input of type `include`, whose value references the `Communication` resource | + +## How you know it worked + +You send the corrected request as a new request and receive `202 Accepted`. + +The answer on `/v1/insuranceplan/on_request` or `/v1/task/on_submit` is an encrypted payload, and `PAYR-1510` does not come back. For an insurance plan request, the decrypted payload is a `Bundle` of type `collection` holding an `InsurancePlan`. + +## When it goes wrong + +1. Compare every `Task.input` type code and system in your request with the table. +2. Check the other coded values in your bundle against the sample bundles and the [NRCeS](../../shared/glossary/nrces.md) code systems. +3. If you cannot find the parameter, contact the NHCX support team. Give them the full message and the `x-hcx-correlation_id`. + +A wrong value, rather than a wrong code, returns [PAYR-1511](payr-1511.md). + +Send every retry as a new request with a new `x-hcx-correlation_id`. A correlation id that ended in an error is inactive. A correlation id that already exists is refused with [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1511.md b/catalogue/nhcx/errors/payr-1511.md new file mode 100644 index 000000000..234a7556d --- /dev/null +++ b/catalogue/nhcx/errors/payr-1511.md @@ -0,0 +1,91 @@ +--- +id: nhcx.error.payr-1511 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1511: a parameter value in your request is not valid' +summary: >- + The scheme payer rejected your request because one of its parameter values is + not a value it accepts. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + flows: + - nhcx.flow.insurance-plan-request + - nhcx.flow.claim-reprocess + - nhcx.flow.preauth-cancel + endpoints: + - nhcx.endpoint.insuranceplan-request + - nhcx.endpoint.task-submit + callbacks: + - nhcx.callback.insuranceplan-on-request + - nhcx.callback.task-on-submit + fhir: + - nhcx.fhir.task + - nhcx.fhir.insurance-plan-bundle + errors: + - nhcx.error.payr-1510 + - nhcx.error.payr-1518 + - nhcx.error.payr-1402 + - nhcx.error.payr-1405 + - nhcx.error.nhcx-1006 +--- + +# PAYR-1511: a parameter value in your request is not valid + +## In plain words + +The [PMJAY](../glossary/pmjay.md) payer checked the parameters in your request and found a value it does not accept. The message does not say which parameter. Your system has to find it before it resends. + +## Before you start + +- Your system sent a request whose bundle holds a `Task` resource. That is an insurance plan request, or a task request such as a reprocess or a cancellation. See [Request a patient's insurance plan](../flows/insurance-plan-request.md) and [Ask the payer to reprocess a claim](../flows/claim-reprocess.md). +- [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. + +The [PMJAY](../glossary/pmjay.md) payer's answer arrived on the callback for that request: `/v1/insuranceplan/on_request` or `/v1/task/on_submit`. The code is in `x-hcx-error_details.code`, and the full text is in `x-hcx-error_details.message`. + +Your callback tells an error from a decision by the `type` field of what arrives. An encrypted payload comes only when the payer processed your request. A `ProtocolResponse` comes when it could not, and carries the error details in clear headers. + +[Error code spaces](../concepts/error-code-spaces.md) explains where `PAYR-15xx` codes come from. + +## What happens + +The payer returns `PAYR-1511` when a parameter value in your request is not valid. + +```text +Invalid parameter value received. Please check and try again with a valid parameter value +``` + +In a `Task` resource, the input parameters are the `Task.input` entries. Each entry has a type code and a value. The documented inputs carry these values: + +| Input type code | Value it carries | +|---|---| +| `policyNumber` | The policy code, for example `PMJAY/HP/S/G` | +| `providerId` | Your hospital's [HFR](../../shared/glossary/hfr.md) id | +| `claimNumber` | The claim's reference number | +| `initimationNumber` | Your internal reference number, or the preauthorisation reference number from the payer | + +## How you know it worked + +You send the corrected request as a new request and receive `202 Accepted`. + +The answer on `/v1/insuranceplan/on_request` or `/v1/task/on_submit` is an encrypted payload, and `PAYR-1511` does not come back. For an insurance plan request, the decrypted payload is a `Bundle` of type `collection` holding an `InsurancePlan`. + +## When it goes wrong + +1. Check each `Task.input` value in your request against the table. +2. Take reference numbers from the payer's earlier responses, not from free text. +3. If you cannot find the parameter, contact the NHCX support team. Give them the full message and the `x-hcx-correlation_id`. + +A wrong type code, rather than a wrong value, returns [PAYR-1510](payr-1510.md). + +Send every retry as a new request with a new `x-hcx-correlation_id`. A correlation id that ended in an error is inactive. A correlation id that already exists is refused with [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1512.md b/catalogue/nhcx/errors/payr-1512.md new file mode 100644 index 000000000..5b3198b02 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1512.md @@ -0,0 +1,87 @@ +--- +id: nhcx.error.payr-1512 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1512: a patient reference does not lead to a Patient resource' +summary: >- + The scheme payer rejected your request because a reference to the patient does + not lead to a valid patient record. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.coverageeligibility-on-check + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + errors: + - nhcx.error.payr-1508 + - nhcx.error.payr-1009 + - nhcx.error.nhcx-1006 +--- + +# PAYR-1512: a patient reference does not lead to a Patient resource + +## In plain words + +A resource in your [FHIR](../../shared/glossary/fhir.md) bundle refers to the patient. The [PMJAY](../glossary/pmjay.md) payer followed that reference and did not find a valid `Patient` resource. It refused the request. + +## Before you start + +- Your system sent a request through [NHCX](../../shared/glossary/nhcx.md), and NHCX answered `202 Accepted`. +- The [PMJAY](../glossary/pmjay.md) payer checked the [FHIR](../../shared/glossary/fhir.md) bundle inside it and refused it. + +The payer's answer arrived on the `on_` callback for that request. For a preauthorisation that is `/v1/preauth/on_submit`, and for a claim `/v1/claim/on_submit`. The code is in `x-hcx-error_details.code`, and the full text is in `x-hcx-error_details.message`. + +Your callback tells an error from a decision by the `type` field of what arrives. An encrypted payload comes only when the payer processed your request. A `ProtocolResponse` comes when it could not, and carries the error details in clear headers. + +[Error code spaces](../concepts/error-code-spaces.md) explains where `PAYR-15xx` codes come from. + +## What happens + +The payer returns `PAYR-1512` when the resource at a patient reference is missing or is not a valid `Patient`. The `%s` in the message is the reference it followed. + +```text +Invalid resource received for patient for url %s. Please try agian with valid Patient resource for the reference +``` + +## How you know it worked + +You send the corrected bundle as a new request and receive `202 Accepted`. + +The payer's answer on the `on_` callback is an encrypted payload, and `PAYR-1512` does not come back. After you decrypt it, the payload is the response for your request, for example a `ClaimResponse` bundle for a preauthorisation or a claim. + +## When it goes wrong + +1. Search your bundle for the reference in the message. +2. Make sure one bundle entry has that reference as its `fullUrl`, and that its resource is a `Patient`. +3. Check the reference is spelled the same in both places. +4. Validate the bundle against the [NRCeS](../../shared/glossary/nrces.md) profiles before you send it. See [bundle validation](../fhir/validation.md). + +A newborn's link to the child record fails with [PAYR-1508](payr-1508.md) instead. + +Send every retry as a new request with a new `x-hcx-correlation_id`. A correlation id that ended in an error is inactive. A correlation id that already exists is refused with [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1513.md b/catalogue/nhcx/errors/payr-1513.md new file mode 100644 index 000000000..961d37817 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1513.md @@ -0,0 +1,99 @@ +--- +id: nhcx.error.payr-1513 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1513: a diagnosis is not sent as a coded concept' +summary: >- + The scheme payer rejected your request because a diagnosis was not sent as a code + with its system. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.coverageeligibility-on-check + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + errors: + - nhcx.error.nhcx-1006 +--- + +# PAYR-1513: a diagnosis is not sent as a coded concept + +## In plain words + +Your [FHIR](../../shared/glossary/fhir.md) bundle lists a diagnosis. The [PMJAY](../glossary/pmjay.md) payer accepts a diagnosis only as a coded concept: a code, its code system and a display text. Yours arrived in another form, so it refused the request. + +## Before you start + +- Your system sent a request through [NHCX](../../shared/glossary/nhcx.md), and NHCX answered `202 Accepted`. +- The [PMJAY](../glossary/pmjay.md) payer checked the [FHIR](../../shared/glossary/fhir.md) bundle inside it and refused it. + +The payer's answer arrived on the `on_` callback for that request. For a preauthorisation that is `/v1/preauth/on_submit`, and for a claim `/v1/claim/on_submit`. The code is in `x-hcx-error_details.code`, and the full text is in `x-hcx-error_details.message`. + +Your callback tells an error from a decision by the `type` field of what arrives. An encrypted payload comes only when the payer processed your request. A `ProtocolResponse` comes when it could not, and carries the error details in clear headers. + +[Error code spaces](../concepts/error-code-spaces.md) explains where `PAYR-15xx` codes come from. + +## What happens + +The payer reads each diagnosis from the diagnosis component. In a preauthorisation or a claim, that is `Claim.diagnosis[].diagnosisCodeableConcept`. Coverage eligibility bundles carry diagnoses in the same shape. The payer returns `PAYR-1513` when a diagnosis is not sent as a `CodeableConcept`. + +```text +Invalid diagnosis received in DiagnosisComponent. In DiagnosisComponent, diagnosis should be sent as CodeableConcept. Please try agian with valid data +``` + +## How you know it worked + +You send the corrected bundle as a new request and receive `202 Accepted`. + +The payer's answer on the `on_` callback is an encrypted payload, and `PAYR-1513` does not come back. After you decrypt it, the payload is the response for your request, for example a `ClaimResponse` bundle for a preauthorisation or a claim. + +## When it goes wrong + +Send every diagnosis as a `diagnosisCodeableConcept` with at least one coding: + +```json +"diagnosis": [ + { + "sequence": 1, + "diagnosisCodeableConcept": { + "coding": [ + { + "system": "", + "code": "", + "display": "" + } + ] + } + } +] +``` + +Check every entry in the list, not only the first. Validate the bundle against the [NRCeS](../../shared/glossary/nrces.md) profiles before you send it. See [bundle validation](../fhir/validation.md). + +Send every retry as a new request with a new `x-hcx-correlation_id`. A correlation id that ended in an error is inactive. A correlation id that already exists is refused with [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1514.md b/catalogue/nhcx/errors/payr-1514.md new file mode 100644 index 000000000..56d1036b5 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1514.md @@ -0,0 +1,106 @@ +--- +id: nhcx.error.payr-1514 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1514: the discharge information entry does not name a discharge stage' +summary: >- + The scheme payer rejected your claim because the discharge information entry was + not text naming the discharge stage. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + errors: + - nhcx.error.payr-1095 + - nhcx.error.payr-1096 + - nhcx.error.payr-1503 + - nhcx.error.payr-1324 + - nhcx.error.payr-1362 + - nhcx.error.nhcx-1006 +--- + +# PAYR-1514: the discharge information entry does not name a discharge stage + +## In plain words + +Your [claim](../glossary/claim.md) carries discharge information as a supporting information entry. The [PMJAY](../glossary/pmjay.md) payer reads it as text naming the discharge stage. Your entry held another kind of value, so it refused the claim. + +## Before you start + +- Your system sent a [claim](../glossary/claim.md) through [NHCX](../../shared/glossary/nhcx.md), and NHCX answered `202 Accepted`. See [Submit a claim after discharge](../flows/claim-submit.md). +- The claim bundle carries a `Claim` resource with `Claim.use` set to `claim`. + +The [PMJAY](../glossary/pmjay.md) payer checked the `Claim` resource and refused it. Its answer arrived on `/v1/claim/on_submit`. The code is in `x-hcx-error_details.code`, and the full text is in `x-hcx-error_details.message`. + +Your callback tells an error from a decision by the `type` field of what arrives. An encrypted payload comes only when the payer processed your request. A `ProtocolResponse` comes when it could not, and carries the error details in clear headers. + +[Error code spaces](../concepts/error-code-spaces.md) explains where `PAYR-15xx` codes come from. + +## What happens + +The payer reads discharge information from the `Claim.supportingInfo` entry with category `DIS`. It returns `PAYR-1514` when that entry's value is not a string. + +The entry carries: + +| Element | Value | +|---|---| +| Category | `DIS` | +| Code | One of `DTH`, `LAMA`, `DAMA` or `DTM` | +| Value | A string naming the discharge stage: `After Surgery`, `Before Surgery` or `During Surgery` | + +```text +Value type received as %s for category - DIS for item with sequence %s in supporting info in claim resource. In supporting info list, item with category - DIS is used to get the discharge related information. So the discharge information should be sent as string value, with value representing discharge stage (After Surgery / Before Surgery / During Surgery), with the category - DIS and code - DTH/LAMA/DAMA/DTM +``` + +The first `%s` is the value type you sent. The second is the entry's `sequence`. + +## How you know it worked + +You send the corrected bundle as a new request and receive `202 Accepted`. + +The answer on `/v1/claim/on_submit` is an encrypted payload, and `PAYR-1514` does not come back. After you decrypt it, the payload is a `ClaimResponse` bundle carrying the payer's decision on the case. + +## When it goes wrong + +1. Find the `supportingInfo` entry whose `sequence` matches the message. +2. Send the discharge stage in that entry as a string, with category `DIS` and the code for the discharge. + +```json +{ + "sequence": 5, + "category": { + "coding": [ + { "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category", "code": "DIS" } + ] + }, + "code": { + "coding": [ + { "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-code", "code": "DTH" } + ] + }, + "valueString": "After Surgery" +} +``` + +A claim with no discharge information returns [PAYR-1095](payr-1095.md). A death discharge also needs the death date entry: see [PAYR-1503](payr-1503.md) and [PAYR-1096](payr-1096.md). A `LAMA` or `DAMA` discharge before or during surgery also needs procedure `LM100`: see [PAYR-1362](payr-1362.md). + +Send every retry as a new request with a new `x-hcx-correlation_id`. A correlation id that ended in an error is inactive. A correlation id that already exists is refused with [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1515.md b/catalogue/nhcx/errors/payr-1515.md new file mode 100644 index 000000000..505f2a403 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1515.md @@ -0,0 +1,85 @@ +--- +id: nhcx.error.payr-1515 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1515: an organisation in your bundle has no name' +summary: >- + The scheme payer rejected your request because an organisation record in it has + no valid name. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.coverageeligibility-on-check + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.validation + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + errors: + - nhcx.error.payr-1013 + - nhcx.error.payr-1015 + - nhcx.error.nhcx-1006 +--- + +# PAYR-1515: an organisation in your bundle has no name + +## In plain words + +Your [FHIR](../../shared/glossary/fhir.md) bundle includes an `Organization` resource for a hospital or a payer. The [PMJAY](../glossary/pmjay.md) payer requires every organisation to carry a name. The organisation at the reference in the message had no valid name, so it refused the request. + +## Before you start + +- Your system sent a request through [NHCX](../../shared/glossary/nhcx.md), and NHCX answered `202 Accepted`. +- The [PMJAY](../glossary/pmjay.md) payer checked the [FHIR](../../shared/glossary/fhir.md) bundle inside it and refused it. + +The payer's answer arrived on the `on_` callback for that request. For a preauthorisation that is `/v1/preauth/on_submit`, and for a claim `/v1/claim/on_submit`. The code is in `x-hcx-error_details.code`, and the full text is in `x-hcx-error_details.message`. + +Your callback tells an error from a decision by the `type` field of what arrives. An encrypted payload comes only when the payer processed your request. A `ProtocolResponse` comes when it could not, and carries the error details in clear headers. + +[Error code spaces](../concepts/error-code-spaces.md) explains where `PAYR-15xx` codes come from. + +## What happens + +The payer returns `PAYR-1515` when the `Organization` resource at a reference has no valid name. The `%s` in the message is that reference. Name is mandatory under the NRCeS Organization profile at https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html. + +```text +Invalid name received for organization resource with url %s. Name is mandatory for organization resource. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html +``` + +## How you know it worked + +You send the corrected bundle as a new request and receive `202 Accepted`. + +The payer's answer on the `on_` callback is an encrypted payload, and `PAYR-1515` does not come back. After you decrypt it, the payload is the response for your request, for example a `ClaimResponse` bundle for a preauthorisation or a claim. + +## When it goes wrong + +1. Find the `Organization` resource whose `fullUrl` matches the reference in the message. +2. Set its `name` to the organisation's name. Do not send an empty string. +3. Check every other `Organization` resource in the bundle, for the provider and the payer alike. +4. Validate the bundle against the [NRCeS](../../shared/glossary/nrces.md) profiles before you send it. See [bundle validation](../fhir/validation.md). + +Send every retry as a new request with a new `x-hcx-correlation_id`. A correlation id that ended in an error is inactive. A correlation id that already exists is refused with [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1516.md b/catalogue/nhcx/errors/payr-1516.md new file mode 100644 index 000000000..c7950c61a --- /dev/null +++ b/catalogue/nhcx/errors/payr-1516.md @@ -0,0 +1,78 @@ +--- +id: nhcx.error.payr-1516 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1516: the payer cannot match your error response to any message' +summary: >- + The scheme payer refused an error response from your system because its identifiers + match no message the payer knows about. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.message-identifiers + flows: + - nhcx.flow.report-a-processing-error + endpoints: + - nhcx.endpoint.communication-on-request + callbacks: + - nhcx.callback.error + - nhcx.callback.communication-request + errors: + - nhcx.error.payr-1517 +--- + +# PAYR-1516: the payer cannot match your error response to any message + +## In plain words + +Your system sent an error response to the [PMJAY](../glossary/pmjay.md) payer through [NHCX](../../shared/glossary/nhcx.md). The payer finds the message your error response answers by three identifiers. It found no message with that combination, so it refused your error response. + +## Before you start + +- Your system received a message from the payer and could not process it. +- Your system answered with an error response in the `ProtocolResponse` structure. See [Report a processing failure on /v1/error](../flows/report-a-processing-error.md). + +The payer refused that error response with this code. [Error code spaces](../concepts/error-code-spaces.md) explains where `PAYR-15xx` codes come from. + +## What happens + +The payer identifies the message your error response answers by these values: + +| In the message | Header in your error response | +|---|---| +| api-caller-id | `x-hcx-api_call_id` | +| correlation id | `x-hcx-correlation_id` | +| sender code | `x-hcx-sender_code` | + +It returns `PAYR-1516` when it holds no event for that combination. + +```text +No event found for api-caller-id %s and correlation id %s for sender code %s. Hence error response willnot be accepted. +``` + +The three `%s` values are the identifiers your error response carried. + +## How you know it worked + +You send the corrected error response and `PAYR-1516` does not come back. + +Your logs show that its three identifiers relate to the message you answered. The rules are in [Correlation id, API call id and workflow id](../concepts/message-identifiers.md). + +## When it goes wrong + +1. Take the identifiers for your error response from the message you are answering. Do not generate a fresh correlation id for a response. +2. Set `x-hcx-sender_code` to your own participant code. Set `x-hcx-recipient_code` to the sender of the message you answer. +3. Follow the identifier rules for responses in [Correlation id, API call id and workflow id](../concepts/message-identifiers.md). +4. If the identifiers match and the code comes back, contact the NHCX support team. Give them the three values from the message. + +An error response in the wrong structure returns [PAYR-1517](payr-1517.md) instead. diff --git a/catalogue/nhcx/errors/payr-1517.md b/catalogue/nhcx/errors/payr-1517.md new file mode 100644 index 000000000..fd7a7ad23 --- /dev/null +++ b/catalogue/nhcx/errors/payr-1517.md @@ -0,0 +1,103 @@ +--- +id: nhcx.error.payr-1517 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1517: your error was sent encrypted instead of as a protocol response' +summary: >- + The scheme payer refused an error from your system because it arrived in the encrypted + structure instead of the protocol response structure. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.message-identifiers + flows: + - nhcx.flow.report-a-processing-error + endpoints: + - nhcx.endpoint.communication-on-request + callbacks: + - nhcx.callback.error + - nhcx.callback.communication-request + errors: + - nhcx.error.payr-1516 +--- + +# PAYR-1517: your error was sent encrypted instead of as a protocol response + +## In plain words + +Your system sent the [PMJAY](../glossary/pmjay.md) payer an error through [NHCX](../../shared/glossary/nhcx.md). An error travels in the `ProtocolResponse` structure, with its details in clear headers. Yours arrived in the encrypted structure, typed `JWEPayloadResponse`. The payer does not read errors in that form. + +## Before you start + +- Your system received a message from the payer and could not process it. +- Your system answered with an error, but in the encrypted structure. + +The payer refused that error with this code. [Error code spaces](../concepts/error-code-spaces.md) explains where `PAYR-15xx` codes come from. + +## What happens + +A response takes one of two forms, told apart by its `type` field: + +| `type` | When it is used | +|---|---| +| `JWEPayloadResponse` | The request was validated and processed. The payload is encrypted with the recipient's public key. | +| `ProtocolResponse` | The request could not be validated or processed: the payload was invalid, it could not be decrypted, or a protocol error occurred. | + +The payer returns `PAYR-1517` when an error reaches it as `JWEPayloadResponse`. + +```text +Invalid error structure received for NHCX error. Protocol response structure is expected, but received JWEPayloadResponse. +``` + +## How you know it worked + +You send the error again as a `ProtocolResponse`, and `PAYR-1517` does not come back. + +## When it goes wrong + +Send the error as a `ProtocolResponse`. Its headers travel in clear, with the error in `x-hcx-error_details`: + +```json +{ + "type": "ProtocolResponse", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-correlation_id": "", + "x-hcx-workflow_id": "", + "x-hcx-timestamp": "", + "x-hcx-debug_flag": "Error", + "x-hcx-status": "response.error", + "x-hcx-redirect_to": "", + "x-hcx-error_details": { + "code": "", + "message": "", + "trace": "" + }, + "x-hcx-debug_details": { + "code": "", + "message": "", + "trace": "" + }, + "x-hcx-domain-header": { + "use_case_name": "", + "amt_processed": "" + }, + "x-hcx-entity-type": "", + "x-hcx-ben-abha-id": "" +} +``` + +`x-hcx-entity-type` is one of `coverageeligibility`, `payment`, `insuranceplan`, `task`, `claim` or `preauth`. `x-hcx-ben-abha-id` carries the beneficiary's [ABHA](../../shared/glossary/abha.md) number. Set the identifiers as [Correlation id, API call id and workflow id](../concepts/message-identifiers.md) describes. + +If the identifiers do not match the message you answer, the payer returns [PAYR-1516](payr-1516.md). diff --git a/catalogue/nhcx/errors/payr-1518.md b/catalogue/nhcx/errors/payr-1518.md new file mode 100644 index 000000000..a7793101e --- /dev/null +++ b/catalogue/nhcx/errors/payr-1518.md @@ -0,0 +1,111 @@ +--- +id: nhcx.error.payr-1518 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1518: your Task resource carries no input parameters' +summary: >- + The scheme payer rejected your task request because the task carries none of the + inputs it needs. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + flows: + - nhcx.flow.insurance-plan-request + - nhcx.flow.claim-reprocess + - nhcx.flow.preauth-cancel + endpoints: + - nhcx.endpoint.insuranceplan-request + - nhcx.endpoint.task-submit + - nhcx.endpoint.communication-on-request + callbacks: + - nhcx.callback.insuranceplan-on-request + - nhcx.callback.task-on-submit + fhir: + - nhcx.fhir.task + - nhcx.fhir.insurance-plan-bundle + errors: + - nhcx.error.payr-1519 + - nhcx.error.payr-1510 + - nhcx.error.payr-1511 + - nhcx.error.nhcx-1006 +--- + +# PAYR-1518: your Task resource carries no input parameters + +## In plain words + +Your request carries a `Task` resource. A `Task` tells the payer what you want, and names the policy or case through its inputs. Yours had no inputs, so the [PMJAY](../glossary/pmjay.md) payer refused it. + +## Before you start + +- Your system sent a request whose bundle holds a `Task` resource. That is an insurance plan request, or a task request such as a reprocess or a cancellation. See [Request a patient's insurance plan](../flows/insurance-plan-request.md) and [Ask the payer to reprocess a claim](../flows/claim-reprocess.md). +- [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. + +The [PMJAY](../glossary/pmjay.md) payer's answer arrived on the callback for that request: `/v1/insuranceplan/on_request` or `/v1/task/on_submit`. The code is in `x-hcx-error_details.code`, and the full text is in `x-hcx-error_details.message`. + +Your callback tells an error from a decision by the `type` field of what arrives. An encrypted payload comes only when the payer processed your request. A `ProtocolResponse` comes when it could not, and carries the error details in clear headers. + +[Error code spaces](../concepts/error-code-spaces.md) explains where `PAYR-15xx` codes come from. + +## What happens + +The payer returns `PAYR-1518` when the `Task` resource has no `input` entries. + +```text +No input parameters received for task resource. Input parameters are expected for task resource, but not received. Please try again with valid data. +``` + +Each use of `Task` needs its own inputs. The type codes use the system `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code`, except the communication input, whose type `include` comes from `http://terminology.hl7.org/CodeSystem/financialtaskinputtype`. + +| Request | Inputs the `Task` carries | +|---|---| +| Insurance plan request | `policyNumber`, `providerId`, or both. At least one is mandatory. | +| Task request on a claim | `claimNumber` | +| Task request on a preauthorisation | `initimationNumber`, spelled as shown | +| Answer to a communication request | An input of type `include`, whose value references the `Communication` resource | + +## How you know it worked + +You send the corrected request as a new request and receive `202 Accepted`. + +The answer on `/v1/insuranceplan/on_request` or `/v1/task/on_submit` is an encrypted payload, and `PAYR-1518` does not come back. For an insurance plan request, the decrypted payload is a `Bundle` of type `collection` holding an `InsurancePlan`. + +## When it goes wrong + +1. Add the inputs your request needs, from the table. +2. Give each input a `type` coding, with a system and a code, and a value. An input with no type returns [PAYR-1519](payr-1519.md). + +This example is the input list of an insurance plan request: + +```json +"input": [ + { + "type": { + "coding": [ + { "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code", "code": "policyNumber" } + ] + }, + "valueString": "" + }, + { + "type": { + "coding": [ + { "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code", "code": "providerId" } + ] + }, + "valueString": "" + } +] +``` + +Send every retry as a new request with a new `x-hcx-correlation_id`. A correlation id that ended in an error is inactive. A correlation id that already exists is refused with [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1519.md b/catalogue/nhcx/errors/payr-1519.md new file mode 100644 index 000000000..fcd4104ff --- /dev/null +++ b/catalogue/nhcx/errors/payr-1519.md @@ -0,0 +1,111 @@ +--- +id: nhcx.error.payr-1519 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1519: a Task input parameter has no type' +summary: >- + The scheme payer rejected your task request because at least one of the task's + inputs does not say what kind of input it is. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + flows: + - nhcx.flow.insurance-plan-request + - nhcx.flow.claim-reprocess + - nhcx.flow.preauth-cancel + endpoints: + - nhcx.endpoint.insuranceplan-request + - nhcx.endpoint.task-submit + - nhcx.endpoint.communication-on-request + callbacks: + - nhcx.callback.insuranceplan-on-request + - nhcx.callback.task-on-submit + fhir: + - nhcx.fhir.task + - nhcx.fhir.insurance-plan-bundle + errors: + - nhcx.error.payr-1518 + - nhcx.error.payr-1510 + - nhcx.error.nhcx-1006 +--- + +# PAYR-1519: a Task input parameter has no type + +## In plain words + +Your request carries a `Task` resource with inputs. Each input must say what kind of input it is, through a type code. At least one of yours had no type, so the [PMJAY](../glossary/pmjay.md) payer refused the request. + +## Before you start + +- Your system sent a request whose bundle holds a `Task` resource. That is an insurance plan request, or a task request such as a reprocess or a cancellation. See [Request a patient's insurance plan](../flows/insurance-plan-request.md) and [Ask the payer to reprocess a claim](../flows/claim-reprocess.md). +- [NHCX](../../shared/glossary/nhcx.md) answered `202 Accepted`. + +The [PMJAY](../glossary/pmjay.md) payer's answer arrived on the callback for that request: `/v1/insuranceplan/on_request` or `/v1/task/on_submit`. The code is in `x-hcx-error_details.code`, and the full text is in `x-hcx-error_details.message`. + +Your callback tells an error from a decision by the `type` field of what arrives. An encrypted payload comes only when the payer processed your request. A `ProtocolResponse` comes when it could not, and carries the error details in clear headers. + +[Error code spaces](../concepts/error-code-spaces.md) explains where `PAYR-15xx` codes come from. + +## What happens + +The payer returns `PAYR-1519` when a `Task.input` entry has no `type`. The `Task` profile is at https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html. + +```text +No type found for task input parameters. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html +``` + +The documented type codes use the system `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code`: + +| Request | Inputs the `Task` carries | +|---|---| +| Insurance plan request | `policyNumber`, `providerId`, or both. At least one is mandatory. | +| Task request on a claim | `claimNumber` | +| Task request on a preauthorisation | `initimationNumber`, spelled as shown | +| Answer to a communication request | An input of type `include`, whose value references the `Communication` resource | + +## How you know it worked + +You send the corrected request as a new request and receive `202 Accepted`. + +The answer on `/v1/insuranceplan/on_request` or `/v1/task/on_submit` is an encrypted payload, and `PAYR-1519` does not come back. For an insurance plan request, the decrypted payload is a `Bundle` of type `collection` holding an `InsurancePlan`. + +## When it goes wrong + +1. Check every `Task.input` entry, not only the first. +2. Give each one a `type.coding` with a system and a code from the table. +3. Keep the value next to its type, as `valueString` or `valueReference`. + +```json +"input": [ + { + "type": { + "coding": [ + { "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code", "code": "policyNumber" } + ] + }, + "valueString": "" + }, + { + "type": { + "coding": [ + { "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code", "code": "providerId" } + ] + }, + "valueString": "" + } +] +``` + +A type code the payer does not accept returns [PAYR-1510](payr-1510.md). + +Send every retry as a new request with a new `x-hcx-correlation_id`. A correlation id that ended in an error is inactive. A correlation id that already exists is refused with [NHCX-1006](nhcx-1006.md). diff --git a/catalogue/nhcx/errors/payr-1520.md b/catalogue/nhcx/errors/payr-1520.md new file mode 100644 index 000000000..008ec70bb --- /dev/null +++ b/catalogue/nhcx/errors/payr-1520.md @@ -0,0 +1,79 @@ +--- +id: nhcx.error.payr-1520 +type: error +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'PAYR-1520: the communication reference does not lead to a Communication + resource' +summary: >- + The scheme payer rejected your answer to its request for information because the + reference to your communication does not lead to a communication record. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.queries-and-communication + endpoints: + - nhcx.endpoint.communication-on-request + callbacks: + - nhcx.callback.communication-request + errors: + - nhcx.error.payr-1518 + - nhcx.error.payr-1512 +--- + +# PAYR-1520: the communication reference does not lead to a Communication resource + +## In plain words + +The payer asked your hospital for more information with a [communication request](../glossary/communication-request.md), through [NHCX](../../shared/glossary/nhcx.md). Your system answered with a `Task` that points at a `Communication` resource. The [PMJAY](../glossary/pmjay.md) payer followed that reference and did not find a valid `Communication`, so it refused the answer. + +## Before you start + +- The payer sent `/v1/communication/request` to your system. See [Receiving POST /v1/communication/request](../callbacks/communication-request.md). +- Your system answered with `POST /v1/communication/on_request`. See [POST /v1/communication/on_request](../endpoints/communication-on-request.md). + +The payer refused that answer with this code. [Error code spaces](../concepts/error-code-spaces.md) explains where `PAYR-15xx` codes come from. + +## What happens + +Your answer is a `Task` bundle. The `Task` carries an input of type `include`, whose `valueReference` points to the `Communication` resource in the same bundle. The payer returns `PAYR-1520` when the resource at that reference is missing or is not a valid `Communication`. The `%s` in the message is the reference it followed. + +```text +Invalid resource received for communication for url %s. Please try agian with valid Communication resource for the reference. +``` + +## How you know it worked + +You send the corrected answer and `PAYR-1520` does not come back. + +The `Task` in your answer carries an `include` input whose reference matches the `fullUrl` of a `Communication` entry in the same bundle. + +## When it goes wrong + +1. Search your bundle for the reference in the message. +2. Make sure one bundle entry has that reference as its `fullUrl`, and that its resource is a `Communication`. +3. Point the `include` input at that entry: + +```json +"input": [ + { + "type": { + "coding": [ + { "system": "http://terminology.hl7.org/CodeSystem/financialtaskinputtype", "code": "include" } + ] + }, + "valueReference": { "reference": "" } + } +] +``` + +A `Task` with no inputs at all returns [PAYR-1518](payr-1518.md). diff --git a/catalogue/nhcx/fhir/claim-request.md b/catalogue/nhcx/fhir/claim-request.md new file mode 100644 index 000000000..620d6b646 --- /dev/null +++ b/catalogue/nhcx/fhir/claim-request.md @@ -0,0 +1,633 @@ +--- +id: nhcx.fhir.claim-request +type: fhir +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Claim request bundle +summary: >- + The bundle a hospital sends after discharge to claim payment, with the final amounts, + the discharge details and the documents the policy requires. +sources: +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sections 9.4.1-9.4.8 and Appendix A.2. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. section 25 LM100 and Discharge Types. +- url: https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip + member: FHIR_bundles_PMJAY_ext/claim/claim_Request.txt + hash: sha256:8c7b24e3022733aaf7e8f517e12c11c0e8eddd6293844a2c4f3e9700fb720dca + fetched: '2026-09-14' + note: Sample FHIR bundles, row 29 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Claim.supportingInfo, Claim.type. +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Claim Error Codes, discharge and death date rules. +- url: https://hcxsbx.abdm.gov.in/images/064cf2e059987011e53a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Claim.pdf + hash: sha256:66290de20d57d69e681946a0101518092ca43b3775bb38997c43beb17fb38076 + fetched: '2026-09-14' + note: Claim, listed on https://hcxsbx.abdm.gov.in/#/documents, not named in the NHCX document sheet. page 1, Claim Submit Request. +verified: + status: unverified +related: + concepts: + - nhcx.concept.claim-cycle + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-response + - nhcx.fhir.collection-bundle + - nhcx.fhir.terminologies + - nhcx.fhir.validation + errors: + - nhcx.error.payr-1095 + - nhcx.error.payr-1096 + - nhcx.error.payr-1099 + - nhcx.error.payr-1502 + - nhcx.error.payr-1362 + - nhcx.error.payr-1043 + - nhcx.error.payr-1044 + tests: + - nhcx.test.provider-uc-09 + - nhcx.test.tc-cl-01 + glossary: + - nhcx.glossary.claim + - nhcx.glossary.pmjay + - shared.glossary.fhir +--- + +# Claim request bundle + +## In plain words + +A [claim](../glossary/claim.md) asks the payer to pay for treatment already given. It uses the same `Claim` resource as a preauthorisation, with `use` set to `claim`, inside a `ClaimBundle`. You send it on `/v1/claim/submit` after discharge. + +Compared with the preauthorisation, the claim carries final amounts, discharge details, and the documents the policy asks for at claim time. + +## Before you start + +- For a package that needs approval, the preauthorisation was approved. See [the preauthorisation response](preauth-response.md). +- The patient is discharged, and you know the discharge type and stage. +- You have the claim-stage documents the InsurancePlan lists for the package. +- You can build a [preauthorisation bundle](preauth-request.md). The claim bundle has the same resources. + +## What happens + +### What changes from the preauthorisation + +- `Claim.use` is `claim`. +- `item` carries the final dates, quantity and amounts. `total` is their sum. +- `supportingInfo` carries the claim-stage documents and the discharge details below. + +### Discharge details in `supportingInfo` + +| Category | Code | Value | Carries | +|---|---|---|---| +| `DIS` | `DTH`, `DTM`, `LAMA` or `DAMA` | `Before Surgery` or `After Surgery` | Discharge type and stage | +| `ONS` | `ADDD` | Date or string | Admission date | +| `ONS` | `DSDE` | Date or string | Discharge date | +| `ONS` | `PSP` | Date or string | Surgery date | +| `ONS` | `DTM` | Date or string | Date of death, required when the discharge type is `DTM` | +| `OTH` | `EDT` | Date or string | Registration date | + +Categories come from `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category`. Codes come from `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-code`. + +`DTH` is a discharge to home. `DTM` is a discharge to the mortuary. `LAMA` is leaving against medical advice. `DAMA` is a discharge against medical advice. + +### LAMA and DAMA under PMJAY + +For a LAMA or DAMA discharge before surgery, claim the procedure code `LM100` as the item. Set its quantity to the number of days admitted. `LM100` is claim-only: never send it on a preauthorisation. + +### Minimal bundle + +```json +{ + "resourceType": "Bundle", + "id": "", + "meta": { + "lastUpdated": "" + }, + "identifier": { + "system": "", + "value": "" + }, + "type": "collection", + "timestamp": "", + "entry": [ + { + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "Claim", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Claim" + ] + }, + "identifier": [ + { + "type": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code", + "code": "CLN", + "display": "Claim number" + } + ] + }, + "system": "", + "value": "" + } + ], + "status": "active", + "type": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "737481003", + "display": "Inpatient care management (procedure)" + } + ] + }, + "use": "claim", + "patient": { + "reference": "urn:uuid:" + }, + "created": "", + "insurer": { + "reference": "urn:uuid:" + }, + "provider": { + "reference": "urn:uuid:" + }, + "priority": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/processpriority", + "code": "normal" + } + ] + }, + "careTeam": [ + { + "sequence": 1, + "provider": { + "reference": "urn:uuid:" + } + } + ], + "supportingInfo": [ + { + "sequence": 1, + "category": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category", + "code": "" + } + ] + }, + "code": { + "coding": [ + { + "system": "", + "code": "" + } + ] + }, + "valueAttachment": { + "contentType": "application/pdf", + "title": "", + "data": "" + } + }, + { + "sequence": 2, + "category": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category", + "code": "DIS" + } + ] + }, + "code": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-code", + "code": "DTH" + } + ] + }, + "valueString": "After Surgery" + }, + { + "sequence": 3, + "category": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category", + "code": "ONS" + } + ] + }, + "code": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-code", + "code": "ADDD" + } + ] + }, + "valueString": "" + }, + { + "sequence": 4, + "category": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category", + "code": "ONS" + } + ] + }, + "code": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-code", + "code": "DSDE" + } + ] + }, + "valueString": "" + }, + { + "sequence": 5, + "category": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category", + "code": "OTH" + } + ] + }, + "code": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-code", + "code": "EDT" + } + ] + }, + "valueString": "" + } + ], + "diagnosis": [ + { + "sequence": 1, + "diagnosisCodeableConcept": { + "coding": [ + { + "system": "http://hl7.org/fhir/sid/icd-10", + "code": "", + "display": "" + } + ] + } + } + ], + "procedure": [ + { + "sequence": 1, + "procedureReference": { + "reference": "urn:uuid:" + } + } + ], + "insurance": [ + { + "sequence": 1, + "focal": true, + "coverage": { + "reference": "urn:uuid:" + } + } + ], + "item": [ + { + "sequence": 1, + "careTeamSequence": [ + 1 + ], + "diagnosisSequence": [ + 1 + ], + "procedureSequence": [ + 1 + ], + "informationSequence": [ + 1 + ], + "category": { + "coding": [ + { + "system": "", + "code": "" + } + ] + }, + "productOrService": { + "coding": [ + { + "system": "", + "code": "", + "display": "" + } + ] + }, + "servicedPeriod": { + "start": "", + "end": "" + }, + "quantity": { + "value": 1 + }, + "unitPrice": { + "value": "" + }, + "net": { + "value": "" + } + } + ], + "total": { + "value": "" + } + } + }, + { + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "Patient", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Patient" + ] + }, + "identifier": [ + { + "type": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code", + "code": "PMJAY" + } + ] + }, + "system": "https://bis.pmjay.gov.in", + "value": "" + }, + { + "type": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code", + "code": "ABHA" + } + ] + }, + "system": "https://bis.pmjay.gov.in", + "value": "" + } + ], + "name": [ + { + "text": "" + } + ], + "gender": "", + "birthDate": "" + } + }, + { + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "Organization", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Organization" + ] + }, + "identifier": [ + { + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + "code": "NPI", + "display": "National provider identifier" + } + ] + }, + "system": "https://facility.abdm.gov.in", + "value": "" + } + ], + "type": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/organization-type", + "code": "prov", + "display": "Healthcare Provider" + } + ] + } + ], + "name": "" + } + }, + { + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "Organization", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Organization" + ] + }, + "identifier": [ + { + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + "code": "NIIP", + "display": "National Insurance Payor Identifier (Payor)" + } + ] + }, + "system": "https://facility.abdm.gov.in", + "value": "" + } + ], + "type": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/organization-type", + "code": "pay", + "display": "Payer" + } + ] + } + ], + "name": "" + } + }, + { + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "Coverage", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Coverage" + ] + }, + "identifier": [ + { + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + "code": "NH", + "display": "National Health Plan Identifier" + } + ] + }, + "system": "", + "value": "" + } + ], + "status": "active", + "beneficiary": { + "reference": "urn:uuid:" + }, + "payor": [ + { + "reference": "urn:uuid:" + } + ] + } + }, + { + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "Practitioner", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Practitioner" + ] + }, + "identifier": [ + { + "type": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code", + "code": "HPIN" + } + ] + }, + "system": "https://hpr.abdm.gov.in", + "value": "" + } + ], + "name": [ + { + "text": "" + } + ] + } + }, + { + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "Procedure", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Procedure" + ] + }, + "identifier": [ + { + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + "code": "SNO", + "display": "Serial Number" + } + ] + }, + "system": "", + "value": "1" + } + ], + "status": "preparation", + "code": { + "coding": [ + { + "system": "", + "code": "", + "display": "" + } + ] + }, + "subject": { + "reference": "urn:uuid:" + } + } + } + ] +} +``` + +## How you know it worked + +Run the validator recipe ([shared.fhir.hl7-validator-recipe](../../shared/fhir/hl7-validator-recipe.md)): + +```bash +java -jar validator_cli.jar bundle.json -version 4.0.1 -ig ndhm.in#6.5.0 -profile https://nrces.in/ndhm/fhir/r4/StructureDefinition/ClaimBundle +``` + +It exits with code 0 and reports no errors. + +After you send the bundle, `/v1/claim/on_submit` arrives with a `ClaimResponse` for your claim number. See [the claim response](claim-response.md). + +## When it goes wrong + +- **[PAYR-1095](../errors/payr-1095.md): invalid discharge information.** Add a `supportingInfo` entry with category `DIS` and a code from `DTH`, `DTM`, `LAMA` or `DAMA`. +- **[PAYR-1096](../errors/payr-1096.md): invalid death date.** A `DTM` discharge needs an `ONS` entry with code `DTM` carrying the date of death. +- **[PAYR-1099](../errors/payr-1099.md) or [PAYR-1502](../errors/payr-1502.md): wrong value type for a date entry.** Send the discharge or admission date as a timing (date or period) or a string. +- **[PAYR-1362](../errors/payr-1362.md): no `LM100` procedure for a LAMA or DAMA case.** Send `LM100` as the only item for a LAMA or DAMA discharge before surgery. +- **[PAYR-1043](../errors/payr-1043.md) or [PAYR-1044](../errors/payr-1044.md).** A date or date-time does not follow the FHIR format. Use `YYYY-MM-DD` or an ISO-8601 date-time with offset. diff --git a/catalogue/nhcx/fhir/claim-response.md b/catalogue/nhcx/fhir/claim-response.md new file mode 100644 index 000000000..113231a87 --- /dev/null +++ b/catalogue/nhcx/fhir/claim-response.md @@ -0,0 +1,278 @@ +--- +id: nhcx.fhir.claim-response +type: fhir +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Claim response bundle +summary: >- + The payer's decision on a claim: approved, partly approved, queried or rejected, + with the approved amount and any deductions. +sources: +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sections 9.5.1-9.5.6. +- url: https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip + member: FHIR_bundles_PMJAY_ext/claim/claim_queryUpdate_response.txt + hash: sha256:8c7b24e3022733aaf7e8f517e12c11c0e8eddd6293844a2c4f3e9700fb720dca + fetched: '2026-09-14' + note: Sample FHIR bundles, row 29 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. ClaimResponse.item.adjudication, total. +- url: https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip + member: FHIR_bundles_PMJAY_ext/claim/claimresponse_withQuery.txt + hash: sha256:8c7b24e3022733aaf7e8f517e12c11c0e8eddd6293844a2c4f3e9700fb720dca + fetched: '2026-09-14' + note: Sample FHIR bundles, row 29 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. ClaimResponse.outcome, adjudication. +verified: + status: unverified +related: + concepts: + - nhcx.concept.claim-cycle + - nhcx.concept.reprocess-and-cancel + flows: + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + - nhcx.flow.claim-reprocess + - nhcx.flow.payer-process-a-request + endpoints: + - nhcx.endpoint.claim-on-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + - nhcx.fhir.task + - nhcx.fhir.payment-notice + - nhcx.fhir.preauth-response + tests: + - nhcx.test.payer-uc-11 + glossary: + - nhcx.glossary.claim + - nhcx.glossary.adjudication + - shared.glossary.fhir +--- + +# Claim response bundle + +## In plain words + +The payer answers a [claim](../glossary/claim.md) with a `ClaimResponseBundle` on `/v1/claim/on_submit`. The focal resource is a `ClaimResponse` with `use` set to `claim`. + +It has the same shape as a preauthorisation response. It adds the claimed amount and any deductions, and an approval leads on to payment. + +## Before you start + +- As a provider, you sent a [claim request](claim-request.md) and stored the claim number and item sequences. +- You can open a sealed callback. See [receive, open and acknowledge a sealed message](../flows/receive-a-sealed-callback.md). +- You know how to read a [preauthorisation response](preauth-response.md). The fields are the same. + +## What happens + +### Reading the decision + +| `outcome` | `adjudication[0].reason.coding.code` | `benefit` total | What to do | +|---|---|---|---| +| `complete` | `approved` | above 0 | Full approval. Wait for the [payment notice](payment-notice.md). | +| `partial` | `approved` | above 0 | Partial approval. Read `processNote` for the reduction. | +| `partial` | `queried` | 0 | Send a [query update](query-update.md). | +| `complete` | `cancelled` | 0 or carried | Rejected. Decide whether to raise a [reprocess task](task.md). | + +`outcome: complete` closes the claim, whether approved or rejected. `outcome: partial` means the claim is still open. + +### Amounts + +| Element | Meaning | +|---|---| +| `item[].adjudication[]` category `eligible` | Amount eligible for the item | +| `item[].adjudication[]` category `deductible` | A deduction, with its reason in `reason`, for example `DEDUCT/01` | +| `total[]` category `benefit` | Amount approved for payment | +| `total[]` category `submitted` | Amount claimed | +| `total[]` with id `PMJAY-T`, category `eligible` | Total eligible amount | + +### Minimal response resource + +A payer's bundle carries this entry plus the `Patient`, `Coverage` and `Organization` entries it references. + +```json +{ + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "ClaimResponse", + "id": "", + "identifier": [ + { + "type": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code", + "code": "CLN", + "display": "Claim number" + } + ] + }, + "system": "", + "value": "" + } + ], + "status": "active", + "type": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "737481003", + "display": "Inpatient care management (procedure)" + } + ] + }, + "use": "claim", + "patient": { + "reference": "" + }, + "created": "", + "insurer": { + "reference": "" + }, + "requestor": { + "reference": "" + }, + "outcome": "complete", + "disposition": "", + "item": [ + { + "itemSequence": 1, + "adjudication": [ + { + "category": { + "coding": [ + { + "system": "https://hl7.org/fhir/R4/valueset-adjudication.html", + "code": "eligible", + "display": "Eligible Amount" + } + ] + }, + "amount": { + "value": "" + } + }, + { + "category": { + "coding": [ + { + "code": "deductible", + "display": "Deductible" + } + ] + }, + "reason": { + "coding": [ + { + "code": "", + "display": "" + } + ] + }, + "amount": { + "value": "" + } + }, + { + "category": { + "coding": [ + { + "system": "https://hl7.org/fhir/R4/valueset-adjudication.html", + "code": "status", + "display": "Item adjudication status" + } + ] + }, + "reason": { + "coding": [ + { + "code": "Approved", + "display": "Approved" + } + ] + } + } + ] + } + ], + "adjudication": [ + { + "category": { + "coding": [ + { + "code": "status", + "display": "Status" + } + ] + }, + "reason": { + "coding": [ + { + "code": "approved", + "display": "Approved" + } + ] + } + } + ], + "total": [ + { + "category": { + "coding": [ + { + "system": "https://hl7.org/fhir/R4/valueset-adjudication.html", + "code": "benefit", + "display": "Benefit Amount" + } + ] + }, + "amount": { + "value": "" + } + }, + { + "category": { + "coding": [ + { + "system": "https://hl7.org/fhir/R4/valueset-adjudication.html", + "code": "submitted", + "display": "Submitted Amount" + } + ] + }, + "amount": { + "value": "" + } + } + ] + } +} +``` + +## How you know it worked + +As a provider: + +- `/v1/claim/on_submit` arrives with a `ClaimResponse` whose `identifier` value equals your claim number. +- `outcome`, the adjudication reason code and the `benefit` total map to one row of the decision table. + +As a payer, run the validator recipe ([shared.fhir.hl7-validator-recipe](../../shared/fhir/hl7-validator-recipe.md)): + +```bash +java -jar validator_cli.jar bundle.json -version 4.0.1 -ig ndhm.in#6.5.0 -profile https://nrces.in/ndhm/fhir/r4/StructureDefinition/ClaimResponseBundle +``` + +It exits with code 0 and reports no errors. + +## When it goes wrong + +- **You recorded a rejection as an approval.** Both are `outcome: complete`. The reason code `cancelled` marks a rejection. +- **You keyed the claim on the identifier system.** The reference payer uses the same identifier system for claims and preauthorisations. Match on the identifier value and your correlation id. +- **The approved amount is lower than you claimed.** Read the `deductible` adjudication and its reason. Raise a [reprocess task](task.md) only if you dispute it. +- **Your parser expects a currency on amounts.** Adjudication amounts carry `value` only. Treat them as INR. diff --git a/catalogue/nhcx/fhir/collection-bundle.md b/catalogue/nhcx/fhir/collection-bundle.md new file mode 100644 index 000000000..c85d31729 --- /dev/null +++ b/catalogue/nhcx/fhir/collection-bundle.md @@ -0,0 +1,229 @@ +--- +id: nhcx.fhir.collection-bundle +type: fhir +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: The NHCX collection bundle and its required elements +summary: >- + Every claims message you send is one bundle of type collection, holding the main + business resource and every resource it points to. +sources: +- url: https://hcxsbx.abdm.gov.in/images/2c3fbb4e6b09f0834f69.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Implementation Guide for Adoption of FHIR in ABDM and NHCX.pdf + hash: sha256:549377c9c26b1bd23decac3a1b9e5ebedfdc8e0fe99e53ef733859b188f51366 + fetched: '2026-09-14' + note: Implementation Guide for Adoption of FHIR in ABDM and NHCX, row 14 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 9-10, 12, 19 and 21. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 1.3 Key Principles. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheets Reprocess, Search, Communication, Insurance Plan. +- url: https://hcxsbx.abdm.gov.in/#/domain-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications.md + hash: sha256:56234dd8a55fe4eb9dd852779b22b522b04760c9bec5c263d5e9bc3ac2c6f167 + fetched: '2026-09-14' + note: Site page /domain-specifications, text as shown on the site. Domain Data Specifications section. +- url: https://hcxsbx.abdm.gov.in/#/domain-specifications/domain-data-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__domain-data-specifications.md + hash: sha256:d5db7e162b098b4c9555367bd64d60ba7734ceee21eee7144a49cefa4f634fd8 + fetched: '2026-09-14' + note: Site page /domain-specifications/domain-data-specifications, text as shown on the site. Key Design Considerations. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. section 7 reference documents. +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.jwe-envelope + - nhcx.concept.error-code-spaces + fhir: + - nhcx.fhir.validation + - nhcx.fhir.terminologies + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.task + - nhcx.fhir.insurance-plan-bundle + - shared.fhir.hl7-validator-recipe + errors: + - nhcx.error.payr-1008 + - nhcx.error.payr-1004 + - nhcx.error.payr-1029 + - nhcx.error.payr-1031 + - nhcx.error.payr-1040 + - nhcx.error.payr-1009 + - nhcx.error.payr-1010 + glossary: + - shared.glossary.fhir + - shared.glossary.nrces + - shared.glossary.nhcx + - nhcx.glossary.jwe + troubleshooting: + - nhcx.troubleshooting.bundle-rejected +--- + +# The NHCX collection bundle and its required elements + +## In plain words + +Every [NHCX](../../shared/glossary/nhcx.md) use case carries its business content as one [FHIR](../../shared/glossary/fhir.md) R4 (4.0.1) `Bundle`. The bundle type is always `collection`. + +A collection bundle groups the resources one workflow step needs. That means the claim or request, the patient, the provider, the payer, the policy and the documents. It is not a clinical document, so it has no `Composition` at its root. + +You build the bundle, seal it inside the [JWE](../glossary/jwe.md) payload of the call, and send it. [NRCeS](../../shared/glossary/nrces.md) publishes the profiles at https://nrces.in/ndhm/fhir/r4/hcx-profile.html. + +## Before you start + +- You know which use case you are building. The table in the next section maps each use case to its bundle profile. +- You can seal a JSON payload. See [the JWE envelope](../concepts/jwe-envelope.md). +- The HL7 validator runs on your machine. See [validating a bundle](validation.md). +- You have read [FHIR in NHCX](../concepts/fhir-in-nhcx.md) for how bundles fit the claim cycle. + +## What happens + +### The six bundle profiles + +| Profile | Canonical URL | Focal resource | Carried on | +|---|---|---|---| +| ClaimBundle | `https://nrces.in/ndhm/fhir/r4/StructureDefinition/ClaimBundle` | `Claim` | `/v1/preauth/submit`, `/v1/predetermination/submit`, `/v1/claim/submit` | +| ClaimResponseBundle | `https://nrces.in/ndhm/fhir/r4/StructureDefinition/ClaimResponseBundle` | `ClaimResponse` | the matching `on_submit` paths | +| CoverageEligibilityRequestBundle | `https://nrces.in/ndhm/fhir/r4/StructureDefinition/CoverageEligibilityRequestBundle` | `CoverageEligibilityRequest` | `/v1/coverageeligibility/check` | +| CoverageEligibilityResponseBundle | `https://nrces.in/ndhm/fhir/r4/StructureDefinition/CoverageEligibilityResponseBundle` | `CoverageEligibilityResponse` | `/v1/coverageeligibility/on_check` | +| TaskBundle | `https://nrces.in/ndhm/fhir/r4/StructureDefinition/TaskBundle` | `Task` | `/v1/insuranceplan/request`, `/v1/communication/*`, `/v1/paymentnotice/*`, `/v1/task/*`, `/v1/search/*` | +| InsurancePlanBundle | `https://nrces.in/ndhm/fhir/r4/StructureDefinition/InsurancePlanBundle` | `InsurancePlan` | `/v1/insuranceplan/on_request` | + +### Bundle-level elements + +| Element | What you put in it | +|---|---| +| `resourceType` | `Bundle` | +| `id` | A logical id you generate for this bundle | +| `meta.lastUpdated` | An ISO-8601 instant with offset, for example `2020-08-15T17:02:53.495+05:30` | +| `identifier` | `system` and `value` of your business number for the case, such as the claim number | +| `type` | `collection` | +| `timestamp` | When you assembled the bundle | +| `entry[]` | One entry per resource, each with `fullUrl` and `resource` | + +### Entry rules + +- Put the focal resource first when you build a request. +- Give every entry a `fullUrl`, either `urn:uuid:` or an absolute URL. +- Every `reference` inside the bundle must equal the `fullUrl` of an entry in the same bundle. +- Declare the NRCeS profile on every resource you build: `meta.profile` = `https://nrces.in/ndhm/fhir/r4/StructureDefinition/`. +- Give every identifier a `type` coding. The payer rejects a Patient, Claim, Organization, Coverage, Procedure or Practitioner identifier without one. +- Attach clinical records as ABDM health-record Compositions inside the same bundle, referenced from `Claim.supportingInfo`. Attach files as base64 in `valueAttachment`. +- Mandatory elements have cardinality `1..1` or `1..*`. A Must Support element is optional to send, and a receiver must be able to process it. + +### Minimal skeleton + +```json +{ + "resourceType": "Bundle", + "id": "", + "meta": { + "lastUpdated": "" + }, + "identifier": { + "system": "", + "value": "" + }, + "type": "collection", + "timestamp": "", + "entry": [ + "", + "" + ] +} +``` + +One entry, showing the `fullUrl` and the profile declaration: + +```json +{ + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "Patient", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Patient" + ] + }, + "identifier": [ + { + "type": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code", + "code": "PMJAY" + } + ] + }, + "system": "https://bis.pmjay.gov.in", + "value": "" + }, + { + "type": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code", + "code": "ABHA" + } + ] + }, + "system": "https://bis.pmjay.gov.in", + "value": "" + } + ], + "name": [ + { + "text": "" + } + ], + "gender": "", + "birthDate": "" + } +} +``` + +The atom for each use case lists the resources its bundle carries. + +## How you know it worked + +Run the HL7 validator recipe ([shared.fhir.hl7-validator-recipe](../../shared/fhir/hl7-validator-recipe.md)) against the bundle you built, with the bundle profile named on the command line: + +```bash +java -jar validator_cli.jar bundle.json -version 4.0.1 -ig ndhm.in#6.5.0 -profile +``` + +You know the bundle is right when: + +- The validator exits with code 0 and reports no errors. +- Every `reference` in the bundle resolves to an entry `fullUrl`. +- After you send it, the callback for your use case arrives as a sealed FHIR bundle, not as a `ProtocolResponse` carrying a bundle error. + +## When it goes wrong + +- **[PAYR-1008](../errors/payr-1008.md): "Invalid FHIR bundle received."** The receiver could not parse the payload as FHIR. Run the validator and fix what it reports. On the payer error sheet the same code means insufficient coverage, so read the message text as well as the code. See [error code spaces](../concepts/error-code-spaces.md). +- **[PAYR-1004](../errors/payr-1004.md): "Received FHIR bundle is malformed."** The message carries error details. Fix them, then validate again. +- **[PAYR-1040](../errors/payr-1040.md) or [PAYR-1031](../errors/payr-1031.md).** A reference points at a `fullUrl` that is not in the bundle, or an entry URL is invalid. Add the missing entry or correct the reference. +- **[PAYR-1009](../errors/payr-1009.md) or [PAYR-1010](../errors/payr-1010.md).** The Patient has no identifier, or the identifier has no `type`. +- **[PAYR-1029](../errors/payr-1029.md): invalid bundle id.** Set `Bundle.id` to a valid FHIR id. +- **You sent a `document` bundle with a root `Composition`.** Claims messages use `collection`. Move the clinical Composition inside the bundle and reference it from `Claim.supportingInfo`. + +See also [the payer rejects your FHIR bundle](../troubleshooting/bundle-rejected.md). diff --git a/catalogue/nhcx/fhir/coverage-eligibility-request.md b/catalogue/nhcx/fhir/coverage-eligibility-request.md new file mode 100644 index 000000000..f4373564a --- /dev/null +++ b/catalogue/nhcx/fhir/coverage-eligibility-request.md @@ -0,0 +1,422 @@ +--- +id: nhcx.fhir.coverage-eligibility-request +type: fhir +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: CoverageEligibilityRequest bundle +summary: >- + The bundle a hospital sends to ask a payer whether a patient's policy is in force, + what it covers, and whether a treatment needs prior approval. +sources: +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 7.5. +- url: https://hcxsbx.abdm.gov.in/images/13093b5f9b88fe826123.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Insurance Plan IG.docx + hash: sha256:e9c6c82b6d67fd8476d6d19a5961419beb04e3c0613533453ed1e16e2a569cc1 + fetched: '2026-09-14' + note: Insurance Plan IG, row 25 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Coverage Eligibility request section. +- url: https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip + member: FHIR_bundles_PMJAY_ext/coverageeligibility/coveragerequest_validation.txt + hash: sha256:8c7b24e3022733aaf7e8f517e12c11c0e8eddd6293844a2c4f3e9700fb720dca + fetched: '2026-09-14' + note: Sample FHIR bundles, row 29 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. CoverageEligibilityRequest, Patient, Organization, Coverage. +- url: https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip + member: FHIR_bundles_PMJAY_ext/coverageeligibility/coveragerequest_auth-requirement.txt + hash: sha256:8c7b24e3022733aaf7e8f517e12c11c0e8eddd6293844a2c4f3e9700fb720dca + fetched: '2026-09-14' + note: Sample FHIR bundles, row 29 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. CoverageEligibilityRequest.item. +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.coverage-eligibility-purposes + - nhcx.concept.policy-linking + - nhcx.concept.fhir-in-nhcx + decisions: + - nhcx.decision.eligibility-purpose + flows: + - nhcx.flow.coverage-eligibility-check + endpoints: + - nhcx.endpoint.coverageeligibility-check + fhir: + - nhcx.fhir.collection-bundle + - nhcx.fhir.coverage-eligibility-response + - nhcx.fhir.insurance-plan-bundle + - nhcx.fhir.validation + errors: + - nhcx.error.payr-1032 + - nhcx.error.payr-1033 + - nhcx.error.payr-1009 + - nhcx.error.payr-1010 + - nhcx.error.payr-1090 + - nhcx.error.payr-1091 + tests: + - nhcx.test.provider-uc-05 + - nhcx.test.tc-ce-01 + glossary: + - nhcx.glossary.coverage-eligibility + - shared.glossary.hfr + - shared.glossary.abha + - nhcx.glossary.pmjay + - shared.glossary.fhir +--- + +# CoverageEligibilityRequest bundle + +## In plain words + +A [coverage eligibility](../glossary/coverage-eligibility.md) request asks a payer about one patient's policy before treatment. It is a [FHIR](../../shared/glossary/fhir.md) collection bundle whose focal resource is `CoverageEligibilityRequest`. + +The `purpose` element says what you are asking: + +- `validation`: is the policy in force? +- `benefits`: what does it cover? +- `auth-requirements`: does this treatment need preauthorisation? +- `discovery`: does a policy exist? + +You send it on `/v1/coverageeligibility/check`. + +## Before you start + +- The patient's policy is linked to their [ABHA](../../shared/glossary/abha.md). See [policy linking](../concepts/policy-linking.md). +- You have fetched the payer's insurance plan, so you hold the package code you are asking about. See [InsurancePlan bundles](insurance-plan-bundle.md). +- You know your facility's [HFR](../../shared/glossary/hfr.md) ID. It must match the registry id recorded for you on NHCX. +- You have chosen a purpose. See [which purpose to send](../decisions/eligibility-purpose.md). +- You have the patient's [PMJAY](../glossary/pmjay.md) beneficiary id and ABHA number. + +## What happens + +### Resources in the bundle + +| Resource | Role | Key elements | +|---|---|---| +| `CoverageEligibilityRequest` | The question | `status` `active`, `purpose`, `patient`, `created`, `provider`, `insurer`, `insurance.coverage`, `item` | +| `Patient` | The beneficiary | Identifiers typed `PMJAY` and `ABHA` from `ndhm-identifier-type-code` | +| `Organization` (provider) | Your facility | Identifier typed `NPI` carrying your HFR ID, system `https://facility.abdm.gov.in`; type `prov` | +| `Organization` (payer) | The insurer | Identifier typed `NIIP`; type `pay` | +| `Coverage` | The policy | Identifier typed `NH` carrying the policy number; `beneficiary`, `payor` | +| `Practitioner` | Who entered the request | Identifier on `https://hpr.abdm.gov.in` | + +Every resource declares `https://nrces.in/ndhm/fhir/r4/StructureDefinition/` in `meta.profile`. + +### Code systems + +- `priority`: `http://terminology.hl7.org/CodeSystem/processpriority`, code `normal`. +- `facility.identifier.system`: `https://nhcx.pmjay.gov.in`, value your HFR ID. +- Identifier types: `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` (`PMJAY`, `ABHA`, `HPIN`) and `http://terminology.hl7.org/CodeSystem/v2-0203` (`NPI`, `NIIP`, `NH`). +- `item.productOrService`: copy the package coding exactly as the payer's InsurancePlan gives it in `coverage.benefit.type`. + +### Minimal bundle + +```json +{ + "resourceType": "Bundle", + "id": "", + "meta": { + "lastUpdated": "" + }, + "identifier": { + "system": "", + "value": "" + }, + "type": "collection", + "timestamp": "", + "entry": [ + { + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "CoverageEligibilityRequest", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/CoverageEligibilityRequest" + ] + }, + "identifier": [ + { + "system": "", + "value": "" + } + ], + "status": "active", + "priority": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/processpriority", + "code": "normal", + "display": "Normal" + } + ] + }, + "purpose": [ + "validation" + ], + "patient": { + "reference": "urn:uuid:" + }, + "servicedDate": "", + "created": "", + "enterer": { + "reference": "urn:uuid:" + }, + "provider": { + "reference": "urn:uuid:" + }, + "insurer": { + "reference": "urn:uuid:" + }, + "facility": { + "identifier": { + "system": "https://nhcx.pmjay.gov.in", + "value": "" + } + }, + "insurance": [ + { + "focal": true, + "coverage": { + "reference": "urn:uuid:" + } + } + ], + "item": [ + { + "productOrService": { + "coding": [ + { + "system": "", + "code": "", + "display": "" + } + ] + } + } + ] + } + }, + { + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "Patient", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Patient" + ] + }, + "identifier": [ + { + "type": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code", + "code": "PMJAY" + } + ] + }, + "system": "https://bis.pmjay.gov.in", + "value": "" + }, + { + "type": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code", + "code": "ABHA" + } + ] + }, + "system": "https://bis.pmjay.gov.in", + "value": "" + } + ], + "name": [ + { + "text": "" + } + ], + "gender": "", + "birthDate": "" + } + }, + { + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "Organization", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Organization" + ] + }, + "identifier": [ + { + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + "code": "NPI", + "display": "National provider identifier" + } + ] + }, + "system": "https://facility.abdm.gov.in", + "value": "" + } + ], + "type": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/organization-type", + "code": "prov", + "display": "Healthcare Provider" + } + ] + } + ], + "name": "" + } + }, + { + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "Organization", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Organization" + ] + }, + "identifier": [ + { + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + "code": "NIIP", + "display": "National Insurance Payor Identifier (Payor)" + } + ] + }, + "system": "https://facility.abdm.gov.in", + "value": "" + } + ], + "type": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/organization-type", + "code": "pay", + "display": "Payer" + } + ] + } + ], + "name": "" + } + }, + { + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "Coverage", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Coverage" + ] + }, + "identifier": [ + { + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + "code": "NH", + "display": "National Health Plan Identifier" + } + ] + }, + "system": "", + "value": "" + } + ], + "status": "active", + "beneficiary": { + "reference": "urn:uuid:" + }, + "payor": [ + { + "reference": "urn:uuid:" + } + ] + } + }, + { + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "Practitioner", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Practitioner" + ] + }, + "identifier": [ + { + "type": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code", + "code": "HPIN" + } + ] + }, + "system": "https://hpr.abdm.gov.in", + "value": "" + } + ], + "name": [ + { + "text": "" + } + ] + } + } + ] +} +``` + +Change `purpose` to `benefits`, `auth-requirements` or `discovery` for the other questions. Send at least one `item`. + +## How you know it worked + +Run the HL7 validator recipe ([shared.fhir.hl7-validator-recipe](../../shared/fhir/hl7-validator-recipe.md)) against the bundle you built, with the bundle profile named on the command line: + +```bash +java -jar validator_cli.jar bundle.json -version 4.0.1 -ig ndhm.in#6.5.0 -profile https://nrces.in/ndhm/fhir/r4/StructureDefinition/CoverageEligibilityRequestBundle +``` + +The validator exits with code 0 and reports no errors. + +After you send the bundle, `/v1/coverageeligibility/on_check` arrives at your registered endpoint. It carries a `CoverageEligibilityResponse` whose `request.reference` points at your request. See [the response bundle](coverage-eligibility-response.md). + +## When it goes wrong + +- **[PAYR-1033](../errors/payr-1033.md): no items received.** Items are mandatory for the purpose you sent. Add the package you are asking about. +- **[PAYR-1032](../errors/payr-1032.md): invalid purpose.** Use one of `validation`, `benefits`, `auth-requirements`, `discovery`. +- **[PAYR-1009](../errors/payr-1009.md) or [PAYR-1010](../errors/payr-1010.md).** The Patient identifier or its `type` is missing. +- **"HFR Id in the request does not match with the associated registry id in NHCX."** The `NPI` identifier on your provider Organization must equal the registry id you registered with. +- **[PAYR-1090](../errors/payr-1090.md) or [PAYR-1091](../errors/payr-1091.md).** The Coverage identifier or its `type` is missing. diff --git a/catalogue/nhcx/fhir/coverage-eligibility-response.md b/catalogue/nhcx/fhir/coverage-eligibility-response.md new file mode 100644 index 000000000..e3f88f4f9 --- /dev/null +++ b/catalogue/nhcx/fhir/coverage-eligibility-response.md @@ -0,0 +1,211 @@ +--- +id: nhcx.fhir.coverage-eligibility-response +type: fhir +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: CoverageEligibilityResponse bundle +summary: >- + The payer's answer to an eligibility check: whether the policy is in force, how + much cover is left, and whether the treatment needs prior approval. +sources: +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 7.6. +- url: https://hcxsbx.abdm.gov.in/images/13093b5f9b88fe826123.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Insurance Plan IG.docx + hash: sha256:e9c6c82b6d67fd8476d6d19a5961419beb04e3c0613533453ed1e16e2a569cc1 + fetched: '2026-09-14' + note: Insurance Plan IG, row 25 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Coverage Eligibility response section. +- url: https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip + member: FHIR_bundles_PMJAY_ext/coverageeligibility/coverageresponse_validation.txt + hash: sha256:8c7b24e3022733aaf7e8f517e12c11c0e8eddd6293844a2c4f3e9700fb720dca + fetched: '2026-09-14' + note: Sample FHIR bundles, row 29 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Bundle entries and CoverageEligibilityResponse. +- url: https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip + member: FHIR_bundles_PMJAY_ext/coverageeligibility/coverageresponse_auth-requirement.txt + hash: sha256:8c7b24e3022733aaf7e8f517e12c11c0e8eddd6293844a2c4f3e9700fb720dca + fetched: '2026-09-14' + note: Sample FHIR bundles, row 29 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. insurance.item. +verified: + status: unverified +related: + concepts: + - nhcx.concept.coverage-eligibility-purposes + - nhcx.concept.fhir-in-nhcx + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.payer-process-a-request + endpoints: + - nhcx.endpoint.coverageeligibility-on-check + callbacks: + - nhcx.callback.coverageeligibility-on-check + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.collection-bundle + - nhcx.fhir.preauth-request + - nhcx.fhir.terminologies + errors: + - nhcx.error.nhcx-1015 + - nhcx.error.nhcx-1017 + tests: + - nhcx.test.payer-uc-07 + glossary: + - nhcx.glossary.coverage-eligibility + - nhcx.glossary.preauthorisation + - shared.glossary.fhir +--- + +# CoverageEligibilityResponse bundle + +## In plain words + +The payer answers a [coverage eligibility](../glossary/coverage-eligibility.md) request with a [FHIR](../../shared/glossary/fhir.md) collection bundle on `/v1/coverageeligibility/on_check`. Its focal resource is `CoverageEligibilityResponse`. + +It tells the hospital whether the policy is in force and how much cover is used and left. It also says whether each item needs [preauthorisation](../glossary/preauthorisation.md). It can also list the documents a preauthorisation must carry. + +## Before you start + +- As a provider, you sent a [CoverageEligibilityRequest bundle](coverage-eligibility-request.md) and kept its `fullUrl` and your correlation id. +- You can open a sealed callback. See [receive, open and acknowledge a sealed message](../flows/receive-a-sealed-callback.md). +- As a payer, you have the request bundle in hand. See [receive, adjudicate and answer a request](../flows/payer-process-a-request.md). + +## What happens + +### How the payer builds the bundle + +The bundle echoes the request's resources first. Each echoed resource carries the tag `SUBSETTED` (system `http://terminology.hl7.org/CodeSystem/v3-ObservationValue`). The payer then adds its own `CoverageEligibilityResponse`, `Patient`, `Coverage` and the two `Organization` resources. + +Find the response by `resourceType`, not by position. + +### Elements to read + +| Element | Meaning | +|---|---| +| `request.reference` | The `fullUrl` of the request it answers | +| `outcome` | `complete` when the payer processed the request | +| `disposition` | Free text, for example `Policy is currently in-force` | +| `insurance[].inforce` | `true` when the policy is in force | +| `insurance[].item[].productOrService` | The item the line answers | +| `insurance[].item[].excluded` | `true` when the item is not covered on its own | +| `insurance[].item[].authorizationRequired` | `true` when the item needs preauthorisation | +| `insurance[].item[].authorizationSupporting[]` | Document codes the preauthorisation must carry, such as `MAND0409` | +| `insurance[].item[].benefit[]` | `allowedMoney` (remaining) and `usedMoney` (used) in `INR`, type from `http://terminology.hl7.org/CodeSystem/ex-benefitcategory` | + +The payer's `Coverage` carries the plan in `class` with type `XV` and the policy in an identifier typed `NH`. + +### Minimal response resource + +A payer's bundle carries this entry plus the echoed request entries and the `Patient`, `Coverage` and `Organization` entries it references. + +```json +{ + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "CoverageEligibilityResponse", + "id": "", + "meta": { + "profile": [ + "http://hl7.org/fhir/StructureDefinition/CoverageEligibilityResponse" + ] + }, + "identifier": [ + { + "system": "", + "value": "" + } + ], + "status": "active", + "purpose": [ + "validation" + ], + "patient": { + "reference": "" + }, + "created": "", + "requestor": { + "reference": "" + }, + "request": { + "reference": "" + }, + "outcome": "complete", + "disposition": "Policy is currently in-force", + "insurer": { + "reference": "" + }, + "insurance": [ + { + "coverage": { + "reference": "" + }, + "inforce": true, + "item": [ + { + "productOrService": { + "coding": [ + { + "system": "", + "code": "", + "display": "" + } + ] + }, + "excluded": false, + "benefit": [ + { + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/ex-benefitcategory", + "code": "30", + "display": "Health Benefit Plan Coverage" + } + ] + }, + "allowedMoney": { + "value": "", + "currency": "INR" + }, + "usedMoney": { + "value": "", + "currency": "INR" + } + } + ], + "authorizationRequired": true + } + ] + } + ] + } +} +``` + +## How you know it worked + +As a provider, you know the check worked when: + +- `/v1/coverageeligibility/on_check` arrives with a `CoverageEligibilityResponse` whose `request.reference` equals your request's `fullUrl`. +- `outcome` is `complete` and `insurance[].inforce` is `true`. +- For an `auth-requirements` check, each item states `authorizationRequired`. + +As a payer, run the validator recipe ([shared.fhir.hl7-validator-recipe](../../shared/fhir/hl7-validator-recipe.md)) on your bundle: + +```bash +java -jar validator_cli.jar bundle.json -version 4.0.1 -ig ndhm.in#6.5.0 -profile https://nrces.in/ndhm/fhir/r4/StructureDefinition/CoverageEligibilityResponseBundle +``` + +It exits with code 0 and reports no errors. + +## When it goes wrong + +- **You cannot match the response to your request.** Match on `request.reference` and the correlation id in the protected header. Do not match on `Bundle.identifier.system`: the reference payer writes it as `https://payer.pmajy.nha.gov.in`. Do not match on the echoed request `id` either: it can differ from the id you sent. +- **A code lookup fails.** The reference payer sends some SNOMED codes under `http://snomed.info/sct0`. Compare the code value and treat the system loosely when you only display the line. +- **An item shows `excluded: true`.** The package is not covered without approval. Read `authorizationRequired` and raise a preauthorisation. +- **[NHCX-1015](../errors/nhcx-1015.md) or [NHCX-1017](../errors/nhcx-1017.md): invalid response received from receiver.** The payer's response failed the exchange's checks. The payer fixes and resends it. diff --git a/catalogue/nhcx/fhir/insurance-plan-bundle.md b/catalogue/nhcx/fhir/insurance-plan-bundle.md new file mode 100644 index 000000000..3c085770c --- /dev/null +++ b/catalogue/nhcx/fhir/insurance-plan-bundle.md @@ -0,0 +1,204 @@ +--- +id: nhcx.fhir.insurance-plan-bundle +type: fhir +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: InsurancePlan request and response bundles +summary: >- + The small task a hospital sends to fetch a payer's digital policy, and the large + bundle of packages, rates and document rules that comes back. +sources: +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sections 6.4 and 6.5. +- url: https://hcxsbx.abdm.gov.in/images/13093b5f9b88fe826123.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Insurance Plan IG.docx + hash: sha256:e9c6c82b6d67fd8476d6d19a5961419beb04e3c0613533453ed1e16e2a569cc1 + fetched: '2026-09-14' + note: Insurance Plan IG, row 25 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Request section; Approach 1 and Approach 2. +- url: https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip + member: FHIR_bundles_PMJAY_ext/insuranceplan/insuranceplan_request.txt + hash: sha256:8c7b24e3022733aaf7e8f517e12c11c0e8eddd6293844a2c4f3e9700fb720dca + fetched: '2026-09-14' + note: Sample FHIR bundles, row 29 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Task.code, Task.input. +- url: https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip + member: FHIR_bundles_PMJAY_ext/insuranceplan/insuranceplan_response.txt + hash: sha256:8c7b24e3022733aaf7e8f517e12c11c0e8eddd6293844a2c4f3e9700fb720dca + fetched: '2026-09-14' + note: Sample FHIR bundles, row 29 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. whole file; InsurancePlan.coverage.benefit. +- url: https://hcxsbx.abdm.gov.in/images/819467ec15aff13cc2a8.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Dummy Payer Implementation.pdf + hash: sha256:97335ebc4cd32c86e0c34328b2f4c526420b32a7a009208364043d6334e9e757 + fetched: '2026-09-14' + note: NHCX Dummy Payer Implementation, row 19 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Insurance Plan. +verified: + status: unverified +related: + concepts: + - nhcx.concept.insurance-plan + - nhcx.concept.fhir-in-nhcx + flows: + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.insuranceplan-request + - nhcx.endpoint.insuranceplan-on-request + callbacks: + - nhcx.callback.insuranceplan-on-request + fhir: + - nhcx.fhir.pmjay-insurance-plan + - nhcx.fhir.collection-bundle + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.validation + sandbox: + - nhcx.sandbox.dummy-payer + errors: + - nhcx.error.payr-1406 + - nhcx.error.payr-1401 + - nhcx.error.payr-1402 + - nhcx.error.payr-1405 + tests: + - nhcx.test.provider-uc-06 + - nhcx.test.payer-uc-08 + - nhcx.test.tc-hbp-01 + glossary: + - nhcx.glossary.insurance-plan + - shared.glossary.hfr + - shared.glossary.fhir +--- + +# InsurancePlan request and response bundles + +## In plain words + +An [insurance plan](../glossary/insurance-plan.md) is a payer's policy published as data. The hospital asks for it with a one-entry `Task` bundle on `/v1/insuranceplan/request`. The payer answers on `/v1/insuranceplan/on_request` with an InsurancePlan bundle. + +The answer lists the covered packages, their rates, the claim conditions, the documents each claim needs and the questionnaires to fill in. Fetch it before you check eligibility or raise a preauthorisation, so your requests use the payer's own codes. + +## Before you start + +- You know the policy number and the provider id the payer knows you by. The provider id is your [HFR](../../shared/glossary/hfr.md) ID in the published guide. With the [dummy payer](../sandbox/dummy-payer.md), use provider id `32722` and policy number `100217`. +- Your callback endpoint accepts large payloads. The sample PMJAY response is about 21 MB. +- You can seal and open payloads. See [send a sealed request](../flows/send-a-sealed-request.md). + +## What happens + +### The request: a Task with code `poll` + +| Element | Value | +|---|---| +| `Task.status` | `requested` | +| `Task.intent` | `order` | +| `Task.code` | `poll` from `http://terminology.hl7.org/CodeSystem/financialtaskcode` | +| `Task.input[].type` | `policyNumber` or `providerId` from `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code` | +| `Task.input[].valueString` | The policy number or the provider id | + +Send at least one input. + +```json +{ + "resourceType": "Bundle", + "id": "", + "meta": { + "lastUpdated": "" + }, + "identifier": { + "system": "", + "value": "" + }, + "type": "collection", + "timestamp": "", + "entry": [ + { + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "Task", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Task" + ] + }, + "status": "requested", + "intent": "order", + "code": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/financialtaskcode", + "code": "poll", + "display": "Poll" + } + ] + }, + "input": [ + { + "type": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code", + "code": "policyNumber", + "display": "PolicyNumber" + } + ] + }, + "valueString": "" + }, + { + "type": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code", + "code": "providerId", + "display": "Provider ID" + } + ] + }, + "valueString": "" + } + ] + } + } + ] +} +``` + +### The response: an InsurancePlan bundle + +The decrypted payload is a `collection` bundle with these entries: + +| Resource | What it carries | +|---|---| +| `InsurancePlan` | The policy: identifiers, period, coverage groups, benefits, rates and claim rules | +| `Organization` | The payer, referenced from `ownedBy` and `administeredBy` | +| `Questionnaire` | Document and treatment-guideline questionnaires, one entry per questionnaire | + +A plan structures its benefits in one of two ways: + +- `plan.specificCost.category.benefit.cost.qualifiers`: specialty, package, package cost, then implant and stratification qualifiers. +- `coverage.benefit.limit`: coverage type, benefit, limit. + +The PMJAY plan uses both, aligned one to one. See [the PMJAY InsurancePlan](pmjay-insurance-plan.md) for every element. + +## How you know it worked + +Run the validator recipe ([shared.fhir.hl7-validator-recipe](../../shared/fhir/hl7-validator-recipe.md)) on your request bundle: + +```bash +java -jar validator_cli.jar bundle.json -version 4.0.1 -ig ndhm.in#6.5.0 -profile https://nrces.in/ndhm/fhir/r4/StructureDefinition/TaskBundle +``` + +It exits with code 0 and reports no errors. + +Then `/v1/insuranceplan/on_request` arrives at your endpoint. The decrypted bundle holds one `InsurancePlan` whose `NH` identifier equals the policy number you asked for. Your package codes appear in `InsurancePlan.coverage[].benefit[].id`. + +## When it goes wrong + +- **[PAYR-1406](../errors/payr-1406.md): an existing request for this hospital and policy is in progress.** Wait 15 to 60 minutes for the first response. Do not resend with a new correlation id. After 60 minutes with no response, contact support. +- **[PAYR-1401](../errors/payr-1401.md): policy not allowed for the hospital.** Your facility is not enrolled for that policy. Contact support. +- **[PAYR-1402](../errors/payr-1402.md): policy not associated with any payer.** Check the policy number you sent. +- **[PAYR-1405](../errors/payr-1405.md): no enrolled hospital found for the HFR id or sender id.** Check the provider id input and your sender code. +- **The callback times out or is cut off.** The response is large. Accept the body, acknowledge with 202 within 30 seconds, and parse after you acknowledge. diff --git a/catalogue/nhcx/fhir/payment-notice.md b/catalogue/nhcx/fhir/payment-notice.md new file mode 100644 index 000000000..9e0a263e8 --- /dev/null +++ b/catalogue/nhcx/fhir/payment-notice.md @@ -0,0 +1,268 @@ +--- +id: nhcx.fhir.payment-notice +type: fhir +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PaymentNotice bundle and its acknowledgement +summary: >- + The bundle a payer sends to tell a hospital a claim has been paid, with the amount + and bank reference, and the short task the hospital sends back to acknowledge + it. +sources: +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sections 11.2, 11.5, 11.6 and implementation notes. +- url: https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip + member: FHIR_bundles_PMJAY_ext/paymentNotice/payment_notice.txt + hash: sha256:8c7b24e3022733aaf7e8f517e12c11c0e8eddd6293844a2c4f3e9700fb720dca + fetched: '2026-09-14' + note: Sample FHIR bundles, row 29 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Task, PaymentNotice, PaymentReconciliation. +- url: https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip + member: FHIR_bundles_PMJAY_ext/paymentNotice/paymentNotice_ack.txt + hash: sha256:8c7b24e3022733aaf7e8f517e12c11c0e8eddd6293844a2c4f3e9700fb720dca + fetched: '2026-09-14' + note: Sample FHIR bundles, row 29 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Task.output. +verified: + status: unverified +related: + concepts: + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.payment-notice + endpoints: + - nhcx.endpoint.paymentnotice-request + - nhcx.endpoint.paymentnotice-on-request + callbacks: + - nhcx.callback.paymentnotice-request + fhir: + - nhcx.fhir.claim-response + - nhcx.fhir.task + - nhcx.fhir.collection-bundle + - nhcx.fhir.validation + sandbox: + - nhcx.sandbox.dummy-payer + tests: + - nhcx.test.provider-uc-11 + - nhcx.test.payer-uc-13 + glossary: + - nhcx.glossary.payment-notice + - shared.glossary.fhir +--- + +# PaymentNotice bundle and its acknowledgement + +## In plain words + +A [payment notice](../glossary/payment-notice.md) tells the hospital that the payer has paid an approved claim. The payer sends a `TaskBundle` on `/v1/paymentnotice/request`. It holds a `Task`, a `PaymentNotice` and a `PaymentReconciliation` with the bank reference and deductions. + +The hospital acknowledges with its own small `TaskBundle` on `/v1/paymentnotice/on_request`. The payment cycle closes when the payer receives that acknowledgement. + +## Before you start + +- The claim is approved. See [the claim response](claim-response.md). +- Your callback endpoint accepts `/v1/paymentnotice/request`. +- In the sandbox, you can trigger a notice from the [dummy payer](../sandbox/dummy-payer.md). + +## What happens + +### The notice the payer sends + +| Resource | Key elements | +|---|---| +| `Task` | `status` `requested`; `intent` `order`; `code` `deliver` from `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-codes`; `input[0].type` `status` from `http://terminology.hl7.org/CodeSystem/financialtaskinputtype`, with `valueReference` to the PaymentNotice | +| `PaymentNotice` | `identifier` typed `CLN` carrying the claim number; `status` `active`; `payment` pointing at the PaymentReconciliation; `recipient` pointing at your Organization; `amount` in `INR`; `paymentStatus` `paid` from `http://terminology.hl7.org/CodeSystem/paymentstatus` | +| `PaymentReconciliation` | `paymentDate`; `paymentAmount` in `INR`; `paymentIdentifier` typed `UTR` carrying the bank's Unique Transaction Reference; `detail[]` lines typed `TDS` (tax deducted at source) and `Payment` | +| `Organization` | The payer and your facility | + +The net payment plus the `TDS` line equals the approved claim amount. Store the UTR from `PaymentReconciliation.paymentIdentifier.value` for audit. + +### The acknowledgement you send + +| Element | Value | +|---|---| +| `Task.status` | `completed` | +| `Task.code` | `status` from `http://terminology.hl7.org/CodeSystem/financialtaskcode` | +| `Task.output[0]` | type `status` from `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-output-type`; value `paymentack` from `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-output-value` | +| `Task.output[1]` | type `claimNumber`, value the claim number | + +```json +{ + "resourceType": "Bundle", + "id": "", + "meta": { + "lastUpdated": "" + }, + "identifier": { + "system": "", + "value": "" + }, + "type": "collection", + "timestamp": "", + "entry": [ + { + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "Task", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Task" + ] + }, + "status": "completed", + "intent": "order", + "code": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/financialtaskcode", + "code": "status" + } + ] + }, + "description": "", + "authoredOn": "", + "requester": { + "reference": "urn:uuid:" + }, + "owner": { + "reference": "urn:uuid:" + }, + "output": [ + { + "type": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-output-type", + "code": "status" + } + ] + }, + "valueCodeableConcept": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-output-value", + "code": "paymentack", + "display": "Payment is acknowledged" + } + ] + } + }, + { + "type": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code", + "code": "claimNumber" + } + ] + }, + "valueString": "" + } + ] + } + }, + { + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "Organization", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Organization" + ] + }, + "identifier": [ + { + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + "code": "NPI", + "display": "National provider identifier" + } + ] + }, + "system": "https://facility.abdm.gov.in", + "value": "" + } + ], + "type": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/organization-type", + "code": "prov", + "display": "Healthcare Provider" + } + ] + } + ], + "name": "" + } + }, + { + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "Organization", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Organization" + ] + }, + "identifier": [ + { + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + "code": "NIIP", + "display": "National Insurance Payor Identifier (Payor)" + } + ] + }, + "system": "https://facility.abdm.gov.in", + "value": "" + } + ], + "type": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/organization-type", + "code": "pay", + "display": "Payer" + } + ] + } + ], + "name": "" + } + } + ] +} +``` + +## How you know it worked + +Run the validator recipe ([shared.fhir.hl7-validator-recipe](../../shared/fhir/hl7-validator-recipe.md)) on your acknowledgement: + +```bash +java -jar validator_cli.jar bundle.json -version 4.0.1 -ig ndhm.in#6.5.0 -profile https://nrces.in/ndhm/fhir/r4/StructureDefinition/TaskBundle +``` + +It exits with code 0 and reports no errors. + +You know the cycle worked when you have stored the UTR and the net amount from the notice. The exchange also accepted your `/v1/paymentnotice/on_request` call with 202. + +## When it goes wrong + +- **Your parser cannot find the PaymentNotice by id.** The payer's resources can arrive without an `id`. Resolve references by entry `fullUrl`. +- **Detail amounts have no currency.** `detail[].amount` carries `value` only. Treat it as INR. +- **You based logic on `Task.description`.** It is free text and can carry typos. Use `Task.code`, `paymentStatus` and the amounts. +- **The payer never marks the payment closed.** You did not send the acknowledgement, or it failed validation. Send the `paymentack` Task for the claim number. diff --git a/catalogue/nhcx/fhir/pmjay-insurance-plan.md b/catalogue/nhcx/fhir/pmjay-insurance-plan.md new file mode 100644 index 000000000..7d20bfd0d --- /dev/null +++ b/catalogue/nhcx/fhir/pmjay-insurance-plan.md @@ -0,0 +1,220 @@ +--- +id: nhcx.fhir.pmjay-insurance-plan +type: fhir +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: The PMJAY InsurancePlan profile, packages and questionnaires +summary: >- + How the government scheme's policy is laid out as data: specialties, packages, + rates, claim rules, required documents and treatment-guideline questionnaires. +sources: +- url: https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip + member: FHIR_bundles_PMJAY_ext/insuranceplan/insuranceplan_response.txt + hash: sha256:8c7b24e3022733aaf7e8f517e12c11c0e8eddd6293844a2c4f3e9700fb720dca + fetched: '2026-09-14' + note: Sample FHIR bundles, row 29 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. InsurancePlan, coverage.benefit, plan.specificCost, Questionnaire entries. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sections 6.5.1 and 6.6 Claim conditions. +verified: + status: unverified +related: + concepts: + - nhcx.concept.insurance-plan + - nhcx.concept.pmjay-on-nhcx + flows: + - nhcx.flow.insurance-plan-request + fhir: + - nhcx.fhir.insurance-plan-bundle + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.query-update + - nhcx.fhir.terminologies + errors: + - nhcx.error.payr-1406 + tests: + - nhcx.test.tc-hbp-01 + glossary: + - nhcx.glossary.pmjay + - nhcx.glossary.hbp + - nhcx.glossary.insurance-plan + - shared.glossary.fhir +--- + +# The PMJAY InsurancePlan profile, packages and questionnaires + +## In plain words + +The [PMJAY](../glossary/pmjay.md) policy arrives as one [FHIR](../../shared/glossary/fhir.md) `InsurancePlan` inside an InsurancePlan bundle. It is the scheme's package list, the Health Benefit Package ([HBP](../glossary/hbp.md)), as data. + +For each package it gives the rate, the rules that apply, the documents a claim needs and the treatment-guideline questions to answer. Your system reads it once per policy and uses its codes in every later request. + +## Before you start + +- You requested the plan. See [InsurancePlan request and response bundles](insurance-plan-bundle.md). +- Your parser can stream a large JSON document. The sample plan is about 21 MB, with 2,217 entries. + +## What happens + +### The resources + +| Resource | Count in the sample | Holds | +|---|---|---| +| `InsurancePlan` | 1 | The policy | +| `Organization` | 1 | The payer | +| `Questionnaire` | 2,215 | 15 plan-level questionnaires and the Standard Treatment Guidelines (STG) questionnaires | + +### InsurancePlan header + +| Element | Sample value | +|---|---| +| `name` | `PMJAY - Universal Health Policy` | +| `type` | `07` "Universal Health Policy", system `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-insuranceplan-type` | +| `identifier` typed `NH` | The policy number | +| `identifier` typed `XV` | The plan id | +| `plan.type` | `03` "Group", system `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-plan-type` | +| `plan.generalCost[0].cost` | The family sum insured, `500000` INR | + +### Coverage: specialty, then package + +`InsurancePlan.coverage[]` has one entry per specialty. Its `type` coding comes from `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-benefitcategory`, for example `SN` Neurosurgery or `MG` General Medicine. Each `coverage.benefit[]` is one package or implant: + +- `id` and `type`: the package code, from `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-productorservice`. +- `limit[]`: the package rate in `INR`, plus one limit per stratification when the package has them. +- A `Claim-Condition` extension with the package rules. +- `Claim-SupportingInfoRequirement` extensions naming the required documents, and an STG questionnaire link in `documentationUrl`. + +One package benefit, cut to three rules and one document: + +```json +{ + "id": "", + "extension": [ + { + "url": "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Claim-Condition", + "extension": [ + { + "url": "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Claim-Condition/ProcedureType", + "valueString": "Surgical" + }, + { + "url": "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Claim-Condition/ApprovalNotRequired", + "valueString": "N" + }, + { + "url": "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Claim-Condition/EnhancementAllowed", + "valueString": "N" + } + ] + }, + { + "url": "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Claim-SupportingInfoRequirement", + "extension": [ + { + "url": "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Claim-SupportingInfoRequirement///", + "extension": [ + { + "url": "category", + "valueCodeableConcept": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category", + "code": "DIA", + "display": "Diagnostic report" + } + ] + } + }, + { + "url": "code", + "valueCodeableConcept": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code", + "code": "", + "display": "" + } + ] + } + } + ] + } + ] + } + ], + "type": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-productorservice", + "code": "", + "display": "" + } + ] + }, + "limit": [ + { + "value": { + "value": "", + "unit": "INR" + }, + "code": { + "coding": [ + { + "code": "" + } + ] + } + } + ] +} +``` + +### Claim-Condition rules + +| Rule | Values | Use it to | +|---|---|---| +| `ProcedureType` | `Surgical`, `Medical`, `Conservative` | Classify the package | +| `ApprovalNotRequired` | `Y` or `N` | Decide whether a preauthorisation is needed | +| `EnhancementAllowed` | `Y` or `N` | Decide whether an enhancement can add to it | +| `StratificationAllowed`, `MultipleStratificationAllowed`, `MaximumStratificationAllowed` | `Y`/`N`, count | Offer ward or ICU levels | +| `ImplantApplicable`, `MultipleImplantsAllowed`, `MaximumImplantsAllowed` | `Y`/`N`, count | Offer implants | +| `IsDayCare` | `Y` or `N` | Mark day-care packages | +| `QuantityAllowed` | count | Cap the item quantity | +| `CyclicProcedure`, `MaximumCyclesAllowed` | `Y`/`N`, count | Allow repeated cycles, such as dialysis, under one approval | +| `GovtReserved`, `ScheduledTATApproval` | `Y` or `N` | Apply scheme rules | + +An implant benefit carries only `ParentProcedure`, naming the package it belongs to. + +### Plan costs + +`plan[0].specificCost[]` mirrors the coverage: one category per specialty, the same benefits in the same order, with ids prefixed `PlanBenefit/`. Each `cost[]` line has a `type` of `Procedure`, `Stratification` or `Implant`, an optional `qualifiers` code such as `STRAT006b` (HDU), and a `value` in `INR`. + +### Plan-level requirements and questionnaires + +`InsurancePlan.extension[]` lists documents every case needs. One is proof of identity (`POI`, `ADN`). The others point at 15 plan questionnaires with category `INF` and code `ODN`, such as Discharge Information, Admission Details and Authentication Consent. + +STG questionnaires use `item[].prefix` for the question and offer `Yes` or `No`. Plan questionnaires use `item[].text`. + +## How you know it worked + +You have read the plan correctly when, for one package code, your system can show: + +- The rate from `coverage.benefit.limit` and the matching `specificCost` cost lines. +- Whether it needs preauthorisation (`ApprovalNotRequired`) and allows enhancement (`EnhancementAllowed`). +- The list of required documents with their category and code. +- The STG questionnaire to answer, fetched from the bundle by its URL. + +A preauthorisation built from these codes passes the validator recipe ([shared.fhir.hl7-validator-recipe](../../shared/fhir/hl7-validator-recipe.md)) and is not rejected for an unknown package, stratification or document code. + +## When it goes wrong + +- **Your parser runs out of memory.** Stream the bundle and index `coverage.benefit` by package code. +- **The same questionnaire appears many times.** Questionnaires repeat, once per benefit that links them, with identical content. Deduplicate by `id`. +- **A cost parser finds no currency.** Cost and limit values carry `unit` = `INR`, not `currency`. +- **A display string has trailing spaces or stray quotes.** Match on codes, not displays. +- **A package is shared by two specialties.** Some package codes appear under more than one specialty. Key on the specialty and package pair. +- **[PAYR-1406](../errors/payr-1406.md) when you fetch again.** A previous request for the same hospital and policy is still running. Cache the plan and wait 15 to 60 minutes before asking again. diff --git a/catalogue/nhcx/fhir/preauth-cancel.md b/catalogue/nhcx/fhir/preauth-cancel.md new file mode 100644 index 000000000..3e3c9f67a --- /dev/null +++ b/catalogue/nhcx/fhir/preauth-cancel.md @@ -0,0 +1,275 @@ +--- +id: nhcx.fhir.preauth-cancel +type: fhir +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Preauthorisation cancel request and response bundles +summary: >- + The task a hospital sends to cancel a preauthorisation it no longer needs, and + the payer's confirmation that the case is cancelled. +sources: +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 8.6 Cancellation Flow. +- url: https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip + member: FHIR_bundles_PMJAY_ext/preauth/cancel/preauth_cancel_req.txt + hash: sha256:8c7b24e3022733aaf7e8f517e12c11c0e8eddd6293844a2c4f3e9700fb720dca + fetched: '2026-09-14' + note: Sample FHIR bundles, row 29 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Task. +- url: https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip + member: FHIR_bundles_PMJAY_ext/preauth/cancel/preauth_cancel_response.txt + hash: sha256:8c7b24e3022733aaf7e8f517e12c11c0e8eddd6293844a2c4f3e9700fb720dca + fetched: '2026-09-14' + note: Sample FHIR bundles, row 29 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Task and ClaimResponse. +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheets Bridge Error and Preauth Error Codes (PAYR-1252). +verified: + status: unverified +related: + concepts: + - nhcx.concept.reprocess-and-cancel + flows: + - nhcx.flow.preauth-cancel + endpoints: + - nhcx.endpoint.task-submit + - nhcx.endpoint.task-on-submit + callbacks: + - nhcx.callback.task-on-submit + fhir: + - nhcx.fhir.task + - nhcx.fhir.preauth-request + - nhcx.fhir.collection-bundle + - nhcx.fhir.validation + errors: + - nhcx.error.payr-1252 + - nhcx.error.payr-1017 + - nhcx.error.payr-1018 + tests: + - nhcx.test.provider-uc-12 + glossary: + - nhcx.glossary.preauthorisation + - shared.glossary.fhir +--- + +# Preauthorisation cancel request and response bundles + +## In plain words + +A hospital cancels a [preauthorisation](../glossary/preauthorisation.md) with a `TaskBundle` on `/v1/task/submit`. The `Task` has code `cancel`, a reason, and the claim number it cancels. + +The payer answers on `/v1/task/on_submit`. Its bundle holds a completed `Task` that points at a `ClaimResponse` marked `cancelled`. + +## Before you start + +- The preauthorisation is in state "preauthorization submitted" or "preauthorization approved". The payer cannot cancel a case in any other state. +- You know the claim number you sent in the original [preauthorisation request](preauth-request.md). +- You know why you are cancelling, so you can pick a reason code. + +## What happens + +### The request + +| Element | Value | +|---|---| +| `Task.status` | `requested` | +| `Task.intent` | `order` | +| `Task.code` | `cancel` from `http://terminology.hl7.org/CodeSystem/financialtaskcode` | +| `Task.reasonCode` | A code from `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-reason-code`, such as `treatmentplanchanged` | +| `Task.input` | `claimNumber` and `initimationNumber`, both from `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code`, both carrying the preauthorisation number | +| `Task.requester` | Your provider Organization | +| `Task.owner` | The payer Organization | + +The input code is spelled `initimationNumber`. Send it with that spelling. + +```json +{ + "resourceType": "Bundle", + "id": "", + "meta": { + "lastUpdated": "" + }, + "identifier": { + "system": "", + "value": "" + }, + "type": "collection", + "timestamp": "", + "entry": [ + { + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "Task", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Task" + ] + }, + "status": "requested", + "intent": "order", + "code": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/financialtaskcode", + "code": "cancel" + } + ] + }, + "description": "", + "authoredOn": "", + "requester": { + "reference": "urn:uuid:" + }, + "owner": { + "reference": "urn:uuid:" + }, + "reasonCode": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-reason-code", + "code": "treatmentplanchanged", + "display": "Treatment plan changed during hospitalization." + } + ] + }, + "input": [ + { + "type": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code", + "code": "claimNumber" + } + ] + }, + "valueString": "" + }, + { + "type": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code", + "code": "initimationNumber" + } + ] + }, + "valueString": "" + } + ] + } + }, + { + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "Organization", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Organization" + ] + }, + "identifier": [ + { + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + "code": "NPI", + "display": "National provider identifier" + } + ] + }, + "system": "https://facility.abdm.gov.in", + "value": "" + } + ], + "type": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/organization-type", + "code": "prov", + "display": "Healthcare Provider" + } + ] + } + ], + "name": "" + } + }, + { + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "Organization", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Organization" + ] + }, + "identifier": [ + { + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + "code": "NIIP", + "display": "National Insurance Payor Identifier (Payor)" + } + ] + }, + "system": "https://facility.abdm.gov.in", + "value": "" + } + ], + "type": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/organization-type", + "code": "pay", + "display": "Payer" + } + ] + } + ], + "name": "" + } + } + ] +} +``` + +### The response + +| Resource | Key elements | +|---|---| +| `Task` | `status` `completed`; `code` `approve` from `http://hl7.org/fhir/CodeSystem/task-code`; `output[0].type` `include` from `http://terminology.hl7.org/CodeSystem/financialtaskinputtype`; `output[0].valueReference` pointing at the ClaimResponse | +| `ClaimResponse` | Your claim number; `use` `preauthorization`; `outcome` `complete`; `adjudication[0].reason.coding.code` `cancelled` | + +## How you know it worked + +Run the validator recipe ([shared.fhir.hl7-validator-recipe](../../shared/fhir/hl7-validator-recipe.md)): + +```bash +java -jar validator_cli.jar bundle.json -version 4.0.1 -ig ndhm.in#6.5.0 -profile https://nrces.in/ndhm/fhir/r4/StructureDefinition/TaskBundle +``` + +It exits with code 0 and reports no errors. + +Then `/v1/task/on_submit` arrives. Its `Task` has `status` `completed`, and the referenced `ClaimResponse` carries your claim number with adjudication reason `cancelled`. + +## When it goes wrong + +- **[PAYR-1252](../errors/payr-1252.md): case not in an active preauthorisation state.** Only submitted or approved cases can be cancelled. The case cannot be cancelled from its current state. +- **"Invalid input, code and reason code received."** The combination of task code, reason code and inputs is not one the payer accepts. Use `cancel` with a reason from `ndhm-reason-code` and both inputs. +- **"Invalid case number received."** Send the preauthorisation number in both `claimNumber` and `initimationNumber`. +- **[PAYR-1017](../errors/payr-1017.md) or [PAYR-1018](../errors/payr-1018.md).** The task code or the task reason code is missing. diff --git a/catalogue/nhcx/fhir/preauth-enhancement.md b/catalogue/nhcx/fhir/preauth-enhancement.md new file mode 100644 index 000000000..06ccbf8ae --- /dev/null +++ b/catalogue/nhcx/fhir/preauth-enhancement.md @@ -0,0 +1,225 @@ +--- +id: nhcx.fhir.preauth-enhancement +type: fhir +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Preauthorisation enhancement request and response bundles +summary: >- + How a hospital asks the payer to raise an approved preauthorisation by adding + a package, and how the payer's answer lists each package. +sources: +- url: https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip + member: FHIR_bundles_PMJAY_ext/preauth/enhancement/enhancement_req.txt + hash: sha256:8c7b24e3022733aaf7e8f517e12c11c0e8eddd6293844a2c4f3e9700fb720dca + fetched: '2026-09-14' + note: Sample FHIR bundles, row 29 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Claim.item, Claim.procedure. +- url: https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip + member: FHIR_bundles_PMJAY_ext/preauth/enhancement/enhancement_resp.txt + hash: sha256:8c7b24e3022733aaf7e8f517e12c11c0e8eddd6293844a2c4f3e9700fb720dca + fetched: '2026-09-14' + note: Sample FHIR bundles, row 29 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. ClaimResponse.item, total. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 6.6 Claim conditions. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Q2 sandbox base URLs. +verified: + status: unverified +related: + concepts: + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.preauth-enhancement + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.preauth-response + - nhcx.fhir.pmjay-insurance-plan + - nhcx.fhir.validation + errors: + - nhcx.error.payr-1025 + - nhcx.error.payr-1026 + - nhcx.error.payr-1027 + - nhcx.error.payr-1028 + glossary: + - nhcx.glossary.enhancement + - nhcx.glossary.preauthorisation + - shared.glossary.fhir +--- + +# Preauthorisation enhancement request and response bundles + +## In plain words + +An [enhancement](../glossary/enhancement.md) asks the payer to extend a [preauthorisation](../glossary/preauthorisation.md) it already decided. You need one when the patient needs a second package or a higher level of care. + +You resend the same `Claim`, with the same claim number, on `/v1/preauth/submit`. Keep every earlier item and add the new one. The payer answers on `/v1/preauth/on_submit` with one adjudicated line per item. + +## Before you start + +- The original preauthorisation has a decision. See [the preauthorisation response](preauth-response.md). +- The new package allows enhancement. In the PMJAY InsurancePlan, its `Claim-Condition` flag `EnhancementAllowed` is `Y`. See [the PMJAY InsurancePlan](pmjay-insurance-plan.md). +- You have the documents the new package requires. + +## What happens + +### The request + +Start from the [preauthorisation bundle](preauth-request.md) and change these elements: + +- Keep `Claim.identifier` and `use: preauthorization`. +- Keep each earlier `item` with its original `sequence`. +- Add the new item with the next `sequence`, its own `Procedure` entry, and a `procedureSequence` pointing at it. +- Add `supportingInfo` entries for the new package's documents. +- Set `total` to the sum of all item `net` values. + +The changed parts of the `Claim`: + +```json +{ + "procedure": [ + { + "sequence": 1, + "procedureReference": { + "reference": "urn:uuid:" + } + }, + { + "sequence": 2, + "procedureReference": { + "reference": "urn:uuid:" + } + } + ], + "item": [ + { + "sequence": 1, + "careTeamSequence": [ + 1 + ], + "diagnosisSequence": [ + 1 + ], + "procedureSequence": [ + 1 + ], + "informationSequence": [ + 1 + ], + "category": { + "coding": [ + { + "system": "", + "code": "" + } + ] + }, + "productOrService": { + "coding": [ + { + "system": "", + "code": "", + "display": "" + } + ] + }, + "servicedPeriod": { + "start": "", + "end": "" + }, + "quantity": { + "value": 1 + }, + "unitPrice": { + "value": "" + }, + "net": { + "value": "" + } + }, + { + "sequence": 2, + "careTeamSequence": [ + 1 + ], + "diagnosisSequence": [ + 1 + ], + "procedureSequence": [ + 2 + ], + "informationSequence": [ + 1 + ], + "category": { + "coding": [ + { + "system": "", + "code": "" + } + ] + }, + "productOrService": { + "coding": [ + { + "system": "", + "code": "", + "display": "" + } + ] + }, + "servicedPeriod": { + "start": "", + "end": "" + }, + "quantity": { + "value": 1 + }, + "unitPrice": { + "value": "" + }, + "net": { + "value": "" + } + } + ], + "total": { + "value": "" + } +} +``` + +Add a second `Procedure` entry with `id` ``, shaped like the first. + +### The response + +A `ClaimResponse` with one `item` per `itemSequence`, each with its own `eligible` amount and `status`. The `benefit` total and the `PMJAY-T` `eligible` total cover all approved items. + +## How you know it worked + +Run the validator recipe ([shared.fhir.hl7-validator-recipe](../../shared/fhir/hl7-validator-recipe.md)): + +```bash +java -jar validator_cli.jar bundle.json -version 4.0.1 -ig ndhm.in#6.5.0 -profile https://nrces.in/ndhm/fhir/r4/StructureDefinition/ClaimBundle +``` + +It exits with code 0 and reports no errors. + +Then `/v1/preauth/on_submit` arrives with a `ClaimResponse` for the same claim number. It has an `item` for the new `itemSequence`, with `status` `Approved` when the payer accepts it. + +## When it goes wrong + +- **[PAYR-1027](../errors/payr-1027.md) or [PAYR-1028](../errors/payr-1028.md).** An item id or sequence is invalid. Keep the original sequences and number the new item after them. +- **[PAYR-1025](../errors/payr-1025.md) or [PAYR-1026](../errors/payr-1026.md).** A procedure sequence is invalid, or `Claim.procedure` points at a Procedure missing from the bundle. +- **The payer rejects the new item.** Check `EnhancementAllowed` for the package in the InsurancePlan before you send. +- **The response lists the new item first.** Match lines on `itemSequence`, not on position. diff --git a/catalogue/nhcx/fhir/preauth-request.md b/catalogue/nhcx/fhir/preauth-request.md new file mode 100644 index 000000000..f5028d13e --- /dev/null +++ b/catalogue/nhcx/fhir/preauth-request.md @@ -0,0 +1,565 @@ +--- +id: nhcx.fhir.preauth-request +type: fhir +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Preauthorisation request bundle, a Claim with use preauthorization +summary: >- + The bundle a hospital sends to ask a payer to approve a planned treatment before + it happens, with the package, the diagnosis and the required documents. +sources: +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 8.4. +- url: https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip + member: FHIR_bundles_PMJAY_ext/preauth/preauth_request.txt + hash: sha256:8c7b24e3022733aaf7e8f517e12c11c0e8eddd6293844a2c4f3e9700fb720dca + fetched: '2026-09-14' + note: Sample FHIR bundles, row 29 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. whole bundle. +- url: https://hcxsbx.abdm.gov.in/#/domain-specifications/domain-data-specifications/domain-data-models/e-objects + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__domain-data-specifications__domain-data-models__e-objects.md + hash: sha256:1d5d7553c709c4d237d623bc77259999f84c1b114ab51b25112cbed075352c5b + fetched: '2026-09-14' + note: Site page /domain-specifications/domain-data-specifications/domain-data-models/e-objects, text as shown on the site. Claim Request. +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.claim-cycle + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.insurance-plan + flows: + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.preauth-submit + fhir: + - nhcx.fhir.collection-bundle + - nhcx.fhir.preauth-response + - nhcx.fhir.preauth-enhancement + - nhcx.fhir.pmjay-insurance-plan + - nhcx.fhir.claim-request + - nhcx.fhir.terminologies + - nhcx.fhir.validation + decisions: + - nhcx.decision.preauth-or-predetermination + errors: + - nhcx.error.payr-1011 + - nhcx.error.payr-1012 + - nhcx.error.payr-1079 + - nhcx.error.payr-1083 + - nhcx.error.payr-1019 + - nhcx.error.payr-1020 + - nhcx.error.payr-1021 + - nhcx.error.payr-1036 + - nhcx.error.payr-1086 + - nhcx.error.payr-1513 + tests: + - nhcx.test.provider-uc-07 + - nhcx.test.tc-pa-01 + glossary: + - nhcx.glossary.preauthorisation + - nhcx.glossary.claim + - shared.glossary.fhir + - shared.glossary.snomed-ct + - shared.glossary.hpr +--- + +# Preauthorisation request bundle, a Claim with use preauthorization + +## In plain words + +A [preauthorisation](../glossary/preauthorisation.md) asks the payer to approve a treatment before the hospital delivers it. It is a [FHIR](../../shared/glossary/fhir.md) `ClaimBundle` whose focal resource is a `Claim` with `use` set to `preauthorization`. + +The same `Claim` shape later carries the final claim with `use` set to `claim`. You send the preauthorisation on `/v1/preauth/submit`. + +## Before you start + +- You have the payer's insurance plan. It gives you the specialty, package and stratification codes, and the documents each package needs. See [the PMJAY InsurancePlan](pmjay-insurance-plan.md). +- An eligibility check with purpose `auth-requirements` told you the package needs approval. See [the eligibility response](coverage-eligibility-response.md). +- You hold the treating doctor's [HPR](../../shared/glossary/hpr.md) id. +- Each required document is ready as a PDF or image to encode in base64, or as an ABDM health record to reference. + +## What happens + +### Resources in the bundle + +| Resource | Role | +|---|---| +| `Claim` (`use` = `preauthorization`) | The request: items, diagnosis, procedure, documents, total | +| `Patient` | Identifiers typed `PMJAY` and `ABHA` | +| `Organization` (provider, payer) | `NPI` carrying your HFR ID; `NIIP` for the payer | +| `Coverage` | The policy, identifier typed `NH` | +| `Practitioner` | The care team member, identifier typed `HPIN` on `https://hpr.abdm.gov.in` | +| `Procedure` | One per item, referenced from `Claim.procedure` | +| ABDM record Compositions and their resources | Clinical documents referenced from `Claim.supportingInfo` | + +### Claim elements + +| Element | What goes in it | +|---|---| +| `identifier` | Your claim number, typed `CLN` from `ndhm-identifier-type-code` | +| `type` | SNOMED CT `737481003` "Inpatient care management (procedure)" | +| `use` | `preauthorization` | +| `priority` | `normal` from `processpriority` | +| `careTeam` | At least one entry, pointing at the Practitioner | +| `diagnosis` | ICD-10 code as a `diagnosisCodeableConcept` | +| `procedure` | One entry per Procedure resource | +| `insurance` | `focal: true`, pointing at the Coverage | +| `item` | Specialty in `category`, package in `productOrService`, dates, quantity, price, and the `procedureSequence` and `informationSequence` it uses | +| `supportingInfo` | One entry per required document, with `sequence`, `category`, `code` and a value | +| `total` | The sum of item `net` values | + +Copy the specialty, package, stratification and document codings exactly as the payer's InsurancePlan gives them. Put a stratification, such as a ward or ICU level, in `item.modifier`. + +A document goes in `supportingInfo` in one of two ways. Send a `valueAttachment` with base64 `data`, a `contentType` such as `application/pdf`, and a `title`. Or send a `valueReference` to a Composition in the bundle. + +### Minimal bundle + +```json +{ + "resourceType": "Bundle", + "id": "", + "meta": { + "lastUpdated": "" + }, + "identifier": { + "system": "", + "value": "" + }, + "type": "collection", + "timestamp": "", + "entry": [ + { + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "Claim", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Claim" + ] + }, + "identifier": [ + { + "type": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code", + "code": "CLN", + "display": "Claim number" + } + ] + }, + "system": "", + "value": "" + } + ], + "status": "active", + "type": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "737481003", + "display": "Inpatient care management (procedure)" + } + ] + }, + "use": "preauthorization", + "patient": { + "reference": "urn:uuid:" + }, + "created": "", + "insurer": { + "reference": "urn:uuid:" + }, + "provider": { + "reference": "urn:uuid:" + }, + "priority": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/processpriority", + "code": "normal" + } + ] + }, + "careTeam": [ + { + "sequence": 1, + "provider": { + "reference": "urn:uuid:" + } + } + ], + "supportingInfo": [ + { + "sequence": 1, + "category": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category", + "code": "" + } + ] + }, + "code": { + "coding": [ + { + "system": "", + "code": "" + } + ] + }, + "valueAttachment": { + "contentType": "application/pdf", + "title": "", + "data": "" + } + } + ], + "diagnosis": [ + { + "sequence": 1, + "diagnosisCodeableConcept": { + "coding": [ + { + "system": "http://hl7.org/fhir/sid/icd-10", + "code": "", + "display": "" + } + ] + } + } + ], + "procedure": [ + { + "sequence": 1, + "procedureReference": { + "reference": "urn:uuid:" + } + } + ], + "insurance": [ + { + "sequence": 1, + "focal": true, + "coverage": { + "reference": "urn:uuid:" + } + } + ], + "item": [ + { + "sequence": 1, + "careTeamSequence": [ + 1 + ], + "diagnosisSequence": [ + 1 + ], + "procedureSequence": [ + 1 + ], + "informationSequence": [ + 1 + ], + "category": { + "coding": [ + { + "system": "", + "code": "" + } + ] + }, + "productOrService": { + "coding": [ + { + "system": "", + "code": "", + "display": "" + } + ] + }, + "servicedPeriod": { + "start": "", + "end": "" + }, + "quantity": { + "value": 1 + }, + "unitPrice": { + "value": "" + }, + "net": { + "value": "" + } + } + ], + "total": { + "value": "" + } + } + }, + { + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "Patient", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Patient" + ] + }, + "identifier": [ + { + "type": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code", + "code": "PMJAY" + } + ] + }, + "system": "https://bis.pmjay.gov.in", + "value": "" + }, + { + "type": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code", + "code": "ABHA" + } + ] + }, + "system": "https://bis.pmjay.gov.in", + "value": "" + } + ], + "name": [ + { + "text": "" + } + ], + "gender": "", + "birthDate": "" + } + }, + { + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "Organization", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Organization" + ] + }, + "identifier": [ + { + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + "code": "NPI", + "display": "National provider identifier" + } + ] + }, + "system": "https://facility.abdm.gov.in", + "value": "" + } + ], + "type": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/organization-type", + "code": "prov", + "display": "Healthcare Provider" + } + ] + } + ], + "name": "" + } + }, + { + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "Organization", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Organization" + ] + }, + "identifier": [ + { + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + "code": "NIIP", + "display": "National Insurance Payor Identifier (Payor)" + } + ] + }, + "system": "https://facility.abdm.gov.in", + "value": "" + } + ], + "type": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/organization-type", + "code": "pay", + "display": "Payer" + } + ] + } + ], + "name": "" + } + }, + { + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "Coverage", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Coverage" + ] + }, + "identifier": [ + { + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + "code": "NH", + "display": "National Health Plan Identifier" + } + ] + }, + "system": "", + "value": "" + } + ], + "status": "active", + "beneficiary": { + "reference": "urn:uuid:" + }, + "payor": [ + { + "reference": "urn:uuid:" + } + ] + } + }, + { + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "Practitioner", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Practitioner" + ] + }, + "identifier": [ + { + "type": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code", + "code": "HPIN" + } + ] + }, + "system": "https://hpr.abdm.gov.in", + "value": "" + } + ], + "name": [ + { + "text": "" + } + ] + } + }, + { + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "Procedure", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Procedure" + ] + }, + "identifier": [ + { + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + "code": "SNO", + "display": "Serial Number" + } + ] + }, + "system": "", + "value": "1" + } + ], + "status": "preparation", + "code": { + "coding": [ + { + "system": "", + "code": "", + "display": "" + } + ] + }, + "subject": { + "reference": "urn:uuid:" + } + } + } + ] +} +``` + +## How you know it worked + +Run the validator recipe ([shared.fhir.hl7-validator-recipe](../../shared/fhir/hl7-validator-recipe.md)): + +```bash +java -jar validator_cli.jar bundle.json -version 4.0.1 -ig ndhm.in#6.5.0 -profile https://nrces.in/ndhm/fhir/r4/StructureDefinition/ClaimBundle +``` + +It exits with code 0 and reports no errors. + +After you send the bundle, `/v1/preauth/on_submit` arrives with a `ClaimResponse` whose identifier carries your claim number. See [the preauthorisation response](preauth-response.md). + +## When it goes wrong + +- **[PAYR-1011](../errors/payr-1011.md) or [PAYR-1012](../errors/payr-1012.md).** The Claim identifier or its `type` is missing. Add the `CLN` identifier. +- **[PAYR-1079](../errors/payr-1079.md) or [PAYR-1083](../errors/payr-1083.md).** No care team, or no HPR id on the Practitioner. Add `careTeam` and a Practitioner identifier typed `HPIN`. +- **[PAYR-1019](../errors/payr-1019.md), [PAYR-1020](../errors/payr-1020.md) or [PAYR-1021](../errors/payr-1021.md).** A `supportingInfo` sequence, category or code is invalid. Copy the category and code from the InsurancePlan requirement. +- **[PAYR-1036](../errors/payr-1036.md), or "Invalid Base64 value received in attachment".** The attachment is not base64, or `contentType` or `title` is empty. Allowed content types are `application/pdf`, `application/jpg`, `application/jpeg`, `application/png` and `application/fhir+json`. +- **[PAYR-1086](../errors/payr-1086.md): no procedure resource found for url.** `Claim.procedure` points at a Procedure that is not in the bundle. +- **[PAYR-1513](../errors/payr-1513.md): invalid diagnosis.** Send the diagnosis as `diagnosisCodeableConcept`, not as a reference. diff --git a/catalogue/nhcx/fhir/preauth-response.md b/catalogue/nhcx/fhir/preauth-response.md new file mode 100644 index 000000000..7bde9cd4b --- /dev/null +++ b/catalogue/nhcx/fhir/preauth-response.md @@ -0,0 +1,261 @@ +--- +id: nhcx.fhir.preauth-response +type: fhir +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Preauthorisation response bundle, a ClaimResponse +summary: >- + The payer's decision on a preauthorisation: approved, partly approved, queried + or rejected, with the amounts it will cover. +sources: +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sections 8.5-8.5.4. +- url: https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip + member: FHIR_bundles_PMJAY_ext/preauth/preauthresponse_with_query.txt + hash: sha256:8c7b24e3022733aaf7e8f517e12c11c0e8eddd6293844a2c4f3e9700fb720dca + fetched: '2026-09-14' + note: Sample FHIR bundles, row 29 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. ClaimResponse. +- url: https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip + member: FHIR_bundles_PMJAY_ext/preauth/Query/preauth_response_queryUpdate_App.txt + hash: sha256:8c7b24e3022733aaf7e8f517e12c11c0e8eddd6293844a2c4f3e9700fb720dca + fetched: '2026-09-14' + note: Sample FHIR bundles, row 29 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. ClaimResponse. +verified: + status: unverified +related: + concepts: + - nhcx.concept.claim-cycle + - nhcx.concept.queries-and-communication + - nhcx.concept.fhir-in-nhcx + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-query-response + - nhcx.flow.payer-process-a-request + endpoints: + - nhcx.endpoint.preauth-on-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.query-update + - nhcx.fhir.claim-response + - nhcx.fhir.collection-bundle + errors: + - nhcx.error.nhcx-1015 + - nhcx.error.nhcx-1017 + tests: + - nhcx.test.payer-uc-09 + glossary: + - nhcx.glossary.preauthorisation + - nhcx.glossary.adjudication + - shared.glossary.fhir +--- + +# Preauthorisation response bundle, a ClaimResponse + +## In plain words + +The payer answers a [preauthorisation](../glossary/preauthorisation.md) with a [FHIR](../../shared/glossary/fhir.md) `ClaimResponseBundle` on `/v1/preauth/on_submit`. The focal resource is a `ClaimResponse` with `use` set to `preauthorization`. + +It carries one of four decisions: approved, partially approved, queried or rejected. Read two fields together to know which one you have. + +## Before you start + +- As a provider, you sent a [preauthorisation request](preauth-request.md) and stored your claim number, item sequences and correlation id. +- You can open a sealed callback. See [receive, open and acknowledge a sealed message](../flows/receive-a-sealed-callback.md). +- As a payer, you have adjudicated the request. See [receive, adjudicate and answer a request](../flows/payer-process-a-request.md). + +## What happens + +### Resources in the bundle + +`ClaimResponse`, the payer's `Patient` and `Coverage`, and the payer and provider `Organization` resources. Payer-built resources carry the `SUBSETTED` tag. + +### Reading the decision + +| Decision | `outcome` | `adjudication[0].reason.coding.code` | Next step | +|---|---|---|---| +| Approved | `complete` | `approved` | Treat the patient. Keep `preAuthRef` when present. | +| Partially approved | `partial` | `approved` | Read `processNote` for the reduction. | +| Queried | `partial` | `queried` | Answer with a [query update](query-update.md). | +| Rejected | `complete` | `cancelled` | The request is closed. | + +### Other elements + +| Element | Meaning | +|---|---| +| `identifier` | Your claim number, typed `CLN` | +| `disposition` | The decision in free text | +| `item[].itemSequence` | The `Claim.item.sequence` the line answers | +| `item[].adjudication[]` | Categories `eligible` (amount), `reason` (query history), `eligpercent`, `eligquant`, `status` (`Approved` or `Queried`) | +| `total[]` | `benefit` total, and an `eligible` total with id `PMJAY-T` | +| `processNote[]` | Explanation of a reduction, linked from `item.noteNumber` | + +The `reason` adjudication carries a pipe-separated history. Each part reads `USER~date and time~type~comment~trust`. Parse it as plain text. + +### Minimal response resource + +A payer's bundle carries this entry plus the `Patient`, `Coverage` and `Organization` entries it references. + +```json +{ + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "ClaimResponse", + "id": "", + "identifier": [ + { + "type": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code", + "code": "CLN", + "display": "Claim number" + } + ] + }, + "system": "", + "value": "" + } + ], + "status": "active", + "type": { + "coding": [ + { + "system": "http://snomed.info/sct", + "code": "737481003", + "display": "Inpatient care management (procedure)" + } + ] + }, + "use": "preauthorization", + "patient": { + "reference": "" + }, + "created": "", + "insurer": { + "reference": "" + }, + "requestor": { + "reference": "" + }, + "outcome": "complete", + "disposition": "", + "payeeType": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/payeetype", + "code": "provider", + "display": "Provider" + } + ] + }, + "item": [ + { + "itemSequence": 1, + "adjudication": [ + { + "category": { + "coding": [ + { + "system": "https://hl7.org/fhir/R4/valueset-adjudication.html", + "code": "eligible", + "display": "Eligible Amount" + } + ] + }, + "amount": { + "value": "" + } + }, + { + "category": { + "coding": [ + { + "system": "https://hl7.org/fhir/R4/valueset-adjudication.html", + "code": "status", + "display": "Item adjudication status" + } + ] + }, + "reason": { + "coding": [ + { + "code": "Approved", + "display": "Approved" + } + ] + } + } + ] + } + ], + "adjudication": [ + { + "category": { + "coding": [ + { + "code": "status", + "display": "Status" + } + ] + }, + "reason": { + "coding": [ + { + "code": "approved", + "display": "Approved" + } + ] + } + } + ], + "total": [ + { + "category": { + "coding": [ + { + "system": "https://hl7.org/fhir/R4/valueset-adjudication.html", + "code": "benefit", + "display": "Benefit Amount" + } + ] + }, + "amount": { + "value": "" + } + } + ] + } +} +``` + +## How you know it worked + +As a provider: + +- `/v1/preauth/on_submit` arrives with a `ClaimResponse` whose `identifier` value equals your claim number. +- `outcome` and `adjudication[0].reason.coding.code` map to one row of the decision table. + +As a payer, run the validator recipe ([shared.fhir.hl7-validator-recipe](../../shared/fhir/hl7-validator-recipe.md)): + +```bash +java -jar validator_cli.jar bundle.json -version 4.0.1 -ig ndhm.in#6.5.0 -profile https://nrces.in/ndhm/fhir/r4/StructureDefinition/ClaimResponseBundle +``` + +It exits with code 0 and reports no errors. + +## When it goes wrong + +- **You treated `outcome: complete` as approval.** A rejection is also `complete`. Always read `adjudication[0].reason.coding.code` as well. +- **Amounts land on the wrong item.** Items can arrive in any order. Match `item.itemSequence` to your `Claim.item.sequence`. +- **The requestor Organization is not yours.** The payer may identify your facility by its own id. Match the response on claim number and correlation id instead. +- **Your parser expects a currency.** Adjudication amounts carry `value` only. Treat them as INR. +- **A payer's validator run fails on `ClaimResponse.type`.** Base FHIR R4 requires `type`. Include it. +- **[NHCX-1015](../errors/nhcx-1015.md): invalid response received from receiver.** The exchange rejected the payer's response. The payer corrects and resends it. diff --git a/catalogue/nhcx/fhir/query-update.md b/catalogue/nhcx/fhir/query-update.md new file mode 100644 index 000000000..63ed4bc51 --- /dev/null +++ b/catalogue/nhcx/fhir/query-update.md @@ -0,0 +1,231 @@ +--- +id: nhcx.fhir.query-update +type: fhir +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Query update bundles for preauthorisation and claim +summary: >- + How to recognise a payer's query on a preauthorisation or claim, and how to resend + the same claim with the documents and answers the payer asked for. +sources: +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sections 8.5.3 and 9.5.4. +- url: https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip + member: FHIR_bundles_PMJAY_ext/preauth/Query/preauth_queryUpdate_req.txt + hash: sha256:8c7b24e3022733aaf7e8f517e12c11c0e8eddd6293844a2c4f3e9700fb720dca + fetched: '2026-09-14' + note: Sample FHIR bundles, row 29 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Claim.supportingInfo, QuestionnaireResponse. +- url: https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip + member: FHIR_bundles_PMJAY_ext/claim/claim_queryUpdate_req.txt + hash: sha256:8c7b24e3022733aaf7e8f517e12c11c0e8eddd6293844a2c4f3e9700fb720dca + fetched: '2026-09-14' + note: Sample FHIR bundles, row 29 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Claim. +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheets Preauth and Claim Error Codes (PAYR-1504, PAYR-1505). +verified: + status: unverified +related: + concepts: + - nhcx.concept.queries-and-communication + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-query-response + fhir: + - nhcx.fhir.preauth-response + - nhcx.fhir.claim-response + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.pmjay-insurance-plan + sandbox: + - nhcx.sandbox.dummy-payer + errors: + - nhcx.error.payr-1504 + - nhcx.error.payr-1505 + - nhcx.error.payr-1084 + - nhcx.error.payr-1085 + - nhcx.error.payr-1047 + tests: + - nhcx.test.tc-pa-02 + - nhcx.test.tc-cl-02 + - nhcx.test.provider-uc-08 + glossary: + - nhcx.glossary.preauthorisation + - nhcx.glossary.claim + - shared.glossary.fhir +--- + +# Query update bundles for preauthorisation and claim + +## In plain words + +A payer that cannot decide a [preauthorisation](../glossary/preauthorisation.md) or [claim](../glossary/claim.md) raises a query. It answers with a `ClaimResponse` that is still open and asks for more information. + +You answer by resending the same `Claim`, with the same claim number, carrying the extra documents and answers in `supportingInfo`. The payer then sends a fresh decision. + +## Before you start + +- You received a [preauthorisation response](preauth-response.md) or [claim response](claim-response.md) marked as queried. +- You hold the original request bundle, or can rebuild it with the same claim number and items. +- You have the documents the query asks for. +- For the transport, follow [answer a query on a preauthorisation](../flows/preauth-query-response.md) or [answer a query on a claim](../flows/claim-query-response.md). + +## What happens + +### Recognising a query + +| Element | Value on a queried response | +|---|---| +| `ClaimResponse.outcome` | `partial` | +| `ClaimResponse.adjudication[0].reason.coding.code` | `queried` | +| `item[].adjudication[]` with category `status` | reason `Queried` | +| `item[].adjudication[]` with category `reason` | the query history in `reason.coding[0].display` | +| `total[]` | `0` while the query is open | + +The history is pipe-separated. Each part reads `USER~date and time~type~comment~trust`. The latest part is the payer's current question. + +### Building the update + +Start from your original request bundle and change these parts: + +- Keep `Claim.identifier`, `use` and every `item`. +- Add the requested documents to `supportingInfo`, as attachments or as references to ABDM record Compositions in the bundle. +- Put case-level remarks in a `supportingInfo` entry with category `NMI` and code `CQD`, as a `valueString`. +- Put a policy or case questionnaire answer in an entry with category `INF` and code `ODN`. Its `valueReference` points at a `QuestionnaireResponse` in the bundle. +- Put a Standard Treatment Guidelines answer in an entry with category `STG`, referencing its `QuestionnaireResponse`. + +The added `supportingInfo` entries: + +```json +{ + "supportingInfo": [ + { + "sequence": 1, + "category": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category", + "code": "" + } + ] + }, + "code": { + "coding": [ + { + "system": "", + "code": "" + } + ] + }, + "valueAttachment": { + "contentType": "application/pdf", + "title": "", + "data": "" + } + }, + { + "sequence": 2, + "category": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category", + "code": "NMI" + } + ] + }, + "code": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-code", + "code": "CQD" + } + ] + }, + "valueString": "" + }, + { + "sequence": 3, + "category": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category", + "code": "INF" + } + ] + }, + "code": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code", + "code": "ODN", + "display": "Other document" + } + ] + }, + "valueReference": { + "reference": "urn:uuid:" + } + } + ] +} +``` + +The `QuestionnaireResponse` entry they reference: + +```json +{ + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "QuestionnaireResponse", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/QuestionnaireResponse" + ] + }, + "questionnaire": "", + "status": "completed", + "item": [ + { + "linkId": "", + "answer": [ + { + "valueString": "" + } + ] + } + ] + } +} +``` + +Take the `questionnaire` URL and each `linkId` from the payer's InsurancePlan. See [the PMJAY InsurancePlan](pmjay-insurance-plan.md). + +## How you know it worked + +Run the validator recipe ([shared.fhir.hl7-validator-recipe](../../shared/fhir/hl7-validator-recipe.md)): + +```bash +java -jar validator_cli.jar bundle.json -version 4.0.1 -ig ndhm.in#6.5.0 -profile https://nrces.in/ndhm/fhir/r4/StructureDefinition/ClaimBundle +``` + +It exits with code 0 and reports no errors. + +The payer's next response for the same claim number no longer has reason `queried`. Its `outcome` and reason code map to approved, partially approved or rejected. + +## When it goes wrong + +- **[PAYR-1504](../errors/payr-1504.md): wrong value type for `NMI` and `CQD`.** Send the remarks as a `valueString`. +- **[PAYR-1505](../errors/payr-1505.md): wrong category or code for a questionnaire response.** Use `INF` with `ODN` for a policy or case questionnaire, and `STG` for a treatment-guideline questionnaire. +- **[PAYR-1084](../errors/payr-1084.md) or [PAYR-1085](../errors/payr-1085.md).** The referenced `QuestionnaireResponse` is missing from the bundle, or the reference points at another resource type. +- **[PAYR-1047](../errors/payr-1047.md): invalid reference in supporting info.** A `valueReference` does not resolve to a resource in the bundle. +- **You sent a new claim number.** The payer treats it as a new case. Reuse the original claim number. diff --git a/catalogue/nhcx/fhir/task.md b/catalogue/nhcx/fhir/task.md new file mode 100644 index 000000000..82ecceb45 --- /dev/null +++ b/catalogue/nhcx/fhir/task.md @@ -0,0 +1,307 @@ +--- +id: nhcx.fhir.task +type: fhir +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Task bundle for reprocess and CRC +summary: >- + The task a hospital sends to dispute a rejected or underpaid claim, which routes + the case to the claim review committee, and the task that carries the payer's + final decision back. +sources: +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sections 22 Erroneous Claim and 23 Claim Reprocess. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sections 10.4 and 10.5. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Reprocess; sheet Value sets, Task Codes. +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Bridge Error. +verified: + status: unverified +related: + concepts: + - nhcx.concept.reprocess-and-cancel + - nhcx.concept.claim-cycle + flows: + - nhcx.flow.claim-reprocess + endpoints: + - nhcx.endpoint.task-submit + - nhcx.endpoint.task-on-submit + callbacks: + - nhcx.callback.task-on-submit + fhir: + - nhcx.fhir.claim-response + - nhcx.fhir.preauth-cancel + - nhcx.fhir.payment-notice + - nhcx.fhir.collection-bundle + - nhcx.fhir.validation + errors: + - nhcx.error.payr-1017 + - nhcx.error.payr-1018 + - nhcx.error.payr-1332 + tests: + - nhcx.test.tc-cl-03 + - nhcx.test.provider-uc-12 + - nhcx.test.payer-uc-14 + glossary: + - nhcx.glossary.reprocess + - nhcx.glossary.crc + - nhcx.glossary.pmjay + - shared.glossary.fhir +--- + +# Task bundle for reprocess and CRC + +## In plain words + +A hospital that disputes a claim decision asks for [reprocessing](../glossary/reprocess.md) with a `TaskBundle` on `/v1/task/submit`. The `Task` has code `reprocess`, a reason, the claim number and a supporting document. + +Under [PMJAY](../glossary/pmjay.md), a reprocess request goes to the Claim Review Committee ([CRC](../glossary/crc.md)). Its decision is final. The payer returns it on `/v1/task/on_submit` as a completed `Task` pointing at a `ClaimResponse`. + +## Before you start + +- You received a claim decision you dispute. See [the claim response](claim-response.md). +- You know which case you have: + +| | Reprocess | Erroneous claim | +|---|---|---| +| When | The claim was fully rejected | The claim was paid, but less than payable | +| Earliest | As soon as the rejection arrives | After the payment cleared notice | +| `reasonCode` | `claimrejected` | `partialpayment` | +| Amount | None sent; the full claim is implied | The shortfall, never more than claimed minus approved | +| Supporting document | Mandatory | Mandatory | +| Times per claim under PMJAY | Once | Once | + +- You hold a document that justifies the request. +- You have not already received a CRC decision on this claim. No erroneous claim can follow a CRC decision. + +## What happens + +### Task codes on `/v1/task/submit` + +`Task.code` comes from `http://terminology.hl7.org/CodeSystem/financialtaskcode`. Use `reprocess` for a reprocess request. The same path carries `cancel` (see [preauthorisation cancel](preauth-cancel.md)), `release` and `nullify`. + +### The request + +| Element | Value | +|---|---| +| `Task.status` | `requested` | +| `Task.intent` | `order` | +| `Task.code` | `reprocess` | +| `Task.reasonCode` | `claimrejected` or `partialpayment`, from `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-reason-code` | +| `Task.input` | `claimNumber` and `initimationNumber` carrying the original claim number, and a `document` input with the supporting file as `valueAttachment`, all from `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code` | +| `Task.requester`, `Task.owner` | Your Organization and the payer's | + +The request carries the original claim number. It does not create a new case number. + +```json +{ + "resourceType": "Bundle", + "id": "", + "meta": { + "lastUpdated": "" + }, + "identifier": { + "system": "", + "value": "" + }, + "type": "collection", + "timestamp": "", + "entry": [ + { + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "Task", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Task" + ] + }, + "status": "requested", + "intent": "order", + "code": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/financialtaskcode", + "code": "reprocess", + "display": "Reprocess" + } + ] + }, + "description": "", + "authoredOn": "", + "requester": { + "reference": "urn:uuid:" + }, + "owner": { + "reference": "urn:uuid:" + }, + "reasonCode": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-reason-code", + "code": "claimrejected" + } + ] + }, + "input": [ + { + "type": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code", + "code": "claimNumber" + } + ] + }, + "valueString": "" + }, + { + "type": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code", + "code": "initimationNumber" + } + ] + }, + "valueString": "" + }, + { + "type": { + "coding": [ + { + "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code", + "code": "document" + } + ] + }, + "valueAttachment": { + "contentType": "application/pdf", + "title": "", + "data": "" + } + } + ] + } + }, + { + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "Organization", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Organization" + ] + }, + "identifier": [ + { + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + "code": "NPI", + "display": "National provider identifier" + } + ] + }, + "system": "https://facility.abdm.gov.in", + "value": "" + } + ], + "type": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/organization-type", + "code": "prov", + "display": "Healthcare Provider" + } + ] + } + ], + "name": "" + } + }, + { + "fullUrl": "urn:uuid:", + "resource": { + "resourceType": "Organization", + "id": "", + "meta": { + "profile": [ + "https://nrces.in/ndhm/fhir/r4/StructureDefinition/Organization" + ] + }, + "identifier": [ + { + "type": { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/v2-0203", + "code": "NIIP", + "display": "National Insurance Payor Identifier (Payor)" + } + ] + }, + "system": "https://facility.abdm.gov.in", + "value": "" + } + ], + "type": [ + { + "coding": [ + { + "system": "http://terminology.hl7.org/CodeSystem/organization-type", + "code": "pay", + "display": "Payer" + } + ] + } + ], + "name": "" + } + } + ] +} +``` + +### The response + +The payer's bundle holds a `Task` with `status` `completed`. `Task.output[0].valueReference` points at a `ClaimResponse` in the same bundle. Read that `ClaimResponse` exactly as you read a [claim response](claim-response.md): approved, partially approved, queried or rejected. + +## How you know it worked + +Run the validator recipe ([shared.fhir.hl7-validator-recipe](../../shared/fhir/hl7-validator-recipe.md)): + +```bash +java -jar validator_cli.jar bundle.json -version 4.0.1 -ig ndhm.in#6.5.0 -profile https://nrces.in/ndhm/fhir/r4/StructureDefinition/TaskBundle +``` + +It exits with code 0 and reports no errors. + +Then `/v1/task/on_submit` arrives with a completed `Task`. Its output resolves to a `ClaimResponse` carrying your claim number and the committee's decision. + +## When it goes wrong + +- **"Invalid input, code and reason code received."** The task code, reason code and inputs are not an accepted combination. Pair `reprocess` with `claimrejected` for a rejection, or with `partialpayment` for an erroneous claim. +- **"Invalid case number received."** Send the original claim number in `claimNumber` and `initimationNumber`. +- **[PAYR-1017](../errors/payr-1017.md) or [PAYR-1018](../errors/payr-1018.md).** The task code or the reason code is missing. +- **[PAYR-1332](../errors/payr-1332.md): invalid CRC request.** Check that the claim was rejected or partially paid, and that no request was already raised for it. Each claim allows one request under PMJAY. +- **An erroneous claim is refused.** Raise it only after the payment cleared notice, and keep the amount within the shortfall. diff --git a/catalogue/nhcx/fhir/terminologies.md b/catalogue/nhcx/fhir/terminologies.md new file mode 100644 index 000000000..9e488ce3f --- /dev/null +++ b/catalogue/nhcx/fhir/terminologies.md @@ -0,0 +1,152 @@ +--- +id: nhcx.fhir.terminologies +type: fhir +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Code systems and value sets used in NHCX bundles +summary: >- + The code systems every claims bundle draws on, where each one is used, and how + strictly each binding applies. +sources: +- url: https://hcxsbx.abdm.gov.in/#/domain-specifications/domain-data-specifications/terminologies + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__domain-data-specifications__terminologies.md + hash: sha256:1cdf48ceb570f19500e672dfb1140271aca01274a1d8c3e83cad336d5a5b082d + fetched: '2026-09-14' + note: Site page /domain-specifications/domain-data-specifications/terminologies, text as shown on the site. Guidlines and proposed binding table. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Appendix A.2, A.3; Sections 10.4, 11.5-11.6; Quick Reference. +- url: https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip + member: FHIR_bundles_PMJAY_ext/preauth/preauth_request.txt + hash: sha256:8c7b24e3022733aaf7e8f517e12c11c0e8eddd6293844a2c4f3e9700fb720dca + fetched: '2026-09-14' + note: Sample FHIR bundles, row 29 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. coding systems throughout. +- url: https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip + member: FHIR_bundles_PMJAY_ext/coverageeligibility/coverageresponse_validation.txt + hash: sha256:8c7b24e3022733aaf7e8f517e12c11c0e8eddd6293844a2c4f3e9700fb720dca + fetched: '2026-09-14' + note: Sample FHIR bundles, row 29 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. meta.tag, Coverage.class. +verified: + status: unverified +related: + fhir: + - nhcx.fhir.collection-bundle + - nhcx.fhir.validation + - nhcx.fhir.pmjay-insurance-plan + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + concepts: + - nhcx.concept.fhir-in-nhcx + errors: + - nhcx.error.payr-1020 + - nhcx.error.payr-1021 + - nhcx.error.payr-1010 + glossary: + - shared.glossary.snomed-ct + - shared.glossary.fhir + - shared.glossary.nrces + - nhcx.glossary.pmjay +--- + +# Code systems and value sets used in NHCX bundles + +## In plain words + +A code system is a published list of codes, such as diagnoses or document types. Claims bundles use international systems like [SNOMED CT](../../shared/glossary/snomed-ct.md), LOINC and ICD-10, and Indian systems published by [NRCeS](../../shared/glossary/nrces.md). + +Payers match codes by exact system URL and code. A code under the wrong system URL fails, even when the code itself is right. + +## Before you start + +- You know which bundle you are building. See [the collection bundle](collection-bundle.md). +- For PMJAY package, specialty, stratification and document codes, you have the payer's insurance plan. See [the PMJAY InsurancePlan](pmjay-insurance-plan.md). + +## What happens + +### Clinical terminologies + +| Terminology | System URL | Used for | +|---|---|---| +| SNOMED CT | `http://snomed.info/sct` | Procedures, clinical findings, `Claim.type` (`737481003` Inpatient care management) | +| LOINC | `http://loinc.org` | Laboratory and clinical observations | +| ICD-10 | `http://hl7.org/fhir/sid/icd-10` | `Claim.diagnosis` | + +In India, SNOMED CT is free to use. ICD codes classify diseases. Laboratories use LOINC. + +### NRCeS code systems + +| System URL | Carries | Example codes | +|---|---|---| +| `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | Identifier types | `PMJAY`, `ABHA`, `HPID`, `HPIN`, `CLN` (claim number), `UTR` | +| `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | `Claim.supportingInfo.category` | `INV`, `DIA`, `DIS`, `ONS`, `OTH`, `NMI`, `INF`, `POI`, `DOB` | +| `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-code` | `Claim.supportingInfo.code` | `DTH`, `DTM`, `LAMA`, `DAMA`, `ADDD`, `DSDE`, `PSP`, `EDT`, `CQD`, `BCF`, `DCB` | +| `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-reason-code` | `Task.reasonCode` | `treatmentplanchanged`, `claimrejected`, `partialpayment` | +| `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code` | `Task.input.type` | `policyNumber`, `providerId`, `claimNumber`, `initimationNumber` | +| `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-output-type` | `Task.output.type` | `status`, `include` | +| `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-output-value` | `Task.output.value` | `paymentack` | +| `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-codes` | `Task.code` for payment notices | `deliver` | + +### HL7 code systems + +| System URL | Used for | +|---|---| +| `http://terminology.hl7.org/CodeSystem/v2-0203` | Identifier types `NPI` (facility HFR ID), `NIIP` (payer), `NH` (policy), `XV` (plan), `JHN`, `SNO`, `MR` | +| `http://terminology.hl7.org/CodeSystem/financialtaskcode` | `Task.code` `poll`, `cancel`, `reprocess`, `status` | +| `http://terminology.hl7.org/CodeSystem/processpriority` | `priority` `normal` | +| `http://terminology.hl7.org/CodeSystem/organization-type` | `prov`, `pay` | +| `http://terminology.hl7.org/CodeSystem/paymentstatus` | `paid` | +| `http://terminology.hl7.org/CodeSystem/v3-ObservationValue` | The `SUBSETTED` tag on payer-built resources | + +### PMJAY master codes + +PMJAY specialty, package, stratification and mandatory-document codes come from the payer's InsurancePlan. Examples are `MG` (General Medicine), `MG004A` (a package), `STRAT006b` (HDU, a high dependency unit) and `MAND0409` (a document). Copy each coding, system and code, exactly as the InsurancePlan gives it. + +### Binding strength + +A binding says how strictly an element must use its value set: + +- `required`: use a code from the value set. +- `preferred` or `extensible`: draw from the value set unless the domain has agreed otherwise. +- `example`: the domain must agree and define the value set. + +Proposed bindings for NHCX elements: + +| Element | Terminology | Binding | +|---|---|---| +| `CoverageEligibilityRequest.insurer` | Insurance company owners | Preferred | +| `Claim.procedure.type` | Procedure type | Example | +| `Claim.procedure.procedureCode` | Procedure code | Example | +| `ClaimResponse.item.adjudication.reason` | Denial codes | Preferred | +| `Claim.item.modifier` | Procedure modifiers | Example | +| `Claim.item.category` | Service categories | Example | +| `Claim.item.productOrService` | Service codes | Preferred | +| `PractitionerRole.speciality` | Medical speciality type | Preferred | +| `Claim.careTeam.role` | Health service provider role | Example | + +## How you know it worked + +Run the validator recipe ([shared.fhir.hl7-validator-recipe](../../shared/fhir/hl7-validator-recipe.md)) online, without `-tx n/a`, so codes are checked: + +```bash +java -jar validator_cli.jar bundle.json -version 4.0.1 -ig ndhm.in#6.5.0 -profile +``` + +It exits with code 0 and reports no binding errors. + +You have understood the codes when you can answer: + +1. Which system carries the facility's HFR ID type code `NPI`? +2. Where do you take a package code from before you put it in `Claim.item.productOrService`? + +## When it goes wrong + +- **A SNOMED code under the wrong URL.** Use `http://snomed.info/sct` exactly. Variants such as `https://snomed.info/sct` or `http://snomed.info/sct0` do not match. +- **An NRCeS URL spelled another way.** Use `https://nrces.in/ndhm/fhir/r4/CodeSystem/`. A `www.` host or a `CodeSystem-` page URL is a web page, not the system. +- **[PAYR-1020](../errors/payr-1020.md) or [PAYR-1021](../errors/payr-1021.md).** A `supportingInfo` category or code is invalid. Take it from the InsurancePlan requirement or the tables above. +- **[PAYR-1010](../errors/payr-1010.md).** An identifier carries no `type`. Add the type coding from `ndhm-identifier-type-code` or `v2-0203`. +- **A PMJAY code typed by hand.** Codes have trailing spaces and case rules. Copy them from the InsurancePlan bundle. diff --git a/catalogue/nhcx/fhir/validation.md b/catalogue/nhcx/fhir/validation.md new file mode 100644 index 000000000..52bc35854 --- /dev/null +++ b/catalogue/nhcx/fhir/validation.md @@ -0,0 +1,139 @@ +--- +id: nhcx.fhir.validation +type: fhir +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Validating an NHCX bundle before you send it +summary: >- + How to check a claims bundle against the national profiles on your own machine, + what the check covers, and the bundle review that precedes sandbox sign-off. +sources: +- url: https://hcxsbx.abdm.gov.in/images/2c3fbb4e6b09f0834f69.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Implementation Guide for Adoption of FHIR in ABDM and NHCX.pdf + hash: sha256:549377c9c26b1bd23decac3a1b9e5ebedfdc8e0fe99e53ef733859b188f51366 + fetched: '2026-09-14' + note: Implementation Guide for Adoption of FHIR in ABDM and NHCX, row 14 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 16-19 Validating FHIR Resources. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. section 7 reference documents. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8. +- url: https://hcxsbx.abdm.gov.in/images/2b7fde4358fd0a4b2086.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Code Snippets references for payload preparation.pdf + hash: sha256:cea0cfbf5897e9642eaf9a515a941b0a1de39474ea39444c9e05abe21cd9ec73 + fetched: '2026-09-14' + note: NHCX Code Snippets references for payload preparation, row 13 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1. +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use cases 5-7 Validations. +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Bridge Error. +verified: + status: unverified +related: + fhir: + - shared.fhir.hl7-validator-recipe + - nhcx.fhir.collection-bundle + - nhcx.fhir.terminologies + - nhcx.fhir.preauth-request + - nhcx.fhir.claim-request + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.task + sandbox: + - nhcx.sandbox.sandbox-exit + - nhcx.sandbox.support-contacts + errors: + - nhcx.error.payr-1008 + - nhcx.error.payr-1004 + troubleshooting: + - nhcx.troubleshooting.bundle-rejected + glossary: + - shared.glossary.fhir + - shared.glossary.nrces +--- + +# Validating an NHCX bundle before you send it + +## In plain words + +Every bundle on the exchange must conform to the [NRCeS](../../shared/glossary/nrces.md) profiles, and both sides check it. The receiver validates what it gets. You validate what you send, before you seal it. + +Validation runs on your machine with the HL7 [FHIR](../../shared/glossary/fhir.md) validator against the ABDM and NHCX profile package. During sandbox exit, NRCeS also reviews sample bundles you send by email. + +## Before you start + +- Java is installed, and the validator jar is downloaded as the recipe shows ([shared.fhir.hl7-validator-recipe](../../shared/fhir/hl7-validator-recipe.md)). +- Your bundle is saved as a `.json` file, before encryption. +- You know which bundle profile your use case takes. See [the collection bundle](collection-bundle.md). + +## What happens + +### Tools + +| Tool | Use it for | +|---|---| +| HL7 validator jar (`validator_cli.jar`) | Command-line checks on your machine and in CI | +| HAPI FHIR validator (Java library) | Checks inside your application before sealing | +| https://validator.fhir.org | One-off checks in a browser | + +### What the validator checks + +Structure, cardinality, value domains, coding and CodeableConcept bindings, invariants, profile rules and business rules such as reference resolution. + +### The command + +The profile package id is `ndhm.in`, published at https://nrces.in/ndhm/fhir/r4/package.tgz. It carries the ABDM and NHCX profiles. Name the bundle profile with `-profile`: + +```bash +java -jar validator_cli.jar bundle.json -version 4.0.1 -ig ndhm.in#6.5.0 -profile https://nrces.in/ndhm/fhir/r4/StructureDefinition/ClaimBundle +``` + +Swap the profile for `ClaimResponseBundle`, `CoverageEligibilityRequestBundle`, `CoverageEligibilityResponseBundle`, `TaskBundle` or `InsurancePlanBundle` as your use case needs. + +### Inside a Java application + +1. Put `package.tgz` on the classpath. +2. Load it with `NpmPackageValidationSupport`. +3. Chain it with `DefaultProfileValidationSupport`, `InMemoryTerminologyServerValidationSupport`, `CommonCodeSystemsTerminologyService` and `SnapshotGeneratingValidationSupport`, wrapped in `CachingValidationSupport`. +4. Register a `FhirInstanceValidator` on the `FhirValidator` and call `validateWithResult` on the bundle. + +The HAPI FHIR artifacts are `hapi-fhir-structures-r4`, `hapi-fhir-validation` and `hapi-fhir-validation-resources-r4`, version 6.4.3. + +### In the browser + +On https://validator.fhir.org open **Options**, choose the implementation guide `ndhm.in`, choose the version, and select **Add**. Paste the bundle under **Enter Resource** and select **Validate**. + +### Bundle review during sandbox exit + +Email sample bundles to `hcx.integration@nha.gov.in`. The NRCeS team validates them as part of functional testing. See [the sandbox exit process](../sandbox/sandbox-exit.md). For questions on building a bundle, write to `nrc-help@cdac.in`. + +## How you know it worked + +You ran: + +```bash +java -jar validator_cli.jar bundle.json -version 4.0.1 -ig ndhm.in#6.5.0 -profile +``` + +The command exits with code 0 and the report lists no errors. Read every warning and decide on each one. + +After you send the bundle, the receiver's callback carries a FHIR bundle, not a `ProtocolResponse` with a bundle error. + +## When it goes wrong + +- **The validator cannot find the profile.** The `-ig` value or the profile URL is wrong. Check `ndhm.in#6.5.0` and the canonical URL. See the recipe ([shared.fhir.hl7-validator-recipe](../../shared/fhir/hl7-validator-recipe.md)). +- **The validator cannot reach a terminology server.** Add `-tx n/a` for an offline run. Codes are then not checked, so run once more online before you rely on the result. +- **The validator passes, and the receiver still rejects the bundle.** The receiver also applies business rules. It checks typed identifiers, resolvable references, supporting-info category and code pairs, and base64 attachments. It also checks that your HFR ID matches your registration. See [the payer rejects your FHIR bundle](../troubleshooting/bundle-rejected.md). +- **[PAYR-1008](../errors/payr-1008.md) or [PAYR-1004](../errors/payr-1004.md) from the receiver.** The bundle did not parse, or failed structure checks. Validate the exact JSON you encrypted, not an earlier copy. +- **You copied a payer response as a template for a request.** Payer-built bundles declare no NRCeS profiles. Start requests from the minimal bundles in the atom for each use case. diff --git a/catalogue/nhcx/flows/biometric-face.md b/catalogue/nhcx/flows/biometric-face.md new file mode 100644 index 000000000..deaeecdf1 --- /dev/null +++ b/catalogue/nhcx/flows/biometric-face.md @@ -0,0 +1,208 @@ +--- +id: nhcx.flow.biometric-face +type: flow +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Authenticate a beneficiary by face on a mobile device +summary: >- + Prove that a scheme beneficiary is at your hospital with a face scan on a phone, + when fingerprint or iris is not possible, and get the same short-lived user token. +sources: +- url: https://hcxsbx.abdm.gov.in/images/9f1e6b545a693d38a704.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Biometric Authentication Implementation Steps.docx + hash: sha256:fac8b14bfe8d518c0e651740537b9441c501d3cf2ab0f0482a07ab9f417e43a9 + fetched: '2026-09-14' + note: Biometric Authentication Implementation Steps, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments, not named in the NHCX document sheet. NHCX Face-Auth API Curl section. +- url: https://hcxsbx.abdm.gov.in/images/a2f07ff8158e86e9e92a.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/FaceAuth Postman Collection.zip + hash: sha256:f2db63f7fe272178ee57acfcfd32dbc40680d69527dc35c6724f0da2a32fcaab + fetched: '2026-09-14' + note: FaceAuth Postman Collection, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments, not named in the NHCX document sheet. FaceAuth init request body; verify headers. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. FAQ 26 question 9; FAQ 27 questions 2 and 4. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. pages 18-19, Biometric Authentication Using ABHA APIs. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.abha-biometric-faceauth-init + - nhcx.endpoint.abha-biometric-capture-pid + - nhcx.endpoint.abha-biometric-v2-auth-verify + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + flows: + - nhcx.flow.biometric-fingerprint-iris + concepts: + - nhcx.concept.biometric-authentication + - nhcx.concept.pmjay-on-nhcx + decisions: + - nhcx.decision.biometric-modality + errors: + - nhcx.error.payr-1272 + - nhcx.error.payr-1256 + - nhcx.error.payr-1363 + - nhcx.error.payr-1366 + glossary: + - nhcx.glossary.pmjay + - nhcx.glossary.rd-service + - shared.glossary.abha +--- + +# Authenticate a beneficiary by face on a mobile device + +## In plain words + +Face authentication proves the same thing as a fingerprint or iris scan: the [PMJAY](../glossary/pmjay.md) beneficiary is at your hospital. The capture happens on a phone, in the [ABHA](../../shared/glossary/abha.md) app, rather than on a hospital device. Your system shows a QR code, the phone scans it, and your system polls until the scan is done. + +It ends with the same 30-minute user token. A PMJAY integration must support all three methods, and one case can use different methods at different stages. + +## Before you start + +- The beneficiary's ABHA is linked to their PMJAY card. +- A session token, sent as `Authorization: Bearer `. +- A phone with the sandbox ABHA app, from `https://sandboxcms.abdm.gov.in/uploads/app_sbx_release_5_d4437e4aa1.apk`. It also needs the Aadhaar face [RD service](../glossary/rd-service.md) app from the Play Store or App Store. +- The beneficiary's Aadhaar number and the mobile number linked to that Aadhaar. +- A way to show a QR code on your screen. +- OpenSSL, for encrypting the Aadhaar number. +- The participant code of the scheme payer, for the `payerid` header. + +## What happens + +```mermaid +sequenceDiagram + participant B as Beneficiary with a phone + participant App as ABHA app and Aadhaar face RD service + participant You as Your HMIS + participant PX as ABDM proxy for face authentication + You->>PX: POST /pmjay/sbxhcx/abdmproxy/abha/biometric/faceauth/init + PX-->>You: txnId + You->>B: QR code for phrsbx.abdm.gov.in/face-auth with the txnId + B->>App: scan the QR code, press Continue, scan the face + Note over App: the face capture completes on the phone + loop until status is COMPLETE + You->>PX: POST /pmjay/sbxhcx/abdmproxy/abha/biometric/capture/pid + PX-->>You: PENDING, then COMPLETE + end + Note over You: encrypt the Aadhaar number with the published public key + You->>PX: POST /pmjay/sbxhcx/abdmproxy/abha/biometric/v2/auth/verify + PX-->>You: tokens and ABHAProfile +``` + +The sandbox host is `https://apisbx.abdm.gov.in`. Every call carries `Accept: application/json`, `Content-Type: application/json`, the `Authorization` header, a fresh UUID in `REQUEST-ID`, and the current ISO time in `TIMESTAMP`. + +### 1. Start + +`POST /pmjay/sbxhcx/abdmproxy/abha/biometric/faceauth/init`: + +```json +{ + "scope": ["abha-enrol", "face-auth"] +} +``` + +The answer carries `txnId` and `message` `Transaction Id generated Successfully`. + +### 2. Show the QR code + +Render this address as a QR code on your screen: + +```text +https://phrsbx.abdm.gov.in/face-auth?txnId= +``` + +### 3. The beneficiary scans + +The beneficiary, or a hospital assistant, opens the sandbox ABHA app. They tap the QR code icon at the top left of the welcome screen and scan your screen. They press **Continue** on the FaceAuth screen and complete the face scan with the Aadhaar face RD service app. + +### 4. Poll for the capture + +`POST /pmjay/sbxhcx/abdmproxy/abha/biometric/capture/pid`: + +```json +{ + "txnId": "" +} +``` + +**Wait:** there is no callback. The answer is `{"status": "PENDING", "message": "Awaiting PID capture"}` until the scan completes. Then it is `{"status": "COMPLETE", "message": "PID capture successful"}`. Poll while the QR code is on screen, and move on at `COMPLETE`. + +### 5. Encrypt the Aadhaar number + +Encrypt the 12-digit Aadhaar number with the published public key, using `RSA/ECB/OAEPWithSHA-1AndMGF1Padding`. With OpenSSL: + +```sh +cat > aadhaar_face_auth_public.pem <<'EOF' +-----BEGIN PUBLIC KEY----- +MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAstWB95C5pHLXiYW59qyO +4Xb+59KYVm9Hywbo77qETZVAyc6VIsxU+UWhd/k/YtjZibCznB+HaXWX9TVTFs9N +wgv7LRGq5uLczpZQDrU7dnGkl/urRA8p0Jv/f8T0MZdFWQgks91uFffeBmJOb58u +68ZRxSYGMPe4hb9XXKDVsgoSJaRNYviH7RgAI2QhTCwLEiMqIaUX3p1SAc178ZlN +8qHXSSGXvhDR1GKM+y2DIyJqlzfik7lD14mDY/I4lcbftib8cv7llkybtjX1Aayf +Zp4XpmIXKWv8nRM488/jOAF81Bi13paKgpjQUUuwq9tb5Qd/DChytYgBTBTJFe7i +rDFCmTIcqPr8+IMB7tXA3YXPp3z605Z6cGoYxezUm2Nz2o6oUmarDUntDhq/PnkN +ergmSeSvS8gD9DHBuJkJWZweG3xOPXiKQAUBr92mdFhJGm6fitO5jsBxgpmulxpG +0oKDy9lAOLWSqK92JMcbMNHn4wRikdI9HSiXrrI7fLhJYTbyU3I4v5ESdEsayHXu +iwO/1C8y56egzKSw44GAtEpbAkTNEEfK5H5R0QnVBIXOvfeF4tzGvmkfOO6nNXU3 +o/WAdOyV3xSQ9dqLY5MEL4sJCGY1iJBIAQ452s8v0ynJG5Yq+8hNhsCVnklCzAls +IzQpnSVDUVEzv17grVAw078CAwEAAQ== +-----END PUBLIC KEY----- +EOF +printf '%s' '' | openssl pkeyutl -encrypt -pubin -inkey aadhaar_face_auth_public.pem -pkeyopt rsa_padding_mode:oaep -pkeyopt rsa_oaep_md:sha1 -pkeyopt rsa_mgf1_md:sha1 | base64 | tr -d '\n' +``` + +The output is a single base64 line of 684 characters. Never log it or store it. + +### 6. Verify + +`POST /pmjay/sbxhcx/abdmproxy/abha/biometric/v2/auth/verify`, adding `payerid: ` and `process`. Use `Preauth` at admission, and `Discharge` at discharge and at each cycle. + +```json +{ + "authData": { + "authMethods": ["face_auth"], + "face": { + "txnId": "", + "aadhaar": "", + "mobile": "" + } + }, + "authMode": "FACE_AUTH" +} +``` + +The answer carries `txnId`, `message`, a `tokens` object and an `ABHAProfile` object. `tokens` holds `token`, `expiresIn`, `refreshExpiresIn` and `refreshToken`. Here `expiresIn` and `refreshExpiresIn` are strings, `"1800"` and `"1296000"`, so parse them as numbers. `ABHAProfile` carries the verified identity, including `ABHANumber` and `abhaStatus`. + +### 7. Use the user token + +Pass the user `token` as a header parameter on the coverage eligibility check, the pre-authorisation and the claim. [Authenticate a beneficiary by fingerprint or iris](biometric-fingerprint-iris.md) covers the details. It lasts 30 minutes. + +## How you know it worked + +`capture/pid` answered `COMPLETE`. Then `v2/auth/verify` returned `tokens.token` with `tokens.expiresIn` `"1800"`, and `ABHAProfile.ABHANumber` equal to the beneficiary's ABHA number. + +```observation schema=exit-condition +channel: synchronous +call: POST /pmjay/sbxhcx/abdmproxy/abha/biometric/v2/auth/verify +precondition: + capture/pid status: COMPLETE +match: + tokens.expiresIn: "1800" + ABHAProfile.ABHANumber: +``` + +## When it goes wrong + +- **`capture/pid` stays `PENDING`.** The beneficiary has not finished the scan, or the face RD service app is missing from the phone. If they abandon the scan, start again with a new `faceauth/init` and a new QR code. +- **Verify fails straight after the scan.** You called it before `capture/pid` answered `COMPLETE`. Keep polling. +- **Verify rejects the Aadhaar value.** It was sent in the clear, or encrypted with other padding. Use the command in step 5 exactly. +- **Verify rejects the mobile.** It is not the mobile number linked to the beneficiary's Aadhaar. +- **The payer rejects the user token.** It expired after 30 minutes, or belongs to another beneficiary. See [PAYR-1272](../errors/payr-1272.md), and [PAYR-1366](../errors/payr-1366.md) at discharge. +- **The payer says the consent questionnaire is missing.** No biometric token and no Authentication Consent Questionnaire went with the request. See [PAYR-1256](../errors/payr-1256.md) and [PAYR-1363](../errors/payr-1363.md). diff --git a/catalogue/nhcx/flows/biometric-fingerprint-iris.md b/catalogue/nhcx/flows/biometric-fingerprint-iris.md new file mode 100644 index 000000000..751852017 --- /dev/null +++ b/catalogue/nhcx/flows/biometric-fingerprint-iris.md @@ -0,0 +1,196 @@ +--- +id: nhcx.flow.biometric-fingerprint-iris +type: flow +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Authenticate a beneficiary by fingerprint or iris +summary: >- + Prove that a scheme beneficiary is physically at your hospital with a fingerprint + or iris scan, and get the short-lived user token their pre-authorisation and claim + carry. +sources: +- url: https://hcxsbx.abdm.gov.in/images/9f1e6b545a693d38a704.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Biometric Authentication Implementation Steps.docx + hash: sha256:fac8b14bfe8d518c0e651740537b9441c501d3cf2ab0f0482a07ab9f417e43a9 + fetched: '2026-09-14' + note: 'Biometric Authentication Implementation Steps, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments, not named in the NHCX document sheet. Fingerprint/IRIS Authentication: Auth INIT, Auth Verify, Auth Refresh Token; policy table.' +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. FAQ 10 (K-547); FAQ 26 questions 2, 6, 9, 11, 12; FAQ 27 question 2. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. pages 18-19, Biometric Authentication Using ABHA APIs. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.abha-biometric-auth-init + - nhcx.endpoint.abha-biometric-auth-verify + - nhcx.endpoint.abha-biometric-auth-refresh-token + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + flows: + - nhcx.flow.biometric-face + - nhcx.flow.send-a-sealed-request + concepts: + - nhcx.concept.biometric-authentication + - nhcx.concept.pmjay-on-nhcx + decisions: + - nhcx.decision.biometric-modality + errors: + - nhcx.error.payr-1272 + - nhcx.error.payr-1256 + - nhcx.error.payr-1363 + - nhcx.error.payr-1366 + glossary: + - nhcx.glossary.pmjay + - nhcx.glossary.rd-service + - nhcx.glossary.pid-block + - shared.glossary.abha +--- + +# Authenticate a beneficiary by fingerprint or iris + +## In plain words + +[PMJAY](../glossary/pmjay.md) pays only for care given to a beneficiary who was physically present. Your hospital proves presence by authenticating the beneficiary against their [ABHA](../../shared/glossary/abha.md), with a fingerprint or iris scan. A success returns a user token that is valid for 30 minutes. + +That token goes with the eligibility check, the pre-authorisation and the claim. These are [ABDM](../../shared/glossary/abdm.md) calls made for the PMJAY payer, not NHCX messages. They are not sealed, and nothing arrives by callback. + +## Before you start + +- The beneficiary's ABHA is linked to their PMJAY card. If it is not, this flow does not apply: follow the PMJAY-approved [KYC](../../shared/glossary/kyc.md) protocols instead. +- A registered fingerprint or iris device, with its [RD service](../glossary/rd-service.md) running on the machine. +- A session token, sent as `Authorization: Bearer `. +- The participant code of the scheme payer the authentication is for, sent in the `payerid` header. +- The beneficiary at the desk, and the stage: `Preauth` at admission, `Discharge` at discharge and at every visit of a cyclic procedure. + +## What happens + +```mermaid +sequenceDiagram + participant B as Beneficiary + participant Dev as Scanner and RD service + participant You as Your HMIS + participant ABHA as ABHA biometric service + participant NHCX as NHCX exchange + You->>ABHA: POST /hcx/abha/biometric/auth/init + ABHA-->>You: txnId + You->>Dev: start a capture + B->>Dev: finger on the scanner, or eyes to the iris camera + Dev-->>You: PID block + You->>ABHA: POST /hcx/abha/biometric/auth/verify with txnId and PID block + ABHA-->>You: authResult success, token, refreshToken and accounts + You->>NHCX: POST /v1/preauth/submit with the user token + opt The user token lapses during the case + You->>ABHA: GET /hcx/abha/biometric/auth/refresh/token + ABHA-->>You: new token and new refreshToken + end +``` + +The sandbox host is `https://apisbx.abdm.gov.in`. Every call answers in its own response. + +### 1. Start the authentication + +`POST /hcx/abha/biometric/auth/init` with these headers: + +| Header | Value | +|---|---| +| `accept` | `*/*` | +| `Content-Type` | `application/json` | +| `Authorization` | `Bearer ` | +| `process` | `Preauth` or `Discharge`, one value | +| `payerid` | `` | + +For a fingerprint, the body is: + +```json +{ + "scope": ["abha-login", "aadhaar-bio-verify"], + "loginHint": "abha-number", + "loginId": "", + "otpSystem": "aadhaar", + "authMode": "FINGERPRINT" +} +``` + +For an iris, `scope` is `["abha-login", "aadhaar-iris-verify"]` and `authMode` is `IRIS`. The answer carries `txnId`. + +### 2. Capture + +Your HMIS asks the RD service for a capture. The beneficiary places a finger on the scanner, or looks into the iris camera. The RD service returns an encrypted [PID block](../glossary/pid-block.md) as a base64 string. + +### 3. Verify + +`POST /hcx/abha/biometric/auth/verify`, with the same five headers: + +```json +{ + "scope": ["abha-login", "aadhaar-bio-verify"], + "authData": { + "authMethods": ["bio"], + "bio": { + "txnId": "", + "fingerPrintAuthPid": "" + } + }, + "authMode": "FINGERPRINT" +} +``` + +For an iris, `authMethods` is `["iris"]`, and an `iris` object carries `txnId` and `irisAuthPid`. Use the iris `scope` and `authMode` from step 1. + +The answer carries `txnId`, `authResult`, `message`, `token`, `refreshToken`, `expiresIn` `1800`, `refreshExpiresIn` `1296000` and an `accounts` array. Each account carries `ABHANumber`, `preferredAbhaAddress`, `name`, `gender`, `dob`, `verifiedStatus`, `verificationType`, `status` and `profilePhoto`. + +### 4. Use the user token + +Pass the user `token` as a header parameter on the PMJAY claim events that follow. These are the coverage eligibility check, the pre-authorisation and, after discharge authentication, the claim. The payer validates it before accepting the request. + +The token lasts 30 minutes. Submit within that time, or refresh it. + +### 5. Refresh + +`GET /hcx/abha/biometric/auth/refresh/token` with `R-token: Bearer `, plus `Authorization`, `payerid` and `process`. The answer carries a new user token and a new refresh token. The new refresh token lasts 15 days from that moment. + +Refresh at least once every 10 days and store the new refresh token. That keeps the chain alive for as long as the case needs. If the refresh token lapses, authenticate again with a live capture. + +A refresh never replaces a live capture on a cyclic procedure. Every visit needs a capture with `process` `Discharge`. A refresh token from the last cycle serves only at the final claim, and a new capture is preferred there too. + +### 6. At discharge + +Authenticate again with `process` `Discharge`, and attach the new token to the claim. The method may differ from admission: a pre-authorisation by fingerprint can end in a claim by iris or face. + +## How you know it worked + +The verify call returns `authResult` `success`, a `token` with `expiresIn` `1800`, and a `refreshToken` with `refreshExpiresIn` `1296000`. `accounts` holds the beneficiary's ABHA number with `status` `ACTIVE`. The payer then accepts the pre-authorisation without [PAYR-1272](../errors/payr-1272.md). + +```observation schema=exit-condition +channel: synchronous +call: POST /hcx/abha/biometric/auth/verify +match: + authResult: success + expiresIn: 1800 + accounts[0].ABHANumber: + accounts[0].status: ACTIVE +``` + +## When it goes wrong + +- **The device fails with `K-547`.** Build the `wadh` value with `lr` set to `'Y'`. Keep `ra` as the device type (`'F'` for fingerprint), `rc` `'Y'`, `de` `'N'` and `pfr` `'N'`: + + ```javascript + text = '2.5' + ra + rc + lr + de + pfr; + wadh = Base64.stringify(sha256(text)); + ``` + +- **The payer rejects the user token.** It expired after 30 minutes, or belongs to another beneficiary. Authenticate again, or refresh. See [PAYR-1272](../errors/payr-1272.md), and [PAYR-1366](../errors/payr-1366.md) at discharge. +- **The payer says the consent questionnaire is missing.** You sent no biometric token and no Authentication Consent Questionnaire. See [PAYR-1256](../errors/payr-1256.md) at pre-authorisation and [PAYR-1363](../errors/payr-1363.md) at the claim. +- **The beneficiary cannot give a biometric.** Obtain the Aadhaar exemption consent document, signed by the patient and a hospital representative. Store it digitally and link it to the beneficiary record. Answer the plan's Authentication Consent Questionnaire. This route is closed for cyclic procedures, which need a live biometric. +- **Verify fails.** The PID block sits under the wrong key for the modality. Fingerprint goes in `bio.fingerPrintAuthPid`, iris in `iris.irisAuthPid`. +- **A cycle goes unpaid.** It was covered by a refresh token instead of a live capture. The payer pays only for captured cycles. diff --git a/catalogue/nhcx/flows/claim-query-response.md b/catalogue/nhcx/flows/claim-query-response.md new file mode 100644 index 000000000..59025a31d --- /dev/null +++ b/catalogue/nhcx/flows/claim-query-response.md @@ -0,0 +1,182 @@ +--- +id: nhcx.flow.claim-query-response +type: flow +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Answer a payer query on a claim +summary: >- + Send the payer the documents or clarification it asked for on a claim, so that + it can finish adjudicating. +sources: +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. 9.5 ClaimResponse outcomes; 9.5.4 Queried Response; query trail mapping table. +- url: https://hcxsbx.abdm.gov.in/images/c42ad170f37c987ed173.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx + hash: sha256:f56dd156c232192296082f23b1561d0ff11fd40992e6675de41c5c991d579e6d + fetched: '2026-09-14' + note: Workflow Status Sheets(with Codes), row 12 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet1, Claim Request Queried and Claim Query Response Submitted. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. pages 36-37, claim query updation. +- url: https://hcxsbx.abdm.gov.in/images/53347f5988b0ce5396f1.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_APIs to be called based on scenario.xlsx + hash: sha256:f92a30673d65dd2cc3cf09e2087c624f23f781dc4ca6b5cd8ec1825e224ac108 + fetched: '2026-09-14' + note: NHCX_APIs to be called based on scenario, row 26 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sheet Scenarios, row 11. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Communication. +- url: https://hcxsbx.abdm.gov.in/images/819467ec15aff13cc2a8.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Dummy Payer Implementation.pdf + hash: sha256:97335ebc4cd32c86e0c34328b2f4c526420b32a7a009208364043d6334e9e757 + fetched: '2026-09-14' + note: NHCX Dummy Payer Implementation, row 19 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Claim steps 2-5; Communication. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.claim-submit + - nhcx.endpoint.claim-on-submit + - nhcx.endpoint.communication-request + - nhcx.endpoint.communication-on-request + callbacks: + - nhcx.callback.claim-on-submit + - nhcx.callback.claim-submit + - nhcx.callback.communication-request + - nhcx.callback.communication-on-request + fhir: + - nhcx.fhir.claim-response + - nhcx.fhir.task + tests: + - nhcx.test.tc-cl-02 + - nhcx.test.provider-uc-08 + - nhcx.test.payer-uc-10 + flows: + - nhcx.flow.claim-submit + - nhcx.flow.preauth-query-response + - nhcx.flow.status-check + concepts: + - nhcx.concept.queries-and-communication + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1011 + - nhcx.error.payr-1001 + - nhcx.error.payr-1303 + - nhcx.error.payr-1304 + glossary: + - nhcx.glossary.claim + - nhcx.glossary.communication-request + - nhcx.glossary.payer + - nhcx.glossary.pmjay + sandbox: + - nhcx.sandbox.dummy-payer + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback +--- + +# Answer a payer query on a claim + +## In plain words + +A claim query means the [payer](../glossary/payer.md) cannot finish adjudicating your [claim](../glossary/claim.md) yet. It needs more documents or a clarification. The claim stays open, with its totals at zero, until you answer. + +The query reaches you by one of two routes. Where it arrives tells you how to answer. + +| The query arrives on | It looks like | You answer on | +|---|---|---| +| `/v1/claim/on_submit` | Workflow `27`. ClaimResponse `outcome` `partial`, adjudication reason `queried` | `/v1/claim/submit` with workflow `151` | +| `/v1/communication/request` | A Task with `code` `poll` carrying a [communication request](../glossary/communication-request.md) | `/v1/communication/on_request` | + +After your answer, the payer sends its adjudication on `/v1/claim/on_submit`. [Payer queries and the communication cycle](../concepts/queries-and-communication.md) explains both routes. + +## Before you start + +- You [submitted the claim](claim-submit.md), and kept its claim identifier and bundle. +- A query has arrived by one of the two routes above, and you answered its delivery with `202` within 30 seconds. +- You have collected the documents or the clarification the query asks for. +- In the sandbox, the [dummy payer](../sandbox/dummy-payer.md) raises a query when you drive it with the action `Query`, and uses the communication route. + +## What happens + +```mermaid +sequenceDiagram + participant P as Provider (your system) + participant N as NHCX + participant Y as Payer + alt query as a ClaimResponse + Y->>N: POST /v1/claim/on_submit (workflow 27) + N->>P: POST /v1/claim/on_submit + P-->>N: HTTP 202 Accepted, within 30 seconds + P->>N: POST /v1/claim/submit (workflow 151) + Note right of P: same Claim identifier, added documents, new correlation id + N-->>P: HTTP 202 Accepted + N->>Y: POST /v1/claim/submit + Y-->>N: HTTP 202 Accepted + else query as a communication request + Y->>N: POST /v1/communication/request + N-->>Y: HTTP 202 Accepted + N->>P: POST /v1/communication/request + P-->>N: HTTP 202 Accepted, within 30 seconds + P->>N: POST /v1/communication/on_request + Note right of P: Communication with the documents, same correlation id + N-->>P: HTTP 202 Accepted + N->>Y: POST /v1/communication/on_request + Y-->>N: HTTP 202 Accepted + end + Note over Y: payer re-adjudicates + Y->>N: POST /v1/claim/on_submit (decision) + N->>P: POST /v1/claim/on_submit + P-->>N: HTTP 202 Accepted +``` + +### The query arrives as a ClaimResponse + +1. Receive [POST /v1/claim/on_submit](../callbacks/claim-on-submit.md) with workflow `27`. Answer `202` within 30 seconds, then decrypt. +2. Read what the payer asked. For [PMJAY](../glossary/pmjay.md), `ClaimResponse.item[].adjudication[].reason.coding.display` carries a trail of entries in the form `USER~datetime~type~comment~trust`, separated by `|`. Parse it as plain text. The comment is the question. +3. Add the requested documents to `supportingInfo` in the same Claim. Keep `Claim.identifier` and `use` `claim`. +4. Set `x-hcx-workflow_id` to `151`, Claim Query Response Submitted. Set `x-hcx-status` to `request.initiated`. +5. Start a new correlation: set `x-hcx-correlation_id` to the value of this call's `x-hcx-api_call_id`. The claim identifier ties the answer to the case. +6. Call [POST /v1/claim/submit](../endpoints/claim-submit.md). NHCX answers `202 Accepted`. + +### The query arrives as a communication request + +1. Receive [POST /v1/communication/request](../callbacks/communication-request.md). Answer `202` within 30 seconds, then decrypt. +2. Read `Task.reasonCode` and the communication resource. They say what the payer needs. +3. Build the answer as a Task bundle whose Task carries a `Communication`. Put the documents in `Communication.payload` as `contentAttachment`. See [the Task bundle](../fhir/task.md). +4. Set `x-hcx-status` to `response.complete`. Set `x-hcx-correlation_id` to the correlation id of the communication request. Use a fresh `x-hcx-api_call_id`. +5. Address it to the sender of the communication request. Call [POST /v1/communication/on_request](../endpoints/communication-on-request.md). NHCX answers `202 Accepted`. + +### Either route: wait for the adjudication + +The payer re-adjudicates and answers on `/v1/claim/on_submit`. Read it as in [submit a claim](claim-submit.md), using `outcome` and the adjudication reason together. + +## How you know it worked + +The query is resolved when all of these hold: + +- NHCX accepted your answer with `202`: on `/v1/claim/submit` with workflow `151`, or on `/v1/communication/on_request`. +- You then received `POST /v1/claim/on_submit` for this case, and its `payload` decrypts. +- The ClaimResponse has `outcome` `complete` with adjudication reason `approved` or `cancelled`, or `outcome` `partial` with reason `approved`. + +`outcome` `partial` with reason `queried` means the payer asks again. Repeat this flow. + +## When it goes wrong + +The payer finds no queried claim. [PAYR-1304](../errors/payr-1304.md) means no queried claim exists for the case number. [PAYR-1303](../errors/payr-1303.md) means no active claim exists for it. Check that you kept the original claim identifier. + +NHCX rejects your query update as a duplicate. [NHCX-1006](../errors/nhcx-1006.md) means you reused an earlier correlation id on `/v1/claim/submit`. Start a new correlation. + +NHCX rejects your communication answer. [NHCX-1010](../errors/nhcx-1010.md) means no request exists with the correlation id you set. Copy it from the communication request exactly. [NHCX-1011](../errors/nhcx-1011.md) means the `x-hcx-status` value is not valid. + +The payer cannot open your answer. A `ProtocolResponse` with [PAYR-1001](../errors/payr-1001.md) means it could not decrypt. Fetch its certificate again and reseal. + +No adjudication follows your answer. [Check the status](status-check.md) of your answer's correlation id. See [accepted, then no callback](../troubleshooting/accepted-then-no-callback.md). diff --git a/catalogue/nhcx/flows/claim-reprocess.md b/catalogue/nhcx/flows/claim-reprocess.md new file mode 100644 index 000000000..55559ff72 --- /dev/null +++ b/catalogue/nhcx/flows/claim-reprocess.md @@ -0,0 +1,161 @@ +--- +id: nhcx.flow.claim-reprocess +type: flow +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Ask the payer to reprocess a claim +summary: >- + Contest a rejected claim, or recover the shortfall on a partly paid one, by sending + the payer a reprocess task with supporting evidence. +sources: +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. FAQ 22 Erroneous Claim, FAQ 23 Claim Reprocess and field comparison; FAQ 15. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Communication reasons (claimArbitration); reprocess workflow codes; reprocess Task table. +- url: https://hcxsbx.abdm.gov.in/taskhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/taskhcxservice.json + hash: sha256:0418eca6478dece4d72c5a49a6547d50772511f7ffaf32f901f245591ba84656 + fetched: '2026-09-14' + note: 'API specification: taskhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths /v1/task/submit and /v1/task/on_submit.' +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.task-submit + - nhcx.endpoint.task-on-submit + - nhcx.endpoint.communication-request + - nhcx.endpoint.communication-on-request + callbacks: + - nhcx.callback.task-submit + - nhcx.callback.task-on-submit + - nhcx.callback.communication-request + - nhcx.callback.error + fhir: + - nhcx.fhir.claim-response + - nhcx.fhir.task + concepts: + - nhcx.concept.claim-cycle + - nhcx.concept.workflow-codes + tests: + - nhcx.test.provider-uc-12 + - nhcx.test.payer-uc-14 + - nhcx.test.tc-cl-03 + flows: + - nhcx.flow.claim-submit + - nhcx.flow.claim-query-response + - nhcx.flow.payment-notice + - nhcx.flow.send-a-sealed-request + - nhcx.flow.status-check + errors: + - nhcx.error.err-pyr-clm-007 + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1001 + glossary: + - nhcx.glossary.communication-request + - nhcx.glossary.crc + - nhcx.glossary.pmjay + - nhcx.glossary.reprocess +--- + +# Ask the payer to reprocess a claim + +## In plain words + +[Reprocessing](../glossary/reprocess.md) asks the payer to look at an adjudicated claim again. You send it as a FHIR Task on `/v1/task/submit`, with evidence. The payer re-adjudicates and answers on `/v1/task/on_submit`. + +There are two cases. Both use workflow `36` and Task code `reprocess`. + +| | Rejected claim | Partly paid claim, the erroneous claim | +|---|---|---| +| When you may send it | As soon as the rejection arrives | Only after the payment settles, workflow `33`, and you acknowledged it, workflow `17` | +| Reason code | `claimrejected` | `partialpayment` | +| Amount | Not sent. The full claim is implied | The shortfall, never more than the claimed amount minus the approved amount | +| Supporting document | Mandatory | Mandatory | +| How often, under [PMJAY](../glossary/pmjay.md) | Once per claim | Once per claim | + +A reprocess request goes to the [CRC](../glossary/crc.md). Its decision is final. No erroneous claim can follow a CRC decision. + +## Before you start + +- The claim was adjudicated. It was rejected, `outcome` `complete` with reason `cancelled`, or it was paid in part. +- For a partly paid claim, you received the payment notice with workflow `33` and sent your acknowledgement with workflow `17`. See [receive a payment notice](payment-notice.md). +- You have the claim number. It is the preauthorisation number your hospital generated, carried forward unchanged. +- You have the document that justifies the request. +- No reprocess or erroneous claim was raised for this claim before. + +## What happens + +```mermaid +sequenceDiagram + participant P as Provider (your system) + participant N as NHCX + participant Y as Payer + P->>N: POST /v1/task/submit (workflow 36) + Note right of P: Task code reprocess, reason claimrejected or partialpayment + N-->>P: HTTP 202 Accepted + N->>Y: POST /v1/task/submit + Y-->>N: HTTP 202 Accepted + opt payer acknowledges the request + Y->>N: POST /v1/communication/request (reason claimArbitration) + N->>P: POST /v1/communication/request + P-->>N: HTTP 202 Accepted + end + Note over Y: review committee re-adjudicates + Y->>N: POST /v1/task/on_submit + N-->>Y: HTTP 202 Accepted + N->>P: POST /v1/task/on_submit + P-->>N: HTTP 202 Accepted, within 30 seconds + alt workflow 252 + Note left of P: approved, payment notices follow + else workflow 254 + Note left of P: queried + else workflow 253 + Note left of P: rejected, the decision stands + end +``` + +1. Build a Task bundle, as in [the Task bundle](../fhir/task.md). Set `status` to `requested`, `intent` to `order`, and `code` to `reprocess`. +2. Set `reasonCode` to `claimrejected` for a rejected claim, or `partialpayment` for a partly paid one. Add the claim number as an input, and point `basedOn` at the original claim. +3. Attach the supporting document as a `valueAttachment`. For a partly paid claim, send the shortfall amount. +4. Seal and set the headers, as in [send a sealed request](send-a-sealed-request.md). Set `x-hcx-workflow_id` to `36` and `x-hcx-status` to `request.initiated`. +5. Start a new correlation. Set `x-hcx-correlation_id` to the value of this call's `x-hcx-api_call_id`. +6. Call [POST /v1/task/submit](../endpoints/task-submit.md). NHCX answers `202 Accepted`. It is not the decision. +7. The payer may confirm it received the request with a [communication request](../glossary/communication-request.md), reason `claimArbitration`. Answer its delivery with `202`, then acknowledge it on [/v1/communication/on_request](../endpoints/communication-on-request.md). +8. Receive [POST /v1/task/on_submit](../callbacks/task-on-submit.md). Answer `202 Accepted` within 30 seconds, then process. +9. Read `type`. `ProtocolResponse` means the payer could not process the request. Otherwise decrypt `payload` with your private key. +10. Find the Task, with `status` `completed`. Follow `Task.output` to the ClaimResponse in the same bundle. Read it as you read a [claim decision](claim-submit.md). + +| `x-hcx-workflow_id` | Meaning | What to do | +|---|---|---| +| `252` | Reprocess approved | Wait for [payment notices](payment-notice.md), workflows `30`, `31` and `33` | +| `254` | Reprocess queried | Send the information the payer asks for | +| `253` | Reprocess rejected | The original decision stands. The case is closed | + +## How you know it worked + +The reprocess request is decided when all of these hold: + +- You received `POST /v1/task/on_submit` whose `x-hcx-correlation_id` equals the one you sent. +- Its `payload` decrypts, and the Task in it has `status` `completed`. +- `Task.output` resolves to a ClaimResponse inside the same bundle. +- `x-hcx-workflow_id` is `252`, approved, or `253`, rejected. +- You recorded the decision against the claim. After `252`, you watch for the payment notice. + +## When it goes wrong + +The payer cannot find the claim. [ERR-PYR-CLM-007](../errors/err-pyr-clm-007.md) means no preauthorisation or claim record exists for the case number. Send the preauthorisation number your hospital generated as the claim number. + +The request is refused as too early or repeated. An erroneous claim sent before workflow `33` arrives is out of order. A second request on the same claim exceeds the once-per-claim limit under PMJAY. Neither can be fixed by resending. + +NHCX rejects the request as a duplicate. [NHCX-1006](../errors/nhcx-1006.md) means you reused a correlation id. Start a new correlation. + +The callback is a `ProtocolResponse`. [PAYR-1001](../errors/payr-1001.md) means the payer could not decrypt your request. Fetch its certificate again and reseal. + +No decision arrives. Reprocess has no fixed turnaround time. [Check the request's status](status-check.md) to confirm the payer holds it. An undeliverable request comes back on [/v1/error](../callbacks/error.md). diff --git a/catalogue/nhcx/flows/claim-search.md b/catalogue/nhcx/flows/claim-search.md new file mode 100644 index 000000000..3ab1562d3 --- /dev/null +++ b/catalogue/nhcx/flows/claim-search.md @@ -0,0 +1,123 @@ +--- +id: nhcx.flow.claim-search +type: flow +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Search for claims +summary: >- + Ask a payer for the claim responses that match a claim number, policy, product + or date range. +sources: +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Search. +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use case 10, Claim Search. +- url: https://hcxsbx.abdm.gov.in/searchhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/searchhcxservice.json + hash: sha256:21749dd2ba84a19c5523772da359d76293493d44b48651f1af2e6042d78fa296 + fetched: '2026-09-14' + note: 'API specification: searchhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths /v1/search/submit and /v1/search/on_submit.' +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.search-submit + - nhcx.endpoint.search-on-submit + callbacks: + - nhcx.callback.search-submit + - nhcx.callback.search-on-submit + - nhcx.callback.error + fhir: + - nhcx.fhir.claim-response + - nhcx.fhir.task + concepts: + - nhcx.concept.four-message-legs + - nhcx.concept.message-identifiers + - nhcx.concept.session-token + tests: + - nhcx.test.provider-uc-10 + - nhcx.test.payer-uc-12 + flows: + - nhcx.flow.status-check + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.send-a-sealed-request + errors: + - nhcx.error.nhcx-1003 + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1001 + glossary: + - nhcx.glossary.payer + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback +--- + +# Search for claims + +## In plain words + +A claim search asks a [payer](../glossary/payer.md) for the claim responses that match your criteria. You can search by claim number, policy number, product number and a date range. Providers use it, and so do regulators. + +You send the criteria in a FHIR Task on `/v1/search/submit`. The payer answers on `/v1/search/on_submit` with a Task whose outputs point to the matching ClaimResponse resources. + +Search only reads. It changes nothing about a claim. To find where a request of yours stands in the exchange, use a [status check](status-check.md) instead. + +## Before you start + +- You are a registered participant with a valid [session token](../concepts/session-token.md) and a callback endpoint that answers within 30 seconds. +- You know the payer to search, and hold its encryption certificate. +- You have at least one criterion: a claim number, a policy number, a product number, or a from and to date. + +## What happens + +```mermaid +sequenceDiagram + participant P as Provider or regulator (your system) + participant N as NHCX + participant Y as Payer + P->>N: POST /v1/search/submit + Note right of P: sealed Task bundle with the search inputs + N-->>P: HTTP 202 Accepted + N->>Y: POST /v1/search/submit + Y-->>N: HTTP 202 Accepted + Note over Y: payer finds the matching claim responses + Y->>N: POST /v1/search/on_submit + N-->>Y: HTTP 202 Accepted + N->>P: POST /v1/search/on_submit + P-->>N: HTTP 202 Accepted, within 30 seconds + Note left of P: follow Task.output to each ClaimResponse +``` + +1. Build a Task bundle with `status` `requested`, as in [the Task bundle](../fhir/task.md). It names the search Task code. +2. Add one Task input per criterion. The input types are `ClaimNumber`, `PolicyNumber`, `ProductNumber`, `FromDate` and `ToDate`. +3. Seal and set the headers, as in [send a sealed request](send-a-sealed-request.md). Set `x-hcx-status` to `request.initiated`. Set `x-hcx-correlation_id` to the value of this call's `x-hcx-api_call_id`. +4. Call [POST /v1/search/submit](../endpoints/search-submit.md). NHCX answers `202 Accepted`. The results are not in it. +5. Receive [POST /v1/search/on_submit](../callbacks/search-on-submit.md). Answer `202 Accepted` within 30 seconds, then process. +6. Read `type`. `ProtocolResponse` means the payer could not process the search. Otherwise decrypt `payload` with your private key. +7. Find the Task. Its `status` is `completed`. Follow each `Task.output` reference to a [ClaimResponse](../fhir/claim-response.md) in the same bundle. +8. Read `x-hcx-status`. `response.partial` means more results may follow on the same correlation id. `response.complete` closes the search. + +## How you know it worked + +The search is finished when all of these hold: + +- You received `POST /v1/search/on_submit` whose `x-hcx-correlation_id` equals the one you sent. +- Its `type` is not `ProtocolResponse`, and `payload` decrypts with your private key. +- The Task in it has `status` `completed`, and each `Task.output` resolves to a ClaimResponse in the bundle. +- The last callback for the search carried `x-hcx-status` `response.complete`. + +## When it goes wrong + +The 202 arrives and no results follow. [Check the request's status](status-check.md). An undeliverable request comes back on [/v1/error](../callbacks/error.md). See [accepted, then no callback](../troubleshooting/accepted-then-no-callback.md). + +NHCX rejects the call. [NHCX-1003](../errors/nhcx-1003.md) means the recipient code is not registered. [NHCX-1006](../errors/nhcx-1006.md) means the correlation id was used before. Start a new correlation for every search. + +The callback is a `ProtocolResponse`. [PAYR-1001](../errors/payr-1001.md) means the payer could not decrypt your request. Fetch its certificate again and reseal. + +The results do not match the claim you meant. Check the input types and values. Values are case-sensitive and must match exactly, with no stray spaces. diff --git a/catalogue/nhcx/flows/claim-submit.md b/catalogue/nhcx/flows/claim-submit.md new file mode 100644 index 000000000..5d8f82098 --- /dev/null +++ b/catalogue/nhcx/flows/claim-submit.md @@ -0,0 +1,177 @@ +--- +id: nhcx.flow.claim-submit +type: flow +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Submit a claim after discharge +summary: >- + After the patient is discharged, send the final bill and records for the approved + preauthorisation, then read the payer's adjudication. +sources: +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: 'NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 9 Claim: request tables, 9.5.1 outcome summary; workflow code table.' +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. page 35, Claim functional points to note. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. FAQ 25 discharge, questions 3 and 7. +- url: https://hcxsbx.abdm.gov.in/images/c42ad170f37c987ed173.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx + hash: sha256:f56dd156c232192296082f23b1561d0ff11fd40992e6675de41c5c991d579e6d + fetched: '2026-09-14' + note: Workflow Status Sheets(with Codes), row 12 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet1. +- url: https://hcxsbx.abdm.gov.in/images/53347f5988b0ce5396f1.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_APIs to be called based on scenario.xlsx + hash: sha256:f92a30673d65dd2cc3cf09e2087c624f23f781dc4ca6b5cd8ec1825e224ac108 + fetched: '2026-09-14' + note: NHCX_APIs to be called based on scenario, row 26 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sheet Scenarios, row 10. +- url: https://hcxsbx.abdm.gov.in/claimhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/claimhcxservice.json + hash: sha256:488eea449c6ee45dc324f4f7c095a862c7d50d0e238075846122b51b2bab4878 + fetched: '2026-09-14' + note: 'API specification: claimhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths /v1/claim/submit and /v1/claim/on_submit.' +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.claim-submit + - nhcx.endpoint.claim-on-submit + callbacks: + - nhcx.callback.claim-submit + - nhcx.callback.claim-on-submit + - nhcx.callback.error + fhir: + - nhcx.fhir.collection-bundle + - nhcx.fhir.validation + - nhcx.fhir.claim-request + - nhcx.fhir.claim-response + concepts: + - nhcx.concept.claim-cycle + - nhcx.concept.status-lifecycle + - nhcx.concept.four-message-legs + tests: + - nhcx.test.provider-uc-09 + - nhcx.test.payer-uc-11 + - nhcx.test.tc-cl-01 + flows: + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.payer-process-a-request + - nhcx.flow.biometric-face + - nhcx.flow.biometric-fingerprint-iris + - nhcx.flow.claim-query-response + - nhcx.flow.claim-reprocess + - nhcx.flow.payment-notice + - nhcx.flow.preauth-submit + - nhcx.flow.send-a-sealed-request + - nhcx.flow.status-check + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1001 + - nhcx.error.payr-1301 + - nhcx.error.payr-1302 + - nhcx.error.payr-1363 + glossary: + - nhcx.glossary.claim + - nhcx.glossary.payer + - nhcx.glossary.pmjay +--- + +# Submit a claim after discharge + +## In plain words + +A [claim](../glossary/claim.md) asks the payer to pay for treatment already delivered. It uses the same Claim structure as the [preauthorisation](preauth-submit.md), with `Claim.use` set to `claim`. It carries final amounts and the full record: discharge summary, operative notes, diagnostics and the itemised bill. + +For [PMJAY](../glossary/pmjay.md) there is no separate discharge submission. Discharge details travel inside the claim, with workflow `15`. + +The [payer](../glossary/payer.md) may answer more than once. `x-hcx-status` `response.partial` means the claim is still open. `response.complete` closes it, and no further submissions are accepted against that claim identifier. + +## Before you start + +- The case holds an approved preauthorisation with a `preAuthRef`. +- No claim has been raised for the case yet. +- The amount you will claim is no more than the preauthorisation's approved amount. +- You authenticated the beneficiary at discharge by [fingerprint or iris](biometric-fingerprint-iris.md) or [face](biometric-face.md). Where that is not possible, you have the Authentication Consent Questionnaire response to attach. +- The discharge documents are ready: discharge summary, operative notes, diagnostic reports and the final itemised bill. +- Your session token, callback endpoint and the payer's certificate are in place, as in [send a sealed request](send-a-sealed-request.md). + +## What happens + +```mermaid +sequenceDiagram + participant P as Provider (your system) + participant N as NHCX + participant Y as Payer + P->>N: POST /v1/claim/submit (workflow 15) + N-->>P: HTTP 202 Accepted + N->>Y: POST /v1/claim/submit + Y-->>N: HTTP 202 Accepted + opt interim updates + Y->>N: POST /v1/claim/on_submit (workflow 25, 28 or 29, response.partial) + N->>P: POST /v1/claim/on_submit + P-->>N: HTTP 202 Accepted + end + Note over Y: payer adjudicates the claim + Y->>N: POST /v1/claim/on_submit (decision) + N-->>Y: HTTP 202 Accepted + N->>P: POST /v1/claim/on_submit + P-->>N: HTTP 202 Accepted, within 30 seconds + alt complete and approved (workflow 26) + Note left of P: approved, wait for the payment notice + else partial and queried (workflow 27) + Note left of P: queried, answer the query + else complete and cancelled + Note left of P: rejected, consider reprocess + end +``` + +1. Start from the preauthorisation bundle. Change `Claim.use` to `claim`. Keep `Claim.identifier`, and reference the approved `preAuthRef`. +2. Replace the estimates with final amounts. Keep the diagnoses and procedures unless the treatment changed. Add the discharge documents to `supportingInfo`. See [the claim request bundle](../fhir/claim-request.md). +3. For PMJAY, record the discharge in `supportingInfo` with category `DIS`. Its code is `DTH`, `DTM`, `LAMA` or `DAMA`, and its value is `Before Surgery` or `After Surgery`. +4. Seal and set the headers, as in [send a sealed request](send-a-sealed-request.md). Set `x-hcx-workflow_id` to `15` and `x-hcx-status` to `request.initiated`. Send `x-hcx-ben-abha-id`. +5. Start a new correlation. Set `x-hcx-correlation_id` to the value of this call's `x-hcx-api_call_id`. Store it against the case. +6. Call [POST /v1/claim/submit](../endpoints/claim-submit.md). NHCX answers `202 Accepted`. It is not the adjudication. +7. Wait. Interim callbacks may arrive on `/v1/claim/on_submit` with `x-hcx-status` `response.partial`: workflow `25` received, `28` in process, `29` forwarded. Answer each with `202` and keep waiting. +8. Receive the decision on [POST /v1/claim/on_submit](../callbacks/claim-on-submit.md). Answer `202 Accepted` within 30 seconds, then process. +9. Read `type`. `ProtocolResponse` means the payer could not process the claim. Otherwise decrypt `payload` and read the [ClaimResponse](../fhir/claim-response.md). +10. Read `ClaimResponse.outcome` and `adjudication[0].reason` together. Both an approval and a rejection carry `outcome` `complete`. + +| `outcome` | Adjudication reason | Meaning | What to do | +|---|---|---|---| +| `complete` | `approved` | Approved, workflow `26` | Wait for the [payment notice](payment-notice.md) | +| `partial` | `approved` | Partly approved at a reduced amount | Read `processNote` for the reduction. Wait for payment | +| `partial` | `queried` | Queried, workflow `27`, totals `0` | [Answer the query](claim-query-response.md) | +| `complete` | `cancelled` | Rejected. The claim is closed | Decide whether to [ask for reprocessing](claim-reprocess.md) | + +## How you know it worked + +The claim is adjudicated when all of these hold: + +- You received `POST /v1/claim/on_submit` whose `x-hcx-correlation_id` equals the one you sent. +- Its `type` is not `ProtocolResponse`, and `payload` decrypts with your private key. +- The ClaimResponse has `use` `claim`, `outcome` `complete`, adjudication reason `approved`, and a `benefit` total above zero. +- `x-hcx-workflow_id` is `26` and `x-hcx-status` is `response.complete`. +- You stored the approved amount against the case, ready to reconcile the payment notice. + +A rejection, `complete` with reason `cancelled`, also ends this flow. A query hands over to the query flow. + +## When it goes wrong + +The payer finds no approved preauthorisation. [PAYR-1302](../errors/payr-1302.md) means no approved record exists for the case number. Check that the claim carries the preauthorisation's claim identifier. + +A claim already exists. [PAYR-1301](../errors/payr-1301.md) means the case number already has a claim. To add documents to a queried claim, [answer the query](claim-query-response.md) instead. + +Authentication is missing at discharge. [PAYR-1363](../errors/payr-1363.md) means you sent neither biometric authentication nor the consent questionnaire response. + +The 202 arrives and no decision follows. Interim `response.partial` callbacks mean the payer is still working. For long waits, [check the request's status](status-check.md). An undeliverable request comes back on [/v1/error](../callbacks/error.md). + +NHCX or the payer rejects the envelope. [NHCX-1006](../errors/nhcx-1006.md) means the correlation id was used before. A `ProtocolResponse` with [PAYR-1001](../errors/payr-1001.md) means the payer could not decrypt your request. diff --git a/catalogue/nhcx/flows/coverage-eligibility-check.md b/catalogue/nhcx/flows/coverage-eligibility-check.md new file mode 100644 index 000000000..a62d78872 --- /dev/null +++ b/catalogue/nhcx/flows/coverage-eligibility-check.md @@ -0,0 +1,181 @@ +--- +id: nhcx.flow.coverage-eligibility-check +type: flow +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Check coverage eligibility +summary: >- + Ask the patient's payer whether the policy is in force, how much balance is left, + and what a planned treatment needs before it can be approved. +sources: +- url: https://hcxsbx.abdm.gov.in/images/cfcbe62e8378d4f48ee6.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Coverage Eligibility.pdf + hash: sha256:69dd680ddac44231a97276a1d735e45777d8e43b5563b7248fd367a838d9744f + fetched: '2026-09-14' + note: Coverage Eligibility, listed on https://hcxsbx.abdm.gov.in/#/documents, not named in the NHCX document sheet. Coverage Eligibility Check request and response. +- url: https://hcxsbx.abdm.gov.in/images/13093b5f9b88fe826123.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Insurance Plan IG.docx + hash: sha256:e9c6c82b6d67fd8476d6d19a5961419beb04e3c0613533453ed1e16e2a569cc1 + fetched: '2026-09-14' + note: Insurance Plan IG, row 25 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. CoverageEligibility purposes; flattened request and response tables. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. 7.3 request guidance; response item elements; discovery note. +- url: https://hcxsbx.abdm.gov.in/images/53347f5988b0ce5396f1.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_APIs to be called based on scenario.xlsx + hash: sha256:f92a30673d65dd2cc3cf09e2087c624f23f781dc4ca6b5cd8ec1825e224ac108 + fetched: '2026-09-14' + note: NHCX_APIs to be called based on scenario, row 26 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sheet Scenarios, rows 3 to 5. +- url: https://hcxsbx.abdm.gov.in/coverageeligibilityhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/coverageeligibilityhcxservice.json + hash: sha256:1723a4020b1b33d0bc1d7175609f0d05e6a6a78e8b4c52041222396639ceb52c + fetched: '2026-09-14' + note: 'API specification: coverageeligibilityhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths /v1/coverageeligibility/check and /on_check.' +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.coverageeligibility-on-check + callbacks: + - nhcx.callback.coverageeligibility-check + - nhcx.callback.coverageeligibility-on-check + - nhcx.callback.error + fhir: + - nhcx.fhir.collection-bundle + - nhcx.fhir.validation + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.coverage-eligibility-response + concepts: + - nhcx.concept.four-message-legs + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.message-identifiers + - nhcx.concept.protocol-headers + - nhcx.concept.coverage-eligibility-purposes + - nhcx.concept.session-token + tests: + - nhcx.test.provider-uc-05 + - nhcx.test.payer-uc-07 + - nhcx.test.tc-ce-01 + - nhcx.test.tc-abha-01 + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.pmjay-patient-to-cashless + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.payer-process-a-request + - nhcx.flow.insurance-plan-request + - nhcx.flow.sandbox-onboarding + - nhcx.flow.send-a-sealed-request + - nhcx.flow.status-check + decisions: + - nhcx.decision.eligibility-purpose + errors: + - nhcx.error.nhcx-1003 + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1018 + - nhcx.error.payr-1001 + - nhcx.error.payr-1004 + - nhcx.error.payr-1007 + - nhcx.error.payr-1032 + - nhcx.error.payr-1033 + - nhcx.error.payr-1116 + glossary: + - nhcx.glossary.jwe + - nhcx.glossary.participant-code + - nhcx.glossary.payer + - nhcx.glossary.pmjay + - shared.glossary.abha-number + - shared.glossary.nhcx + sandbox: + - nhcx.sandbox.callback-url-requirements + - nhcx.sandbox.dummy-payer + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback + - nhcx.troubleshooting.recipient-cannot-decrypt +--- + +# Check coverage eligibility + +## In plain words + +A coverage eligibility check asks a payer about one patient before treatment. Is the policy in force? How much balance is left? Does the planned treatment need approval, and with which documents? + +Your system sends the question to the [NHCX](../../shared/glossary/nhcx.md) exchange, sealed so that only the [payer](../glossary/payer.md) can read it. The exchange forwards it. The payer's answer arrives later, as a callback to the endpoint you registered. + +Every request names a purpose. The purpose decides what the payer returns. + +| Purpose | What the payer returns | +|---|---| +| `validation` | Whether the policy is in force, the amount already used and the balance left | +| `benefits` | The benefits the policy covers | +| `auth-requirements` | For each treatment you name: whether it is covered at your hospital, the covered amount, and the documents and questionnaires preauthorisation needs | +| `discovery` | The active policy code, when the policy lookup finds nothing for the patient | + +[Which coverage eligibility purpose to send](../decisions/eligibility-purpose.md) explains when each one fits. [The three coverage eligibility purposes](../concepts/coverage-eligibility-purposes.md) explains the model. + +## Before you start + +- Your hospital is an active participant with a [participant code](../glossary/participant-code.md). [Sandbox onboarding](sandbox-onboarding.md) gets you there. +- You hold a valid [session token](../concepts/session-token.md). +- Your callback endpoint is registered and meets the [callback URL rules](../sandbox/callback-url-requirements.md). It answers every callback within 30 seconds. +- You know who adjudicates this patient's policy. The [policy lookup](../endpoints/participant-get-policies.md) returns a `payerid` and a `processingid`. Address the request to the `processingid`. +- You hold that participant's encryption certificate, fetched with [/fetch/certs](../endpoints/fetch-certs.md). +- You have the patient's [ABHA number](../../shared/glossary/abha-number.md). For [PMJAY](../glossary/pmjay.md) you also have the member ID. +- For `auth-requirements`, you know the package codes you plan to treat. The [insurance plan](insurance-plan-request.md) lists them. +- In the sandbox, address the request to the [dummy payer](../sandbox/dummy-payer.md). + +## What happens + +```mermaid +sequenceDiagram + participant P as Provider (your system) + participant N as NHCX + participant Y as Payer + P->>N: POST /v1/coverageeligibility/check + Note right of P: sealed CoverageEligibilityRequest bundle, x-hcx-status request.initiated + N-->>P: HTTP 202 Accepted + N->>Y: POST /v1/coverageeligibility/check + Y-->>N: HTTP 202 Accepted + Note over Y: payer checks the policy, the wallet and the named treatments + Y->>N: POST /v1/coverageeligibility/on_check + N-->>Y: HTTP 202 Accepted + N->>P: POST /v1/coverageeligibility/on_check + P-->>N: HTTP 202 Accepted, within 30 seconds + Note left of P: decrypt and read the CoverageEligibilityResponse +``` + +1. Build the [CoverageEligibilityRequest bundle](../fhir/coverage-eligibility-request.md). Include the patient, the active coverage, your hospital and the payer as organisations, and the person running the check as `enterer`. +2. Set `purpose`. For `auth-requirements`, add one `item` per package, with its category code, package code and quantity. +3. Seal the bundle as a [JWE](../glossary/jwe.md) and set the protected headers, as in [send a sealed request](send-a-sealed-request.md). Set `x-hcx-status` to `request.initiated` and send `x-hcx-ben-abha-id`. +4. Start a new correlation. Set `x-hcx-correlation_id` to the value of this call's `x-hcx-api_call_id`. +5. Call [POST /v1/coverageeligibility/check](../endpoints/coverageeligibility-check.md). NHCX answers `202 Accepted`. The envelope passed validation and is on its way to the payer. It is not the answer. +6. Wait for the callback. The payer answers once it has checked the policy. A payer may instead ask NHCX to forward the same request to another payer. +7. Receive [POST /v1/coverageeligibility/on_check](../callbacks/coverageeligibility-on-check.md). Answer `202 Accepted` within 30 seconds, then process. +8. Read the body's `type`. `ProtocolResponse` means the payer could not process the request, and `x-hcx-error_details` says why. Any other type carries the sealed answer in `payload`. Decrypt it with your private key. +9. Read the [CoverageEligibilityResponse](../fhir/coverage-eligibility-response.md). Business problems, such as an expired policy, sit inside this sealed response, never in the headers. + +## How you know it worked + +The check is finished when all of these hold: + +- You received `POST /v1/coverageeligibility/on_check` whose `x-hcx-correlation_id` equals the correlation id you sent. +- Its `type` is not `ProtocolResponse`, and `payload` decrypts with your private key. +- The bundle holds a `CoverageEligibilityResponse` with `outcome` `complete`. +- For `validation`, `insurance[].inforce` is `true` and the benefit carries the balance left in `allowedMoney`. +- For `auth-requirements`, each item carries `excluded`, `authorizationRequired` and the `authorizationSupporting` document codes, such as `MAND0409`. +- You answered the callback with `202` within 30 seconds, so NHCX does not deliver it again. + +## When it goes wrong + +The 202 arrives and the callback never does. Check your endpoint against the [callback URL rules](../sandbox/callback-url-requirements.md), then [check the request's status](status-check.md). A request NHCX cannot deliver comes back to you on [/v1/error](../callbacks/error.md). See [accepted, then no callback](../troubleshooting/accepted-then-no-callback.md). + +NHCX rejects the call. [NHCX-1006](../errors/nhcx-1006.md) means the correlation id was used before. [NHCX-1003](../errors/nhcx-1003.md) means the recipient code is not registered. [NHCX-1018](../errors/nhcx-1018.md) means the ABHA number in `x-hcx-ben-abha-id` is in the wrong format. + +The callback is a `ProtocolResponse` with [PAYR-1001](../errors/payr-1001.md). The payer could not decrypt your request. Fetch its certificate again and reseal. See [the recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). + +The payer refuses the purpose or the items. [PAYR-1032](../errors/payr-1032.md) is an invalid purpose. [PAYR-1033](../errors/payr-1033.md) means `auth-requirements` arrived without items. + +The policy or the hospital does not qualify. From a payer on the published standard, [PAYR-1004](../errors/payr-1004.md) means your hospital is not registered with it for this policy. [PAYR-1007](../errors/payr-1007.md) means the policy has expired. [PAYR-1116](../errors/payr-1116.md) means your hospital may not raise cases under this policy. diff --git a/catalogue/nhcx/flows/generate-and-register-certificate.md b/catalogue/nhcx/flows/generate-and-register-certificate.md new file mode 100644 index 000000000..240990b8a --- /dev/null +++ b/catalogue/nhcx/flows/generate-and-register-certificate.md @@ -0,0 +1,169 @@ +--- +id: nhcx.flow.generate-and-register-certificate +type: flow +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Generate an encryption certificate and register it +summary: >- + Make the key pair and self-signed certificate that other participants use to seal + messages to you, and publish the certificate in your participant record. +sources: +- url: https://hcxsbx.abdm.gov.in/images/ec361a6c3e90e766d227.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Steps to generate encryption Certificate.pdf + hash: sha256:94605e935f05ebb49e24dee50787cb4f3f1c401983a9616a5aaabdbc302f664b + fetched: '2026-09-14' + note: Steps to generate encryption Certificate, row 20 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-3, Steps 1 to 4. +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths /participant/create, /participant/update, /v2/participant/update, /v2/update/cert, /fetch/certs.' +- url: https://hcxsbx.abdm.gov.in/images/260d0dec19a681e80262.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Production.pdf + hash: sha256:c38476fb90101f13fdfea447861292718d561e1dc088ae20950b193606500d2e + fetched: '2026-09-14' + note: Onboarding providers and payers in Production, row 5 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Steps 3 and 4, Participant Updation. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. 2.4 Encryption Steps; 3.3 Certificate Fetch. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.participant-create + - nhcx.endpoint.participant-update + - nhcx.endpoint.v2-participant-update + - nhcx.endpoint.update-validate + - nhcx.endpoint.v2-update-cert + - nhcx.endpoint.fetch-certs + flows: + - nhcx.flow.sandbox-onboarding + - nhcx.flow.production-onboarding + - nhcx.flow.rotate-certificate + - nhcx.flow.receive-a-sealed-callback + concepts: + - nhcx.concept.encryption-certificate + - nhcx.concept.jwe-envelope + glossary: + - nhcx.glossary.x509-certificate + - nhcx.glossary.jwe + errors: + - nhcx.error.payr-1001 + - nhcx.error.payr-1002 + troubleshooting: + - nhcx.troubleshooting.recipient-cannot-decrypt +--- + +# Generate an encryption certificate and register it + +## In plain words + +Every message on the [National Health Claims Exchange](../../shared/glossary/nhcx.md) (NHCX) is sealed so that only its recipient can open it. A sender seals with the recipient's public key. The recipient opens the message with the matching private key, which never leaves the recipient's systems. + +This flow makes that key pair and wraps the public key in a self-signed [X.509 certificate](../glossary/x509-certificate.md). It then publishes the certificate in your participant record. From then on, any participant can fetch it and seal a [JWE](../glossary/jwe.md) to you. + +## Before you start + +- OpenSSL on the machine where your private key will live. +- A session token, for the registration call. See [the session token concept](../concepts/session-token.md). +- One of: the sandbox create call you are about to make, or an existing participant code. See [Onboard as a participant in the NHCX sandbox](sandbox-onboarding.md). +- `jq`, for the check in section 4. + +## What happens + +```mermaid +sequenceDiagram + participant You as Your system + participant PS as NHCX participant service + participant Peer as Another participant + Note over You: openssl makes private.key and certificate.crt, then base64 + You->>PS: POST /participant/create or /participant/update with encryption_cert + PS-->>You: participant_code + You->>PS: POST /fetch/certs with your own participant code + PS-->>You: the certificate you registered + Peer->>PS: POST /fetch/certs with your participant code + PS-->>Peer: your encryption_cert + Note over Peer: caches it for 24 hours and seals messages to you with it +``` + +### 1. Make the private key + +```sh +openssl genpkey -algorithm RSA -out private.key -pkeyopt rsa_keygen_bits:2048 +``` + +This writes a 2048-bit RSA private key in PKCS#8 form, beginning `-----BEGIN PRIVATE KEY-----`. You decrypt every message sent to you with it. Keep it out of logs, repositories and messages. + +### 2. Make a certificate signing request + +```sh +openssl req -new -key private.key -out request.csr +``` + +OpenSSL prompts for country, state, organisation and similar fields, then writes `request.csr`. + +### 3. Make the self-signed certificate + +```sh +openssl x509 -req -in request.csr -signkey private.key -out certificate.crt -days 365 +``` + +`certificate.crt` is valid for 365 days. Put the expiry date in your calendar now, and rotate before it. + +### 4. Base64-encode the whole certificate + +```sh +base64 < certificate.crt | tr -d '\n' > certificate_base64.txt +``` + +Encode the entire file, including the `-----BEGIN CERTIFICATE-----` and `-----END CERTIFICATE-----` lines. The result is one line, and it decodes back to your PEM file byte for byte. + +### 5. Register it + +| Where you are | Call | Field that takes the base64 | +|---|---|---| +| Sandbox, new participant | `POST /participant/create` | `encryption_cert` | +| Sandbox, existing participant | `POST /participant/update` with `participant_code` | `encryption_cert` | +| Production, first registration | `POST /v2/participant/update`, then `GET /update/validate` with the SMS passcode | `encryptioncert` | +| Production, replacing a certificate | `POST /v2/update/cert` with `participantId` | `certificate` | + +Each call is described in its own endpoint atom: [create](../endpoints/participant-create.md), [update](../endpoints/participant-update.md), [v2 update](../endpoints/v2-participant-update.md) and [v2 update cert](../endpoints/v2-update-cert.md). + +### 6. What senders do with it + +Before sealing a message to you, a sender calls `POST /fetch/certs` with your participant code. It caches the answer for 24 hours rather than fetching on every message. The answer is an X.509 PEM certificate, or a bare public key. + +## How you know it worked + +The public key that `/fetch/certs` returns for your code is the one in your `certificate.crt`. Save the answer body as `response.json`, then run: + +```sh +jq -r .encryption_cert response.json > fetched.pem +openssl x509 -in certificate.crt -pubkey -noout > mine.pub +openssl x509 -in fetched.pem -pubkey -noout > theirs.pub +diff mine.pub theirs.pub && echo "registered key matches" +``` + +If `fetched.pem` holds a bare public key rather than a certificate, compare it with `mine.pub` directly. + +```observation schema=exit-condition +channel: synchronous +call: POST /fetch/certs +request: + participantid: +match: + encryption_cert: diff of mine.pub and theirs.pub is empty +``` + +The first sealed message you receive then opens with `private.key`. + +## When it goes wrong + +- **Registration is refused.** The value is not base64, or you encoded only the lines between `BEGIN` and `END`. Encode the whole file as in step 4. +- **A payer reports it cannot encrypt to you.** Your registered certificate is missing, wrong or expired. Register a valid one. See [PAYR-1002](../errors/payr-1002.md). +- **A recipient cannot open what you send.** You sealed with an old or wrong copy of its certificate. Fetch it again. See [PAYR-1001](../errors/payr-1001.md) and [The recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). +- **You sent `private.key` instead of `certificate.crt`.** Treat the key as exposed. Make a new pair and register the new certificate at once. +- **The certificate expired after 365 days.** Messages to you start failing. Follow [Rotate your encryption certificate](rotate-certificate.md). diff --git a/catalogue/nhcx/flows/insurance-plan-request.md b/catalogue/nhcx/flows/insurance-plan-request.md new file mode 100644 index 000000000..37542feba --- /dev/null +++ b/catalogue/nhcx/flows/insurance-plan-request.md @@ -0,0 +1,173 @@ +--- +id: nhcx.flow.insurance-plan-request +type: flow +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Request a patient's insurance plan +summary: >- + Ask the payer for the policy's rules as they apply at your hospital: the packages + you may treat, their rates, their conditions and the documents each one needs. +sources: +- url: https://hcxsbx.abdm.gov.in/images/13093b5f9b88fe826123.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Insurance Plan IG.docx + hash: sha256:e9c6c82b6d67fd8476d6d19a5961419beb04e3c0613533453ed1e16e2a569cc1 + fetched: '2026-09-14' + note: Insurance Plan IG, row 25 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Core APIs, InsurancePlan Task tables; plan structure Approach 1. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: 'NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. InsurancePlan section: key characteristics, claim condition table, error scenarios.' +- url: https://hcxsbx.abdm.gov.in/images/53347f5988b0ce5396f1.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_APIs to be called based on scenario.xlsx + hash: sha256:f92a30673d65dd2cc3cf09e2087c624f23f781dc4ca6b5cd8ec1825e224ac108 + fetched: '2026-09-14' + note: NHCX_APIs to be called based on scenario, row 26 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sheet Scenarios, row 2. +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. PAYR-1406 row. +- url: https://hcxsbx.abdm.gov.in/images/819467ec15aff13cc2a8.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Dummy Payer Implementation.pdf + hash: sha256:97335ebc4cd32c86e0c34328b2f4c526420b32a7a009208364043d6334e9e757 + fetched: '2026-09-14' + note: NHCX Dummy Payer Implementation, row 19 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Insurance Plan. +- url: https://hcxsbx.abdm.gov.in/insuranceplanhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/insuranceplanhcxservice.json + hash: sha256:03665c6e6a5c8d86e3d621ab577dd683cf13c155d5b9529f5be6ca70fef13dee + fetched: '2026-09-14' + note: 'API specification: insuranceplanhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths /v1/insuranceplan/request and /on_request.' +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.insuranceplan-request + - nhcx.endpoint.insuranceplan-on-request + callbacks: + - nhcx.callback.insuranceplan-request + - nhcx.callback.insuranceplan-on-request + - nhcx.callback.error + fhir: + - nhcx.fhir.task + - nhcx.fhir.validation + - nhcx.fhir.insurance-plan-bundle + - nhcx.fhir.pmjay-insurance-plan + concepts: + - nhcx.concept.four-message-legs + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.message-identifiers + - nhcx.concept.insurance-plan + - nhcx.concept.session-token + tests: + - nhcx.test.provider-uc-06 + - nhcx.test.payer-uc-08 + - nhcx.test.tc-hbp-01 + flows: + - nhcx.flow.pmjay-patient-to-cashless + - nhcx.flow.preauth-submit + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.send-a-sealed-request + - nhcx.flow.status-check + errors: + - nhcx.error.payr-1001 + - nhcx.error.payr-1401 + - nhcx.error.payr-1402 + - nhcx.error.payr-1405 + - nhcx.error.payr-1406 + glossary: + - nhcx.glossary.insurance-plan + - nhcx.glossary.payer + - nhcx.glossary.pmjay + - shared.glossary.hfr + - shared.glossary.nhcx + sandbox: + - nhcx.sandbox.callback-url-requirements + - nhcx.sandbox.dummy-payer + - nhcx.sandbox.support-contacts + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback +--- + +# Request a patient's insurance plan + +## In plain words + +The [insurance plan](../glossary/insurance-plan.md) is the patient's policy in machine-readable form, as it applies at your hospital. It lists the specialties and packages your hospital is empanelled for, the package rates, the claim conditions, and the documents each treatment needs. + +You ask the [payer](../glossary/payer.md) for it through the [NHCX](../../shared/glossary/nhcx.md) exchange, with a Task. The plan arrives later, on your callback. Fetch it before any preauthorisation or claim for a payer and policy, then cache it. + +The plan is filtered to your hospital. It shows only what the payer's agreement with your hospital covers. [The insurance plan](../concepts/insurance-plan.md) explains the model. + +## Before you start + +- Your hospital is an active participant, holds a valid [session token](../concepts/session-token.md), and has a registered callback endpoint that answers within 30 seconds. +- You have the policy number and the payer's `processingid` from the [policy lookup](../endpoints/participant-get-policies.md). The `processingid` goes in `x-hcx-recipient_code`. +- You have your hospital's [HFR](../../shared/glossary/hfr.md) ID. +- You hold the recipient's encryption certificate, fetched with [/fetch/certs](../endpoints/fetch-certs.md). +- No other plan request for this hospital and policy is still open. +- In the sandbox, use the [dummy payer](../sandbox/dummy-payer.md) with the test provider id and policy number it names. + +## What happens + +```mermaid +sequenceDiagram + participant P as Provider (your system) + participant N as NHCX + participant Y as Payer + P->>N: POST /v1/insuranceplan/request + Note right of P: sealed Task bundle, Task.code poll, x-hcx-status request.initiated + N-->>P: HTTP 202 Accepted + N->>Y: POST /v1/insuranceplan/request + Y-->>N: HTTP 202 Accepted + Note over Y: payer builds the plan for this policy and hospital + Y->>N: POST /v1/insuranceplan/on_request + N-->>Y: HTTP 202 Accepted + N->>P: POST /v1/insuranceplan/on_request + P-->>N: HTTP 202 Accepted, within 30 seconds + Note left of P: decrypt, then cache the plan +``` + +1. Build a Task bundle, as in [the insurance plan bundles](../fhir/insurance-plan-bundle.md). Set Task `status` to `requested`, `intent` to `order` and `code` to `poll`. +2. Add two Task inputs: the policy number, and your HFR ID as the provider id. Send both, so the payer returns the view contracted for your hospital. +3. Seal the bundle and set the headers, as in [send a sealed request](send-a-sealed-request.md). Set `x-hcx-status` to `request.initiated`. Set `x-hcx-correlation_id` to the value of this call's `x-hcx-api_call_id`. +4. Call [POST /v1/insuranceplan/request](../endpoints/insuranceplan-request.md). NHCX answers `202 Accepted` and forwards the request. +5. Wait. Do not send a second plan request for the same hospital and policy until this one completes. +6. Receive [POST /v1/insuranceplan/on_request](../callbacks/insuranceplan-on-request.md). Answer `202 Accepted` within 30 seconds, then process. +7. Read the body's `type`. `ProtocolResponse` carries `x-hcx-error_details`. Any other type carries the sealed plan in `payload`. Decrypt it with your private key. +8. Find the `InsurancePlan` resource in the decrypted bundle, with its `Organization` and `Questionnaire` resources. +9. Cache the plan with the date you fetched it. Fetch it again once every 15 days, and after a policy update or a change of treatment. + +For [PMJAY](../glossary/pmjay.md), read the plan like this. [The PMJAY InsurancePlan profile](../fhir/pmjay-insurance-plan.md) has the full mapping. + +| Plan element | What it holds | +|---|---| +| `plan.specificCost.category` | A specialty, such as General Medicine | +| `plan.specificCost.benefit` | A package, such as `SE012A`, Corneal Grafting | +| `specificCost.benefit.cost` | The package rate | +| `cost.qualifiers` | Extra cost types: `Implant`, and `Stratification` for the bed category | +| `claimCondition` extension | Package rules, such as `EnhancementAllowed`, `ApprovalNotRequired` and `IsDayCare` | +| `claimSupportingInfoRequirement` extension | Documents the payer requires during claim processing | + +## How you know it worked + +The request is finished when all of these hold: + +- You received `POST /v1/insuranceplan/on_request` whose `x-hcx-correlation_id` equals the one you sent. +- Its `type` is not `ProtocolResponse`, and `payload` decrypts with your private key. +- The bundle holds an `InsurancePlan` resource listing benefits for the specialties your hospital is empanelled for. +- You answered the callback with `202` within 30 seconds. +- The plan sits in your cache with its fetch date, ready for eligibility and preauthorisation. + +## When it goes wrong + +The payer answers [PAYR-1406](../errors/payr-1406.md). An earlier plan request is still in progress with the payer. Wait 15 to 60 minutes, then ask again with a new correlation id. + +The 202 arrives and the callback never does. [Check the request's status](status-check.md) and your [callback URL](../sandbox/callback-url-requirements.md). An undeliverable request comes back on [/v1/error](../callbacks/error.md). See [accepted, then no callback](../troubleshooting/accepted-then-no-callback.md). + +The payer refuses the policy or your hospital. [PAYR-1401](../errors/payr-1401.md) means the policy is not allowed for your hospital. [PAYR-1402](../errors/payr-1402.md) means no payer holds the policy. [PAYR-1405](../errors/payr-1405.md) means the payer has no enrolled hospital for your HFR ID or sender code. Each message asks you to contact [technical support](../sandbox/support-contacts.md). + +The plan arrives empty. No coverage matches this policy and hospital. Check the policy number and the HFR ID you sent. + +The callback is a `ProtocolResponse` with [PAYR-1001](../errors/payr-1001.md). The payer could not decrypt your request. Fetch its certificate again and reseal. diff --git a/catalogue/nhcx/flows/notification-subscribe.md b/catalogue/nhcx/flows/notification-subscribe.md new file mode 100644 index 000000000..1df319d99 --- /dev/null +++ b/catalogue/nhcx/flows/notification-subscribe.md @@ -0,0 +1,191 @@ +--- +id: nhcx.flow.notification-subscribe +type: flow +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Subscribe a patient app to notifications +summary: >- + Have a patient's health record app receive plain-language updates on their pre-authorisations, + claims and payments, by subscribing each time the patient logs in. +sources: +- url: https://hcxsbx.abdm.gov.in/images/01db86335b7c226eb745.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Notification Integration.docx + hash: sha256:05908862c103522fac0dbb482f8eb6a0f8536fc12b1ae3bdb0e98615f30812aa + fetched: '2026-09-14' + note: NHCX Notification Integration, listed on https://hcxsbx.abdm.gov.in/#/documents, not named in the NHCX document sheet. sections 2 to 7. +- url: https://hcxsbx.abdm.gov.in/subscriptionhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/subscriptionhcxservice.json + hash: sha256:0d0d4781aa96017c06c8c2533e63dd1a6b36bb2342ebb51aeefca3349d892029 + fetched: '2026-09-14' + note: 'API specification: subscriptionhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths /v1/notification/subscribe and /on_subscribe.' +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. FAQ 7 role codes; Session API table. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.session-token + - nhcx.endpoint.notification-subscribe + callbacks: + - nhcx.callback.notification-delivery + flows: + - nhcx.flow.sandbox-onboarding + - nhcx.flow.production-onboarding + - nhcx.flow.send-a-sealed-request + concepts: + - nhcx.concept.notifications + - nhcx.concept.beneficiary-consent + - nhcx.concept.jwe-envelope + decisions: + - nhcx.decision.session-endpoint + - nhcx.decision.key-encryption-algorithm + sandbox: + - nhcx.sandbox.support-contacts + - nhcx.sandbox.callback-url-requirements + glossary: + - shared.glossary.phr + - shared.glossary.abha-address + - shared.glossary.eua +--- + +# Subscribe a patient app to notifications + +## In plain words + +A patient's [PHR](../../shared/glossary/phr.md) app can show the patient what is happening to their pre-authorisations, claims and payments. The app acts as a Beneficiary Service Provider (BSP). It subscribes the patient's [ABHA address](../../shared/glossary/abha-address.md) to the [National Health Claims Exchange](../../shared/glossary/nhcx.md) (NHCX). NHCX then pushes a short, readable message to the app whenever a matching event occurs. + +Only one app receives a patient's notifications at a time. The most recent subscription for an ABHA address replaces any earlier one, so the app subscribes again at every login. + +## Before you start + +- Your app has completed [ABDM](../../shared/glossary/abdm.md) [Milestone 1](../../shared/glossary/m1.md) integration. +- You are registered as a BSP: sandbox testing on `hcxsbx.abdm.gov.in`, sandbox certification, then production registry onboarding. An [end user application](../../shared/glossary/eua.md) such as a PHR app registers with role `10009`. See [Onboard as a participant in the NHCX sandbox](sandbox-onboarding.md). +- You host an HTTPS endpoint with TLS 1.2 or higher, where notifications will arrive. +- You have the NHCX gateway's participant code and certificate, which you seal the subscription for. See [Where to get help with NHCX](../sandbox/support-contacts.md). +- The patient has given explicit consent to receive claim updates in your app. See [beneficiary consent](../concepts/beneficiary-consent.md). +- You hold a client ID and secret for the session token. + +## What happens + +```mermaid +sequenceDiagram + participant Pt as Patient + participant App as PHR app, the BSP + participant GW as ABDM session gateway + participant NHCX as NHCX + participant HP as Hospital and payer + Pt->>App: log in with ABHA address and give consent + App->>GW: POST /api/hiecm/gateway/v3/sessions, when no valid token is held + GW-->>App: access token + App->>NHCX: POST /v1/notification/subscribe with a sealed payload + NHCX-->>App: subscription state + Note over NHCX: any earlier subscription for this ABHA address is replaced + HP->>NHCX: pre-authorisation, claim or payment messages for this patient + NHCX->>App: POST to your on_notification_url + App->>Pt: shows the message text +``` + +### 1. Log in and ask for consent + +The patient logs in with their ABHA address. Your app reads their ABHA ID and asks for consent before subscribing. + +### 2. Hold a valid token + +If your token has expired, get a new one. [Which session token endpoint to call](../decisions/session-endpoint.md) settles the address. Read the token's lifetime from the answer, and refresh before it lapses. + +### 3. Build the subscription + +The payload: + +```json +{ + "subscription_id": "", + "topic_code": ["workflow_events"], + "recipient_code": "", + "subscriber": { + "id": "" + }, + "on_notification_url": "" +} +``` + +An optional `expiry` sets when the subscription ends. The topics: + +| `topic_code` | Covers | +|---|---| +| `workflow_events` | Claim lifecycle events: pre-authorisation, claim, payment | +| `network_events` | NHCX platform updates and maintenance | +| `participant_events` | Changes to payer and provider registrations | + +Most PHR apps need only `workflow_events`. + +Seal the payload as a JWE. Its protected header carries `alg`, `enc` `A256GCM`, `x-hcx-sender_code` set to your BSP code, and `x-hcx-recipient_code` set to the NHCX gateway code. It also carries `x-hcx-timestamp` in ISO 8601 and a fresh UUID in `x-hcx-correlation_id` for every attempt. For `alg`, see [RSA-OAEP or RSA-OAEP-256](../decisions/key-encryption-algorithm.md). + +### 4. Subscribe + +`POST https://hcxsbx.abdm.gov.in/v1/notification/subscribe` with `Authorization: Bearer ` and `Content-Type: application/json`. The body is `{"payload": ""}`. + +The answer returns the subscription state, including `subscription_id` and `subscription_status`. Store `subscription_id` in your app. + +### 5. Wait for events + +**Wait:** there is no fixed time. When a hospital sends a pre-authorisation or claim for this patient and the payer responds, NHCX posts a notification to your `on_notification_url`: + +| Field | Meaning | +|---|---| +| `notification_id` | Unique notification identifier | +| `topic_code` | The topic, for example `workflow_events` | +| `timestamp` | Event time, ISO 8601 | +| `subscriber.id` | The patient's ABHA ID | +| `message` | Readable text you can show the patient as it is | +| `domain_values` | Optional. The `x-hcx-*` values behind the event, for audit or custom display | + +The events under `workflow_events`: + +| Event type | Meaning | Status values | +|---|---|---| +| `preauth_request` | The provider submitted a pre-authorisation | `queued`, `processing` | +| `preauth_response` | The payer decided it | `approved`, `rejected` | +| `claim_request` | The provider submitted a claim | `queued`, `processing` | +| `claim_response` | The payer adjudicated it | `approved`, `rejected` | +| `payment_notice` | Payment processed | `paid`, `pending` | +| `communication` | Information requested | `information_required` | + +In `domain_values`, `x-hcx-action` names the event and `x-hcx-status` carries its protocol status. + +On every incoming notification, enforce TLS 1.2 or higher, validate the JWT from NHCX, and check that the sender code is NHCX's. Rate-limit the endpoint. The full delivery is described in [Receiving a notification on a patient app](../callbacks/notification-delivery.md). + +### 6. Show the state + +Display the subscription status in your app's settings. At the next login, subscribe again. + +## How you know it worked + +The subscribe call returns `subscription_status` `active` for your `subscription_id`. Later, after a hospital and payer exchange a message for that patient, your `on_notification_url` receives a notification. Its `subscriber.id` is the patient's ABHA ID, and your app shows its `message`. + +```observation schema=exit-condition +channel: callback +path: +precondition: + subscribe answer: subscription_status active +match: + subscriber.id: + topic_code: workflow_events +``` + +## When it goes wrong + +| Status | Meaning | What to do | +|---|---|---| +| `401 Unauthorized` | Token expired | Get a new token and subscribe again | +| `403 Forbidden` | Not authorised | Check your BSP registration and status in the registry | +| `409 Conflict` | A conflict on the subscription | Subscribe again under a fresh correlation ID | +| `500 Server Error` | Gateway issue | Retry with backoff | + +- **Notifications stop arriving.** Another app subscribed this patient more recently, so yours was replaced. Subscribe again at the next login, and show the status in settings. +- **Nothing ever arrives.** Your endpoint does not offer TLS 1.2 or higher, or NHCX cannot reach it. See [Callback URL rules and the egress addresses to allow](../sandbox/callback-url-requirements.md). +- **Values are refused or never match.** A copied value carries a stray space, such as a trailing space in a URL. Trim every value before sending it. diff --git a/catalogue/nhcx/flows/payer-process-a-request.md b/catalogue/nhcx/flows/payer-process-a-request.md new file mode 100644 index 000000000..8f3ba87e7 --- /dev/null +++ b/catalogue/nhcx/flows/payer-process-a-request.md @@ -0,0 +1,234 @@ +--- +id: nhcx.flow.payer-process-a-request +type: flow +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Receive, adjudicate and answer a request as a payer +summary: >- + As an insurer or claims administrator, take a provider's request from the exchange, + decide it, and send the sealed decision back on the paired answer path. +sources: +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use cases 7 to 15, API logic rows. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Acceptance scenario and error scenario. +- file: catalogue/openapi/.raw/nhcx-site-2026-09-14/not-on-site/External_NHCX_Payer_Service_API_Workflow_Guide.docx + hash: sha256:1028d480d2fabe3204301f1c1b192a0077ddfa64f7f9084b01f73e004253fdd7 + fetched: '2026-09-05' + note: NHCX Payer Service API Workflow Guide for External Integrators, not listed on hcxsbx.abdm.gov.in and not named in the NHCX document sheet, received separately. get/user-role, process/case and role table. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Communication. +- url: https://hcxsbx.abdm.gov.in/images/c42ad170f37c987ed173.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx + hash: sha256:f56dd156c232192296082f23b1561d0ff11fd40992e6675de41c5c991d579e6d + fetched: '2026-09-14' + note: Workflow Status Sheets(with Codes), row 12 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet1. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Status Description. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.coverageeligibility-on-check + - nhcx.endpoint.insuranceplan-on-request + - nhcx.endpoint.preauth-on-submit + - nhcx.endpoint.claim-on-submit + - nhcx.endpoint.task-on-submit + - nhcx.endpoint.search-on-submit + - nhcx.endpoint.communication-request + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.session-token + - nhcx.endpoint.status + - nhcx.endpoint.payer-service-get-user-role + - nhcx.endpoint.payer-service-process-case + callbacks: + - nhcx.callback.coverageeligibility-check + - nhcx.callback.insuranceplan-request + - nhcx.callback.preauth-submit + - nhcx.callback.claim-submit + - nhcx.callback.task-submit + - nhcx.callback.search-submit + - nhcx.callback.communication-on-request + - nhcx.callback.error + - nhcx.callback.on-status + flows: + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.report-a-processing-error + - nhcx.flow.send-a-sealed-request + - nhcx.flow.policy-link-and-delink + concepts: + - nhcx.concept.four-message-legs + - nhcx.concept.message-identifiers + - nhcx.concept.workflow-codes + - nhcx.concept.status-lifecycle + - nhcx.concept.queries-and-communication + - nhcx.concept.claim-cycle + decisions: + - nhcx.decision.payer-implementation + tests: + - nhcx.test.payer-uc-07 + - nhcx.test.payer-uc-08 + - nhcx.test.payer-uc-09 + - nhcx.test.payer-uc-10 + - nhcx.test.payer-uc-11 + - nhcx.test.payer-uc-14 + - nhcx.test.payer-uc-15 + errors: + - nhcx.error.payr-1001 + - nhcx.error.nhcx-1010 + glossary: + - nhcx.glossary.payer + - nhcx.glossary.adjudication + - nhcx.glossary.tpa +--- + +# Receive, adjudicate and answer a request as a payer + +## In plain words + +As a [payer](../glossary/payer.md), you receive providers' requests from the [National Health Claims Exchange](../../shared/glossary/nhcx.md) (NHCX): eligibility checks, pre-authorisations, claims and more. Each arrives at your registered address on the request path, for example `/v1/preauth/submit`. You acknowledge it at once, decide it in your own time, and send the decision back on the paired answer path, for example `/v1/preauth/on_submit`. + +The decision is sealed for the provider. If you cannot process the request at all, you send an unsealed `ProtocolResponse` instead. + +## Before you start + +- You are onboarded as a payer or [TPA](../glossary/tpa.md). Your registered address serves the request paths for your use cases, and `/v1/error`. See [Onboard as a participant in production](production-onboarding.md). +- Your private key matches the certificate in your participant record. +- Your policies are linked, so providers can find them. See [Link and de-link an ABHA and a policy](policy-link-and-delink.md). +- You hold a session token. +- You can validate bundles against the [NRCeS](../../shared/glossary/nrces.md) profiles. + +| Request you receive | Answer you send | What the answer carries | +|---|---|---| +| `/v1/coverageeligibility/check` | `/v1/coverageeligibility/on_check` | Eligibility and plan details | +| `/v1/insuranceplan/request` | `/v1/insuranceplan/on_request` | The insurance plan details | +| `/v1/preauth/submit` | `/v1/preauth/on_submit` | The adjudicated pre-authorisation | +| `/v1/claim/submit` | `/v1/claim/on_submit` | The adjudicated claim | +| `/v1/search/submit` | `/v1/search/on_submit` | The claim responses that match the criteria | +| `/v1/task/submit` | `/v1/task/on_submit` | The answer to a reprocess or cancel task | + +## What happens + +```mermaid +sequenceDiagram + participant Prov as Provider + participant NHCX as NHCX exchange + participant You as Your payer endpoint + participant PS as NHCX participant service + participant Rev as Reviewer acting for the payer + participant PSvc as PMJAY payer service + Prov->>NHCX: POST /v1/preauth/submit + NHCX->>You: POST /v1/preauth/submit + You-->>NHCX: 202 with the acceptance body, within 30 seconds + Note over You: decrypt with your private key and validate the bundle + opt More information needed + You->>NHCX: POST /v1/communication/request + NHCX->>Prov: POST /v1/communication/request + Prov->>NHCX: POST /v1/communication/on_request + NHCX->>You: POST /v1/communication/on_request + end + opt A PMJAY case held in the PMJAY payer service + Rev->>PSvc: POST /pmjay/sbxhcx/nhcxpayerservice/v1/get/user-role + PSvc-->>Rev: the role that holds the case + Rev->>PSvc: POST /pmjay/hcx/nhcxpayerservice/wrapper/process/case + end + Note over You: the decision is ready + You->>PS: POST /fetch/certs with the provider code + PS-->>You: the provider's certificate + You->>NHCX: POST /v1/preauth/on_submit with the sealed decision + NHCX-->>You: 202 + NHCX->>Prov: POST /v1/preauth/on_submit + opt Delivery to the provider fails five times + NHCX->>You: POST /v1/error + end +``` + +### 1. Receive and acknowledge + +Acknowledge within 30 seconds, before any processing. Follow [Receive, open and acknowledge a sealed message](receive-a-sealed-callback.md). + +### 2. Open and validate + +Decrypt the payload with your private key. Validate the bundle against the NRCeS profiles. + +If you cannot decrypt it, the payload is invalid, or a protocol error occurs, do not adjudicate. Answer with a `ProtocolResponse` as in [Report a processing failure on /v1/error](report-a-processing-error.md). A payload you cannot decrypt takes [PAYR-1001](../errors/payr-1001.md). + +### 3. Adjudicate + +Decide the request in your own system, with no fixed turnaround. + +**Wait, when you need documents:** send `POST /v1/communication/request` to the provider, with `x-hcx-status` `request.initiated`. The payload is a TaskBundle that carries a CommunicationRequest. The provider's answer arrives on your `/v1/communication/on_request`. See [queries and communication](../concepts/queries-and-communication.md). + +### 4. Seal the answer + +Fetch the provider's certificate with `POST /fetch/certs`, using the request's `x-hcx-sender_code`. Cache it for 24 hours. Then build the protected header: + +| Header | Rule | +|---|---| +| `x-hcx-sender_code` | Your participant code | +| `x-hcx-recipient_code` | The request's `x-hcx-sender_code` | +| `x-hcx-api_call_id` | A new UUID, different from the correlation ID | +| `x-hcx-correlation_id` | As [message identifiers](../concepts/message-identifiers.md) sets out, so the provider can match your answer | +| `x-hcx-status` | `response.complete` for a final decision. A claim answer can be `response.partial` | +| `x-hcx-workflow_id` | The payer-side stage code, for example `21` approved, `23` rejected or `24` queried. See [workflow codes](../concepts/workflow-codes.md) | + +The answer's `type` is `JWEPayloadResponse` for a sealed decision. Only a request you could not process gets `ProtocolResponse`. + +### 5. Send it + +`POST /v1/preauth/on_submit`, or the paired path from the table, with `{"payload": ""}`. NHCX answers `202` and forwards it to the provider. The provider acknowledges it to NHCX. + +**Wait:** if NHCX cannot deliver your answer after five attempts, the report arrives on your `/v1/error`. + +### 6. PMJAY cases in the PMJAY payer service + +A PMJAY case is adjudicated role by role in the PMJAY payer service. `POST /pmjay/sbxhcx/nhcxpayerservice/v1/get/user-role`, with `caseid` and `payerid`, returns the role that holds the case now. `POST /pmjay/hcx/nhcxpayerservice/wrapper/process/case` applies an action as that role. Call the role lookup before every claim action. + +| Stage | Role | Actions | `usecase` | +|---|---|---|---| +| Pre-authorisation | `PPD-Trust` | `Approve`, `Reject`, `Query` | `PREAUTH` | +| Claim step 1 | `CEX-Trust` | `Forward` | `CLAIM` | +| Claim step 2 | `CPD-Trust` | `Pending`, `cpdApprove`, `cpdReject` | `CLAIM` | +| Claim step 3 | `Medical Audit Committee` | `Approve`, `Reject`, `iQuery` | `Medical Audit Committee` | +| Claim step 4 | `ACO-Trust` | `Approve`, `Reject`, `Pending` | `CLAIM` | +| Claim step 5 | `SHA-Trust` | `Approve`, `Reject`, `Pending` | `CLAIM` | +| Claim step 6 | `Claim Review Committee` | `Approve`, `Reject`, `Pending` | `Claim Review Committee` | + +The `process/case` body carries `casenumber`, `action`, `receivercode`, `usecase`, `correlationid`, `sendercode`, `memberid` and `remarks`. Action names are case-sensitive. Give each call a unique correlation ID. See [POST /pmjay/hcx/nhcxpayerservice/wrapper/process/case](../endpoints/payer-service-process-case.md) and [Answer as your own payer system or through the PMJAY payer service](../decisions/payer-implementation.md). + +## How you know it worked + +NHCX answered `202` to your answer on the paired path, and no `/v1/error` arrives for it. To confirm delivery, send `POST /v1/status` about your answer. The reply on `/v1/on_status` carries `x-hcx-status` `request.dispatched`, meaning the provider's system received it. + +```observation schema=exit-condition +channel: callback +path: /v1/on_status +precondition: + your answer on /v1/preauth/on_submit: HTTP 202 from NHCX +match: + x-hcx-status: request.dispatched +absent: + /v1/error report for your answer +``` + +## When it goes wrong + +- **The same request keeps arriving.** You process inside the 30-second window, or your acknowledgement has the wrong code or body. Acknowledge first, then process. +- **You cannot decrypt the request.** The provider sealed it with an old copy of your certificate. Answer with a `ProtocolResponse` carrying [PAYR-1001](../errors/payr-1001.md), and check [Rotate your encryption certificate](rotate-certificate.md). +- **NHCX refuses your answer, saying no data exists for its correlation ID.** Your `x-hcx-correlation_id` does not match the request. See [NHCX-1010](../errors/nhcx-1010.md). +- **The provider never gets your answer.** `x-hcx-recipient_code` is not the request's sender code. Swap sender and recipient. +- **You sent a `ProtocolResponse` for a rejection.** The provider treats it as a protocol failure. Send a sealed decision with the rejected workflow code. +- **A PMJAY action is refused.** The case sits with another role, or the action name is misspelt. Call `get/user-role` first, and use the action names exactly as in the table. diff --git a/catalogue/nhcx/flows/payment-notice.md b/catalogue/nhcx/flows/payment-notice.md new file mode 100644 index 000000000..ede684773 --- /dev/null +++ b/catalogue/nhcx/flows/payment-notice.md @@ -0,0 +1,158 @@ +--- +id: nhcx.flow.payment-notice +type: flow +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Receive a payment notice and acknowledge it +summary: >- + Receive the payer's notice that a claim is being paid or has been paid, record + the bank reference, and send the acknowledgement back. +sources: +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: 'NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Payment Notice chapter: workflow table, Task deliver, PaymentReconciliation fields.' +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: 'NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Code tables: Payment Type Code and Task output values.' +- url: https://hcxsbx.abdm.gov.in/images/c42ad170f37c987ed173.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx + hash: sha256:f56dd156c232192296082f23b1561d0ff11fd40992e6675de41c5c991d579e6d + fetched: '2026-09-14' + note: Workflow Status Sheets(with Codes), row 12 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet1, Payment Notice rows. +- url: https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip + member: FHIR_bundles_PMJAY_ext/paymentNotice/paymentNotice_ack.txt + hash: sha256:8c7b24e3022733aaf7e8f517e12c11c0e8eddd6293844a2c4f3e9700fb720dca + fetched: '2026-09-14' + note: Sample FHIR bundles, row 29 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Task resource. +- url: https://hcxsbx.abdm.gov.in/images/53347f5988b0ce5396f1.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_APIs to be called based on scenario.xlsx + hash: sha256:f92a30673d65dd2cc3cf09e2087c624f23f781dc4ca6b5cd8ec1825e224ac108 + fetched: '2026-09-14' + note: NHCX_APIs to be called based on scenario, row 26 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sheet Scenarios, row 13. +- url: https://hcxsbx.abdm.gov.in/images/819467ec15aff13cc2a8.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Dummy Payer Implementation.pdf + hash: sha256:97335ebc4cd32c86e0c34328b2f4c526420b32a7a009208364043d6334e9e757 + fetched: '2026-09-14' + note: NHCX Dummy Payer Implementation, row 19 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Payment Notice; Payment Notice Trigger API. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.paymentnotice-request + - nhcx.endpoint.paymentnotice-on-request + - nhcx.endpoint.dummy-payer-paymentnotice-init + callbacks: + - nhcx.callback.paymentnotice-request + - nhcx.callback.paymentnotice-on-request + fhir: + - nhcx.fhir.payment-notice + - nhcx.fhir.task + concepts: + - nhcx.concept.claim-cycle + - nhcx.concept.message-identifiers + - nhcx.concept.synchronous-acknowledgement + tests: + - nhcx.test.provider-uc-11 + - nhcx.test.payer-uc-13 + flows: + - nhcx.flow.claim-submit + - nhcx.flow.claim-reprocess + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.rotate-certificate + errors: + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1011 + - nhcx.error.payr-1002 + glossary: + - nhcx.glossary.payer + - nhcx.glossary.payment-notice + sandbox: + - nhcx.sandbox.callback-url-requirements + - nhcx.sandbox.dummy-payer + troubleshooting: + - nhcx.troubleshooting.callback-url-rejected +--- + +# Receive a payment notice and acknowledge it + +## In plain words + +A [payment notice](../glossary/payment-notice.md) tells your hospital that the payer is paying an approved claim. It carries the amount, the tax deducted at source, the payment date and the bank's Unique Transaction Reference. The claim decision says what will be paid. The notice says what was paid. + +This flow runs the other way from the others. The [payer](../glossary/payer.md) starts it, and your system answers. It arrives some time after the claim approval, not straight away. + +| Workflow | Stage | +|---|---| +| `30` | Payment initiated | +| `31` | Payment processed | +| `33` | Payment settled. The Unique Transaction Reference is available | +| `17` | Your acknowledgement of a notice | + +Acknowledge each notice. The claim is financially closed when you have received workflow `33`, stored its Unique Transaction Reference, and acknowledged it. + +## Before you start + +- A claim for the case was approved: `outcome` `complete`, reason `approved`, workflow `26`. See [submit a claim](claim-submit.md). +- Your callback endpoint is registered, answers within 30 seconds, and receives `/v1/paymentnotice/request`. +- Your current encryption certificate is registered, so the payer can seal the notice for you. +- You can match a notice to a claim by its claim number. +- In the sandbox, trigger a notice from the [dummy payer](../sandbox/dummy-payer.md) with [POST /paymentNotice/init](../endpoints/dummy-payer-paymentnotice-init.md), giving your participant code and the claim number. + +## What happens + +```mermaid +sequenceDiagram + participant Y as Payer + participant N as NHCX + participant P as Provider (your system) + loop for each notice, workflow 30, 31 and 33 + Y->>N: POST /v1/paymentnotice/request + Note left of Y: x-hcx-status request.initiated + N-->>Y: HTTP 202 Accepted + N->>P: POST /v1/paymentnotice/request + P-->>N: HTTP 202 Accepted, within 30 seconds + Note right of P: decrypt, record the amount and the bank reference + P->>N: POST /v1/paymentnotice/on_request (workflow 17) + Note right of P: Task output paymentack, same correlation id + N-->>P: HTTP 202 Accepted + N->>Y: POST /v1/paymentnotice/on_request + Y-->>N: HTTP 202 Accepted + end +``` + +1. Receive [POST /v1/paymentnotice/request](../callbacks/paymentnotice-request.md). Answer `202 Accepted` within 30 seconds, then process. +2. Read `x-hcx-workflow_id`: `30`, `31` or `33`. Decrypt `payload` with your private key. +3. Read the [PaymentNotice bundle](../fhir/payment-notice.md). A Task with `code` `deliver` points to the `PaymentNotice`. The notice points to the `PaymentReconciliation`. +4. Take the claim number from `PaymentNotice.identifier` and the net amount from `PaymentNotice.amount`. +5. From `PaymentReconciliation`, take `paymentDate` and the Unique Transaction Reference in `paymentIdentifier.value`. In `detail`, the entry of type `TDS` is the tax deducted, and the entry of type `Payment` is the net amount. +6. Check that the net amount plus the tax deducted equals the approved claim amount. Store the Unique Transaction Reference against the claim. +7. Build the acknowledgement: a Task with `status` `completed` and `code` `status`. Set `output[0]` to `paymentack`, Payment is acknowledged, and `output[1]` to the claim number. +8. Seal it for the payer. Set `x-hcx-workflow_id` to `17` and `x-hcx-status` to `response.complete`. +9. Set `x-hcx-correlation_id` to the notice's correlation id. Use a fresh `x-hcx-api_call_id`. Address it to the payer that sent the notice. +10. Call [POST /v1/paymentnotice/on_request](../endpoints/paymentnotice-on-request.md). NHCX answers `202 Accepted` and delivers it to the payer. + +## How you know it worked + +The payment is closed when all of these hold: + +- You received `POST /v1/paymentnotice/request` with `x-hcx-workflow_id` `33`, and its `payload` decrypted. +- You stored `PaymentReconciliation.paymentIdentifier.value` against the claim. +- The net amount plus the tax deducted equals the approved amount. +- NHCX answered `202` to your `POST /v1/paymentnotice/on_request` for that notice, with workflow `17` and output `paymentack`. +- You acknowledged the earlier notices, `30` and `31`, the same way. + +## When it goes wrong + +No notice arrives. The notice follows the claim approval after a delay, not straight away. If none comes, check your endpoint against the [callback URL rules](../sandbox/callback-url-requirements.md). See [your callback URL is rejected or never called](../troubleshooting/callback-url-rejected.md). + +You cannot decrypt the notice. The payer sealed it with the certificate registered for you. A payer on the published standard reports [PAYR-1002](../errors/payr-1002.md) when it cannot encrypt for you. [Update your certificate](rotate-certificate.md) and ask the payer to resend. + +NHCX rejects your acknowledgement. [NHCX-1010](../errors/nhcx-1010.md) means no request exists with the correlation id you set. Copy it from the notice exactly. [NHCX-1011](../errors/nhcx-1011.md) means the `x-hcx-status` value is not valid. + +The amounts do not reconcile. Keep the notice, acknowledge it, and raise the shortfall with an [erroneous claim](claim-reprocess.md) after workflow `33`. diff --git a/catalogue/nhcx/flows/pmjay-hospital-migration.md b/catalogue/nhcx/flows/pmjay-hospital-migration.md new file mode 100644 index 000000000..c21cb1140 --- /dev/null +++ b/catalogue/nhcx/flows/pmjay-hospital-migration.md @@ -0,0 +1,193 @@ +--- +id: nhcx.flow.pmjay-hospital-migration +type: flow +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Migrate a PMJAY hospital to HMIS through NHCX +summary: >- + Move a scheme-empanelled hospital from the central claims portal to its own hospital + system, by onboarding it on the exchange and having its hospital ID mapped to + its participant code. +sources: +- url: https://hcxsbx.abdm.gov.in/images/be2e25fede3bf711f783.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/PMJAY Hospital Migration to HMIS via NHCX.docx + hash: sha256:cf5c9bf1c402b214f65bbb7bd0822f3a76d8ccda9b69c7bf77ba131befef3bc6 + fetched: '2026-09-14' + note: PMJAY Hospital Migration to HMIS via NHCX, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments, not named in the NHCX document sheet. sections 3.1 to 4.1. +- url: https://hcxsbx.abdm.gov.in/images/260d0dec19a681e80262.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Production.pdf + hash: sha256:c38476fb90101f13fdfea447861292718d561e1dc088ae20950b193606500d2e + fetched: '2026-09-14' + note: Onboarding providers and payers in Production, row 5 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Steps 1 to 4. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.session-token + - nhcx.endpoint.v2-participant-create + - nhcx.endpoint.validate + - nhcx.endpoint.v2-participant-update + - nhcx.endpoint.update-validate + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.preauth-submit + flows: + - nhcx.flow.production-onboarding + - nhcx.flow.generate-and-register-certificate + - nhcx.flow.send-a-sealed-request + - nhcx.flow.biometric-fingerprint-iris + concepts: + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.hmis-integration-architecture + - nhcx.concept.participant-registry + sandbox: + - nhcx.sandbox.going-live + - nhcx.sandbox.support-contacts + - nhcx.sandbox.callback-url-requirements + errors: + - nhcx.error.nhcx-401 + glossary: + - nhcx.glossary.pmjay + - nhcx.glossary.tms + - shared.glossary.hmis + - shared.glossary.hfr +--- + +# Migrate a PMJAY hospital to HMIS through NHCX + +## In plain words + +A [PMJAY](../glossary/pmjay.md)-empanelled hospital submits claims through the [TMS](../glossary/tms.md) Provider portal until it migrates. After migration, its own [HMIS](../../shared/glossary/hmis.md) sends pre-authorisations and claims through the [National Health Claims Exchange](../../shared/glossary/nhcx.md) (NHCX). Cases already in flight finish in TMS. + +Migration has six steps. The first four are production onboarding with PMJAY's rules. The fifth is a manual mapping by NHA's NHCX Operations team, and that mapping is the switch that takes the hospital live. + +## Before you start + +- The hospital is active in PMJAY, and you know its Hospital Empanelment Module (HEM) ID, the hospital ID used in TMS. +- The hospital is registered in the [Health Facility Registry](../../shared/glossary/hfr.md) (HFR). Someone can receive SMS on the mobile number in that record. +- Your HMIS has passed the NHCX sandbox exit. See [The sandbox exit process and sign-off](../sandbox/sandbox-exit.md). +- You hold a production client ID with the provider role, and a production certificate in base64. See [Generate an encryption certificate and register it](generate-and-register-certificate.md). +- Your HMIS endpoint is HTTPS, publicly accessible and reachable from NHCX. See [the callback address rules](../sandbox/callback-url-requirements.md). + +## What happens + +```mermaid +sequenceDiagram + participant H as Hospital staff + participant You as Hospital HMIS + participant PS as NHCX participant service + participant Ops as NHA NHCX Operations team + participant NHCX as NHCX exchange + participant TMS as PMJAY TMS + You->>PS: POST /v2/participant/create with registrytype 10001 and role 10001 + PS-->>You: participantid and transactionid + PS->>H: SMS passcode + You->>PS: GET /validate with transactionId and passcode + PS-->>You: participant confirmed + You->>PS: POST /v2/participant/update with encryptioncert and endpointurl + PS-->>You: status and a new transactionid + PS->>H: SMS passcode + You->>PS: GET /update/validate with transactionId and passcode + PS-->>You: endpoint active and certificate registered + H->>Ops: ticket with HEM ID, participant ID and the other details + Note over Ops: manual mapping of the HEM ID to the participant ID + You->>NHCX: POST /v1/preauth/submit for cases started after mapping + Note over TMS: cases started before mapping finish here +``` + +Every call goes to the production participant service, `https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice`, with your session token. The mechanics of steps 1 to 4 are in [Onboard as a participant in production](production-onboarding.md). This flow adds PMJAY's rules. + +### 1. Create the participant + +`POST /v2/participant/create`: + +```json +{ + "registrytype": "10001", + "registryid": "", + "role": ["10001"], + "endpoint_url": "", + "mobilenumber": "", + "email": "" +} +``` + +- `registrytype` must be `10001`, HFR. A PMJAY hospital cannot use the other registry codes. +- `role` must be `10001`, provider. Any other role is rejected. +- `registryid` must exist in HFR. +- `mobilenumber` must exist in NHCX and match the HFR record exactly. This is the check that fails most. +- If a participant already exists for the registry ID, the call may reject or return the existing participant. + +The answer carries `participantid`, `facilityname`, `facilitycontact`, `facilityemail`, `transactionid` and a null `error`. The participant starts in a pending state. + +**Wait:** a passcode arrives by SMS. + +### 2. Confirm it + +`GET /validate?transactionId=&passcode=`. On success the participant becomes active, and you can register the technical details. + +### 3. Register the endpoint and certificate + +`POST /v2/participant/update` with `participantcode`, `encryptioncert` (the base64 certificate) and `endpointurl` (the HMIS base address). The participant must be active. The answer carries `participant_code`, `status` and a new `transactionid`. + +**Wait:** a second passcode arrives by SMS. + +### 4. Confirm the update + +`GET /update/validate?transactionId=&passcode=`. The passcode is valid for 24 hours. On success the endpoint is active and the certificate is registered, so NHCX can send requests to your HMIS and receive its responses. + +### 5. Ask for the mapping + +Raise a ticket with NHA's NHCX Operations team. They map the hospital's HEM ID to its NHCX participant ID by hand. The ticket carries: + +| Detail | Must be | +|---|---| +| PMJAY Hospital ID (HEM ID) | Active in TMS | +| NHCX participant ID | Active and configured | +| Hospital name | The same as in official records | +| Registered mobile | The same as in HFR | +| Endpoint URL | Live | +| Confirmation status | Step 4 completed | + +**Wait:** the mapping is manual. See [Where to get help with NHCX](../sandbox/support-contacts.md) for the channel. + +### 6. Go live + +The mapping is the go-live trigger. After it, processing splits by when each case was submitted: + +| Case | Processed in | +|---|---| +| Pre-authorisations and claims submitted before mapping | The TMS Provider portal | +| Pre-authorisations and claims submitted after mapping | Your HMIS, through NHCX | + +Your HMIS starts sending claim requests and status updates through NHCX. TMS stops taking new claims from the hospital and receives only the statuses of existing cases. + +Before go-live, confirm the checklist: participant created and validated, endpoint accessible, certificate configured, APIs tested, mapping completed, pilot successful. + +## How you know it worked + +`GET /update/validate` succeeded, and `POST /fetch/certs` for the hospital's participant code returns its certificate. After the mapping, a new pre-authorisation sent from the HMIS on `/v1/preauth/submit` receives `202`. The payer's answer then arrives at the HMIS endpoint on `/v1/preauth/on_submit`. + +```observation schema=exit-condition +channel: callback +path: /v1/preauth/on_submit +precondition: + mapping of HEM ID to participant ID: completed by the NHCX Operations team +match: + x-hcx-recipient_code: +``` + +## When it goes wrong + +| Symptom | Cause | Action | +|---|---|---| +| Create rejected for the registry | `registrytype` is not `10001` | Send `10001` | +| Create rejected for the role | `role` is not `10001` | Send `10001` | +| Create rejected for the mobile | It does not match HFR | Update the mobile number, then create again | +| No passcode arrives | A network issue | Retry the call | +| The transaction is lost | A session issue | Start the step again for a fresh transaction ID | + +- **The participant already exists.** The call rejected the create or returned the existing participant. Continue with the existing participant ID. +- **The mapping ticket is sent back.** One detail fails its check. It may be an inactive HEM ID, a participant not yet configured, or a name or mobile mismatch. An endpoint that is not live, or an incomplete step 4, also fails. +- **New cases still go to TMS.** The mapping has not been done yet. Nothing on your side switches routing. +- **`401` on any call.** The token has expired, or it came from a sandbox client ID. See [NHCX-401](../errors/nhcx-401.md). diff --git a/catalogue/nhcx/flows/pmjay-patient-to-cashless.md b/catalogue/nhcx/flows/pmjay-patient-to-cashless.md new file mode 100644 index 000000000..cb36cdebb --- /dev/null +++ b/catalogue/nhcx/flows/pmjay-patient-to-cashless.md @@ -0,0 +1,184 @@ +--- +id: nhcx.flow.pmjay-patient-to-cashless +type: flow +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Take a PMJAY patient from registration to cashless treatment +summary: >- + Take a PMJAY patient from registration to an approved preauthorisation: find the + payer and policy, fetch the plan, check eligibility, authenticate, then submit. +sources: +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Chapter I and II; 5.5 payer search; 5.6 identifier cascade; admission layers table. +- url: https://hcxsbx.abdm.gov.in/images/53347f5988b0ce5396f1.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_APIs to be called based on scenario.xlsx + hash: sha256:f92a30673d65dd2cc3cf09e2087c624f23f781dc4ca6b5cd8ec1825e224ac108 + fetched: '2026-09-14' + note: NHCX_APIs to be called based on scenario, row 26 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sheet Scenarios, rows 1 to 6. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, item 7. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. FAQ 27 question 4. +- url: https://hcxsbx.abdm.gov.in/images/c42ad170f37c987ed173.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx + hash: sha256:f56dd156c232192296082f23b1561d0ff11fd40992e6675de41c5c991d579e6d + fetched: '2026-09-14' + note: Workflow Status Sheets(with Codes), row 12 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet1. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.get-session + - nhcx.endpoint.fetch-participants-list + - nhcx.endpoint.participant-get-policies + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.insuranceplan-request + - nhcx.endpoint.insuranceplan-on-request + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.coverageeligibility-on-check + - nhcx.endpoint.abha-biometric-auth-init + - nhcx.endpoint.abha-biometric-auth-verify + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.preauth-on-submit + callbacks: + - nhcx.callback.insuranceplan-on-request + - nhcx.callback.coverageeligibility-on-check + - nhcx.callback.preauth-on-submit + concepts: + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.hmis-integration-architecture + - nhcx.concept.policy-linking + - nhcx.concept.biometric-authentication + - nhcx.concept.claim-cycle + - nhcx.concept.session-token + flows: + - nhcx.flow.pmjay-hospital-migration + - nhcx.flow.claim-submit + - nhcx.flow.biometric-face + - nhcx.flow.biometric-fingerprint-iris + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.insurance-plan-request + - nhcx.flow.preauth-query-response + - nhcx.flow.preauth-submit + tests: + - nhcx.test.tc-abha-01 + - nhcx.test.tc-hbp-01 + - nhcx.test.tc-ce-01 + - nhcx.test.tc-pa-01 + errors: + - nhcx.error.nhcx-401 + - nhcx.error.payr-1004 + - nhcx.error.payr-1256 + - nhcx.error.payr-1401 + - nhcx.error.payr-1405 + glossary: + - nhcx.glossary.pmjay + - nhcx.glossary.tpa + - shared.glossary.abha-number + - shared.glossary.hfr + - shared.glossary.hmis + - shared.glossary.nhcx + troubleshooting: + - nhcx.troubleshooting.everything-returns-401 +--- + +# Take a PMJAY patient from registration to cashless treatment + +## In plain words + +A [PMJAY](../glossary/pmjay.md) patient does not become cashless because they hold a card. Your hospital must first find the payer, confirm the linked policy, and learn the plan's rules. Only then can you check eligibility and ask for preauthorisation. + +Two things must both be true. In your [HMIS](../../shared/glossary/hmis.md), the admission is converted from cash to insurance, with the scheme, payer, identifier and policy number attached. For the [NHCX](../../shared/glossary/nhcx.md) exchange, you have resolved the payer's code, the policy and the member ID. + +The order is fixed: find the payer, find the policy, resolve the codes, fetch the plan, check eligibility, authenticate, submit the preauthorisation. [PMJAY on NHCX](../concepts/pmjay-on-nhcx.md) explains how PMJAY differs from the standard exchange. + +## Before you start + +- Your hospital is migrated to HMIS through NHCX and mapped to its PMJAY hospital ID. See [migrate a PMJAY hospital](pmjay-hospital-migration.md). +- You hold your client credentials and can get a [session token](../concepts/session-token.md) from [/get/session](../endpoints/get-session.md). +- Your callback endpoint is registered and answers within 30 seconds. +- The patient is present, with their [ABHA number](../../shared/glossary/abha-number.md), member ID or registered mobile number. +- Your HMIS supports all three biometric methods: fingerprint, iris and face. + +## What happens + +```mermaid +sequenceDiagram + participant Pt as Patient + participant H as HMIS (your system) + participant N as NHCX + participant Y as Payer + Pt->>H: registers, gives ABHA number, member ID or mobile + H->>N: POST /fetch/participants/list (role PAYER) + N-->>H: payer list + H->>N: POST /participant/get/policies + N-->>H: linked policies with payerid and processingid + H->>N: POST /fetch/certs + N-->>H: recipient certificate + H->>N: POST /v1/insuranceplan/request + N-->>H: HTTP 202 Accepted + N->>Y: POST /v1/insuranceplan/request + Y->>N: POST /v1/insuranceplan/on_request + N->>H: POST /v1/insuranceplan/on_request + H->>N: POST /v1/coverageeligibility/check (validation, then auth-requirements) + N-->>H: HTTP 202 Accepted + N->>Y: POST /v1/coverageeligibility/check + Y->>N: POST /v1/coverageeligibility/on_check + N->>H: POST /v1/coverageeligibility/on_check + Pt->>H: biometric capture + H->>N: POST /hcx/abha/biometric/auth/init, then auth/verify + N-->>H: authentication result + H->>N: POST /v1/preauth/submit (workflow 12) + N-->>H: HTTP 202 Accepted + N->>Y: POST /v1/preauth/submit + Y->>N: POST /v1/preauth/on_submit + N->>H: POST /v1/preauth/on_submit (approval, query or rejection) + H-->>Pt: cashless treatment confirmed +``` + +Every exchange call is acknowledged with `202 Accepted`. Its answer arrives later on your callback, which you acknowledge with `202` within 30 seconds. + +1. Register the patient. In your HMIS, convert the admission from cash to insurance, with the scheme, payer, identifier type and value, and policy number. +2. Find the payer. Call [POST /fetch/participants/list](../endpoints/fetch-participants-list.md) with role `PAYER`, and let the user pick one. +3. Find the linked policies. Call [POST /participant/get/policies](../endpoints/participant-get-policies.md). Try the ABHA number first, then the member ID, then the mobile number. +4. If no policy comes back, send a [coverage eligibility check](coverage-eligibility-check.md) with purpose `discovery` to get the active policy code. +5. Resolve three values: the policy number, the member ID and the recipient code. Use the `processingid` from the policy lookup as `x-hcx-recipient_code`, not the `payerid`. +6. If you cannot resolve a recipient code, stop. Do not send eligibility or preauthorisation until the policy lookup succeeds. +7. Fetch the recipient's certificate with [POST /fetch/certs](../endpoints/fetch-certs.md). +8. [Request the insurance plan](insurance-plan-request.md) and cache it. It holds the packages, rates, conditions and document rules. +9. [Check coverage eligibility](coverage-eligibility-check.md). Use `validation` after registration for the wallet balance. Use `benefits` before the preauthorisation, and `auth-requirements` once the packages are chosen. +10. Authenticate the beneficiary by [fingerprint or iris](biometric-fingerprint-iris.md) or [face](biometric-face.md). Where that is not possible, complete the Authentication Consent Questionnaire. +11. [Submit the preauthorisation](preauth-submit.md) with workflow `12`, for no more than the balance left. + +## How you know it worked + +The patient is cashless when all of these hold: + +- The admission in your HMIS is marked insurance, with the scheme, payer, member ID and policy number. +- You stored the recipient code, from the policy lookup's `processingid`, against the admission. +- The insurance plan and the eligibility responses are stored against the admission. +- You received `POST /v1/preauth/on_submit` with `x-hcx-workflow_id` `21`, and stored its `preAuthRef`. + +A preauthorisation query, workflow `24`, hands over to [answer a payer query](preauth-query-response.md). A rejection, workflow `23`, ends the cashless path for this admission. + +## When it goes wrong + +The policy lookup returns nothing. Try the next identifier in the order ABHA number, member ID, mobile number. Then use eligibility with purpose `discovery`. See [linking an ABHA to a policy](../concepts/policy-linking.md). + +The request goes to the wrong participant. The `payerid` names the insurer. The `processingid` names who adjudicates, the [TPA](../glossary/tpa.md) where there is one. Address every request to the `processingid`. + +The payer refuses the policy or your hospital. [PAYR-1401](../errors/payr-1401.md) means the policy is not allowed for your hospital. [PAYR-1405](../errors/payr-1405.md) means the payer has no enrolled hospital for your [HFR](../../shared/glossary/hfr.md) ID. [PAYR-1004](../errors/payr-1004.md) from a payer on the published standard means your hospital is not registered for this policy. + +Authentication is missing. [PAYR-1256](../errors/payr-1256.md) means the preauthorisation carried neither biometric authentication nor the consent questionnaire response. + +Every call returns 401. [NHCX-401](../errors/nhcx-401.md) means your session token is missing or expired. Get a new one and retry. See [every NHCX call returns 401](../troubleshooting/everything-returns-401.md). diff --git a/catalogue/nhcx/flows/policy-link-and-delink.md b/catalogue/nhcx/flows/policy-link-and-delink.md new file mode 100644 index 000000000..900c7d401 --- /dev/null +++ b/catalogue/nhcx/flows/policy-link-and-delink.md @@ -0,0 +1,180 @@ +--- +id: nhcx.flow.policy-link-and-delink +type: flow +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Link and de-link an ABHA and a policy +summary: >- + As an insurer or claims administrator, record which beneficiaries hold which products + so that hospitals can find their cover, and remove the record when it ends. +sources: +- url: https://hcxsbx.abdm.gov.in/images/539853c50347b32b9a5e.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Policy Linking and De-Linking Process.pdf + hash: sha256:420115b9a54e15fa625312a56362164d92d23dd0d6ebf9195135bb00055d1911 + fetched: '2026-09-14' + note: Policy Linking and De-Linking Process, row 8 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2. +- url: https://hcxsbx.abdm.gov.in/images/b885e59891fedc7e725c.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-PARTICIPANT SERVICE_APIs Postman Collection.zip + hash: sha256:2d082f244ee41d137a62af82380dcd2d5db9ebbab66824fd54a23c506d4d9a7f + fetched: '2026-09-14' + note: AWS(Sandbox)-PARTICIPANT SERVICE_APIs Postman Collection, row 16 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Get Policies request body. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, item 10. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.session-token + - nhcx.endpoint.participant-link-abha-policy + - nhcx.endpoint.participant-get-policies + - nhcx.endpoint.participant-delink-abha-policy + flows: + - nhcx.flow.production-onboarding + - nhcx.flow.sandbox-onboarding + - nhcx.flow.send-a-sealed-request + concepts: + - nhcx.concept.policy-linking + - nhcx.concept.participant-code + tests: + - nhcx.test.payer-uc-01 + - nhcx.test.payer-uc-02 + - nhcx.test.payer-uc-03 + - nhcx.test.provider-uc-02 + sandbox: + - nhcx.sandbox.environments-and-base-urls + - nhcx.sandbox.support-contacts + errors: + - nhcx.error.nhcx-401 + glossary: + - nhcx.glossary.payer + - nhcx.glossary.tpa + - shared.glossary.abha-number +--- + +# Link and de-link an ABHA and a policy + +## In plain words + +A hospital finds a patient's insurance on the [National Health Claims Exchange](../../shared/glossary/nhcx.md) (NHCX) by looking up the patient's [ABHA number](../../shared/glossary/abha-number.md), member ID or mobile. The lookup finds only policies a [payer](../glossary/payer.md) has linked. A link records which products a member holds, and which participants handle them. + +The payer links a policy when the individual buys it. It de-links the policy when the policy ends, or when the insurer moves to another [TPA](../glossary/tpa.md). + +## Before you start + +- Every insurer has its own participant code, even when a TPA processes its claims. See [Onboard as a participant in production](production-onboarding.md). +- You hold a session token minted with the client ID used when the payer or TPA participant was created. De-linking checks this. +- For each member you have the ABHA number, mobile number and member ID, and each product's ID and name. +- You know the participant service base address: `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice` in the sandbox, `https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice` in production. + +## What happens + +```mermaid +sequenceDiagram + participant Pay as Payer system, insurer or TPA + participant PS as NHCX participant service + participant Prov as Provider system + Pay->>PS: POST /participant/link/abha/policy + PS-->>Pay: response + Prov->>PS: POST /participant/get/policies with the ABHA number + PS-->>Prov: linked policies with payerid and processingid + Note over Prov: sends requests to the processingid + Pay->>PS: POST /participant/delink/abha/policy + Note over PS: the token's client ID must belong to the payerid or processingid participant + PS-->>Pay: de-linked, or refused with an error message +``` + +Every call answers in its own response. Nothing arrives later. + +### 1. Link + +`POST {base}/participant/link/abha/policy`: + +```json +{ + "requestid": "", + "abhanumber": "", + "mobilenumber": "", + "memberid": "", + "payerid": "", + "processingid": "", + "policies": [ + { + "productid": "", + "productname": "" + } + ] +} +``` + +- `payerid` is always the insurer's own participant code. +- `processingid` is the participant code of the TPA under which the insurer is mapped. +- `policies` lists every product the member holds with this insurer. + +Put `/participant/link/abha/policy` directly after the base address. The base already ends in `/participanthcxservice`, so that segment appears once. + +### 2. Check the link + +`POST {base}/participant/get/policies`: + +```json +{ + "identifiertype": "AbhaNumber", + "identifiervalue": "" +} +``` + +`identifiertype` is `AbhaNumber`, `MemberId` or `MobileNo`. This is the same call a hospital makes. The hospital then addresses its requests to the `processingid` in the answer. + +### 3. De-link + +`POST {base}/participant/delink/abha/policy`: + +```json +{ + "requestid": "", + "payerid": "", + "memberid": "", + "processingid": "", + "policies": [ + { + "productid": "", + "productname": "" + } + ] +} +``` + +Include `processingid` when the policy was linked with one. List only the products to remove. + +NHCX reads the client ID from your token. It allows the de-link only when that client ID registered the insurer named in `payerid` or the TPA named in `processingid`. + +### 4. When the insurer changes TPA + +De-link the existing policies. Link them again with the new TPA's participant code as `processingid`. + +## How you know it worked + +After linking, `POST /participant/get/policies` with the member's ABHA number returns the policy with your `payerid` and `processingid`. After de-linking, the same lookup no longer returns the products you removed. + +```observation schema=exit-condition +channel: synchronous +call: POST /participant/get/policies +request: + identifiertype: AbhaNumber + identifiervalue: +match: + after link: the policy appears with your payerid and processingid + after de-link: the removed products are absent +``` + +## When it goes wrong + +- **The de-link is refused.** Your token was minted with a client ID that did not register the `payerid` or `processingid` participant. Mint it with the right client ID. If the IDs still do not match, confirm them with the NHCX team by email. See [Where to get help with NHCX](../sandbox/support-contacts.md). +- **"There is no policies with requested details".** The product you asked to de-link is not in the member's linked list. Check `productid`, `productname` and `memberid` against what you linked. +- **`404` on link or de-link.** The address repeats `/participanthcxservice`. Use it once. +- **Hospitals send requests to the wrong participant.** They addressed the `payerid` instead of the `processingid` from the lookup. +- **`401` on any call.** Get a new session token. See [NHCX-401](../errors/nhcx-401.md). diff --git a/catalogue/nhcx/flows/preauth-cancel.md b/catalogue/nhcx/flows/preauth-cancel.md new file mode 100644 index 000000000..c54038f50 --- /dev/null +++ b/catalogue/nhcx/flows/preauth-cancel.md @@ -0,0 +1,141 @@ +--- +id: nhcx.flow.preauth-cancel +type: flow +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Cancel a preauthorisation +summary: >- + Withdraw a preauthorisation you no longer need, for example after the treatment + plan changes, before any claim is raised against it. +sources: +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. pages 32-33, 8.4.5 Cancellation. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Preauth cancel Task table; workflow code table. +- url: https://hcxsbx.abdm.gov.in/images/c42ad170f37c987ed173.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx + hash: sha256:f56dd156c232192296082f23b1561d0ff11fd40992e6675de41c5c991d579e6d + fetched: '2026-09-14' + note: Workflow Status Sheets(with Codes), row 12 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet1, Preauthorization Cancellation rows. +- url: https://hcxsbx.abdm.gov.in/images/53347f5988b0ce5396f1.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_APIs to be called based on scenario.xlsx + hash: sha256:f92a30673d65dd2cc3cf09e2087c624f23f781dc4ca6b5cd8ec1825e224ac108 + fetched: '2026-09-14' + note: NHCX_APIs to be called based on scenario, row 26 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sheet Scenarios, row 9. +- url: https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip + member: FHIR_bundles_PMJAY_ext/preauth/cancel/preauth_cancel_response.txt + hash: sha256:8c7b24e3022733aaf7e8f517e12c11c0e8eddd6293844a2c4f3e9700fb720dca + fetched: '2026-09-14' + note: Sample FHIR bundles, row 29 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. ClaimResponse resource. +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. PAYR-1237 and PAYR-1238 rows. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.task-submit + - nhcx.endpoint.task-on-submit + callbacks: + - nhcx.callback.task-submit + - nhcx.callback.task-on-submit + - nhcx.callback.error + fhir: + - nhcx.fhir.preauth-cancel + - nhcx.fhir.task + concepts: + - nhcx.concept.reprocess-and-cancel + - nhcx.concept.workflow-codes + tests: + - nhcx.test.provider-uc-12 + - nhcx.test.payer-uc-14 + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + - nhcx.flow.send-a-sealed-request + - nhcx.flow.status-check + errors: + - nhcx.error.err-pyr-clm-007 + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1001 + glossary: + - nhcx.glossary.payer +--- + +# Cancel a preauthorisation + +## In plain words + +Cancelling withdraws a preauthorisation you no longer need. The patient may have changed treatment, or left before the procedure. Until the claim is raised, you can cancel. + +An open preauthorisation blocks a new one for the same beneficiary, at your hospital and at any other. Cancelling releases it. + +You cancel with a FHIR Task, not a Claim, on `/v1/task/submit`. The workflow code is `PC01`. The [payer](../glossary/payer.md) confirms on `/v1/task/on_submit` with a completed Task that points to a ClaimResponse whose adjudication reason is `cancelled`. + +## Before you start + +- The preauthorisation exists and no claim has been raised against it. +- You have its claim identifier, the case number the payer knows it by. +- You know why you are cancelling. `treatmentplanchanged` is the published reason code for a changed treatment plan. +- Your session token, callback endpoint and the payer's certificate are in place, as in [send a sealed request](send-a-sealed-request.md). + +## What happens + +```mermaid +sequenceDiagram + participant P as Provider (your system) + participant N as NHCX + participant Y as Payer + P->>N: POST /v1/task/submit (workflow PC01) + Note right of P: Task code cancel, input claim number + N-->>P: HTTP 202 Accepted + N->>Y: POST /v1/task/submit + Y-->>N: HTTP 202 Accepted + Note over Y: payer cancels the case + Y->>N: POST /v1/task/on_submit (workflow PC02) + N-->>Y: HTTP 202 Accepted + N->>P: POST /v1/task/on_submit + P-->>N: HTTP 202 Accepted, within 30 seconds + Note left of P: Task completed, ClaimResponse reason cancelled +``` + +1. Build a Task bundle, as in [the preauthorisation cancel bundles](../fhir/preauth-cancel.md). Set Task `status` to `requested`, `intent` to `order`, and `code` to `cancel` from the financial task code system. +2. Set `reasonCode`, for example `treatmentplanchanged`. Add the inputs for the claim number and the intimation number. Both carry the preauthorisation's claim identifier. Set `requester` to your organisation and `owner` to the payer. +3. Seal and set the headers, as in [send a sealed request](send-a-sealed-request.md). Set `x-hcx-workflow_id` to `PC01`, Preauthorization Cancellation, and `x-hcx-status` to `request.initiated`. +4. Start a new correlation. Set `x-hcx-correlation_id` to the value of this call's `x-hcx-api_call_id`. +5. Call [POST /v1/task/submit](../endpoints/task-submit.md). NHCX answers `202 Accepted`. It is not the confirmation. +6. Receive [POST /v1/task/on_submit](../callbacks/task-on-submit.md). Answer `202 Accepted` within 30 seconds, then process. +7. Read `type`. `ProtocolResponse` means the payer could not process the request. Otherwise decrypt `payload` with your private key. +8. Find the Task. Its `status` is `completed`. Follow its `output` reference to the ClaimResponse in the same bundle. +9. Confirm the ClaimResponse `outcome` is `complete` and its adjudication reason is `cancelled`. Workflow `PC02`, Preauthorization Cancellation Accomplished, names this answer. + +## How you know it worked + +The preauthorisation is cancelled when all of these hold: + +- You received `POST /v1/task/on_submit` whose `x-hcx-correlation_id` equals the one you sent. +- Its `payload` decrypts, and the Task in it has `status` `completed`. +- The ClaimResponse the Task points to has `outcome` `complete` and adjudication reason `cancelled`. +- You marked the case cancelled, and stopped any claim work on it. + +## When it goes wrong + +The payer cannot find the case. [ERR-PYR-CLM-007](../errors/err-pyr-clm-007.md) means no preauthorisation or claim record exists for the case number. Check the claim number in the Task inputs against the identifier you used on the preauthorisation. + +A claim was already raised. Cancelling is allowed only until the claim is raised. Continue with the [claim](claim-submit.md) instead. + +NHCX rejects the request as a duplicate. [NHCX-1006](../errors/nhcx-1006.md) means you reused a correlation id. Start a new correlation for the cancellation. + +The callback is a `ProtocolResponse`. [PAYR-1001](../errors/payr-1001.md) means the payer could not decrypt your request. Fetch its certificate again and reseal. + +The 202 arrives and no confirmation follows. [Check the request's status](status-check.md). An undeliverable request comes back on [/v1/error](../callbacks/error.md). diff --git a/catalogue/nhcx/flows/preauth-enhancement.md b/catalogue/nhcx/flows/preauth-enhancement.md new file mode 100644 index 000000000..9fb51606b --- /dev/null +++ b/catalogue/nhcx/flows/preauth-enhancement.md @@ -0,0 +1,157 @@ +--- +id: nhcx.flow.preauth-enhancement +type: flow +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Request a preauthorisation enhancement +summary: >- + Ask the payer to raise an approved preauthorisation when the patient needs more + treatment than was approved, such as a move to intensive care. +sources: +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. page 32, 8.4.3 Enhancement. +- url: https://hcxsbx.abdm.gov.in/images/c42ad170f37c987ed173.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx + hash: sha256:f56dd156c232192296082f23b1561d0ff11fd40992e6675de41c5c991d579e6d + fetched: '2026-09-14' + note: Workflow Status Sheets(with Codes), row 12 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet1, Enhancement rows. +- url: https://hcxsbx.abdm.gov.in/images/53347f5988b0ce5396f1.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_APIs to be called based on scenario.xlsx + hash: sha256:f92a30673d65dd2cc3cf09e2087c624f23f781dc4ca6b5cd8ec1825e224ac108 + fetched: '2026-09-14' + note: NHCX_APIs to be called based on scenario, row 26 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sheet Scenarios, rows 4, 5 and 7. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. InsurancePlan claim condition table. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth, x-hcx-use_case row. +- url: https://hcxsbx.abdm.gov.in/preauthhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/preauthhcxservice.json + hash: sha256:2e8c594c51d9640ae4a576be34a5d190614918d1e7697d6718bc91c31fa66948 + fetched: '2026-09-14' + note: 'API specification: preauthhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths /v1/preauth/submit and /v1/preauth/on_submit.' +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.preauth-on-submit + callbacks: + - nhcx.callback.preauth-submit + - nhcx.callback.preauth-on-submit + - nhcx.callback.error + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.preauth-response + - nhcx.fhir.preauth-enhancement + concepts: + - nhcx.concept.claim-cycle + - nhcx.concept.message-identifiers + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.insurance-plan-request + - nhcx.flow.preauth-query-response + - nhcx.flow.send-a-sealed-request + - nhcx.flow.status-check + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1212 + - nhcx.error.payr-1213 + - nhcx.error.payr-1235 + glossary: + - nhcx.glossary.enhancement + - nhcx.glossary.payer +--- + +# Request a preauthorisation enhancement + +## In plain words + +An [enhancement](../glossary/enhancement.md) asks the payer to raise an approved preauthorisation. You send it when the patient needs more than was approved. A transfer from the ward to intensive care is the common case. + +It travels on the same path as the first [preauthorisation](preauth-submit.md), `/v1/preauth/submit`, with workflow `13`. It is a new request: new correlation id, same claim identifier. The Claim lists the approved items plus the new ones. + +The [payer](../glossary/payer.md) answers on `/v1/preauth/on_submit`. Workflow `22` approves the enhancement, `231` denies it and `241` queries it. + +## Before you start + +- The case holds an approved preauthorisation: you received workflow `21` and stored its `preAuthRef`. +- No adjudication is running on the case. A pending query or an earlier enhancement must finish first. +- Each package you plan to add allows enhancement. Check its `EnhancementAllowed` claim condition in the cached [insurance plan](insurance-plan-request.md). +- You ran a [coverage eligibility check](coverage-eligibility-check.md) with `benefits`, and with `auth-requirements` for the new packages, and collected the documents it named. +- You still have the claim identifier and the bundle you sent for the approved preauthorisation. + +## What happens + +```mermaid +sequenceDiagram + participant P as Provider (your system) + participant N as NHCX + participant Y as Payer + P->>N: POST /v1/preauth/submit (workflow 13) + Note right of P: same Claim identifier, new correlation id, added items + N-->>P: HTTP 202 Accepted + N->>Y: POST /v1/preauth/submit + Y-->>N: HTTP 202 Accepted + Note over Y: payer adjudicates the added treatment + Y->>N: POST /v1/preauth/on_submit + N-->>Y: HTTP 202 Accepted + N->>P: POST /v1/preauth/on_submit + P-->>N: HTTP 202 Accepted, within 30 seconds + alt workflow 22 + Note left of P: enhancement approved + else workflow 241 + Note left of P: enhancement queried, answer with workflow 131 + else workflow 231 + Note left of P: enhancement denied + end +``` + +1. Start from the bundle of the approved preauthorisation. Keep `Claim.identifier` and keep `use` `preauthorization`. +2. Add the new items, such as an intensive care stratification, with their procedures and documents in `supportingInfo`. Update `Claim.total`. See [the enhancement bundles](../fhir/preauth-enhancement.md). +3. Seal and set the headers, as in [send a sealed request](send-a-sealed-request.md). Set `x-hcx-workflow_id` to `13` and `x-hcx-status` to `request.initiated`. `x-hcx-use_case` `Enhancement` is optional. +4. Start a new correlation. Set `x-hcx-correlation_id` to the value of this call's `x-hcx-api_call_id`. The claim identifier, not the correlation id, ties the enhancement to the case. +5. Call [POST /v1/preauth/submit](../endpoints/preauth-submit.md). NHCX answers `202 Accepted`. It is not the decision. +6. Receive [POST /v1/preauth/on_submit](../callbacks/preauth-on-submit.md). Answer `202 Accepted` within 30 seconds, then process. +7. Read `type`. `ProtocolResponse` means the payer could not process the request. Otherwise decrypt `payload` with your private key. +8. Read `x-hcx-workflow_id`: + +| `x-hcx-workflow_id` | Meaning | What to do | +|---|---|---| +| `22` | Enhancement approved | Store the new approved `benefit` amount against the case | +| `241` | Enhancement queried | [Answer the query](preauth-query-response.md) with workflow `131` | +| `231` | Enhancement denied | Read `disposition` and the adjudication for the reason | + +## How you know it worked + +The enhancement is approved when all of these hold: + +- You received `POST /v1/preauth/on_submit` whose `x-hcx-correlation_id` equals the correlation id of your enhancement request. +- Its `type` is not `ProtocolResponse`, and `payload` decrypts with your private key. +- `x-hcx-workflow_id` is `22`, and the ClaimResponse carries the approved `benefit` for the added items. +- You updated the approved amount stored against the case. + +A callback with workflow `231` also ends this flow, as a denial. + +## When it goes wrong + +The payer finds no approved preauthorisation. [PAYR-1212](../errors/payr-1212.md) means no approved record exists for the case number. Check that you kept the original claim identifier. If the case was never approved, submit a new [preauthorisation](preauth-submit.md). + +The payer finds work in progress. [PAYR-1213](../errors/payr-1213.md) means adjudication is still running on the case. Wait for the current decision, then send the enhancement. + +NHCX rejects the request as a duplicate. [NHCX-1006](../errors/nhcx-1006.md) means you reused the correlation id of the original preauthorisation. Start a new correlation for every enhancement. + +The wallet cannot cover the increase. [PAYR-1235](../errors/payr-1235.md) means the balance is too low. Run a `validation` eligibility check to see the balance. + +The 202 arrives and no decision follows. [Check the request's status](status-check.md). An undeliverable request comes back on [/v1/error](../callbacks/error.md). diff --git a/catalogue/nhcx/flows/preauth-query-response.md b/catalogue/nhcx/flows/preauth-query-response.md new file mode 100644 index 000000000..9dd742bdc --- /dev/null +++ b/catalogue/nhcx/flows/preauth-query-response.md @@ -0,0 +1,182 @@ +--- +id: nhcx.flow.preauth-query-response +type: flow +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Answer a payer query on a preauthorisation +summary: >- + Send the payer the documents or clarification it asked for on a preauthorisation, + so that it can reach a decision. +sources: +- url: https://hcxsbx.abdm.gov.in/images/c42ad170f37c987ed173.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx + hash: sha256:f56dd156c232192296082f23b1561d0ff11fd40992e6675de41c5c991d579e6d + fetched: '2026-09-14' + note: Workflow Status Sheets(with Codes), row 12 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet1. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. 8.5 preauth response outcomes; query trail mapping table. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. pages 32-33, 8.4.4 Query updation. +- url: https://hcxsbx.abdm.gov.in/images/53347f5988b0ce5396f1.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_APIs to be called based on scenario.xlsx + hash: sha256:f92a30673d65dd2cc3cf09e2087c624f23f781dc4ca6b5cd8ec1825e224ac108 + fetched: '2026-09-14' + note: NHCX_APIs to be called based on scenario, row 26 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sheet Scenarios, row 8. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Communication. +- url: https://hcxsbx.abdm.gov.in/images/819467ec15aff13cc2a8.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Dummy Payer Implementation.pdf + hash: sha256:97335ebc4cd32c86e0c34328b2f4c526420b32a7a009208364043d6334e9e757 + fetched: '2026-09-14' + note: NHCX Dummy Payer Implementation, row 19 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Preauth steps 2 to 5. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.preauth-on-submit + - nhcx.endpoint.communication-request + - nhcx.endpoint.communication-on-request + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.preauth-submit + - nhcx.callback.communication-request + - nhcx.callback.communication-on-request + fhir: + - nhcx.fhir.preauth-response + - nhcx.fhir.task + tests: + - nhcx.test.tc-pa-02 + - nhcx.test.provider-uc-08 + - nhcx.test.payer-uc-10 + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.preauth-enhancement + - nhcx.flow.claim-query-response + - nhcx.flow.status-check + concepts: + - nhcx.concept.queries-and-communication + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1011 + - nhcx.error.payr-1001 + - nhcx.error.payr-1218 + - nhcx.error.payr-1219 + glossary: + - nhcx.glossary.communication-request + - nhcx.glossary.payer + - nhcx.glossary.pmjay + sandbox: + - nhcx.sandbox.dummy-payer + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback +--- + +# Answer a payer query on a preauthorisation + +## In plain words + +A payer query means the [payer](../glossary/payer.md) cannot decide your preauthorisation yet. It needs more documents or a clarification. The case stays open until you answer. + +A query reaches you by one of two routes. Where it arrives tells you how to answer. + +| The query arrives on | It looks like | You answer on | +|---|---|---| +| `/v1/preauth/on_submit` | Workflow `24`, or `241` for an enhancement. ClaimResponse `outcome` `partial`, adjudication reason `queried` | `/v1/preauth/submit`, workflow `19`, or `131` for an enhancement | +| `/v1/communication/request` | A Task with `code` `poll` carrying a [communication request](../glossary/communication-request.md) | `/v1/communication/on_request` | + +After your answer, the payer sends its decision on `/v1/preauth/on_submit`. [Payer queries and the communication cycle](../concepts/queries-and-communication.md) explains both routes. + +## Before you start + +- You submitted a [preauthorisation](preauth-submit.md) or an [enhancement](preauth-enhancement.md), and kept its claim identifier and bundle. +- A query has arrived by one of the two routes above, and you answered its delivery with `202` within 30 seconds. +- You have collected the documents or the clarification the query asks for. +- In the sandbox, the [dummy payer](../sandbox/dummy-payer.md) raises a query when you drive it with the action `Query`, and uses the communication route. + +## What happens + +```mermaid +sequenceDiagram + participant P as Provider (your system) + participant N as NHCX + participant Y as Payer + alt query as a ClaimResponse + Y->>N: POST /v1/preauth/on_submit (workflow 24) + N->>P: POST /v1/preauth/on_submit + P-->>N: HTTP 202 Accepted, within 30 seconds + P->>N: POST /v1/preauth/submit (workflow 19) + Note right of P: same Claim identifier, added documents, new correlation id + N-->>P: HTTP 202 Accepted + N->>Y: POST /v1/preauth/submit + Y-->>N: HTTP 202 Accepted + else query as a communication request + Y->>N: POST /v1/communication/request + N-->>Y: HTTP 202 Accepted + N->>P: POST /v1/communication/request + P-->>N: HTTP 202 Accepted, within 30 seconds + P->>N: POST /v1/communication/on_request + Note right of P: Communication with the documents, same correlation id + N-->>P: HTTP 202 Accepted + N->>Y: POST /v1/communication/on_request + Y-->>N: HTTP 202 Accepted + end + Note over Y: payer decides + Y->>N: POST /v1/preauth/on_submit (workflow 21, 23 or 24) + N->>P: POST /v1/preauth/on_submit + P-->>N: HTTP 202 Accepted +``` + +### The query arrives as a ClaimResponse + +1. Receive [POST /v1/preauth/on_submit](../callbacks/preauth-on-submit.md) with workflow `24`. Answer `202` within 30 seconds, then decrypt. +2. Read what the payer asked. For [PMJAY](../glossary/pmjay.md), `ClaimResponse.item[].adjudication[].reason.coding.display` carries a trail of entries in the form `USER~datetime~type~comment~trust`, separated by `|`. Parse it as plain text. The comment is the question. +3. Add the requested documents to `supportingInfo` in the same Claim. Keep `Claim.identifier` and `use` `preauthorization`. +4. Set `x-hcx-workflow_id` to `19`, or `131` when the query was on an enhancement. Set `x-hcx-status` to `request.initiated`. +5. Start a new correlation: set `x-hcx-correlation_id` to the value of this call's `x-hcx-api_call_id`. The claim identifier ties the answer to the case. +6. Call [POST /v1/preauth/submit](../endpoints/preauth-submit.md). NHCX answers `202 Accepted`. + +### The query arrives as a communication request + +1. Receive [POST /v1/communication/request](../callbacks/communication-request.md). Answer `202` within 30 seconds, then decrypt. +2. Read `Task.reasonCode` and the communication resource. They say what the payer needs. +3. Build the answer as a Task bundle whose Task carries a `Communication`. Put the documents in `Communication.payload` as `contentAttachment`. See [the Task bundle](../fhir/task.md). +4. Set `x-hcx-status` to `response.complete`. Set `x-hcx-correlation_id` to the correlation id of the communication request. Use a fresh `x-hcx-api_call_id`. +5. Address it to the sender of the communication request. Call [POST /v1/communication/on_request](../endpoints/communication-on-request.md). NHCX answers `202 Accepted`. + +### Either route: wait for the decision + +The payer re-adjudicates and sends its decision on `/v1/preauth/on_submit`. Read it as in [submit a preauthorisation](preauth-submit.md): `21` approved, `23` rejected, `24` queried again. + +## How you know it worked + +The query is resolved when all of these hold: + +- NHCX accepted your answer with `202`: on `/v1/preauth/submit` with workflow `19` or `131`, or on `/v1/communication/on_request`. +- You then received `POST /v1/preauth/on_submit` for this case, and its `payload` decrypts. +- Its `x-hcx-workflow_id` is `21` or `22` with a `preAuthRef`, or `23`, a rejection. + +A further `24` or `241` means the payer asks again. Repeat this flow. + +## When it goes wrong + +The payer says the case is not queried. [PAYR-1219](../errors/payr-1219.md) means the case number is not in a queried state. [PAYR-1218](../errors/payr-1218.md) means the payer has no queried preauthorisation for it. Check that you kept the original claim identifier, and that you answered the query rather than the first submission. + +NHCX rejects your query update as a duplicate. [NHCX-1006](../errors/nhcx-1006.md) means you reused an earlier correlation id on `/v1/preauth/submit`. Start a new correlation. + +NHCX rejects your communication answer. [NHCX-1010](../errors/nhcx-1010.md) means no request exists with the correlation id you set. Copy the correlation id from the communication request exactly. [NHCX-1011](../errors/nhcx-1011.md) means the `x-hcx-status` value is not valid. + +The payer cannot open your answer. A `ProtocolResponse` with [PAYR-1001](../errors/payr-1001.md) means it could not decrypt. Fetch its certificate again and reseal. + +No decision follows your answer. [Check the status](status-check.md) of your answer's correlation id. See [accepted, then no callback](../troubleshooting/accepted-then-no-callback.md). diff --git a/catalogue/nhcx/flows/preauth-submit.md b/catalogue/nhcx/flows/preauth-submit.md new file mode 100644 index 000000000..d6464dfa4 --- /dev/null +++ b/catalogue/nhcx/flows/preauth-submit.md @@ -0,0 +1,201 @@ +--- +id: nhcx.flow.preauth-submit +type: flow +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Submit a preauthorisation +summary: >- + Ask the payer to approve a planned treatment before it starts, then read the decision + when it arrives. +sources: +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: 'NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 8 PreAuth: Claim tables, 8.5 response outcomes, workflow codes.' +- url: https://hcxsbx.abdm.gov.in/images/3799f26f2a0b2c9a80c5.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Preauthorization.pdf + hash: sha256:75d5628e7dd8a8e1a55c4ab3836c0591088ba378a8cd498e8277d83911129439 + fetched: '2026-09-14' + note: Preauthorization, listed on https://hcxsbx.abdm.gov.in/#/documents, not named in the NHCX document sheet. Preauthorization Submission request and response. +- url: https://hcxsbx.abdm.gov.in/images/53347f5988b0ce5396f1.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_APIs to be called based on scenario.xlsx + hash: sha256:f92a30673d65dd2cc3cf09e2087c624f23f781dc4ca6b5cd8ec1825e224ac108 + fetched: '2026-09-14' + note: NHCX_APIs to be called based on scenario, row 26 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sheet Scenarios, row 6. +- url: https://hcxsbx.abdm.gov.in/images/c42ad170f37c987ed173.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx + hash: sha256:f56dd156c232192296082f23b1561d0ff11fd40992e6675de41c5c991d579e6d + fetched: '2026-09-14' + note: Workflow Status Sheets(with Codes), row 12 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet1. +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. PAYR-1237 and PAYR-1238 rows. +- url: https://hcxsbx.abdm.gov.in/preauthhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/preauthhcxservice.json + hash: sha256:2e8c594c51d9640ae4a576be34a5d190614918d1e7697d6718bc91c31fa66948 + fetched: '2026-09-14' + note: 'API specification: preauthhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths /v1/preauth/submit and /v1/preauth/on_submit.' +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.preauth-on-submit + callbacks: + - nhcx.callback.preauth-submit + - nhcx.callback.preauth-on-submit + - nhcx.callback.error + fhir: + - nhcx.fhir.collection-bundle + - nhcx.fhir.terminologies + - nhcx.fhir.validation + - nhcx.fhir.preauth-request + - nhcx.fhir.preauth-response + concepts: + - nhcx.concept.claim-cycle + - nhcx.concept.four-message-legs + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.status-lifecycle + - nhcx.concept.workflow-codes + tests: + - nhcx.test.provider-uc-07 + - nhcx.test.payer-uc-09 + - nhcx.test.tc-pa-01 + flows: + - nhcx.flow.pmjay-patient-to-cashless + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.payer-process-a-request + - nhcx.flow.biometric-face + - nhcx.flow.biometric-fingerprint-iris + - nhcx.flow.claim-submit + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.insurance-plan-request + - nhcx.flow.preauth-cancel + - nhcx.flow.preauth-enhancement + - nhcx.flow.preauth-query-response + - nhcx.flow.send-a-sealed-request + - nhcx.flow.status-check + decisions: + - nhcx.decision.preauth-or-predetermination + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1001 + - nhcx.error.payr-1201 + - nhcx.error.payr-1216 + - nhcx.error.payr-1217 + - nhcx.error.payr-1231 + - nhcx.error.payr-1235 + - nhcx.error.payr-1237 + - nhcx.error.payr-1238 + - nhcx.error.payr-1256 + glossary: + - nhcx.glossary.payer + - nhcx.glossary.pmjay + - nhcx.glossary.preauthorisation + - shared.glossary.abha-number + - shared.glossary.hpr + - shared.glossary.nhcx + - shared.glossary.snomed-ct + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback + - nhcx.troubleshooting.bundle-rejected +--- + +# Submit a preauthorisation + +## In plain words + +[Preauthorisation](../glossary/preauthorisation.md) asks the payer to approve a treatment before you deliver it. You send a Claim bundle whose `Claim.use` is `preauthorization`. The [payer](../glossary/payer.md) answers later with one of four decisions: approved, partially approved, queried or rejected. + +An approval carries a preauthorisation reference, `ClaimResponse.preAuthRef`. It is the payer's commitment to pay the approved amount. You need it to submit the [claim](claim-submit.md) after discharge. + +The request travels through the [NHCX](../../shared/glossary/nhcx.md) exchange, sealed for the payer. The decision comes back as a callback to your registered endpoint. + +## Before you start + +- You have run a [coverage eligibility check](coverage-eligibility-check.md) with `auth-requirements` for the packages, and collected the documents it named. +- You hold the patient's [insurance plan](insurance-plan-request.md), so package codes, rates and document rules are known. +- The amount you will request is no more than the balance the eligibility check returned. +- The Patient resource carries the patient's [ABHA number](../../shared/glossary/abha-number.md). For [PMJAY](../glossary/pmjay.md) it also carries the member ID. +- You authenticated the beneficiary by [fingerprint or iris](biometric-fingerprint-iris.md) or [face](biometric-face.md). Where that is not possible, you have the completed Authentication Consent Questionnaire response to attach. +- You have the treating practitioner's [HPR](../../shared/glossary/hpr.md) ID. +- The beneficiary has no other active preauthorisation, here or at another hospital. +- Your session token, callback endpoint and the payer's certificate are in place, as in [send a sealed request](send-a-sealed-request.md). + +## What happens + +```mermaid +sequenceDiagram + participant P as Provider (your system) + participant N as NHCX + participant Y as Payer + P->>N: POST /v1/preauth/submit (workflow 12) + N-->>P: HTTP 202 Accepted + N->>Y: POST /v1/preauth/submit + Y-->>N: HTTP 202 Accepted + opt payer acknowledges receipt + Y->>N: POST /v1/preauth/on_submit (workflow 20, response.partial) + N->>P: POST /v1/preauth/on_submit + P-->>N: HTTP 202 Accepted + end + Note over Y: payer adjudicates the request + Y->>N: POST /v1/preauth/on_submit (decision) + N-->>Y: HTTP 202 Accepted + N->>P: POST /v1/preauth/on_submit + P-->>N: HTTP 202 Accepted, within 30 seconds + alt workflow 21 + Note left of P: approved, store preAuthRef + else workflow 24 + Note left of P: queried, answer the query + else workflow 23 + Note left of P: rejected, the preauthorisation is closed + end +``` + +1. Build the [preauthorisation request bundle](../fhir/preauth-request.md). It is a Claim with `use` `preauthorization` and `type` [SNOMED CT](../../shared/glossary/snomed-ct.md) `737481003`, Inpatient care management. +2. Add the diagnoses, coded in ICD-10, and the care team. Add one `item` per package, with its category and package code. +3. Add a `supportingInfo` entry for every document the eligibility check or the plan named. Set `total` to the amount you request. +4. Give the Claim an identifier and keep it for the whole case. The claim after discharge carries the same identifier. +5. Seal the bundle and set the headers, as in [send a sealed request](send-a-sealed-request.md). Set `x-hcx-workflow_id` to `12` and `x-hcx-status` to `request.initiated`. Send `x-hcx-ben-abha-id`. +6. Start a new correlation. Set `x-hcx-correlation_id` to the value of this call's `x-hcx-api_call_id`. Store it against the case. +7. Call [POST /v1/preauth/submit](../endpoints/preauth-submit.md). NHCX answers `202 Accepted`. The request is on its way to the payer. It is not the decision. +8. Wait. The payer may first acknowledge receipt on `/v1/preauth/on_submit` with workflow `20` and `x-hcx-status` `response.partial`. Answer `202` and keep waiting. +9. Receive the decision on [POST /v1/preauth/on_submit](../callbacks/preauth-on-submit.md). Answer `202 Accepted` within 30 seconds, then process. +10. Read the body's `type`. `ProtocolResponse` means the payer could not process the request. Any other type carries the sealed [ClaimResponse](../fhir/preauth-response.md). Decrypt it with your private key. +11. Read `x-hcx-workflow_id` first. It names the decision. Do not decide on `ClaimResponse.outcome` alone. + +| `x-hcx-workflow_id` | What the ClaimResponse shows | What to do | +|---|---|---| +| `21` | Approved. `preAuthRef` is present. If the approved `benefit` is lower than submitted, `processNote` explains the reduction | Store `preAuthRef` and the approved amount. Treat within that amount | +| `24` | Queried. `outcome` `partial`, adjudication reason `queried`, totals `0` | [Answer the query](preauth-query-response.md) | +| `23` | Rejected. `outcome` `complete`, adjudication reason `cancelled`, a `disposition` giving the reason | The preauthorisation is closed | + +Some payers ask for documents with a communication request on `/v1/communication/request` instead of workflow `24`. [Answer a payer query on a preauthorisation](preauth-query-response.md) covers both routes. The codes are listed in [workflow codes](../concepts/workflow-codes.md). + +## How you know it worked + +The preauthorisation is approved when all of these hold: + +- You received `POST /v1/preauth/on_submit` whose `x-hcx-correlation_id` equals the one you sent. +- Its `type` is not `ProtocolResponse`, and `payload` decrypts with your private key. +- `x-hcx-workflow_id` is `21`, and the ClaimResponse has `use` `preauthorization` and a `preAuthRef`. +- You stored `preAuthRef` and the approved `benefit` amount against the case. +- You answered every callback with `202` within 30 seconds. + +A callback with workflow `23` also ends this flow, as a rejection. Workflow `24` hands over to the query flow. + +## When it goes wrong + +The 202 arrives and no decision follows. Answer any workflow `20` acknowledgement and keep waiting. For long waits, [check the request's status](status-check.md). An undeliverable request comes back on [/v1/error](../callbacks/error.md). See [accepted, then no callback](../troubleshooting/accepted-then-no-callback.md). + +The payer finds an open case for the beneficiary. [PAYR-1238](../errors/payr-1238.md) means an active preauthorisation exists at your hospital. [PAYR-1237](../errors/payr-1237.md) means one exists at another hospital. [PAYR-1216](../errors/payr-1216.md) means a case is still being adjudicated. [Cancel](preauth-cancel.md) the stale preauthorisation, or claim against it. + +The case already moved on. [PAYR-1217](../errors/payr-1217.md) means an approved preauthorisation exists: send an [enhancement](preauth-enhancement.md) instead. [PAYR-1231](../errors/payr-1231.md) means a claim was already raised. + +The amount or authentication is refused. [PAYR-1201](../errors/payr-1201.md) means the amount is zero or above the wallet balance. [PAYR-1235](../errors/payr-1235.md) means the wallet balance is too low. [PAYR-1256](../errors/payr-1256.md) means you sent neither biometric authentication nor the consent questionnaire response. + +NHCX or the payer rejects the envelope. [NHCX-1006](../errors/nhcx-1006.md) means the correlation id was used before. A `ProtocolResponse` with [PAYR-1001](../errors/payr-1001.md) means the payer could not decrypt your request. See [the payer rejects your FHIR bundle](../troubleshooting/bundle-rejected.md) for bundle problems. diff --git a/catalogue/nhcx/flows/predetermination.md b/catalogue/nhcx/flows/predetermination.md new file mode 100644 index 000000000..c45c0724f --- /dev/null +++ b/catalogue/nhcx/flows/predetermination.md @@ -0,0 +1,131 @@ +--- +id: nhcx.flow.predetermination +type: flow +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Request a predetermination +summary: >- + Before a planned admission, ask the payer what it would approve for a proposed + treatment, as an estimate that commits nobody. +sources: +- url: https://hcxsbx.abdm.gov.in/images/af8d243edcc2139a515d.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Usecases.pdf + hash: sha256:8709b2907a0d5a0dbb36f5e63ed8deae269e0c75372b05d71ce7380c8a0929e7 + fetched: '2026-09-14' + note: NHCX Usecases, row 1 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2, Predetermination Request Submission. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. API list table. +- url: https://hcxsbx.abdm.gov.in/images/2c3fbb4e6b09f0834f69.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Implementation Guide for Adoption of FHIR in ABDM and NHCX.pdf + hash: sha256:549377c9c26b1bd23decac3a1b9e5ebedfdc8e0fe99e53ef733859b188f51366 + fetched: '2026-09-14' + note: Implementation Guide for Adoption of FHIR in ABDM and NHCX, row 14 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. API list table, rows 5 and 6. +- url: https://hcxsbx.abdm.gov.in/images/819467ec15aff13cc2a8.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Dummy Payer Implementation.pdf + hash: sha256:97335ebc4cd32c86e0c34328b2f4c526420b32a7a009208364043d6334e9e757 + fetched: '2026-09-14' + note: NHCX Dummy Payer Implementation, row 19 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, dummy payer use case list. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.predetermination-submit + - nhcx.endpoint.predetermination-on-submit + callbacks: + - nhcx.callback.predetermination-submit + - nhcx.callback.predetermination-on-submit + - nhcx.callback.error + fhir: + - nhcx.fhir.claim-request + - nhcx.fhir.claim-response + - nhcx.fhir.collection-bundle + concepts: + - nhcx.concept.claim-cycle + - nhcx.concept.four-message-legs + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.send-a-sealed-request + - nhcx.flow.status-check + decisions: + - nhcx.decision.preauth-or-predetermination + errors: + - nhcx.error.nhcx-1003 + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1001 + glossary: + - nhcx.glossary.predetermination + sandbox: + - nhcx.sandbox.dummy-payer + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback +--- + +# Request a predetermination + +## In plain words + +A [predetermination](../glossary/predetermination.md) asks the payer what it would approve for a treatment you are planning. You send it before the patient is admitted. The payer answers with an estimate, judged against the policy and the beneficiary's history. + +The estimate commits nobody. Nothing is reserved against the policy. When the patient is admitted, you still send a [preauthorisation](preauth-submit.md). + +The request is a Claim bundle with `Claim.use` set to `predetermination`, on `/v1/predetermination/submit`. The answer is a ClaimResponse on `/v1/predetermination/on_submit`. [Preauthorisation or predetermination](../decisions/preauth-or-predetermination.md) compares the two. + +## Before you start + +- The payer answers predetermination requests. Confirm this with the payer before you build the exchange. +- You have the planned treatment: diagnosis, packages and the estimated amounts. +- Your session token, callback endpoint and the payer's certificate are in place, as in [send a sealed request](send-a-sealed-request.md). +- The sandbox [dummy payer](../sandbox/dummy-payer.md) does not answer predetermination. Test against a payer that does. + +## What happens + +```mermaid +sequenceDiagram + participant P as Provider (your system) + participant N as NHCX + participant Y as Payer + P->>N: POST /v1/predetermination/submit + Note right of P: Claim.use predetermination, x-hcx-status request.initiated + N-->>P: HTTP 202 Accepted + N->>Y: POST /v1/predetermination/submit + Y-->>N: HTTP 202 Accepted + Note over Y: payer estimates against the policy and past history + Y->>N: POST /v1/predetermination/on_submit + N-->>Y: HTTP 202 Accepted + N->>P: POST /v1/predetermination/on_submit + P-->>N: HTTP 202 Accepted, within 30 seconds + Note left of P: store the estimate, not an approval +``` + +1. Build a Claim bundle shaped like the preauthorisation bundle, as in [the claim request bundle](../fhir/claim-request.md). Set `Claim.use` to `predetermination`. +2. Give the Claim your own predetermination reference as its identifier. Add the planned items, diagnoses and amounts. +3. Seal and set the headers, as in [send a sealed request](send-a-sealed-request.md). Set `x-hcx-status` to `request.initiated`. No workflow code is published for predetermination. +4. Start a new correlation. Set `x-hcx-correlation_id` to the value of this call's `x-hcx-api_call_id`. +5. Call [POST /v1/predetermination/submit](../endpoints/predetermination-submit.md). NHCX answers `202 Accepted`. It is not the estimate. +6. Receive [POST /v1/predetermination/on_submit](../callbacks/predetermination-on-submit.md). Answer `202 Accepted` within 30 seconds, then process. +7. Read `type`. `ProtocolResponse` means the payer could not process the request. Otherwise decrypt `payload` with your private key. +8. Read the [ClaimResponse](../fhir/claim-response.md). Its `use` is `predetermination`. The estimated benefit is in `ClaimResponse.total`, category `benefit`. + +## How you know it worked + +The estimate is in when all of these hold: + +- You received `POST /v1/predetermination/on_submit` whose `x-hcx-correlation_id` equals the one you sent. +- Its `type` is not `ProtocolResponse`, and `payload` decrypts with your private key. +- The ClaimResponse has `use` `predetermination` and a `total` with category `benefit`. +- You stored the amount against the planned case, labelled as an estimate. + +## When it goes wrong + +The 202 arrives and no estimate follows. The payer may not answer predetermination. Confirm support with the payer, then [check the request's status](status-check.md). See [accepted, then no callback](../troubleshooting/accepted-then-no-callback.md). + +NHCX rejects the call. [NHCX-1003](../errors/nhcx-1003.md) means the recipient code is not registered. [NHCX-1006](../errors/nhcx-1006.md) means the correlation id was used before. + +The callback is a `ProtocolResponse`. [PAYR-1001](../errors/payr-1001.md) means the payer could not decrypt your request. Fetch its certificate again and reseal. + +The estimate treated as an approval. A predetermination reserves nothing. Send a preauthorisation at admission, with workflow `12`. diff --git a/catalogue/nhcx/flows/production-onboarding.md b/catalogue/nhcx/flows/production-onboarding.md new file mode 100644 index 000000000..506ff4d83 --- /dev/null +++ b/catalogue/nhcx/flows/production-onboarding.md @@ -0,0 +1,212 @@ +--- +id: nhcx.flow.production-onboarding +type: flow +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Onboard as a participant in production +summary: >- + Create and confirm your live claims exchange participant record, then register + your certificate and callback address, each step confirmed by a passcode sent + to your registered mobile. +sources: +- url: https://hcxsbx.abdm.gov.in/images/260d0dec19a681e80262.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Production.pdf + hash: sha256:c38476fb90101f13fdfea447861292718d561e1dc088ae20950b193606500d2e + fetched: '2026-09-14' + note: Onboarding providers and payers in Production, row 5 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Steps 1 to 4; role and registry enums. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, item 5. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. Functional Testing and production steps. +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. path /v2/update/cert.' +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Session API table. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.session-token + - nhcx.endpoint.v2-participant-create + - nhcx.endpoint.validate + - nhcx.endpoint.v2-participant-update + - nhcx.endpoint.update-validate + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.v2-update-cert + flows: + - nhcx.flow.sandbox-onboarding + - nhcx.flow.generate-and-register-certificate + - nhcx.flow.rotate-certificate + - nhcx.flow.pmjay-hospital-migration + - nhcx.flow.policy-link-and-delink + concepts: + - nhcx.concept.participant-registry + - nhcx.concept.participant-code + - nhcx.concept.participant-roles + - nhcx.concept.session-token + sandbox: + - nhcx.sandbox.sandbox-exit + - nhcx.sandbox.going-live + - nhcx.sandbox.environments-and-base-urls + - nhcx.sandbox.callback-url-requirements + - nhcx.sandbox.support-contacts + decisions: + - nhcx.decision.session-endpoint + errors: + - nhcx.error.nhcx-401 + troubleshooting: + - nhcx.troubleshooting.everything-returns-401 + glossary: + - nhcx.glossary.participant-code + - nhcx.glossary.sandbox-exit + - shared.glossary.hfr +--- + +# Onboard as a participant in production + +## In plain words + +Production on the [National Health Claims Exchange](../../shared/glossary/nhcx.md) (NHCX) has its own participant registry. You create a separate production record in four calls. Two of them confirm a passcode sent by SMS, so the person holding your registered mobile takes part. + +The first pair creates the participant and returns a [participant code](../glossary/participant-code.md) ending in `@hcx`. The second pair registers your encryption certificate and callback address. Only after the second pair can NHCX send requests to you and receive your responses. + +## Before you start + +- **Sandbox sign-off.** You passed the [sandbox exit](../glossary/sandbox-exit.md): bundle validation by [NRCeS](../../shared/glossary/nrces.md), an internal demo, a Health Tech Committee demo, and NHA's confirmation email. See [The sandbox exit process and sign-off](../sandbox/sandbox-exit.md). +- **Production credentials.** NHA has assigned your role to your [Milestone 1](../../shared/glossary/m1.md) production client ID. You use that client ID for every production call. +- **The registered mobile.** For a [provider](../glossary/provider.md), the number recorded against the facility in the [Health Facility Registry](../../shared/glossary/hfr.md) (HFR). For a [payer](../glossary/payer.md), the number in the NHCX payer details. A person with that phone is available during the calls. +- **Your registry ID.** The HFR ID for a provider. The [IRDAI](../glossary/irdai.md) registry ID for a payer, without leading zeros: `0123` is sent as `123`. +- **A production certificate** in base64, from [Generate an encryption certificate and register it](generate-and-register-certificate.md). +- **A live callback address** that meets the [callback address rules](../sandbox/callback-url-requirements.md). + +## What happens + +Every call goes to the production participant service, `https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice`, with your session token. + +```mermaid +sequenceDiagram + participant P as Person holding the registered mobile + participant You as Your system + participant GW as ABDM session gateway + participant PS as NHCX participant service, production + You->>GW: POST /api/hiecm/gateway/v3/sessions with the production client ID + GW-->>You: accessToken + You->>PS: POST /v2/participant/create + PS-->>You: participantid ending @hcx, and transactionid + PS->>P: SMS passcode for this transactionid + P->>You: reads out the passcode + You->>PS: GET /validate with transactionId and passcode + PS-->>You: creation confirmed + You->>PS: POST /v2/participant/update + PS-->>You: participant_code, status and a new transactionid + PS->>P: SMS passcode for the update + P->>You: reads out the passcode + You->>PS: GET /update/validate with transactionId and passcode + PS-->>You: certificate and endpoint registered + You->>PS: POST /fetch/certs with your participant code + PS-->>You: your encryption_cert +``` + +### 1. Get a session token + +Use your production client ID. [Which session token endpoint to call](../decisions/session-endpoint.md) settles the address, and [NHCX environments, hosts and base URLs](../sandbox/environments-and-base-urls.md) lists the production hosts. + +### 2. Create the participant + +`POST /v2/participant/create`: + +```json +{ + "registrytype": "10001", + "registryid": "", + "role": ["10001"], + "endpoint_url": "", + "mobilenumber": "", + "email": "" +} +``` + +`registrytype` takes a registry code: `10001` HFR, `10002` NIN, `10003` ROHINI or `10004` PAYER. `role` takes role codes: `10001` provider, `10002` payer, `10003` TPA or `10009` end user application. The full enum list is in [POST /v2/participant/create](../endpoints/v2-participant-create.md). You can leave `endpoint_url` empty here, because step 4 sets it. + +The answer carries `participantid`, `facilityname`, `facilitycontact`, `facilityemail`, `transactionid` and an `error` object with `code`, `message` and `trace`. On success the three error fields are null. + +**Wait:** the passcode arrives by SMS on the registered mobile. + +### 3. Confirm the creation + +```text +GET /validate?transactionId=&passcode= +``` + +The transaction ID and passcode stay valid for 24 hours. Each create call issues a new pair, and a passcode works only with its own transaction ID. + +### 4. Register the certificate and callback address + +`POST /v2/participant/update`, after step 3 has succeeded: + +```json +{ + "participantcode": "", + "encryptioncert": "", + "endpointurl": "" +} +``` + +The answer carries `participant_code`, `status` and a new `transactionid`. + +**Wait:** a second passcode arrives by SMS. + +### 5. Confirm the update + +```text +GET /update/validate?transactionId=&passcode= +``` + +The same 24-hour rule applies. When this succeeds, your callback address is active and your certificate is registered. + +### 6. Read your record back + +`POST /fetch/certs` with your `@hcx` code returns the certificate stored against it. Later certificate changes can skip the passcode through `POST /v2/update/cert`. See [Rotate your encryption certificate](rotate-certificate.md). + +## How you know it worked + +`GET /update/validate` succeeds for the transaction ID from step 4. `POST /fetch/certs` on the production participant service returns, for your `@hcx` code, a certificate whose public key matches your production `certificate.crt`. + +```observation schema=exit-condition +channel: synchronous +call: POST /fetch/certs +host: https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice +request: + participantid: +match: + encryption_cert: public key equals the one in your production certificate.crt +``` + +Your production code now goes in `x-hcx-sender_code` on everything you send. Next steps: + +- A PMJAY hospital continues with [Migrate a PMJAY hospital to HMIS through NHCX](pmjay-hospital-migration.md). +- A payer links its policies with [Link and de-link an ABHA and a policy](policy-link-and-delink.md). +- Plan staff training and a pilot with a few clients before full go-live. See [Going live on NHCX production](../sandbox/going-live.md). + +## When it goes wrong + +- **Create fails on the mobile number.** It must match the HFR record for a provider, or the NHCX payer details for a payer, exactly. Correct the number at its source, then create again. +- **Create fails on the registry ID for a payer.** Strip leading zeros from the IRDAI ID. +- **Create is refused on `registrytype` or `role`.** Use only codes from the lists in step 2. +- **The passcode is refused.** It is older than 24 hours, or it belongs to another transaction ID. Run the create or update call again for a fresh pair. +- **You lost the transaction ID.** Run the create or update call again. There is no way to look it up. +- **The update is refused.** Step 3 has not succeeded yet. The update needs a participant whose creation is confirmed. +- **Every call returns `401`.** The token has expired, or it was minted with a sandbox client ID. See [NHCX-401](../errors/nhcx-401.md). diff --git a/catalogue/nhcx/flows/receive-a-sealed-callback.md b/catalogue/nhcx/flows/receive-a-sealed-callback.md new file mode 100644 index 000000000..4183d18c8 --- /dev/null +++ b/catalogue/nhcx/flows/receive-a-sealed-callback.md @@ -0,0 +1,197 @@ +--- +id: nhcx.flow.receive-a-sealed-callback +type: flow +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Receive, open and acknowledge a sealed message +summary: >- + Accept a message the exchange delivers to your callback address, acknowledge it + within thirty seconds, then open it with your private key and match it to its + conversation. +sources: +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Acceptance scenario and error scenario. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. FAQ 14 callback requirements; callback URL FAQ. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Inbound decryption steps. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/data-security-and-privacy/api-security + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy__api-security.md + hash: sha256:9fe2d5a643356558131e5de801b5f325b76f80aa48e931ee6b77e088dd90a65c + fetched: '2026-09-14' + note: Site page /technical-specifications/open-protocol/data-security-and-privacy/api-security, text as shown on the site. API security, NHCX to participant tokens. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Status Description. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.preauth-on-submit + - nhcx.endpoint.claim-on-submit + - nhcx.endpoint.coverageeligibility-on-check + - nhcx.endpoint.insuranceplan-on-request + - nhcx.endpoint.status + callbacks: + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + - nhcx.callback.coverageeligibility-on-check + - nhcx.callback.insuranceplan-on-request + - nhcx.callback.communication-request + - nhcx.callback.paymentnotice-request + - nhcx.callback.preauth-submit + - nhcx.callback.claim-submit + - nhcx.callback.error + flows: + - nhcx.flow.send-a-sealed-request + - nhcx.flow.report-a-processing-error + - nhcx.flow.payer-process-a-request + - nhcx.flow.generate-and-register-certificate + - nhcx.flow.rotate-certificate + concepts: + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.retries-and-expiry + - nhcx.concept.status-lifecycle + sandbox: + - nhcx.sandbox.callback-url-requirements + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback + - nhcx.troubleshooting.callback-url-rejected + - nhcx.troubleshooting.recipient-cannot-decrypt + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + glossary: + - nhcx.glossary.jwe + - nhcx.glossary.protected-header + - nhcx.glossary.correlation-id + - nhcx.glossary.api-call-id +--- + +# Receive, open and acknowledge a sealed message + +## In plain words + +The [National Health Claims Exchange](../../shared/glossary/nhcx.md) (NHCX) delivers messages to you as HTTP calls to your registered callback address. Answers to your requests arrive this way, and so do requests addressed to you. Each delivery needs an immediate acknowledgement: HTTP `202` with a fixed JSON body, within 30 seconds. + +Acknowledge first, open later. The acknowledgement only says you received the message. Decrypting it and acting on it happen after you have answered. + +## Before you start + +- Your `endpoint_url` is registered and meets the [callback address rules](../sandbox/callback-url-requirements.md). +- Your private key matches the certificate in your participant record. See [Generate an encryption certificate and register it](generate-and-register-certificate.md). +- You have a store that keeps each raw message before any processing. +- You host the paths that can reach you. Everyone hosts `/v1/error`. A sender hosts the answer paths, such as `/v1/preauth/on_submit`. A payer hosts the request paths, such as `/v1/preauth/submit`. A provider also hosts `/v1/communication/request` and `/v1/paymentnotice/request`. + +## What happens + +```mermaid +sequenceDiagram + participant S as Sender, a payer or provider + participant NHCX as NHCX exchange + participant EP as Your callback endpoint + participant W as Your worker + S->>NHCX: POST /v1/preauth/on_submit with a sealed payload + NHCX->>EP: POST /v1/preauth/on_submit + Note over EP: store the raw body, read the protected header + EP-->>NHCX: 202 with the acceptance body, within 30 seconds + EP->>W: hand over the stored message + Note over W: decrypt with your private key, match the conversation, update the case + opt No valid 202 within 30 seconds + NHCX->>EP: the same message again, up to five attempts + end +``` + +### 1. Receive + +NHCX posts to your `endpoint_url` plus the path, for example `/v1/preauth/on_submit`. The body takes one of two forms: + +- A sealed message: `{"payload": ""}`. +- A plain JSON object with `"type": "ProtocolResponse"`, sent when the other side could not process your request. It is not sealed. + +NHCX signs its calls to you with its own JWT, using `RS256`. Validate that signature with the public key of the NHCX instance. + +### 2. Store, then acknowledge within 30 seconds + +Store the raw body. Read the identifiers from the protected header: it is the first of the five parts, base64url-encoded but not encrypted. Then answer HTTP `202` with this body: + +```json +{ + "timestamp": "DD/MM/YYYY hh:mm:ss:sss", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "coverageeligibility/preauth/claim/task/payment/insuranceplan", + "protocol_status": "request.queued/request.dispatched/request.error" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +`timestamp` uses the pattern shown. `entity_type` takes one of the listed values, and `protocol_status` one of its three. The error `code` and `message` stay empty when you accept. [Synchronous acknowledgement](../concepts/synchronous-acknowledgement.md) covers the body in detail. + +### 3. Open it + +Check that the payload has five dot-separated parts. Decrypt it with your PKCS#8 private key. If the authentication tag fails, reject the message without using any of its content. + +From the protected header, read `x-hcx-sender_code`, `x-hcx-recipient_code`, `x-hcx-api_call_id`, `x-hcx-correlation_id`, `x-hcx-workflow_id` and `x-hcx-status`. `x-hcx-recipient_code` must be your own code. + +### 4. Match it + +Keep the `x-hcx-api_call_id` and the `x-hcx-correlation_id` of every request you send. Match an incoming answer on its `x-hcx-correlation_id` against both. Its `x-hcx-sender_code` must be the participant you addressed. The rule for each identifier is in [message identifiers](../concepts/message-identifiers.md). + +### 5. Recognise repeats + +NHCX resends a message when your acknowledgement was late, not `202`, or not in the format above. A repeat carries the same `x-hcx-api_call_id`. Acknowledge it again, and do not process it twice. + +### 6. Act + +Deserialise the plaintext into its FHIR bundle and update the case. `x-hcx-status` tells you what kind of answer it is: + +| `x-hcx-status` | Meaning | +|---|---| +| `response.complete` | The final answer, closing the request cycle | +| `response.partial` | A partial or intermediate answer | +| `response.error` | The request was rejected, or an error occurred | + +`x-hcx-workflow_id` names the stage. See [workflow codes](../concepts/workflow-codes.md). If the message is a request to you, answer it later on its paired path. A payer follows [Receive, adjudicate and answer a request as a payer](payer-process-a-request.md). + +If the body is a `ProtocolResponse`, read `x-hcx-error_details`. Its `code` names the failure. See [Report a processing failure on /v1/error](report-a-processing-error.md). + +## How you know it worked + +Your endpoint answered `202` with the acceptance body within 30 seconds, and NHCX does not deliver the same `x-hcx-api_call_id` again. The decrypted bundle is stored against the case its identifiers name. + +```observation schema=exit-condition +channel: callback +path: / +acknowledge: HTTP 202 with the acceptance body within 30 seconds +match: + redelivery of the same x-hcx-api_call_id: none +``` + +## When it goes wrong + +- **Nothing arrives.** The address uses an IP address or a port, or the server is outside India. A firewall or router may also block the NHCX addresses. See [Your callback URL is rejected or never called](../troubleshooting/callback-url-rejected.md) and [The request was accepted with 202 and no callback arrives](../troubleshooting/accepted-then-no-callback.md). +- **The same message keeps arriving.** Your acknowledgement is late, uses a code other than `202`, or has the wrong body. After five failed attempts NHCX deletes the request, and the sender hears on `/v1/error`. +- **Processing runs past 30 seconds.** Move decryption and business logic after the acknowledgement. +- **Decryption fails.** The sender used a copy of your certificate from before a rotation. Try your previous key, as in [Rotate your encryption certificate](rotate-certificate.md). Otherwise see [The recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). +- **An answer matches no request.** See [Responses arrive against the wrong request](../troubleshooting/duplicate-or-mismatched-correlation.md). diff --git a/catalogue/nhcx/flows/report-a-processing-error.md b/catalogue/nhcx/flows/report-a-processing-error.md new file mode 100644 index 000000000..ce78103ed --- /dev/null +++ b/catalogue/nhcx/flows/report-a-processing-error.md @@ -0,0 +1,184 @@ +--- +id: nhcx.flow.report-a-processing-error +type: flow +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Report a processing failure on /v1/error +summary: >- + Tell the sender when you cannot process its message, and handle the report the + exchange sends you when your own message cannot be delivered. +sources: +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Error scenario and ProtocolResponse body. +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use cases 7 to 15, API logic rows. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. items 2 and 8. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Status Description. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.preauth-on-submit + - nhcx.endpoint.claim-on-submit + - nhcx.endpoint.coverageeligibility-on-check + - nhcx.endpoint.status + callbacks: + - nhcx.callback.error + - nhcx.callback.on-status + - nhcx.callback.preauth-on-submit + flows: + - nhcx.flow.send-a-sealed-request + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.payer-process-a-request + concepts: + - nhcx.concept.error-code-spaces + - nhcx.concept.retries-and-expiry + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.status-lifecycle + - nhcx.concept.message-identifiers + decisions: + - nhcx.decision.status-poll-or-wait + errors: + - nhcx.error.payr-1001 + - nhcx.error.nhcx-1010 + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback + - nhcx.troubleshooting.duplicate-or-mismatched-correlation +--- + +# Report a processing failure on /v1/error + +## In plain words + +A failed message must be reported back, or its sender waits for a decision that will never come. On the [National Health Claims Exchange](../../shared/glossary/nhcx.md) (NHCX) there are two reports, and every participant handles both. + +When you receive a message you cannot process, you answer with a `ProtocolResponse`: a plain, unsealed JSON error on the paired answer path. When NHCX cannot deliver your own message, it gives up after five attempts. It then posts the rejection details to your `/v1/error` endpoint, which every participant must host. + +## Before you start + +- You acknowledge deliveries as in [Receive, open and acknowledge a sealed message](receive-a-sealed-callback.md). +- Your registered address serves `/v1/error`. +- You record the `x-hcx-api_call_id` and `x-hcx-correlation_id` of every message you send and receive. +- You know which error codes your side uses. See [error code spaces](../concepts/error-code-spaces.md). + +## What happens + +```mermaid +sequenceDiagram + participant S as Sender + participant NHCX as NHCX exchange + participant R as Recipient + S->>NHCX: POST /v1/preauth/submit + NHCX-->>S: 202 + alt The recipient receives the message but cannot process it + NHCX->>R: POST /v1/preauth/submit + R-->>NHCX: 202 with the acceptance body + Note over R: cannot decrypt, invalid bundle or a protocol error + R->>NHCX: POST /v1/preauth/on_submit with a ProtocolResponse + NHCX-->>R: 202 + NHCX->>S: POST /v1/preauth/on_submit with the ProtocolResponse + S-->>NHCX: 202 + else NHCX cannot deliver the message + loop up to five attempts + NHCX->>R: POST /v1/preauth/submit + R--xNHCX: rejected, no answer, or a malformed acknowledgement + end + Note over NHCX: request deleted, correlation ID made inactive + NHCX->>S: POST /v1/error with the rejection details + S-->>NHCX: 202 with the acceptance body + end +``` + +### Part 1: report a message you cannot process + +Send a `ProtocolResponse` only when you could not validate or process the request. The three cases are an invalid payload, a payload you cannot decrypt, and a protocol error. A business decision, even a rejection, is sealed and sent as a normal answer instead. + +Send it on the paired answer path, the call you would have used for a decision. Its shape: + +```json +{ + "type": "ProtocolResponse", + "x-hcx-sender_code": "", + "x-hcx-recipient_code": "", + "x-hcx-api_call_id": "", + "x-hcx-correlation_id": "", + "x-hcx-workflow_id": "", + "x-hcx-timestamp": "", + "x-hcx-debug_flag": "Error", + "x-hcx-status": "response.error", + "x-hcx-redirect_to": "", + "x-hcx-error_details": { + "code": "", + "message": "", + "trace": "" + }, + "x-hcx-debug_details": { + "code": "", + "message": "", + "trace": "" + }, + "x-hcx-domain-header": { + "use_case_name": "", + "amt_processed": "" + }, + "x-hcx-entity-type": "coverageeligibility | payment | insuranceplan | task | claim | preauth", + "x-hcx-ben-abha-id": "" +} +``` + +- `x-hcx-recipient_code` is the sender of the message you are answering. +- `x-hcx-api_call_id` is new, and differs from the correlation ID. +- `x-hcx-correlation_id` follows [message identifiers](../concepts/message-identifiers.md), so the sender can match it. +- `x-hcx-error_details.code` is a code from your error space, such as [PAYR-1001](../errors/payr-1001.md) for a payload you could not decrypt. + +NHCX acknowledges your `ProtocolResponse` with `202` and forwards it to the sender. + +### Part 2: handle `/v1/error` for a message you sent + +NHCX treats a delivery as failed when the recipient rejects the payload, does not answer, or answers outside the acceptance format. It resends the same request, up to five attempts in all. Then it ends the request, deletes it from NHCX, and makes its correlation ID inactive. + +**Wait:** the report arrives on your `/v1/error` after the fifth failed attempt. What it carries is the rejection details for the request NHCX gave up on. + +When it arrives: + +1. Store the report whole, as received. Accept a body shape you do not recognise rather than refusing it. +2. Answer `202` with the acceptance body, as for any delivery. +3. Mark the case it names as undelivered, so nobody waits for a decision. +4. When the recipient is reachable again, send a fresh request with a new correlation ID. + +If a case goes quiet and no `/v1/error` has arrived, ask with `POST /v1/status`. The answer on `/v1/on_status` carries `x-hcx-status`. `request.stopped` means NHCX stopped trying to reach the recipient. See [Poll with /v1/status or wait for the callback](../decisions/status-poll-or-wait.md). + +## How you know it worked + +As the recipient reporting a failure, NHCX answered `202` to your `ProtocolResponse`. As the sender, your `/v1/error` handler answered `202`, stored the report and marked the case undelivered. A fresh request under a new correlation ID then receives `202`. + +```observation schema=exit-condition +channel: callback +path: /v1/error +acknowledge: HTTP 202 with the acceptance body within 30 seconds +state: + case named in the report: marked undelivered +``` + +## When it goes wrong + +- **You never learn that a request died.** You do not host `/v1/error`. Host it before anything else asynchronous. +- **Your `/v1/error` handler answers `4xx`.** It validates the body against a fixed schema. Accept any body and store it. +- **A retry fails.** It reuses the correlation ID of the failed request, which NHCX made inactive. Start again with a new one. See [Responses arrive against the wrong request](../troubleshooting/duplicate-or-mismatched-correlation.md). +- **NHCX refuses your answer, saying no data exists for its correlation ID.** Your `x-hcx-correlation_id` does not match the request. See [NHCX-1010](../errors/nhcx-1010.md). +- **You sent a `ProtocolResponse` for a business rejection.** The sender handles it as a protocol failure. Send a sealed decision instead. diff --git a/catalogue/nhcx/flows/rotate-certificate.md b/catalogue/nhcx/flows/rotate-certificate.md new file mode 100644 index 000000000..71664eb3e --- /dev/null +++ b/catalogue/nhcx/flows/rotate-certificate.md @@ -0,0 +1,155 @@ +--- +id: nhcx.flow.rotate-certificate +type: flow +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Rotate your encryption certificate +summary: >- + Replace the certificate other participants use to seal messages to you, without + losing messages already sealed with the old one. +sources: +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy__message-security-and-integrity.md + hash: sha256:3768fd89932e4081c9e03a8695619bcaf70c641e28bb55a77eec090bb926eeb3 + fetched: '2026-09-14' + note: Site page /technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity, text as shown on the site. Message security and integrity, key rotation note. +- url: https://hcxsbx.abdm.gov.in/images/ec361a6c3e90e766d227.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Steps to generate encryption Certificate.pdf + hash: sha256:94605e935f05ebb49e24dee50787cb4f3f1c401983a9616a5aaabdbc302f664b + fetched: '2026-09-14' + note: Steps to generate encryption Certificate, row 20 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Step 3. +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths /v2/update/cert and /participant/update.' +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. 3.3 Certificate Fetch. +- url: https://hcxsbx.abdm.gov.in/images/260d0dec19a681e80262.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Production.pdf + hash: sha256:c38476fb90101f13fdfea447861292718d561e1dc088ae20950b193606500d2e + fetched: '2026-09-14' + note: Onboarding providers and payers in Production, row 5 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Steps 3 and 4. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.session-token + - nhcx.endpoint.v2-update-cert + - nhcx.endpoint.v2-participant-update + - nhcx.endpoint.update-validate + - nhcx.endpoint.participant-update + - nhcx.endpoint.fetch-certs + flows: + - nhcx.flow.generate-and-register-certificate + - nhcx.flow.production-onboarding + - nhcx.flow.sandbox-onboarding + - nhcx.flow.receive-a-sealed-callback + concepts: + - nhcx.concept.encryption-certificate + sandbox: + - nhcx.sandbox.support-contacts + errors: + - nhcx.error.payr-1001 + - nhcx.error.payr-1002 + troubleshooting: + - nhcx.troubleshooting.recipient-cannot-decrypt + glossary: + - nhcx.glossary.x509-certificate +--- + +# Rotate your encryption certificate + +## In plain words + +Your encryption certificate lasts as long as you set when you made it: 365 days with the standard command. Rotate your encryption keys once a year, and at once if a private key may have leaked. + +Rotation has one catch. Senders cache your certificate for 24 hours. For a day after the switch, some messages still arrive sealed with your old key. Keep the old key working until that window closes. + +## Before you start + +- A new key pair and base64 certificate, made as in [Generate an encryption certificate and register it](generate-and-register-certificate.md). Give the files new names, such as `private-2027.key`, so the old ones survive. +- The old private key, still available to your decryption code. +- A session token and your [participant code](../glossary/participant-code.md). +- For the production passcode route only: the person holding your registered mobile. + +## What happens + +```mermaid +sequenceDiagram + participant You as Your system + participant PS as NHCX participant service + participant Peer as Sender with a cached copy + Note over You: make a new key pair and certificate + alt Production, no passcode + You->>PS: POST /v2/update/cert with participantId and certificate + PS-->>You: accepted + else Production, with passcode + You->>PS: POST /v2/participant/update with encryptioncert + PS-->>You: transactionid, and an SMS passcode is sent + You->>PS: GET /update/validate with transactionId and passcode + PS-->>You: certificate registered + else Sandbox + You->>PS: POST /participant/update with participant_code and encryption_cert + PS-->>You: participant_code + end + You->>PS: POST /fetch/certs with your participant code + PS-->>You: the new certificate + Peer->>You: messages sealed with the old key, for up to 24 hours + Note over You: try the new key first, then the old one +``` + +### 1. Make the new pair + +Follow steps 1 to 4 of [the certificate flow](generate-and-register-certificate.md) with new file names. + +### 2. Register the new certificate + +In production, the direct route needs no passcode: + +```json +{ + "participantId": "", + "certificate": "" +} +``` + +Post it to `POST /v2/update/cert` on `https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice`. Both fields are mandatory, and the certificate is base64-encoded. See [POST /v2/update/cert](../endpoints/v2-update-cert.md). + +The passcode route, `POST /v2/participant/update` followed by `GET /update/validate`, also works. It is described in [Onboard as a participant in production](production-onboarding.md). + +In the sandbox, send `POST /participant/update` with your `participant_code` and the new `encryption_cert`. See [POST /participant/update](../endpoints/participant-update.md). + +### 3. Run both keys for 24 hours + +From the moment of registration, decrypt with the new key first. If that fails, try the old key. Senders that fetched your certificate before the switch keep using it until their 24-hour cache expires. + +### 4. Retire the old key + +After 24 hours, remove the old key from your decryption path and destroy it. + +If you rotated because a key may have leaked, report the compromise to the NHCX operators at once. See [Where to get help with NHCX](../sandbox/support-contacts.md). + +## How you know it worked + +`POST /fetch/certs` for your participant code returns the new public key. Compare it with the commands in [the certificate flow](generate-and-register-certificate.md). Messages sealed after the 24-hour window open with the new key, and none needs the old one. + +```observation schema=exit-condition +channel: synchronous +call: POST /fetch/certs +request: + participantid: +match: + encryption_cert: public key equals the one in the new certificate +``` + +## When it goes wrong + +- **A message will not open with the new key.** The sender used a cached copy of the old certificate. Open it with the old key. If both keys fail, answer as in [Report a processing failure on /v1/error](report-a-processing-error.md). A payer uses [PAYR-1001](../errors/payr-1001.md) for this. +- **A payer reports it cannot encrypt to you.** The certificate you registered is wrong or expired. Register a valid one. See [PAYR-1002](../errors/payr-1002.md). +- **The production passcode expired.** It lasts 24 hours. Start the update again, or use `POST /v2/update/cert`. +- **You destroyed the old key too early.** Messages sealed with it inside the 24-hour window cannot be opened. Ask each sender to resend under a fresh request. See [The recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). diff --git a/catalogue/nhcx/flows/sandbox-onboarding.md b/catalogue/nhcx/flows/sandbox-onboarding.md new file mode 100644 index 000000000..7b5a2b3dc --- /dev/null +++ b/catalogue/nhcx/flows/sandbox-onboarding.md @@ -0,0 +1,191 @@ +--- +id: nhcx.flow.sandbox-onboarding +type: flow +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Onboard as a participant in the NHCX sandbox +summary: >- + Register your system in the claims exchange test environment so it holds a participant + code, a registered certificate and a callback address. +sources: +- url: https://hcxsbx.abdm.gov.in/images/e683dda0a8cf953abbc7.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)NHCX-OnBoarding APIs Postman Collection.zip + hash: sha256:ca4348e8a373c54bdcabd07eff8e49a55d93cdfae65fa5008ae0d56526a769f2 + fetched: '2026-09-14' + note: AWS(Sandbox)NHCX-OnBoarding APIs Postman Collection, row 6 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Participant Create and Update request bodies. +- url: https://hcxsbx.abdm.gov.in/images/bc2efb078b98548f8e6b.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Sandbox.pdf + hash: sha256:cbd03baf428655f0305e2f60ca331f8b76700496b070c522cafcc95001710b3a + fetched: '2026-09-14' + note: Onboarding providers and payers in Sandbox, row 4 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Create and Update Participant API definitions. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. Sandbox registration steps. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. FAQ 6, 11, callback URL FAQ, Session API table. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.session-token + - nhcx.endpoint.participant-create + - nhcx.endpoint.validate + - nhcx.endpoint.participant-update + - nhcx.endpoint.fetch-certs + flows: + - nhcx.flow.generate-and-register-certificate + - nhcx.flow.production-onboarding + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.report-a-processing-error + concepts: + - nhcx.concept.participant-registry + - nhcx.concept.participant-code + - nhcx.concept.participant-roles + - nhcx.concept.session-token + - nhcx.concept.encryption-certificate + sandbox: + - nhcx.sandbox.prerequisites + - nhcx.sandbox.environments-and-base-urls + - nhcx.sandbox.callback-url-requirements + - nhcx.sandbox.sandbox-exit + - nhcx.sandbox.support-contacts + decisions: + - nhcx.decision.session-endpoint + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1002 + tests: + - nhcx.test.provider-uc-03 + - nhcx.test.provider-uc-04 + - nhcx.test.payer-uc-05 + - nhcx.test.payer-uc-06 + troubleshooting: + - nhcx.troubleshooting.everything-returns-401 + - nhcx.troubleshooting.callback-url-rejected + glossary: + - nhcx.glossary.participant-code + - shared.glossary.hfr + - shared.glossary.nhcx +--- + +# Onboard as a participant in the NHCX sandbox + +## In plain words + +Every system that sends or receives claims messages on the [National Health Claims Exchange](../../shared/glossary/nhcx.md) (NHCX) must first exist in its participant registry. Onboarding creates that record. + +The record gives you a [participant code](../glossary/participant-code.md), such as `100001@sbx`. It holds your public encryption certificate and the address where NHCX delivers your messages. Nothing else on NHCX works for you until the record exists. + +## Before you start + +Each item is something you can check before the first call. + +- **Registry identity.** A [provider](../glossary/provider.md) has its facility in the [Health Facility Registry](../../shared/glossary/hfr.md) (HFR) and knows its HFR ID. A [payer](../glossary/payer.md) or [TPA](../glossary/tpa.md) knows the ID its [IRDAI](../glossary/irdai.md) or equivalent authority issued. An end user application, such as a [PHR](../../shared/glossary/phr.md) app, uses its client ID. +- **Sandbox credentials.** You hold an [ABDM](../../shared/glossary/abdm.md) sandbox client ID and secret. Apply at `https://sandbox.abdm.gov.in/sandbox/v3/` with the intent "Providers and Payer" and [Milestone 1](../../shared/glossary/m1.md). See [What you need before you register on the NHCX sandbox](../sandbox/prerequisites.md). +- **Milestone 1 working, for a provider.** Your software creates and verifies [ABHA](../../shared/glossary/abha.md) numbers. +- **NHCX sandbox access.** You registered at `https://sandbox.abdm.gov.in/sandbox/v3/sandbox-registration` with that client ID and secret, and roles were assigned to you. +- **A certificate.** You have `certificate_base64.txt` from [Generate an encryption certificate and register it](generate-and-register-certificate.md). +- **A callback address.** Your HTTPS endpoint meets the [callback address rules](../sandbox/callback-url-requirements.md). It uses a domain name with no IP address or port. The server is in India, and its firewall is open to `3.109.99.210`, `13.126.152.0` and `13.200.129.223`. + +## What happens + +```mermaid +sequenceDiagram + participant You as Your system + participant GW as ABDM session gateway + participant PS as NHCX participant service + You->>GW: POST /api/hiecm/gateway/v3/sessions + GW-->>You: accessToken and expiresIn + You->>PS: POST /participant/create + PS-->>You: participant_code, for example 100001@sbx + opt Create answers with a transactionid instead + Note over You: a passcode arrives by SMS on the registered mobile + You->>PS: GET /validate with transactionId and passcode + PS-->>You: creation confirmed + end + You->>PS: POST /fetch/certs with your participant code + PS-->>You: the encryption_cert you registered + opt Change the endpoint or certificate later + You->>PS: POST /participant/update + PS-->>You: participant_code + end +``` + +Every call in this flow answers in its own response. Two waits sit outside the calls. The manual review of your sandbox registration comes before step 1. The SMS passcode arrives in step 3, when that step applies. + +### 1. Get a session token + +Call the session endpoint with your client ID and secret. [Which session token endpoint to call](../decisions/session-endpoint.md) settles the address. Read the token's lifetime from `expiresIn` in the answer. Get a new token before it lapses, and after any `401`. + +Every participant service call below carries this token. The [session token endpoint](../endpoints/session-token.md) shows the header. + +### 2. Create the participant + +Call `POST /participant/create` on the sandbox participant service, `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice`. The body carries your profile: + +| Field | What to put | +|---|---| +| `linked_registry_codes` | Your registry code, from the table below | +| `registryid` | Your ID in that registry, as listed under Before you start | +| `participant_name` | Your legal or facility name | +| `scheme_code`, `state`, `district` | Your scheme, for example `PMJAY`, and your location | +| `roles` | Your role code, from the table below | +| `primaryEmail`, `phone`, `primaryMobile` | Your contacts | +| `signing_cert_path` | Path to your signing certificate, if you have one | +| `encryption_cert` | The contents of `certificate_base64.txt` | +| `endpoint_url` | Your callback base address | + +| You are | `roles` | `linked_registry_codes` | +|---|---|---| +| Provider | `10001` | `10001` (HFR) | +| Payer | `10002` | `10004` (PAYER) | +| TPA | `10003` | `10004` (PAYER) | +| End user application | `10009` | `10001` | + +The answer carries your `participant_code`. The full request is in [POST /participant/create](../endpoints/participant-create.md). + +An entity with several facilities creates one participant code per HFR ID. It uses the same client credentials for all of them. + +### 3. Confirm, when the answer asks for it + +If the create answer carries a `transactionid` instead of a participant code, a passcode arrives by SMS on the registered mobile. Confirm with `GET /validate`, passing `transactionId` and `passcode`. The rules for that pair are in [Onboard as a participant in production](production-onboarding.md). + +### 4. Read your record back + +Call `POST /fetch/certs` with `{"participantid": ""}`. The answer carries the `encryption_cert` stored against your code. Compare it with your certificate as shown in [Generate an encryption certificate and register it](generate-and-register-certificate.md). + +### 5. Change it later + +`POST /participant/update` changes the endpoint address, the certificate or any other attribute. `participant_code` is mandatory in its body. + +On success every call here answers HTTP `200`. Failures answer `400` for a client error, `404` for a resource not found, or `500` when downstream systems are down. + +## How you know it worked + +You hold a `participant_code` from `POST /participant/create`, or from `GET /validate` when a passcode was asked for. `POST /fetch/certs` with that code returns an `encryption_cert` whose public key matches your `certificate.crt`. + +```observation schema=exit-condition +channel: synchronous +call: POST /fetch/certs +request: + participantid: +match: + encryption_cert: public key equals the one in certificate.crt +``` + +Next, build your message handling with [Receive, open and acknowledge a sealed message](receive-a-sealed-callback.md) and [Report a processing failure on /v1/error](report-a-processing-error.md). Then work through [the sandbox exit process](../sandbox/sandbox-exit.md). + +## When it goes wrong + +- **Every call returns `401`.** The token is missing, lacks the `Bearer ` prefix, or has expired. Get a new token and retry once. See [NHCX-401](../errors/nhcx-401.md) and [Every NHCX call returns 401](../troubleshooting/everything-returns-401.md). +- **Create is refused with `400`.** Check `roles` and `linked_registry_codes` against the table in step 2. A wrong pairing causes rejection or misrouted traffic later. +- **Use-case calls say the sender is not registered.** You are calling before the record exists, or with a different code. See [NHCX-1002](../errors/nhcx-1002.md). +- **Nothing ever reaches your endpoint.** The address uses an IP address or a port, or the server is outside India. A firewall may also block the NHCX addresses. See [Your callback URL is rejected or never called](../troubleshooting/callback-url-rejected.md). +- **`/fetch/certs` returns a different key.** You registered a certificate from another key pair. Replace it with `POST /participant/update`. +- **You are still waiting for sandbox access.** Registration approval is a manual review with no published turnaround. You cannot call anything until roles are assigned. See [Where to get help with NHCX](../sandbox/support-contacts.md). diff --git a/catalogue/nhcx/flows/send-a-sealed-request.md b/catalogue/nhcx/flows/send-a-sealed-request.md new file mode 100644 index 000000000..62f3da7bc --- /dev/null +++ b/catalogue/nhcx/flows/send-a-sealed-request.md @@ -0,0 +1,263 @@ +--- +id: nhcx.flow.send-a-sealed-request +type: flow +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Send a sealed request through NHCX +summary: >- + Seal a claims message for one recipient, post it to the exchange, and wait for + the recipient's answer to arrive at your callback address. +sources: +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 2 JWE header and compact format; 2.4 Encryption Steps; 3.3 Certificate Fetch. +- url: https://hcxsbx.abdm.gov.in/images/b885e59891fedc7e725c.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-PARTICIPANT SERVICE_APIs Postman Collection.zip + hash: sha256:2d082f244ee41d137a62af82380dcd2d5db9ebbab66824fd54a23c506d4d9a7f + fetched: '2026-09-14' + note: AWS(Sandbox)-PARTICIPANT SERVICE_APIs Postman Collection, row 16 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Get Policies and Fetch Participants List bodies. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. items 4, 6, 7 and 8. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Error scenario. +- url: https://hcxsbx.abdm.gov.in/images/819467ec15aff13cc2a8.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Dummy Payer Implementation.pdf + hash: sha256:97335ebc4cd32c86e0c34328b2f4c526420b32a7a009208364043d6334e9e757 + fetched: '2026-09-14' + note: NHCX Dummy Payer Implementation, row 19 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Test Usecase Action API. +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. PAYR-1005 row (timestamp). +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.session-token + - nhcx.endpoint.participant-get-policies + - nhcx.endpoint.fetch-participants-list + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + - nhcx.endpoint.status + - nhcx.endpoint.dummy-payer-process-request + callbacks: + - nhcx.callback.coverageeligibility-on-check + - nhcx.callback.preauth-on-submit + - nhcx.callback.claim-on-submit + - nhcx.callback.communication-request + - nhcx.callback.error + - nhcx.callback.on-status + flows: + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.report-a-processing-error + - nhcx.flow.payer-process-a-request + - nhcx.flow.generate-and-register-certificate + - nhcx.flow.sandbox-onboarding + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + - nhcx.concept.four-message-legs + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.workflow-codes + - nhcx.concept.status-lifecycle + - nhcx.concept.retries-and-expiry + - nhcx.concept.fhir-in-nhcx + decisions: + - nhcx.decision.session-endpoint + - nhcx.decision.key-encryption-algorithm + - nhcx.decision.jwe-serialisation + - nhcx.decision.status-poll-or-wait + sandbox: + - nhcx.sandbox.dummy-payer + - nhcx.sandbox.environments-and-base-urls + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1002 + - nhcx.error.nhcx-1003 + - nhcx.error.nhcx-1005 + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1001 + - nhcx.error.payr-1005 + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback + - nhcx.troubleshooting.recipient-cannot-decrypt + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + tests: + - nhcx.test.provider-uc-05 + - nhcx.test.provider-uc-07 + - nhcx.test.provider-uc-09 + glossary: + - nhcx.glossary.jwe + - nhcx.glossary.protected-header + - nhcx.glossary.correlation-id + - nhcx.glossary.api-call-id + - nhcx.glossary.workflow-id +--- + +# Send a sealed request through NHCX + +## In plain words + +The [National Health Claims Exchange](../../shared/glossary/nhcx.md) (NHCX) carries claims messages between providers and payers, but it cannot read them. You seal the business content, a [FHIR](../../shared/glossary/fhir.md) bundle, with the recipient's public key. The routing details ride in the sealed envelope's [protected header](../glossary/protected-header.md). + +NHCX answers your call at once, but only to say it accepted the message. The recipient's decision arrives later, as a separate call from NHCX to your callback address. No NHCX use-case call returns a decision in its own response. + +## Before you start + +- You are onboarded, with a participant code and a registered callback address. See [Onboard as a participant in the NHCX sandbox](sandbox-onboarding.md). +- Your callback endpoint acknowledges within 30 seconds. See [Receive, open and acknowledge a sealed message](receive-a-sealed-callback.md). +- Your `/v1/error` endpoint is live, so you hear when delivery fails. See [Report a processing failure on /v1/error](report-a-processing-error.md). +- You hold a session token. +- You have a FHIR bundle for the use case that passes validation against the [NRCeS](../../shared/glossary/nrces.md) profiles. See [FHIR in NHCX](../concepts/fhir-in-nhcx.md). + +## What happens + +The example is a pre-authorisation from a provider to a payer. Every use case follows the same four legs. + +```mermaid +sequenceDiagram + participant You as Your system, the sender + participant PS as NHCX participant service + participant NHCX as NHCX exchange + participant R as Recipient, the payer + You->>PS: POST /participant/get/policies + PS-->>You: policies with payerid and processingid + You->>PS: POST /fetch/certs with the recipient code + PS-->>You: recipient encryption_cert, cache it for 24 hours + Note over You: build the protected header and seal a compact JWE + You->>NHCX: POST /v1/preauth/submit with the payload + NHCX-->>You: 202 accepted + NHCX->>R: POST /v1/preauth/submit + R-->>NHCX: 202 within 30 seconds + Note over R: adjudicates, with no fixed turnaround + R->>NHCX: POST /v1/preauth/on_submit + NHCX->>You: POST /v1/preauth/on_submit + You-->>NHCX: 202 within 30 seconds + opt Delivery to the recipient fails five times + NHCX->>You: POST /v1/error + end + opt Sandbox, with the dummy payer as recipient + You->>R: POST /process/request with action, method and correlationId + end +``` + +### 1. Find the recipient + +A provider looks up the patient's policies with `POST /participant/get/policies`. Send `identifiertype` as `AbhaNumber`, `MemberId` or `MobileNo`, with the value in `identifiervalue`. Address the request to the `processingid` in the answer, not the `payerid`. + +To browse payers instead, call `POST /fetch/participants/list` with `role`, `fromdate` and `todate`. Dates are `dd/MM/yyyy`. + +### 2. Fetch the recipient's certificate + +Call `POST /fetch/certs` with `{"participantid": ""}`. Cache the answer for 24 hours. Import it as an X.509 certificate. If that fails, import it as a bare public key. + +### 3. Build the protected header + +| Header | Value | +|---|---| +| `alg` | The key algorithm from [RSA-OAEP or RSA-OAEP-256](../decisions/key-encryption-algorithm.md) | +| `enc` | `A256GCM` | +| `x-hcx-sender_code` | Your participant code | +| `x-hcx-recipient_code` | The recipient's participant code | +| `x-hcx-api_call_id` | A new random UUID for this call | +| `x-hcx-request_id` | A new random UUID for this request | +| `x-hcx-correlation_id` | The conversation's UUID, as [message identifiers](../concepts/message-identifiers.md) sets out | +| `x-hcx-workflow_id` | The stage code, for example `12` for a new pre-authorisation. See [workflow codes](../concepts/workflow-codes.md) | +| `x-hcx-timestamp` | The current time, in the format [protocol headers](../concepts/protocol-headers.md) gives | +| `x-hcx-status` | `request.initiated` | +| `x-hcx-ben-abha-id` | The beneficiary's ABHA number, where the use case carries it | + +The `x-hcx-*` values travel only inside the protected header, never as plain HTTP headers. + +### 4. Seal it + +Encrypt the bundle into a [JWE](../glossary/jwe.md) in compact serialisation: five base64url parts joined by dots. See [Compact or flattened JWE serialisation](../decisions/jwe-serialisation.md). The request body is: + +```json +{ + "payload": "" +} +``` + +### 5. Post it + +Post to the use-case path on the use-case base address in [NHCX environments, hosts and base URLs](../sandbox/environments-and-base-urls.md). Send `Accept: application/json` and `Content-Type: application/json`. Send the session token in both `bearer_auth` and `Authorization`, each as `Bearer `. + +NHCX answers `202` at once. A gateway error, an `NHCX-` code, comes back in this response instead. + +### 6. Wait for the answer + +NHCX forwards your message and the recipient acknowledges it. The recipient then decides, with no fixed turnaround. Its answer arrives at your registered address on the paired path: + +| You posted | The answer arrives on | +|---|---| +| `/v1/coverageeligibility/check` | `/v1/coverageeligibility/on_check` | +| `/v1/insuranceplan/request` | `/v1/insuranceplan/on_request` | +| `/v1/preauth/submit` | `/v1/preauth/on_submit` | +| `/v1/claim/submit` | `/v1/claim/on_submit` | +| `/v1/task/submit` | `/v1/task/on_submit` | +| `/v1/search/submit` | `/v1/search/on_submit` | + +The answer is a sealed decision, or a plain `ProtocolResponse` when the recipient could not process your request. Handle it with [Receive, open and acknowledge a sealed message](receive-a-sealed-callback.md). A payer that needs more documents first sends you `/v1/communication/request`. + +### 7. When it goes quiet + +Check your `/v1/error` records first. Then ask with `POST /v1/status`, whose answer arrives on `/v1/on_status`. See [Poll with /v1/status or wait for the callback](../decisions/status-poll-or-wait.md). + +If you resend a message, give it a new `x-hcx-api_call_id`. After a failure, NHCX makes the correlation ID inactive, so start a fresh request with a new correlation ID. + +### 8. In the sandbox + +The dummy payer is `1000003538@hcx`. After a pre-authorisation or claim, trigger its answer with `POST /process/request` on `https://apisbx.abdm.gov.in/pmjay/sbxhcx/dummyhcxpayer`: + +```json +{ + "action": "Approve", + "method": "Preauth", + "correlationId": "" +} +``` + +`action` is `Approve`, `Reject` or `Query`, and `method` is `Preauth` or `Claim`. A `Query` makes the dummy payer send `/v1/communication/request` first. You answer it on `/v1/communication/on_request`, and the final answer follows on the `on_submit` path. See [The dummy payer and what it answers](../sandbox/dummy-payer.md). + +## How you know it worked + +NHCX answered `202` to your post. Later, NHCX delivered the paired answer to your registered address, and you answered it `202` within 30 seconds. In that answer's protected header: + +- `x-hcx-sender_code` is the recipient you addressed. +- `x-hcx-recipient_code` is your participant code. +- The identifiers match your request as [message identifiers](../concepts/message-identifiers.md) sets out. +- `x-hcx-status` is `response.complete`, `response.partial` or `response.error`. + +```observation schema=exit-condition +channel: callback +path: /v1/preauth/on_submit +match: + x-hcx-sender_code: + x-hcx-recipient_code: + x-hcx-status: one of response.complete, response.partial, response.error +acknowledge: HTTP 202 within 30 seconds +``` + +## When it goes wrong + +- **`401` on any call.** Get a new session token and retry once. See [NHCX-401](../errors/nhcx-401.md). +- **The sender or receiver is not registered.** One of the codes in your header is wrong or not onboarded. For a payer, use the `processingid` from the policy lookup. See [NHCX-1002](../errors/nhcx-1002.md) and [NHCX-1003](../errors/nhcx-1003.md). +- **Invalid request header.** A mandatory protected header is missing, or its prefix is not `x-hcx-`. See [NHCX-1005](../errors/nhcx-1005.md). +- **Duplicate request.** The correlation ID already belongs to another request. See [NHCX-1006](../errors/nhcx-1006.md) and [Responses arrive against the wrong request](../troubleshooting/duplicate-or-mismatched-correlation.md). +- **The recipient cannot decrypt.** You sealed with a stale certificate, or a key algorithm it does not accept. Fetch the certificate again. See [PAYR-1001](../errors/payr-1001.md) and [The recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). +- **The timestamp is refused.** The PMJAY reference payer refuses a timestamp more than 24 hours away from its clock. Keep your clock synchronised. See [PAYR-1005](../errors/payr-1005.md). +- **Accepted, and no answer arrives.** See [The request was accepted with 202 and no callback arrives](../troubleshooting/accepted-then-no-callback.md). diff --git a/catalogue/nhcx/flows/status-check.md b/catalogue/nhcx/flows/status-check.md new file mode 100644 index 000000000..b3ba3833c --- /dev/null +++ b/catalogue/nhcx/flows/status-check.md @@ -0,0 +1,140 @@ +--- +id: nhcx.flow.status-check +type: flow +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Check the status of a request +summary: >- + Ask the exchange where a request you sent now stands: still queued, delivered + to the recipient, or stopped. +sources: +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Status. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Status Description. +- url: https://hcxsbx.abdm.gov.in/statushcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/statushcxservice.json + hash: sha256:93b6355a234ef56607427fcdfa32da4921124180c9df08ecd73c8af8955c2adf + fetched: '2026-09-14' + note: 'API specification: statushcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. path /v1/status; StatusSuccessResponse.' +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use case 13, Get status. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Error scenario. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, item 8. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.status + callbacks: + - nhcx.callback.on-status + - nhcx.callback.error + concepts: + - nhcx.concept.status-lifecycle + - nhcx.concept.message-identifiers + - nhcx.concept.retries-and-expiry + tests: + - nhcx.test.provider-uc-13 + - nhcx.test.payer-uc-15 + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + - nhcx.flow.send-a-sealed-request + decisions: + - nhcx.decision.status-poll-or-wait + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1012 + - nhcx.error.nhcx-401 + troubleshooting: + - nhcx.troubleshooting.everything-returns-401 + glossary: + - shared.glossary.nhcx +--- + +# Check the status of a request + +## In plain words + +A status check asks the [NHCX](../../shared/glossary/nhcx.md) exchange where a request you sent now stands. It answers with the request's protocol status: still queued at the exchange, delivered to the recipient's system, or stopped. + +It does not return the payer's decision. The decision arrives on the request's own callback, such as `/v1/preauth/on_submit`. + +Providers and payers both use it, for requests they sent. Use it when a callback is late, before you think of resubmitting. [Poll or wait](../decisions/status-poll-or-wait.md) helps you decide when. + +## Before you start + +- You sent the request you want to check, and you stored its `x-hcx-api_call_id` and recipient code. +- Your session token and callback endpoint are in place. The status answer arrives on `/v1/on_status`. + +## What happens + +```mermaid +sequenceDiagram + participant P as Provider (your system) + participant N as NHCX + participant Y as Payer + P->>N: POST /v1/preauth/submit (earlier request) + N-->>P: HTTP 202 Accepted + N->>Y: forwards when the payer's system is reachable + Note over P: the callback is late + P->>N: POST /v1/status + Note right of P: x-hcx-correlation_id is the earlier call's x-hcx-api_call_id + N-->>P: HTTP 202 Accepted, result.protocol_status + N->>P: POST /v1/on_status + P-->>N: HTTP 202 Accepted + Note left of P: read the status, then wait, or send a fresh request +``` + +1. Find the `x-hcx-api_call_id` of the request you are checking. +2. Build the protected header. Set `x-hcx-correlation_id` to that earlier `x-hcx-api_call_id`. Use a fresh `x-hcx-api_call_id` for the status call itself. +3. Set `x-hcx-status` to `request.initiated`. Use the same sender and recipient codes as the earlier request, and send `x-hcx-ben-abha-id`. +4. Seal the body as `{"payload": ""}`, as for every call. See [send a sealed request](send-a-sealed-request.md). +5. Call [POST /v1/status](../endpoints/status.md). NHCX answers `202 Accepted`. The body's `result.protocol_status` names where the request stands. +6. Receive [POST /v1/on_status](../callbacks/on-status.md). Its protected header carries the request's attributes, including `x-hcx-status`. Answer `202 Accepted`. +7. Act on the status: + +| Status | Meaning | What to do | +|---|---|---| +| `request.queued` | Queued at the exchange, ready to be picked up | Wait. Do not resend | +| `request.dispatched` | Reached the recipient's system | The recipient holds it. Wait for its callback | +| `request.stopped` | Stopped after failed attempts to reach the recipient | It will not be delivered. Check `/v1/error`, then send a fresh request | + +A fresh request always gets a new correlation id. After a failure, the old one is inactive. + +## How you know it worked + +The check is finished when all of these hold: + +- NHCX answered `POST /v1/status` with `202` and a `result.protocol_status`. +- You received `POST /v1/on_status` with the correlation id you asked about, and answered `202`. +- You hold one protocol status for the request: `request.queued`, `request.dispatched` or `request.stopped`. +- You acted on it: waited, or sent a fresh request with a new correlation id. + +## When it goes wrong + +NHCX finds no request. [NHCX-1012](../errors/nhcx-1012.md) means no record matches the api call id you gave. You probably put a new id in `x-hcx-correlation_id`. Use the earlier request's `x-hcx-api_call_id`. + +The request was deleted. After five failed delivery attempts, the exchange deletes a request. Its details come back to you on [/v1/error](../callbacks/error.md). Send a fresh request. + +You resent instead of checking. [NHCX-1006](../errors/nhcx-1006.md) means a request with that correlation id already exists. A queued request is still being worked on. Check its status rather than resending. + +Every call returns 401. [NHCX-401](../errors/nhcx-401.md) means your session token is missing or expired. See [every NHCX call returns 401](../troubleshooting/everything-returns-401.md). diff --git a/catalogue/nhcx/glossary/adjudication.md b/catalogue/nhcx/glossary/adjudication.md new file mode 100644 index 000000000..d4298537b --- /dev/null +++ b/catalogue/nhcx/glossary/adjudication.md @@ -0,0 +1,56 @@ +--- +id: nhcx.glossary.adjudication +type: glossary +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Adjudication +summary: >- + The payer's decision on whether a request is payable and how much. +sources: +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. page 9-10, section 3 PMJAY Overview and 4.1 Claims Adjudication Process. +- url: https://hcxsbx.abdm.gov.in/images/af8d243edcc2139a515d.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Usecases.pdf + hash: sha256:8709b2907a0d5a0dbb36f5e63ed8deae269e0c75372b05d71ce7380c8a0929e7 + fetched: '2026-09-14' + note: NHCX Usecases, row 1 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2, HCX Key Use cases table. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Acceptance scenario. +verified: + status: unverified +related: + glossary: + - nhcx.glossary.payer + - nhcx.glossary.tms + decisions: + - nhcx.decision.payer-implementation +--- + +# Adjudication + +## In plain words + +Adjudication is the payer's decision on a request: whether it is admissible under the policy and, if so, how much is payable. The payer adjudicates your preauthorisation or claim and returns the result in a ClaimResponse on the `on_submit` callback. [NHCX](../../shared/glossary/nhcx.md) carries the request and the result; the decision is the payer's. Under [PMJAY](../glossary/pmjay.md), named roles in [TMS](../glossary/tms.md) adjudicate. + +## Before you start + +Nothing. A glossary entry assumes no prior reading. + +## What happens + +Nothing happens here. This entry defines a term, it does not describe a call. + +## How you know it worked + +You have understood this when you can say where an adjudication result reaches your system. + +## When it goes wrong + +Waiting on the `202` for a decision. It only means the exchange accepted the request. diff --git a/catalogue/nhcx/glossary/api-call-id.md b/catalogue/nhcx/glossary/api-call-id.md new file mode 100644 index 000000000..29bbc5885 --- /dev/null +++ b/catalogue/nhcx/glossary/api-call-id.md @@ -0,0 +1,55 @@ +--- +id: nhcx.glossary.api-call-id +type: glossary +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: API call id +summary: >- + The identifier your system generates afresh for every single call. +sources: +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 3, FAQ 4. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Message Structure, NHCX Protocol Headers table. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Status, x-hcx-correlation_id row. +verified: + status: unverified +related: + concepts: + - nhcx.concept.message-identifiers + glossary: + - nhcx.glossary.correlation-id +--- + +# API call id + +## In plain words + +The api call id, sent in `x-hcx-api_call_id`, is a random 36-character identifier that your system generates for every single call to [NHCX](../../shared/glossary/nhcx.md). It is new on every attempt, including retries. On an answer it differs from the correlation id. A status check uses the api call id of the request being checked. + +## Before you start + +Nothing. A glossary entry assumes no prior reading. + +## What happens + +Nothing happens here. This entry defines a term, it does not describe a call. + +## How you know it worked + +You have understood this when you can say which of the api call id and the correlation id changes on a retry. + +## When it goes wrong + +Copying an api call id from an example instead of generating a fresh one for every call. diff --git a/catalogue/nhcx/glossary/bis.md b/catalogue/nhcx/glossary/bis.md new file mode 100644 index 000000000..334346401 --- /dev/null +++ b/catalogue/nhcx/glossary/bis.md @@ -0,0 +1,44 @@ +--- +id: nhcx.glossary.bis +type: glossary +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: BIS, Beneficiary Identification System +summary: >- + One of the government scheme systems whose workflows decide a claim. +sources: +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. page 9, section 3 PMJAY Overview. +verified: + status: unverified +related: + glossary: + - nhcx.glossary.pmjay + - nhcx.glossary.tms +--- + +# BIS, Beneficiary Identification System + +## In plain words + +BIS stands for Beneficiary Identification System. It is one of three [PMJAY](../glossary/pmjay.md) systems whose workflows decide a claim, with the Transaction Management System and the Hospital Empanelment Module. You meet the name where PMJAY claim adjudication is described; the decisions themselves are taken in [TMS](../glossary/tms.md). + +## Before you start + +Nothing. A glossary entry assumes no prior reading. + +## What happens + +Nothing happens here. This entry defines a term, it does not describe a call. + +## How you know it worked + +You have understood this when you can name the three PMJAY systems behind a claim decision. + +## When it goes wrong + +Confusing BIS with TMS. Preauthorisation and claim decisions are taken in TMS. diff --git a/catalogue/nhcx/glossary/claim.md b/catalogue/nhcx/glossary/claim.md new file mode 100644 index 000000000..95bd0a3f8 --- /dev/null +++ b/catalogue/nhcx/glossary/claim.md @@ -0,0 +1,57 @@ +--- +id: nhcx.glossary.claim +type: glossary +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Claim +summary: >- + A request asking the payer to pay for treatment already given. +sources: +- url: https://hcxsbx.abdm.gov.in/images/af8d243edcc2139a515d.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Usecases.pdf + hash: sha256:8709b2907a0d5a0dbb36f5e63ed8deae269e0c75372b05d71ce7380c8a0929e7 + fetched: '2026-09-14' + note: NHCX Usecases, row 1 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, Claim Request Submission. +- url: https://hcxsbx.abdm.gov.in/images/064cf2e059987011e53a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Claim.pdf + hash: sha256:66290de20d57d69e681946a0101518092ca43b3775bb38997c43beb17fb38076 + fetched: '2026-09-14' + note: Claim, listed on https://hcxsbx.abdm.gov.in/#/documents, not named in the NHCX document sheet. Claim Submit request and response. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. page 35, Claim functional points to note. +verified: + status: unverified +related: + flows: + - nhcx.flow.claim-submit + endpoints: + - nhcx.endpoint.claim-submit + concepts: + - nhcx.concept.claim-cycle +--- + +# Claim + +## In plain words + +A claim asks the payer to pay for treatment already given. After discharge your system sends a Claim bundle through [NHCX](../../shared/glossary/nhcx.md) on `/v1/claim/submit`. The payer answers with a ClaimResponse on `/v1/claim/on_submit`. Under [PMJAY](../glossary/pmjay.md), discharge details travel inside the claim, and a claim cannot be cancelled. + +## Before you start + +Nothing. A glossary entry assumes no prior reading. + +## What happens + +Nothing happens here. This entry defines a term, it does not describe a call. + +## How you know it worked + +You have understood this when you can say how a claim differs from a preauthorisation. + +## When it goes wrong + +Expecting a decision in the `202`. It means the exchange accepted the request; the decision arrives on `/v1/claim/on_submit`. diff --git a/catalogue/nhcx/glossary/communication-request.md b/catalogue/nhcx/glossary/communication-request.md new file mode 100644 index 000000000..65c4309a3 --- /dev/null +++ b/catalogue/nhcx/glossary/communication-request.md @@ -0,0 +1,51 @@ +--- +id: nhcx.glossary.communication-request +type: glossary +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Communication request +summary: >- + The payer asking the hospital for more information while a request is under review. +sources: +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use case 10, Raise communication request. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. page 6, Query flow row; page 32-33, 8.4.4 Query updation. +verified: + status: unverified +related: + concepts: + - nhcx.concept.queries-and-communication + endpoints: + - nhcx.endpoint.communication-request + - nhcx.endpoint.communication-on-request +--- + +# Communication request + +## In plain words + +A communication request is the payer asking the provider for more information, such as additional documents, while a preauthorisation or claim is with the payer. The payer sends it through [NHCX](../../shared/glossary/nhcx.md) on `/v1/communication/request`, and your system replies with the documents on `/v1/communication/on_request`. Under [PMJAY](../glossary/pmjay.md), queries arrive in the preauthorisation or claim response instead, and you answer with the query response workflow id. + +## Before you start + +Nothing. A glossary entry assumes no prior reading. + +## What happens + +Nothing happens here. This entry defines a term, it does not describe a call. + +## How you know it worked + +You have understood this when you can say which path carries your reply. + +## When it goes wrong + +Waiting for a communication request on a PMJAY case. PMJAY queries arrive in the response itself. diff --git a/catalogue/nhcx/glossary/correlation-id.md b/catalogue/nhcx/glossary/correlation-id.md new file mode 100644 index 000000000..48b2c9938 --- /dev/null +++ b/catalogue/nhcx/glossary/correlation-id.md @@ -0,0 +1,64 @@ +--- +id: nhcx.glossary.correlation-id +type: glossary +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Correlation id +summary: >- + The identifier that ties every message of one request and its answers together. +sources: +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Message Structure, x-hcx-correlation_id row. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 3, FAQ 4. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, item 8. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet Preauth, x-hcx-correlation_id row. +verified: + status: unverified +related: + concepts: + - nhcx.concept.message-identifiers + glossary: + - nhcx.glossary.api-call-id + troubleshooting: + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + errors: + - nhcx.error.nhcx-1006 +--- + +# Correlation id + +## In plain words + +The correlation id, sent in `x-hcx-correlation_id`, is a random 36-character identifier that ties every message of one request cycle on [NHCX](../../shared/glossary/nhcx.md) together. The request that opens the cycle sets it, equal to that request's api call id. Every answer and callback in the cycle carries it unchanged. After an error it becomes inactive, and a fresh request needs a new one. + +## Before you start + +Nothing. A glossary entry assumes no prior reading. + +## What happens + +Nothing happens here. This entry defines a term, it does not describe a call. + +## How you know it worked + +You have understood this when you can say what value a payer puts in the correlation id of its answer. + +## When it goes wrong + +Retrying a failed request with its old correlation id. It is refused as a duplicate, [NHCX-1006](../errors/nhcx-1006.md). See [responses arrive against the wrong request](../troubleshooting/duplicate-or-mismatched-correlation.md). diff --git a/catalogue/nhcx/glossary/coverage-eligibility.md b/catalogue/nhcx/glossary/coverage-eligibility.md new file mode 100644 index 000000000..13ce2180c --- /dev/null +++ b/catalogue/nhcx/glossary/coverage-eligibility.md @@ -0,0 +1,59 @@ +--- +id: nhcx.glossary.coverage-eligibility +type: glossary +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Coverage eligibility +summary: >- + The check a hospital runs to confirm a patient's policy and what it covers. +sources: +- url: https://hcxsbx.abdm.gov.in/images/cfcbe62e8378d4f48ee6.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Coverage Eligibility.pdf + hash: sha256:69dd680ddac44231a97276a1d735e45777d8e43b5563b7248fd367a838d9744f + fetched: '2026-09-14' + note: Coverage Eligibility, listed on https://hcxsbx.abdm.gov.in/#/documents, not named in the NHCX document sheet. Coverage Eligibility Check request and response. +- url: https://hcxsbx.abdm.gov.in/images/13093b5f9b88fe826123.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Insurance Plan IG.docx + hash: sha256:e9c6c82b6d67fd8476d6d19a5961419beb04e3c0613533453ed1e16e2a569cc1 + fetched: '2026-09-14' + note: Insurance Plan IG, row 25 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Core APIs, CoverageEligibility purposes list. +- url: https://hcxsbx.abdm.gov.in/images/53347f5988b0ce5396f1.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_APIs to be called based on scenario.xlsx + hash: sha256:f92a30673d65dd2cc3cf09e2087c624f23f781dc4ca6b5cd8ec1825e224ac108 + fetched: '2026-09-14' + note: NHCX_APIs to be called based on scenario, row 26 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sheet Scenarios, rows 3 to 5. +verified: + status: unverified +related: + flows: + - nhcx.flow.coverage-eligibility-check + endpoints: + - nhcx.endpoint.coverageeligibility-check + concepts: + - nhcx.concept.coverage-eligibility-purposes + decisions: + - nhcx.decision.eligibility-purpose +--- + +# Coverage eligibility + +## In plain words + +Coverage eligibility is the check a provider runs to confirm a patient's policy and what it covers. Your system sends a `CoverageEligibilityRequest` through [NHCX](../../shared/glossary/nhcx.md) on `/v1/coverageeligibility/check`, with a `purpose` of `discovery`, `validation`, `benefits` or `auth-requirements`. The payer answers on `/v1/coverageeligibility/on_check`. You run it at registration and again before each preauthorisation. + +## Before you start + +Nothing. A glossary entry assumes no prior reading. + +## What happens + +Nothing happens here. This entry defines a term, it does not describe a call. + +## How you know it worked + +You have understood this when you can say which purpose to send before a preauthorisation. + +## When it goes wrong + +Skipping the `auth-requirements` check and learning the required documents from a query instead. See [which coverage eligibility purpose to send](../decisions/eligibility-purpose.md). diff --git a/catalogue/nhcx/glossary/crc.md b/catalogue/nhcx/glossary/crc.md new file mode 100644 index 000000000..50d358344 --- /dev/null +++ b/catalogue/nhcx/glossary/crc.md @@ -0,0 +1,51 @@ +--- +id: nhcx.glossary.crc +type: glossary +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: CRC +summary: >- + The committee that decides appeals against rejected claims in the government health + scheme. +sources: +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Erroneous claim FAQ 15. +- file: catalogue/openapi/.raw/nhcx-site-2026-09-14/not-on-site/External_NHCX_Payer_Service_API_Workflow_Guide.docx + hash: sha256:1028d480d2fabe3204301f1c1b192a0077ddfa64f7f9084b01f73e004253fdd7 + fetched: '2026-09-05' + note: NHCX Payer Service API Workflow Guide for External Integrators, not listed on hcxsbx.abdm.gov.in and not named in the NHCX document sheet, received separately. CLAIM Step 6 and role table. +verified: + status: unverified +related: + glossary: + - nhcx.glossary.reprocess + - nhcx.glossary.pmjay + endpoints: + - nhcx.endpoint.payer-service-process-case +--- + +# CRC + +## In plain words + +CRC stands for Claim Review Committee, the body that decides [PMJAY](../glossary/pmjay.md) reprocess appeals. Its decision is final: no erroneous claim can be raised against it. In the PMJAY payer service it is the last role in the claim chain, acting with `Approve`, `Reject` or `Pending`. + +## Before you start + +Nothing. A glossary entry assumes no prior reading. + +## What happens + +Nothing happens here. This entry defines a term, it does not describe a call. + +## How you know it worked + +You have understood this when you can say what can follow a CRC decision. + +## When it goes wrong + +Raising an erroneous claim for the balance after a CRC partial approval. It is not accepted. diff --git a/catalogue/nhcx/glossary/enhancement.md b/catalogue/nhcx/glossary/enhancement.md new file mode 100644 index 000000000..c2497bd20 --- /dev/null +++ b/catalogue/nhcx/glossary/enhancement.md @@ -0,0 +1,57 @@ +--- +id: nhcx.glossary.enhancement +type: glossary +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Enhancement +summary: >- + A request to extend an approved preauthorisation or add procedures to it. +sources: +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. page 32, 8.4.3 Enhancement. +- url: https://hcxsbx.abdm.gov.in/images/c42ad170f37c987ed173.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx + hash: sha256:f56dd156c232192296082f23b1561d0ff11fd40992e6675de41c5c991d579e6d + fetched: '2026-09-14' + note: Workflow Status Sheets(with Codes), row 12 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet1, Enhancement Request Initiated. +- url: https://hcxsbx.abdm.gov.in/images/53347f5988b0ce5396f1.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_APIs to be called based on scenario.xlsx + hash: sha256:f92a30673d65dd2cc3cf09e2087c624f23f781dc4ca6b5cd8ec1825e224ac108 + fetched: '2026-09-14' + note: NHCX_APIs to be called based on scenario, row 26 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sheet Scenarios, row 7. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-enhancement + concepts: + - nhcx.concept.workflow-codes + glossary: + - nhcx.glossary.preauthorisation +--- + +# Enhancement + +## In plain words + +An enhancement asks the payer to extend an already approved preauthorisation or add procedures to it. It travels through [NHCX](../../shared/glossary/nhcx.md) on `/v1/preauth/submit` with workflow id `13`, carrying the approved treatments and the new ones. You can raise several until discharge, within the limit, but only after the previous request has closed. + +## Before you start + +Nothing. A glossary entry assumes no prior reading. + +## What happens + +Nothing happens here. This entry defines a term, it does not describe a call. + +## How you know it worked + +You have understood this when you can say what must be true before you send an enhancement. + +## When it goes wrong + +Sending an enhancement while the previous preauthorisation or resubmission is still open. Wait for it to close. diff --git a/catalogue/nhcx/glossary/hbp.md b/catalogue/nhcx/glossary/hbp.md new file mode 100644 index 000000000..7e84f8f23 --- /dev/null +++ b/catalogue/nhcx/glossary/hbp.md @@ -0,0 +1,50 @@ +--- +id: nhcx.glossary.hbp +type: glossary +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: HBP, Health Benefit Package +summary: >- + The list of treatment packages a government scheme beneficiary can be treated + under. +sources: +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. FAQ 24 Unspecified Procedure, questions 1 and 7. +- url: https://hcxsbx.abdm.gov.in/images/4d333fa6ce5ef99920de.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Test Cases.xlsx + hash: sha256:0d95021974cfe81ab2e3bf66f983228a70b8fed8d7d251eb6d7eeab7354ecad2 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Test Cases, row 31 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Test case TC-HBP-01. +verified: + status: unverified +related: + glossary: + - nhcx.glossary.pmjay + - nhcx.glossary.insurance-plan +--- + +# HBP, Health Benefit Package + +## In plain words + +HBP is the package list of a [PMJAY](../glossary/pmjay.md) policy: the packages a beneficiary can be treated under. Each package has a code, a rate and claim conditions, delivered in the [insurance plan](../glossary/insurance-plan.md). A procedure outside the package list is an unspecified procedure, coded with its specialty prefix and `215`, such as `SG215`. + +## Before you start + +Nothing. A glossary entry assumes no prior reading. + +## What happens + +Nothing happens here. This entry defines a term, it does not describe a call. + +## How you know it worked + +You have understood this when you can say where your system reads a patient's HBP packages from. + +## When it goes wrong + +Booking a procedure outside the package list as a normal package. Use the unspecified procedure code for its specialty. diff --git a/catalogue/nhcx/glossary/insurance-plan.md b/catalogue/nhcx/glossary/insurance-plan.md new file mode 100644 index 000000000..ee4ba7b70 --- /dev/null +++ b/catalogue/nhcx/glossary/insurance-plan.md @@ -0,0 +1,59 @@ +--- +id: nhcx.glossary.insurance-plan +type: glossary +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Insurance plan +summary: >- + The payer's policy in machine-readable form, with its packages, rates and rules. +sources: +- url: https://hcxsbx.abdm.gov.in/images/13093b5f9b88fe826123.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Insurance Plan IG.docx + hash: sha256:e9c6c82b6d67fd8476d6d19a5961419beb04e3c0613533453ed1e16e2a569cc1 + fetched: '2026-09-14' + note: Insurance Plan IG, row 25 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Core APIs, InsurancePlan Task table. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. InsurancePlan Response, Key Characteristics. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. page 13, 6.1 High-Level NHCX Process Flow. +verified: + status: unverified +related: + flows: + - nhcx.flow.insurance-plan-request + endpoints: + - nhcx.endpoint.insuranceplan-request + concepts: + - nhcx.concept.insurance-plan + errors: + - nhcx.error.payr-1406 +--- + +# Insurance plan + +## In plain words + +An insurance plan is the payer's policy in machine-readable form: covered specialties, packages, package rates, conditions and document rules. Your system asks for it with a `Task` on `/v1/insuranceplan/request` and receives an InsurancePlan bundle on `/v1/insuranceplan/on_request`. For [PMJAY](../glossary/pmjay.md) the plan is specific to your hospital and drives what your preauthorisations and claims must carry. + +## Before you start + +Nothing. A glossary entry assumes no prior reading. + +## What happens + +Nothing happens here. This entry defines a term, it does not describe a call. + +## How you know it worked + +You have understood this when you can say what your system reads from the plan before a preauthorisation. + +## When it goes wrong + +Fetching the plan on every transaction. Cache it and refresh it on a schedule. A second request for the same hospital and policy while one is running is refused with [PAYR-1406](../errors/payr-1406.md). diff --git a/catalogue/nhcx/glossary/irdai.md b/catalogue/nhcx/glossary/irdai.md new file mode 100644 index 000000000..aba0167c8 --- /dev/null +++ b/catalogue/nhcx/glossary/irdai.md @@ -0,0 +1,55 @@ +--- +id: nhcx.glossary.irdai +type: glossary +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: IRDAI +summary: >- + The regulator of insurance in India, which helps set who may join the claims exchange. +sources: +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Registries section. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, item 5. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. Functional Testing, HTC demo. +verified: + status: unverified +related: + glossary: + - nhcx.glossary.payer + - nhcx.glossary.tpa + - shared.glossary.nha +--- + +# IRDAI + +## In plain words + +IRDAI is the Insurance Regulatory and Development Authority of India. With [NHA](../../shared/glossary/nha.md), it sets the procedure for enrolling participants on [NHCX](../../shared/glossary/nhcx.md). A payer or [TPA](../glossary/tpa.md) registers with its IRDAI registry ID, without leading zeros: `0123` is sent as `123`. IRDAI also takes part in the demo that ends functional testing. + +## Before you start + +Nothing. A glossary entry assumes no prior reading. + +## What happens + +Nothing happens here. This entry defines a term, it does not describe a call. + +## How you know it worked + +You have understood this when you can say which registry ID a payer registers with. + +## When it goes wrong + +Sending the IRDAI registry ID with its leading zeros. diff --git a/catalogue/nhcx/glossary/jwe.md b/catalogue/nhcx/glossary/jwe.md new file mode 100644 index 000000000..fd55af2ff --- /dev/null +++ b/catalogue/nhcx/glossary/jwe.md @@ -0,0 +1,59 @@ +--- +id: nhcx.glossary.jwe +type: glossary +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: JWE, JSON Web Encryption +summary: >- + The encryption standard that seals every exchange payload so only the recipient + can read it. +sources: +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Message Structure, Protected Header and Signatures. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. FAQ 13. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Request rows of each use case sheet. +verified: + status: unverified +related: + concepts: + - nhcx.concept.jwe-envelope + decisions: + - nhcx.decision.jwe-serialisation + - nhcx.decision.key-encryption-algorithm + glossary: + - nhcx.glossary.protected-header +--- + +# JWE, JSON Web Encryption + +## In plain words + +JWE stands for JSON Web Encryption, the standard (RFC 7516) that seals every [NHCX](../../shared/glossary/nhcx.md) payload so only the recipient can read it. The [protected header](../glossary/protected-header.md) stays readable, so NHCX can route the message, and is integrity protected with the ciphertext. Every use case request carries one JWE in compact form inside the `payload` field. See [the JWE envelope that seals every payload](../concepts/jwe-envelope.md). + +## Before you start + +Nothing. A glossary entry assumes no prior reading. + +## What happens + +Nothing happens here. This entry defines a term, it does not describe a call. + +## How you know it worked + +You have understood this when you can say which part of a JWE the exchange reads and which part it cannot. + +## When it goes wrong + +Sending the flattened JSON form. Send the compact string in `payload`. See [compact or flattened JWE serialisation](../decisions/jwe-serialisation.md). diff --git a/catalogue/nhcx/glossary/participant-code.md b/catalogue/nhcx/glossary/participant-code.md new file mode 100644 index 000000000..45b3df45f --- /dev/null +++ b/catalogue/nhcx/glossary/participant-code.md @@ -0,0 +1,54 @@ +--- +id: nhcx.glossary.participant-code +type: glossary +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Participant code +summary: >- + The address the exchange gives your organisation when you register. +sources: +- url: https://hcxsbx.abdm.gov.in/images/260d0dec19a681e80262.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Production.pdf + hash: sha256:c38476fb90101f13fdfea447861292718d561e1dc088ae20950b193606500d2e + fetched: '2026-09-14' + note: Onboarding providers and payers in Production, row 5 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Participant creation response. +- url: https://hcxsbx.abdm.gov.in/images/bc2efb078b98548f8e6b.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Sandbox.pdf + hash: sha256:cbd03baf428655f0305e2f60ca331f8b76700496b070c522cafcc95001710b3a + fetched: '2026-09-14' + note: Onboarding providers and payers in Sandbox, row 4 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Participant APIs, response structure. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Message Structure, NHCX Protocol Headers table. +verified: + status: unverified +related: + concepts: + - nhcx.concept.participant-code + - nhcx.concept.participant-registry +--- + +# Participant code + +## In plain words + +A participant code is the address [NHCX](../../shared/glossary/nhcx.md) assigns to your organisation when you register. It carries a suffix after the `@` naming the instance, as in `100001@sbx` or `1000003538@hcx`. Every message names its sender and recipient by participant code, in `x-hcx-sender_code` and `x-hcx-recipient_code`. See [participant codes and how every message is addressed](../concepts/participant-code.md). + +## Before you start + +Nothing. A glossary entry assumes no prior reading. + +## What happens + +Nothing happens here. This entry defines a term, it does not describe a call. + +## How you know it worked + +You have understood this when you can name the two protocol headers that carry participant codes. + +## When it goes wrong + +Typing a code from an example instead of using the one returned when you registered. diff --git a/catalogue/nhcx/glossary/payer.md b/catalogue/nhcx/glossary/payer.md new file mode 100644 index 000000000..9c51ec639 --- /dev/null +++ b/catalogue/nhcx/glossary/payer.md @@ -0,0 +1,57 @@ +--- +id: nhcx.glossary.payer +type: glossary +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Payer +summary: >- + The insurance company or scheme that pays for a patient's treatment. +sources: +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. FAQ 7, role codes. +- url: https://hcxsbx.abdm.gov.in/images/539853c50347b32b9a5e.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Policy Linking and De-Linking Process.pdf + hash: sha256:420115b9a54e15fa625312a56362164d92d23dd0d6ebf9195135bb00055d1911 + fetched: '2026-09-14' + note: Policy Linking and De-Linking Process, row 8 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Policy Linking Process. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, item 7. +verified: + status: unverified +related: + concepts: + - nhcx.concept.participant-roles + glossary: + - nhcx.glossary.provider + - nhcx.glossary.tpa + - nhcx.glossary.participant-code +--- + +# Payer + +## In plain words + +A payer is the insurance company or scheme that pays for a patient's treatment. On [NHCX](../../shared/glossary/nhcx.md) it registers with the role `PAYER` (`10002`) and holds its own participant code, whether or not a [TPA](../glossary/tpa.md) processes its claims. You meet payers as the recipients of eligibility checks, preauthorisations and claims, and as the senders of payment notices. See [participant roles](../concepts/participant-roles.md). + +## Before you start + +Nothing. A glossary entry assumes no prior reading. + +## What happens + +Nothing happens here. This entry defines a term, it does not describe a call. + +## How you know it worked + +You have understood this when you can say which participant code a payer's requests go to when a TPA processes them. + +## When it goes wrong + +Addressing requests to the insurer's code when a TPA processes its policies. Send them to the processing ID. diff --git a/catalogue/nhcx/glossary/payment-notice.md b/catalogue/nhcx/glossary/payment-notice.md new file mode 100644 index 000000000..5017d2203 --- /dev/null +++ b/catalogue/nhcx/glossary/payment-notice.md @@ -0,0 +1,60 @@ +--- +id: nhcx.glossary.payment-notice +type: glossary +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Payment notice +summary: >- + The payer's message that it is paying or has paid a claim. +sources: +- url: https://hcxsbx.abdm.gov.in/images/af8d243edcc2139a515d.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Usecases.pdf + hash: sha256:8709b2907a0d5a0dbb36f5e63ed8deae269e0c75372b05d71ce7380c8a0929e7 + fetched: '2026-09-14' + note: NHCX Usecases, row 1 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, Payment Notice. +- url: https://hcxsbx.abdm.gov.in/images/b7260763ce8270b6baac.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Payment.pdf + hash: sha256:6d372cdeec0abaea66b4d267c5ee6137a01830c577360dba7699e0244e49615f + fetched: '2026-09-14' + note: Payment, listed on https://hcxsbx.abdm.gov.in/#/documents, not named in the NHCX document sheet. Payment Notice request and response. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Erroneous claim FAQ 4 and 6. +- url: https://hcxsbx.abdm.gov.in/images/c42ad170f37c987ed173.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx + hash: sha256:f56dd156c232192296082f23b1561d0ff11fd40992e6675de41c5c991d579e6d + fetched: '2026-09-14' + note: Workflow Status Sheets(with Codes), row 12 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet1, Payment Notice Recived. +verified: + status: unverified +related: + flows: + - nhcx.flow.payment-notice + endpoints: + - nhcx.endpoint.paymentnotice-request +--- + +# Payment notice + +## In plain words + +A payment notice is the payer's message about paying a claim, with bank reference numbers. The payer sends it through [NHCX](../../shared/glossary/nhcx.md) on `/v1/paymentnotice/request`, and your system acknowledges it. Workflow `30` marks payment initiated, `33` marks payment cleared, and your acknowledgement carries `17`. + +## Before you start + +Nothing. A glossary entry assumes no prior reading. + +## What happens + +Nothing happens here. This entry defines a term, it does not describe a call. + +## How you know it worked + +You have understood this when you can say which workflow id means the money has cleared. + +## When it goes wrong + +Raising an erroneous claim before workflow `33` arrives. Wait for payment to clear, and acknowledge it first. diff --git a/catalogue/nhcx/glossary/pid-block.md b/catalogue/nhcx/glossary/pid-block.md new file mode 100644 index 000000000..f2fec5e9c --- /dev/null +++ b/catalogue/nhcx/glossary/pid-block.md @@ -0,0 +1,48 @@ +--- +id: nhcx.glossary.pid-block +type: glossary +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PID block +summary: >- + The captured biometric data passed to the verify call. +sources: +- url: https://hcxsbx.abdm.gov.in/images/9f1e6b545a693d38a704.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Biometric Authentication Implementation Steps.docx + hash: sha256:fac8b14bfe8d518c0e651740537b9441c501d3cf2ab0f0482a07ab9f417e43a9 + fetched: '2026-09-14' + note: Biometric Authentication Implementation Steps, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments, not named in the NHCX document sheet. Fingerprint/IRIS Auth Verify; Face Auth Capture PID and Aadhar Verify. +verified: + status: unverified +related: + concepts: + - nhcx.concept.biometric-authentication + endpoints: + - nhcx.endpoint.abha-biometric-auth-verify + - nhcx.endpoint.abha-biometric-capture-pid + glossary: + - nhcx.glossary.rd-service +--- + +# PID block + +## In plain words + +A PID block is the captured biometric data that your system passes to the verify call in [PMJAY](../glossary/pmjay.md) beneficiary authentication. Fingerprint and iris verification carry it in `fingerPrintAuthPid` or `irisAuthPid`, with the `txnId` from `auth/init`. For face authentication your system never holds it: you poll `capture/pid` until it reports `COMPLETE`, then call `v2/auth/verify`. + +## Before you start + +Nothing. A glossary entry assumes no prior reading. + +## What happens + +Nothing happens here. This entry defines a term, it does not describe a call. + +## How you know it worked + +You have understood this when you can say which call tells you a face capture has finished. + +## When it goes wrong + +Calling `v2/auth/verify` while `capture/pid` still reports `PENDING`. Poll until it reports `COMPLETE`. diff --git a/catalogue/nhcx/glossary/pmjay.md b/catalogue/nhcx/glossary/pmjay.md new file mode 100644 index 000000000..be7257729 --- /dev/null +++ b/catalogue/nhcx/glossary/pmjay.md @@ -0,0 +1,50 @@ +--- +id: nhcx.glossary.pmjay +type: glossary +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: PMJAY +summary: >- + The government health assurance scheme that runs on the claims exchange with extra + scheme rules. +sources: +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. page 9, section 3 PMJAY Overview; page 5-6 requirements table. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. InsurancePlan Response, Key Characteristics. +verified: + status: unverified +related: + concepts: + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.hmis-integration-architecture +--- + +# PMJAY + +## In plain words + +PMJAY is the Pradhan Mantri Jan Arogya Yojana, the government health assurance scheme. It covers up to Rs 5 lakh per family per year for secondary and tertiary hospitalisation. It runs on the same [NHCX](../../shared/glossary/nhcx.md) framework as private insurance, with extra onboarding and scheme rules. You meet it when your hospital treats scheme beneficiaries: biometric authentication, hospital-specific insurance plans and structured clinical documents become mandatory. See [PMJAY on NHCX](../concepts/pmjay-on-nhcx.md). + +## Before you start + +Nothing. A glossary entry assumes no prior reading. + +## What happens + +Nothing happens here. This entry defines a term, it does not describe a call. + +## How you know it worked + +You have understood this when you can name two things PMJAY integration adds to plain NHCX. + +## When it goes wrong + +Treating PMJAY as a separate network. The calls are the same; the scheme rules differ. diff --git a/catalogue/nhcx/glossary/preauthorisation.md b/catalogue/nhcx/glossary/preauthorisation.md new file mode 100644 index 000000000..4f2ab264e --- /dev/null +++ b/catalogue/nhcx/glossary/preauthorisation.md @@ -0,0 +1,55 @@ +--- +id: nhcx.glossary.preauthorisation +type: glossary +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Preauthorisation +summary: >- + A request asking the payer to approve planned treatment before it happens. +sources: +- url: https://hcxsbx.abdm.gov.in/images/3799f26f2a0b2c9a80c5.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Preauthorization.pdf + hash: sha256:75d5628e7dd8a8e1a55c4ab3836c0591088ba378a8cd498e8277d83911129439 + fetched: '2026-09-14' + note: Preauthorization, listed on https://hcxsbx.abdm.gov.in/#/documents, not named in the NHCX document sheet. Preauthorization Submission request and response. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. pages 31-33, 8.4.2 to 8.4.4. +verified: + status: unverified +related: + flows: + - nhcx.flow.preauth-submit + endpoints: + - nhcx.endpoint.preauth-submit + decisions: + - nhcx.decision.preauth-or-predetermination + glossary: + - nhcx.glossary.enhancement + - nhcx.glossary.predetermination +--- + +# Preauthorisation + +## In plain words + +A preauthorisation asks the payer to approve planned treatment before it happens. Your system sends a Claim bundle through [NHCX](../../shared/glossary/nhcx.md) on `/v1/preauth/submit`. The payer answers with a ClaimResponse on `/v1/preauth/on_submit`: approved, rejected or queried. Enhancements and resubmissions travel on the same path. + +## Before you start + +Nothing. A glossary entry assumes no prior reading. + +## What happens + +Nothing happens here. This entry defines a term, it does not describe a call. + +## How you know it worked + +You have understood this when you can name the path a preauthorisation's answer arrives on. + +## When it goes wrong + +Resubmitting to answer a query. A query gets a query response, not a resubmission. diff --git a/catalogue/nhcx/glossary/predetermination.md b/catalogue/nhcx/glossary/predetermination.md new file mode 100644 index 000000000..d7c1a7342 --- /dev/null +++ b/catalogue/nhcx/glossary/predetermination.md @@ -0,0 +1,54 @@ +--- +id: nhcx.glossary.predetermination +type: glossary +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Predetermination +summary: >- + A request asking the payer to judge a planned claim in advance against the policy. +sources: +- url: https://hcxsbx.abdm.gov.in/images/af8d243edcc2139a515d.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Usecases.pdf + hash: sha256:8709b2907a0d5a0dbb36f5e63ed8deae269e0c75372b05d71ce7380c8a0929e7 + fetched: '2026-09-14' + note: NHCX Usecases, row 1 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2, Predetermination Request Submission. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. API list table. +verified: + status: unverified +related: + flows: + - nhcx.flow.predetermination + endpoints: + - nhcx.endpoint.predetermination-submit + decisions: + - nhcx.decision.preauth-or-predetermination + glossary: + - nhcx.glossary.preauthorisation +--- + +# Predetermination + +## In plain words + +A predetermination asks the payer to adjudicate a planned claim in advance, against the policy and the beneficiary's past history. Your system sends a Claim bundle through [NHCX](../../shared/glossary/nhcx.md) on `/v1/predetermination/submit`, and the payer answers on `/v1/predetermination/on_submit`. The Claim's `use` marks it as a predetermination rather than a preauthorisation or a claim. + +## Before you start + +Nothing. A glossary entry assumes no prior reading. + +## What happens + +Nothing happens here. This entry defines a term, it does not describe a call. + +## How you know it worked + +You have understood this when you can say how a predetermination differs from a preauthorisation. + +## When it goes wrong + +Sending a predetermination where a preauthorisation is required. See [preauthorisation or predetermination](../decisions/preauth-or-predetermination.md). diff --git a/catalogue/nhcx/glossary/protected-header.md b/catalogue/nhcx/glossary/protected-header.md new file mode 100644 index 000000000..1f06a1d22 --- /dev/null +++ b/catalogue/nhcx/glossary/protected-header.md @@ -0,0 +1,56 @@ +--- +id: nhcx.glossary.protected-header +type: glossary +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Protected header +summary: >- + The readable first part of a sealed message, holding the routing information. +sources: +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Message Structure, Protected Header and Signatures. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy__message-security-and-integrity.md + hash: sha256:3768fd89932e4081c9e03a8695619bcaf70c641e28bb55a77eec090bb926eeb3 + fetched: '2026-09-14' + note: Site page /technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity, text as shown on the site. Message security, JWE encryption steps. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. FAQ 13. +verified: + status: unverified +related: + concepts: + - nhcx.concept.protocol-headers + - nhcx.concept.jwe-envelope + glossary: + - nhcx.glossary.jwe +--- + +# Protected header + +## In plain words + +The protected header is the first part of a [JWE](../glossary/jwe.md): a JSON object holding `alg`, `enc` and the `x-hcx-` protocol headers, Base64url encoded. [NHCX](../../shared/glossary/nhcx.md) reads it to route and audit the message without opening the payload. It is integrity protected together with the ciphertext, so any change to it makes decryption fail. See [the x-hcx protocol headers](../concepts/protocol-headers.md). + +## Before you start + +Nothing. A glossary entry assumes no prior reading. + +## What happens + +Nothing happens here. This entry defines a term, it does not describe a call. + +## How you know it worked + +You have understood this when you can list three `x-hcx-` headers every message carries. + +## When it goes wrong + +Putting the protocol headers in the HTTP headers. They belong inside the protected header. diff --git a/catalogue/nhcx/glossary/provider.md b/catalogue/nhcx/glossary/provider.md new file mode 100644 index 000000000..c09341901 --- /dev/null +++ b/catalogue/nhcx/glossary/provider.md @@ -0,0 +1,50 @@ +--- +id: nhcx.glossary.provider +type: glossary +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Provider +summary: >- + The hospital, clinic or other facility that treats the patient and is paid for + it. +sources: +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. FAQ 6, 7 and 11. +verified: + status: unverified +related: + concepts: + - nhcx.concept.participant-roles + flows: + - nhcx.flow.sandbox-onboarding + glossary: + - nhcx.glossary.payer + - nhcx.glossary.participant-code + - shared.glossary.hfr +--- + +# Provider + +## In plain words + +A provider is the hospital, clinic or other facility that treats the patient and is paid for it. On [NHCX](../../shared/glossary/nhcx.md) it registers with the role `PROVIDER` (`10001`), using its [HFR](../../shared/glossary/hfr.md) ID as the registry ID. One entity can hold several participant codes, one per HFR ID. You are the provider when your system sends eligibility checks, preauthorisations and claims. + +## Before you start + +Nothing. A glossary entry assumes no prior reading. + +## What happens + +Nothing happens here. This entry defines a term, it does not describe a call. + +## How you know it worked + +You have understood this when you can say which registry ID a provider registers with. + +## When it goes wrong + +Registering several facilities under one participant code. Each HFR ID gets its own. diff --git a/catalogue/nhcx/glossary/rd-service.md b/catalogue/nhcx/glossary/rd-service.md new file mode 100644 index 000000000..08a72aa9d --- /dev/null +++ b/catalogue/nhcx/glossary/rd-service.md @@ -0,0 +1,53 @@ +--- +id: nhcx.glossary.rd-service +type: glossary +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: RD service, registered device service +summary: >- + The Aadhaar software that runs a biometric capture. +sources: +- url: https://hcxsbx.abdm.gov.in/images/9f1e6b545a693d38a704.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Biometric Authentication Implementation Steps.docx + hash: sha256:fac8b14bfe8d518c0e651740537b9441c501d3cf2ab0f0482a07ab9f417e43a9 + fetched: '2026-09-14' + note: Biometric Authentication Implementation Steps, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments, not named in the NHCX document sheet. Fingerprint/IRIS Auth Verify. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. FAQ 10 (K-547). +verified: + status: unverified +related: + concepts: + - nhcx.concept.biometric-authentication + flows: + - nhcx.flow.biometric-face + - nhcx.flow.biometric-fingerprint-iris + glossary: + - nhcx.glossary.pid-block +--- + +# RD service, registered device service + +## In plain words + +An RD service is the Aadhaar software that runs a biometric capture. For face authentication, the patient's phone scans the face with the Aadhaar RD Service app from the Play Store or App Store. For fingerprint and iris, your desk captures from a scanner and places the result in `fingerPrintAuthPid` or `irisAuthPid`. You meet it when you build [PMJAY](../glossary/pmjay.md) beneficiary authentication. + +## Before you start + +Nothing. A glossary entry assumes no prior reading. + +## What happens + +Nothing happens here. This entry defines a term, it does not describe a call. + +## How you know it worked + +You have understood this when you can say which modality uses the RD Service app on a phone. + +## When it goes wrong + +Fingerprint capture failing with `K-547`. Build the `wadh` value with `lr` set to `Y`. diff --git a/catalogue/nhcx/glossary/reprocess.md b/catalogue/nhcx/glossary/reprocess.md new file mode 100644 index 000000000..e5f4bf5fd --- /dev/null +++ b/catalogue/nhcx/glossary/reprocess.md @@ -0,0 +1,59 @@ +--- +id: nhcx.glossary.reprocess +type: glossary +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Reprocess +summary: >- + A request asking the payer to reconsider a claim it rejected or paid only in part. +sources: +- url: https://hcxsbx.abdm.gov.in/images/53347f5988b0ce5396f1.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_APIs to be called based on scenario.xlsx + hash: sha256:f92a30673d65dd2cc3cf09e2087c624f23f781dc4ca6b5cd8ec1825e224ac108 + fetched: '2026-09-14' + note: NHCX_APIs to be called based on scenario, row 26 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sheet Scenarios, rows 12 and 14. +- url: https://hcxsbx.abdm.gov.in/images/af8d243edcc2139a515d.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Usecases.pdf + hash: sha256:8709b2907a0d5a0dbb36f5e63ed8deae269e0c75372b05d71ce7380c8a0929e7 + fetched: '2026-09-14' + note: NHCX Usecases, row 1 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, Reprocess Request. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Erroneous claim FAQs, comparison table, 11 and 15. +verified: + status: unverified +related: + flows: + - nhcx.flow.claim-reprocess + endpoints: + - nhcx.endpoint.task-submit + concepts: + - nhcx.concept.reprocess-and-cancel + glossary: + - nhcx.glossary.crc +--- + +# Reprocess + +## In plain words + +A reprocess asks the payer to reconsider a claim it rejected or paid only in part. Your system sends a `Task` bundle with `Task.code` `reprocess` through [NHCX](../../shared/glossary/nhcx.md) on `/v1/task/submit`, with a supporting document, and the answer arrives on `/v1/task/on_submit`. Under [PMJAY](../glossary/pmjay.md), a reprocess can be raised once per claim and goes to the [CRC](../glossary/crc.md). + +## Before you start + +Nothing. A glossary entry assumes no prior reading. + +## What happens + +Nothing happens here. This entry defines a term, it does not describe a call. + +## How you know it worked + +You have understood this when you can say which path carries a reprocess and its answer. + +## When it goes wrong + +Raising a reprocess without a supporting document. The document is mandatory. diff --git a/catalogue/nhcx/glossary/sandbox-exit.md b/catalogue/nhcx/glossary/sandbox-exit.md new file mode 100644 index 000000000..7ca0a9a93 --- /dev/null +++ b/catalogue/nhcx/glossary/sandbox-exit.md @@ -0,0 +1,56 @@ +--- +id: nhcx.glossary.sandbox-exit +type: glossary +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Sandbox exit +summary: >- + The set of checks that moves you from the sandbox towards production access. +sources: +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use cases 1 to 13. +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use cases 1 to 15. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. Functional Testing, steps 2 and 3. +verified: + status: unverified +related: + sandbox: + - nhcx.sandbox.sandbox-exit + tests: + - nhcx.test.provider-uc-01 + - nhcx.test.payer-uc-01 +--- + +# Sandbox exit + +## In plain words + +Sandbox exit is the set of checks that moves you from the [NHCX](../../shared/glossary/nhcx.md) sandbox towards production access. Providers demonstrate 13 use cases and payers 15, from fetching the participant list to checking status, each with its own pass condition. After [FHIR](../../shared/glossary/fhir.md) bundle validation and two demos, you receive confirmation of successful sandbox integration, and production access follows. See [sandbox exit](../sandbox/sandbox-exit.md). + +## Before you start + +Nothing. A glossary entry assumes no prior reading. + +## What happens + +Nothing happens here. This entry defines a term, it does not describe a call. + +## How you know it worked + +You have understood this when you can say what must be done before production access is granted. + +## When it goes wrong + +Treating one working sandbox call as sandbox exit. Exit needs every use case demonstrated and the bundles validated. diff --git a/catalogue/nhcx/glossary/sha.md b/catalogue/nhcx/glossary/sha.md new file mode 100644 index 000000000..64b52e559 --- /dev/null +++ b/catalogue/nhcx/glossary/sha.md @@ -0,0 +1,50 @@ +--- +id: nhcx.glossary.sha +type: glossary +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: SHA, State Health Agency +summary: >- + The state body that runs the government health scheme and reviews its claims. +sources: +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. page 10, 4.2 Claims Payment Process. +- file: catalogue/openapi/.raw/nhcx-site-2026-09-14/not-on-site/External_NHCX_Payer_Service_API_Workflow_Guide.docx + hash: sha256:1028d480d2fabe3204301f1c1b192a0077ddfa64f7f9084b01f73e004253fdd7 + fetched: '2026-09-05' + note: NHCX Payer Service API Workflow Guide for External Integrators, not listed on hcxsbx.abdm.gov.in and not named in the NHCX document sheet, received separately. CLAIM Step 5 and role table; get/user-role. +verified: + status: unverified +related: + glossary: + - nhcx.glossary.pmjay + - nhcx.glossary.tms + endpoints: + - nhcx.endpoint.payer-service-get-user-role +--- + +# SHA, State Health Agency + +## In plain words + +SHA stands for State Health Agency, the state body that runs [PMJAY](../glossary/pmjay.md) in its state. It is also called the State Health Authority. It reviews claims before the bank pays the hospital. In the PMJAY payer service, `SHA-Trust` is the fifth role in the claim chain. + +## Before you start + +Nothing. A glossary entry assumes no prior reading. + +## What happens + +Nothing happens here. This entry defines a term, it does not describe a call. + +## How you know it worked + +You have understood this when you can say where the SHA sits in the order of PMJAY claim roles. + +## When it goes wrong + +Expecting the SHA to act on a claim before the earlier roles have. Read the current role with `get/user-role`. diff --git a/catalogue/nhcx/glossary/tms.md b/catalogue/nhcx/glossary/tms.md new file mode 100644 index 000000000..793a84752 --- /dev/null +++ b/catalogue/nhcx/glossary/tms.md @@ -0,0 +1,56 @@ +--- +id: nhcx.glossary.tms +type: glossary +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: TMS, Transaction Management System +summary: >- + The government scheme system in which preauthorisations and claims are decided. +sources: +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. page 9 section 3; page 11 section 5 TMS for Providers. +- url: https://hcxsbx.abdm.gov.in/images/be2e25fede3bf711f783.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/PMJAY Hospital Migration to HMIS via NHCX.docx + hash: sha256:cf5c9bf1c402b214f65bbb7bd0822f3a76d8ccda9b69c7bf77ba131befef3bc6 + fetched: '2026-09-14' + note: PMJAY Hospital Migration to HMIS via NHCX, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments, not named in the NHCX document sheet. sections 2.1, 3.5 and 3.6. +- url: https://hcxsbx.abdm.gov.in/images/b6bd99dab49a5e928ea3.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Overview.pdf + hash: sha256:c95469758a25cb8aca8c47757d8b18b4dedb8b4d42669663cff7343205f77fda + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Overview, row 27 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. page 2, Current Challenges. +verified: + status: unverified +related: + flows: + - nhcx.flow.pmjay-hospital-migration + glossary: + - nhcx.glossary.pmjay + - shared.glossary.hmis +--- + +# TMS, Transaction Management System + +## In plain words + +TMS stands for Transaction Management System, the [PMJAY](../glossary/pmjay.md) system in which preauthorisations and claims are decided. Hospitals without an integrated [HMIS](../../shared/glossary/hmis.md) enter cases by hand in the TMS 2.0 Provider portal. After a hospital is mapped to its [NHCX](../../shared/glossary/nhcx.md) participant code, new cases go from its HMIS through NHCX. TMS keeps only the cases already open there. + +## Before you start + +Nothing. A glossary entry assumes no prior reading. + +## What happens + +Nothing happens here. This entry defines a term, it does not describe a call. + +## How you know it worked + +You have understood this when you can say what happens to cases opened in TMS before your hospital is mapped. + +## When it goes wrong + +Sending new cases through NHCX before the mapping is done. Until the mapping, the hospital works in TMS. diff --git a/catalogue/nhcx/glossary/tpa.md b/catalogue/nhcx/glossary/tpa.md new file mode 100644 index 000000000..1304e401b --- /dev/null +++ b/catalogue/nhcx/glossary/tpa.md @@ -0,0 +1,63 @@ +--- +id: nhcx.glossary.tpa +type: glossary +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: TPA, third party administrator +summary: >- + A company that processes and decides claims on behalf of an insurer. +sources: +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. FAQ 7, role codes. +- url: https://hcxsbx.abdm.gov.in/images/bc2efb078b98548f8e6b.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Sandbox.pdf + hash: sha256:cbd03baf428655f0305e2f60ca331f8b76700496b070c522cafcc95001710b3a + fetched: '2026-09-14' + note: Onboarding providers and payers in Sandbox, row 4 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, registration validation. +- url: https://hcxsbx.abdm.gov.in/images/539853c50347b32b9a5e.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Policy Linking and De-Linking Process.pdf + hash: sha256:420115b9a54e15fa625312a56362164d92d23dd0d6ebf9195135bb00055d1911 + fetched: '2026-09-14' + note: Policy Linking and De-Linking Process, row 8 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Policy Linking Process. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, item 7. +verified: + status: unverified +related: + concepts: + - nhcx.concept.policy-linking + - nhcx.concept.participant-roles + endpoints: + - nhcx.endpoint.participant-get-policies + glossary: + - nhcx.glossary.payer +--- + +# TPA, third party administrator + +## In plain words + +A third party administrator processes and adjudicates claims on behalf of an insurance company. On [NHCX](../../shared/glossary/nhcx.md) it registers with the role `AGENCY_TPA` (`10003`) and is validated against a trusted TPA registry. When an insurer works through a TPA, a policy names the insurer's code as `payerid` and the TPA's code as `processingid`. You meet it in the `processingid` returned by `/participant/get/policies`, which is where your requests go. + +## Before you start + +Nothing. A glossary entry assumes no prior reading. + +## What happens + +Nothing happens here. This entry defines a term, it does not describe a call. + +## How you know it worked + +You have understood this when you can say whose participant code goes in `x-hcx-recipient_code` for a policy under a TPA. + +## When it goes wrong + +Using the payer ID from `/participant/get/policies` as the receiver code. Use the processing ID. diff --git a/catalogue/nhcx/glossary/workflow-id.md b/catalogue/nhcx/glossary/workflow-id.md new file mode 100644 index 000000000..2190675fb --- /dev/null +++ b/catalogue/nhcx/glossary/workflow-id.md @@ -0,0 +1,54 @@ +--- +id: nhcx.glossary.workflow-id +type: glossary +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Workflow id +summary: >- + The code that names which business stage a message belongs to. +sources: +- url: https://hcxsbx.abdm.gov.in/images/c42ad170f37c987ed173.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx + hash: sha256:f56dd156c232192296082f23b1561d0ff11fd40992e6675de41c5c991d579e6d + fetched: '2026-09-14' + note: Workflow Status Sheets(with Codes), row 12 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet1. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Message Structure, x-hcx-workflow_id row. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 2.1 JWE Protected Header table. +verified: + status: unverified +related: + concepts: + - nhcx.concept.workflow-codes + - nhcx.concept.protocol-headers +--- + +# Workflow id + +## In plain words + +The workflow id, sent in `x-hcx-workflow_id`, names the business stage a message belongs to. For example, `12` is a new preauthorisation and `15` is a claim. Some ids cover several stages, told apart by `x-hcx-status`. Send it on every message to [NHCX](../../shared/glossary/nhcx.md): [PMJAY](../glossary/pmjay.md) requires it. See [workflow codes and the stage each one names](../concepts/workflow-codes.md). + +## Before you start + +Nothing. A glossary entry assumes no prior reading. + +## What happens + +Nothing happens here. This entry defines a term, it does not describe a call. + +## How you know it worked + +You have understood this when you can say what tells apart two messages that share a workflow id. + +## When it goes wrong + +Leaving it out because the header is optional for some payers. PMJAY submissions need it on every message. diff --git a/catalogue/nhcx/glossary/x509-certificate.md b/catalogue/nhcx/glossary/x509-certificate.md new file mode 100644 index 000000000..7b3527e28 --- /dev/null +++ b/catalogue/nhcx/glossary/x509-certificate.md @@ -0,0 +1,53 @@ +--- +id: nhcx.glossary.x509-certificate +type: glossary +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: X.509 certificate +summary: >- + The standard file that carries your public encryption key. +sources: +- url: https://hcxsbx.abdm.gov.in/images/ec361a6c3e90e766d227.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Steps to generate encryption Certificate.pdf + hash: sha256:94605e935f05ebb49e24dee50787cb4f3f1c401983a9616a5aaabdbc302f664b + fetched: '2026-09-14' + note: Steps to generate encryption Certificate, row 20 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-3, Steps 1 to 4. +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use case 3, Get public Key. +verified: + status: unverified +related: + concepts: + - nhcx.concept.encryption-certificate + flows: + - nhcx.flow.generate-and-register-certificate + - nhcx.flow.rotate-certificate + endpoints: + - nhcx.endpoint.fetch-certs +--- + +# X.509 certificate + +## In plain words + +An X.509 certificate is the standard file that carries a public key and the identity it belongs to. On [NHCX](../../shared/glossary/nhcx.md) your encryption certificate is an X.509 certificate over a 2048-bit RSA key, registered Base64 encoded. Senders fetch it with `/fetch/certs` and seal payloads to you with the key inside. See [your encryption certificate and the recipient's](../concepts/encryption-certificate.md). + +## Before you start + +Nothing. A glossary entry assumes no prior reading. + +## What happens + +Nothing happens here. This entry defines a term, it does not describe a call. + +## How you know it worked + +You have understood this when you can say which key a sender uses to seal a message to you. + +## When it goes wrong + +Letting the registered certificate expire. One made with the published OpenSSL steps is valid for 365 days. See [rotate your encryption certificate](../flows/rotate-certificate.md). diff --git a/catalogue/nhcx/sandbox/callback-url-requirements.md b/catalogue/nhcx/sandbox/callback-url-requirements.md new file mode 100644 index 000000000..3da4fd596 --- /dev/null +++ b/catalogue/nhcx/sandbox/callback-url-requirements.md @@ -0,0 +1,143 @@ +--- +id: nhcx.sandbox.callback-url-requirements +type: sandbox +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Callback URL rules and the egress addresses to allow +summary: >- + What the web address that receives exchange messages must look like, the three + addresses the exchange sends from, and how fast your server must answer. +sources: +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Q14 and Q21 (Not getting call back). +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1. +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use cases 5, 7 and 9. +- url: https://hcxsbx.abdm.gov.in/images/260d0dec19a681e80262.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Production.pdf + hash: sha256:c38476fb90101f13fdfea447861292718d561e1dc088ae20950b193606500d2e + fetched: '2026-09-14' + note: Onboarding providers and payers in Production, row 5 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Steps 1 and 3 payloads. +verified: + status: unverified +related: + callbacks: + - nhcx.callback.error + sandbox: + - nhcx.sandbox.prerequisites + - nhcx.sandbox.environments-and-base-urls + - shared.sandbox.callback-url + concepts: + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.retries-and-expiry + - nhcx.concept.four-message-legs + - nhcx.concept.participant-registry + flows: + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.report-a-processing-error + - nhcx.flow.sandbox-onboarding + endpoints: + - nhcx.endpoint.participant-update + - nhcx.endpoint.v2-participant-update + decisions: + - nhcx.decision.status-poll-or-wait + troubleshooting: + - nhcx.troubleshooting.callback-url-rejected + - nhcx.troubleshooting.accepted-then-no-callback + glossary: + - shared.glossary.nhcx +--- + +# Callback URL rules and the egress addresses to allow + +## In plain words + +[NHCX](../../shared/glossary/nhcx.md) delivers every answer, query and notice to a web address you register, your callback URL. Nothing comes back in the response to your own call. + +The address must follow a few rules, your firewall must accept the exchange's addresses, and your server must answer each delivery quickly. + +## Before you start + +- You have a server you control, hosted in India, with a domain name and a valid HTTPS certificate. +- You know which callback paths your role receives. A provider receives paths such as `/v1/coverageeligibility/on_check`, `/v1/preauth/on_submit` and `/v1/claim/on_submit`. +- You can change firewall rules on that server. + +## What happens + +### The address rules + +- Use a domain name. An IP address is not accepted. +- Do not put a port number in the URL. +- Host the server in India. +- Register the base address as `endpoint_url` when you create or update your participant. Serve each callback path under it. + +### Allow the exchange's addresses + +Deliveries come from these three NAT addresses. Allow all three in your firewall, load balancer and any gateway in front of your service: + +- `3.109.99.210` +- `13.126.152.0` +- `13.200.129.223` + +### Answer every delivery + +Reply to each delivery with HTTP `202 Accepted` within 30 seconds. The body echoes the ids from the message: + +```json +{ + "timestamp": "", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "", + "recipient_code": "", + "entity_type": "", + "protocol_status": "request.queued" + }, + "error": { + "code": "", + "message": "" + } +} +``` + +If the exchange gets no `202` in time, it treats the delivery as failed and retries. It resends a rejected or malformed exchange up to five times, then ends the request. After the fifth failure, it deletes the request for that correlation id. + +Process the message after you reply. If the message cannot be processed, report it on `/v1/error`. See [report a processing failure](../flows/report-a-processing-error.md). + +### Changing the address + +Update `endpoint_url` with the participant update call. See [onboard as a participant in the sandbox](../flows/sandbox-onboarding.md). + +## How you know it worked + +Send a coverage eligibility check to the [dummy payer](dummy-payer.md). Your server logs a `POST /v1/coverageeligibility/on_check` from one of the three NAT addresses. Your server answered it with `202`. + +A registered URL that has never received a delivery is not yet proven. + +## When it goes wrong + +**It never arrives.** Check in this order: + +1. The registered URL uses a domain name, with no IP address and no port. +2. The server is hosted in India. +3. All three NAT addresses are allowed in every firewall and gateway in front of the server. +4. The URL path, load balancer rules and service routing send the path to the right handler, on the right version. +5. Your server answers with `202` within 30 seconds. + +If all five hold, ask the exchange for the status of the request. See [poll with /v1/status or wait](../decisions/status-poll-or-wait.md) and [accepted with 202 and no callback](../troubleshooting/accepted-then-no-callback.md). + +**The same message arrives again.** Your earlier reply was late or not `202`, so the exchange retried. Make your handler safe to run twice for the same `x-hcx-api_call_id`. + +**The registration update rejects your URL.** See [your callback URL is rejected or never called](../troubleshooting/callback-url-rejected.md). diff --git a/catalogue/nhcx/sandbox/dummy-payer.md b/catalogue/nhcx/sandbox/dummy-payer.md new file mode 100644 index 000000000..c3e2df193 --- /dev/null +++ b/catalogue/nhcx/sandbox/dummy-payer.md @@ -0,0 +1,126 @@ +--- +id: nhcx.sandbox.dummy-payer +type: sandbox +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: The dummy payer and what it answers +summary: >- + The built-in test insurer in the sandbox, which use cases it answers, and the + two test calls that make it approve, reject, query or send a payment notice. +sources: +- url: https://hcxsbx.abdm.gov.in/images/819467ec15aff13cc2a8.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Dummy Payer Implementation.pdf + hash: sha256:97335ebc4cd32c86e0c34328b2f4c526420b32a7a009208364043d6334e9e757 + fetched: '2026-09-14' + note: NHCX Dummy Payer Implementation, row 19 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-3. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Q3 and Q16. +verified: + status: unverified +related: + sandbox: + - nhcx.sandbox.test-participants + - nhcx.sandbox.callback-url-requirements + - nhcx.sandbox.sandbox-exit + endpoints: + - nhcx.endpoint.dummy-payer-process-request + - nhcx.endpoint.dummy-payer-paymentnotice-init + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.claim-submit + - nhcx.endpoint.communication-on-request + - nhcx.endpoint.paymentnotice-on-request + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.claim-submit + - nhcx.flow.payment-notice + - nhcx.flow.insurance-plan-request + fhir: + - nhcx.fhir.insurance-plan-bundle + - nhcx.fhir.query-update + - nhcx.fhir.payment-notice + concepts: + - nhcx.concept.message-identifiers + glossary: + - nhcx.glossary.payer + - nhcx.glossary.correlation-id +--- + +# The dummy payer and what it answers + +## In plain words + +The dummy payer is a test insurer in the NHCX sandbox, participant code `1000003538@hcx`. Send your requests to it as you would to a real payer. + +For eligibility and insurance plan requests it answers on its own. For preauthorisations, claims and payment notices, you tell it what to do through two test calls. + +## Before you start + +- You have a sandbox session token. See [environments and base URLs](environments-and-base-urls.md). +- You fetched the dummy payer's certificate with `/fetch/certs` for `1000003538@hcx`. +- Your callback URL receives deliveries. See [callback URL rules](callback-url-requirements.md). + +## What happens + +### Use cases + +| Use case | What you do | +|---|---| +| Insurance plan | Send `/v1/insuranceplan/request`. Use provider id `32722` and policy number `100217` in the FHIR bundle. | +| Coverage eligibility | Send `/v1/coverageeligibility/check`. | +| Preauthorisation | Send `/v1/preauth/submit`, then call the action API. | +| Claim | Send `/v1/claim/submit`, then call the action API. | +| Communication | Submit, then call the action API with `Query`. | +| Payment notice | Call the payment notice trigger. | + +### The action API + +After a preauthorisation or claim submit, choose the payer's answer. Pass the correlation id of your submit: + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/dummyhcxpayer/process/request' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -d '{ + "action": "", + "method": "", + "correlationId": "" + }' +``` + +- `Approve` or `Reject`: the final answer arrives on `/v1/preauth/on_submit` or `/v1/claim/on_submit`. +- `Query`: the dummy payer sends `/v1/communication/request` while the case stays with it. Answer with the supporting documents on `/v1/communication/on_request`. The final answer then arrives on the `on_submit` path. + +### The payment notice trigger + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/dummyhcxpayer/paymentNotice/init' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -d '{ + "providerId": "", + "claimNumber": "" + }' +``` + +`/v1/paymentnotice/request` then arrives at your endpoint. Acknowledge it on `/v1/paymentnotice/on_request`. See [the payment notice bundle](../fhir/payment-notice.md). + +These two test APIs take the token in the `bearer_auth` header, prefixed with `Bearer`. + +## How you know it worked + +- After `Approve`, `/v1/preauth/on_submit` or `/v1/claim/on_submit` arrives with a `ClaimResponse` for your claim number, reason code `approved`. +- After `Query`, `/v1/communication/request` arrives first, and the final `on_submit` arrives after your `/v1/communication/on_request`. +- After the payment notice trigger, `/v1/paymentnotice/request` arrives for the claim number you passed. + +## When it goes wrong + +- **Nothing arrives after your submit.** For preauthorisations and claims, the dummy payer waits for the action API. Call it with the correlation id of the submit. +- **The action API cannot find your case.** The `correlationId` is not the one you sent in the submit's protected header. Copy it from your request log. +- **The action API returns `401`.** The token expired or is missing its `Bearer ` prefix. Get a fresh token. +- **The trigger works, and still nothing reaches your server.** The problem is your callback path. See [callback URL rules](callback-url-requirements.md). diff --git a/catalogue/nhcx/sandbox/environments-and-base-urls.md b/catalogue/nhcx/sandbox/environments-and-base-urls.md new file mode 100644 index 000000000..270eea2fd --- /dev/null +++ b/catalogue/nhcx/sandbox/environments-and-base-urls.md @@ -0,0 +1,119 @@ +--- +id: nhcx.sandbox.environments-and-base-urls +type: sandbox +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: NHCX environments, hosts and base URLs +summary: >- + The two environments, the web portals, and the two base addresses every call is + built on, for testing and for live claims. +sources: +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 13 Important Links and URLs. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Q2, Q17 and Q19. +- url: https://hcxsbx.abdm.gov.in/images/260d0dec19a681e80262.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Production.pdf + hash: sha256:c38476fb90101f13fdfea447861292718d561e1dc088ae20950b193606500d2e + fetched: '2026-09-14' + note: Onboarding providers and payers in Production, row 5 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Step 1. +- url: https://hcxsbx.abdm.gov.in/images/819467ec15aff13cc2a8.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Dummy Payer Implementation.pdf + hash: sha256:97335ebc4cd32c86e0c34328b2f4c526420b32a7a009208364043d6334e9e757 + fetched: '2026-09-14' + note: NHCX Dummy Payer Implementation, row 19 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 2-3 curl examples. +- url: https://hcxsbx.abdm.gov.in/#/domain-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications.md + hash: sha256:56234dd8a55fe4eb9dd852779b22b522b04760c9bec5c263d5e9bc3ac2c6f167 + fetched: '2026-09-14' + note: Site page /domain-specifications, text as shown on the site. Guidelines for Participant Onboarding. +verified: + status: unverified +related: + sandbox: + - nhcx.sandbox.prerequisites + - nhcx.sandbox.going-live + - nhcx.sandbox.dummy-payer + - nhcx.sandbox.callback-url-requirements + concepts: + - nhcx.concept.session-token + - nhcx.concept.participant-code + decisions: + - nhcx.decision.session-endpoint + endpoints: + - nhcx.endpoint.fetch-participants-list + - nhcx.endpoint.coverageeligibility-check + errors: + - nhcx.error.nhcx-401 + troubleshooting: + - nhcx.troubleshooting.everything-returns-401 + glossary: + - shared.glossary.nhcx + - shared.glossary.sandbox + - shared.glossary.abdm +--- + +# NHCX environments, hosts and base URLs + +## In plain words + +[NHCX](../../shared/glossary/nhcx.md) runs in two environments. The [sandbox](../../shared/glossary/sandbox.md) is for building and testing. Production carries live claims. + +Each environment has two API base addresses. Participant APIs manage your registration, certificates and policies. Use-case APIs carry eligibility checks, preauthorisations, claims and the other claim messages. + +## Before you start + +- You have credentials for the environment you are calling. See [what you need before you register](prerequisites.md). +- You know how to get a session token. See [the session token](../concepts/session-token.md) and [which session endpoint to call](../decisions/session-endpoint.md). + +## What happens + +### Addresses by environment + +| | Sandbox | Production | +|---|---|---| +| Portal | https://hcxsbx.abdm.gov.in/ | https://nhcx.abdm.gov.in/ | +| Integration documents | https://hcxsbx.abdm.gov.in/#/documents | https://nhcx.abdm.gov.in/#/documents | +| PMJAY hospital system documents | https://hcxsbx.abdm.gov.in/#/hmisdocuments | | +| Participant APIs (`participantBaseUrl`) | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice` | `https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice` | +| Use-case APIs (`useCaseBaseUrl`) | `https://apisbx.abdm.gov.in/hcx` | `https://apisprod.nha.gov.in/hcx` | +| Dummy payer test APIs | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/dummyhcxpayer` | | +| [ABDM](../../shared/glossary/abdm.md) sandbox, for client credentials | https://sandbox.abdm.gov.in/sandbox/v3/ | | + +### Building a full URL + +Append the operation path to the base, with one slash between them: + +| Call | Full sandbox URL | +|---|---| +| Fetch participant list | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/fetch/participants/list` | +| Fetch certificates | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/fetch/certs` | +| Get policies | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/participant/get/policies` | +| Coverage eligibility check | `https://apisbx.abdm.gov.in/hcx/v1/coverageeligibility/check` | +| Payment notice acknowledgement | `https://apisbx.abdm.gov.in/hcx/v1/paymentnotice/on_request` | + +Every use-case path starts with `/v1/`. + +### Participant codes + +Treat a participant code as an opaque string, including the part after `@`. Sandbox examples carry `@sbx` or `@hcx`, and the sandbox dummy payer is `1000003538@hcx`. + +## How you know it worked + +You know you are on the right host when a call to `{participantBaseUrl}/fetch/participants/list` with a valid session token returns the participant list, not `401`. + +A use-case call to `{useCaseBaseUrl}/v1/...` with a valid sealed payload returns `202`. + +## When it goes wrong + +- **Every call returns `401`.** The token expired, or you sent a sandbox token to production. Get a fresh token for the same environment. See [every NHCX call returns 401](../troubleshooting/everything-returns-401.md) and [NHCX-401](../errors/nhcx-401.md). +- **The host does not resolve.** Check for a missing slash between `apisbx.abdm.gov.in` and `hcx`. +- **A use-case call returns not found.** The path is missing `/v1/`, or it is on the participant base instead of the use-case base. +- **Production calls fail after sandbox sign-off.** Production access starts when the provider role is assigned to your production client. Until then, wait for the sign-off communication. See [going live](going-live.md). diff --git a/catalogue/nhcx/sandbox/going-live.md b/catalogue/nhcx/sandbox/going-live.md new file mode 100644 index 000000000..08a1f3c50 --- /dev/null +++ b/catalogue/nhcx/sandbox/going-live.md @@ -0,0 +1,120 @@ +--- +id: nhcx.sandbox.going-live +type: sandbox +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Going live on NHCX production +summary: >- + What happens after sandbox sign-off: the production role, registering and confirming + your participant with a passcode, adding your certificate and callback address, + and the first live claims. +sources: +- url: https://hcxsbx.abdm.gov.in/images/260d0dec19a681e80262.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Production.pdf + hash: sha256:c38476fb90101f13fdfea447861292718d561e1dc088ae20950b193606500d2e + fetched: '2026-09-14' + note: Onboarding providers and payers in Production, row 5 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Steps 1-4 and certificate update. +- url: https://hcxsbx.abdm.gov.in/#/domain-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications.md + hash: sha256:56234dd8a55fe4eb9dd852779b22b522b04760c9bec5c263d5e9bc3ac2c6f167 + fetched: '2026-09-14' + note: Site page /domain-specifications, text as shown on the site. Go Live Process. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item 5. +- url: https://hcxsbx.abdm.gov.in/images/b6bd99dab49a5e928ea3.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Overview.pdf + hash: sha256:c95469758a25cb8aca8c47757d8b18b4dedb8b4d42669663cff7343205f77fda + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Overview, row 27 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. integration roadmap. +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths /v2/participant/create, /validate, /v2/participant/update, /update/validate, /v2/update/cert.' +verified: + status: unverified +related: + flows: + - nhcx.flow.production-onboarding + - nhcx.flow.rotate-certificate + endpoints: + - nhcx.endpoint.v2-participant-create + - nhcx.endpoint.validate + - nhcx.endpoint.v2-participant-update + - nhcx.endpoint.update-validate + - nhcx.endpoint.v2-update-cert + sandbox: + - nhcx.sandbox.sandbox-exit + - nhcx.sandbox.environments-and-base-urls + - nhcx.sandbox.support-contacts + - shared.sandbox.wasa + concepts: + - nhcx.concept.participant-roles + - nhcx.concept.encryption-certificate + glossary: + - shared.glossary.m1 + - shared.glossary.hfr + - shared.glossary.otp + - shared.glossary.nha +--- + +# Going live on NHCX production + +## In plain words + +Going live moves your system from the sandbox to production, where claims are real. After sign-off, [NHA](../../shared/glossary/nha.md) enables your production client for NHCX. You then register your participant in production and confirm each step with a passcode sent to your registered mobile number. + +## Before you start + +- You hold the sandbox sign-off email. See [the sandbox exit process](sandbox-exit.md). +- You hold production credentials for [Milestone 1](../../shared/glossary/m1.md). These follow Milestone 1 functional testing, the security audit ([WASA](../../shared/sandbox/wasa.md)) and the Health Tech Committee demo. +- The mobile number on your [HFR](../../shared/glossary/hfr.md) record, or your payer record, is one you can receive messages on. +- You have a production certificate and a production callback URL. + +## What happens + +### 1. Role assignment + +NHA assigns the provider role to your Milestone 1 production client ID. The same client ID gives you NHCX production access. Production participant APIs are under `https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice`. + +### 2. Create and confirm your participant + +| Step | Call | What you send | What happens | +|---|---|---|---| +| 1 | `POST /v2/participant/create` | `registrytype`, `registryid`, `role`, `endpoint_url`, `mobilenumber`, `email` | Returns `participantid` and `transactionid`; a passcode goes to the registered mobile | +| 2 | `GET /validate?transactionId=&passcode=` | | Confirms the participant | +| 3 | `POST /v2/participant/update` | `participantcode`, `encryptioncert` (base64 certificate), `endpointurl` | Returns a new `transactionid`; a new passcode goes to the mobile | +| 4 | `GET /update/validate?transactionId=&passcode=` | | Activates your certificate and callback URL | + +Each transaction id and passcode is valid for 24 hours. Each passcode belongs to one transaction id. + +A provider's registry id is its HFR ID. A payer passes its IRDAI registry id without leading zeros: pass `123`, not `0123`. + +See [onboard as a participant in production](../flows/production-onboarding.md) for each call. + +### 3. Rotate certificates later + +`POST /v2/update/cert` with `participantId` and a base64 `certificate` replaces your certificate without a passcode. See [rotate your encryption certificate](../flows/rotate-certificate.md). + +### 4. Go live + +- Keep production secrets safe. Report any compromise to the NHCX operators at once. +- Train your staff and plan the change before go-live. +- Start with a pilot on a small set of cases. + +## How you know it worked + +- Step 2 and step 4 both return success for their transaction ids. +- `/fetch/certs` on the production participant base returns your new certificate for your participant code. +- A first production request is accepted with `202`, and its callback arrives at your production `endpoint_url`. + +## When it goes wrong + +- **You are waiting for the production role.** Role assignment follows the sign-off email and has no fixed turnaround time. Until it is done, production calls fail. Ask about it through [where to get help](support-contacts.md), quoting your sign-off email. +- **The passcode expired, or you lost the transaction id.** Start that step again. Creating or updating again issues a new transaction id and passcode. +- **Creation fails the mobile number check.** The number must match the HFR record for providers, or the payer record for payers. +- **Production rejects your registry id.** Providers send the HFR ID. Payers drop leading zeros from the IRDAI id. diff --git a/catalogue/nhcx/sandbox/prerequisites.md b/catalogue/nhcx/sandbox/prerequisites.md new file mode 100644 index 000000000..660debcb2 --- /dev/null +++ b/catalogue/nhcx/sandbox/prerequisites.md @@ -0,0 +1,130 @@ +--- +id: nhcx.sandbox.prerequisites +type: sandbox +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: What you need before you register on the NHCX sandbox +summary: >- + The checklist to complete before your system can register on the claims exchange + sandbox: a facility registration, sandbox credentials, basic health ID features, + a role, a certificate and a callback address. +sources: +- url: https://hcxsbx.abdm.gov.in/#/domain-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications.md + hash: sha256:56234dd8a55fe4eb9dd852779b22b522b04760c9bec5c263d5e9bc3ac2c6f167 + fetched: '2026-09-14' + note: Site page /domain-specifications, text as shown on the site. Guidelines for Participant Onboarding; NHCX Sandbox Process. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. pages 3 and 5. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Q6 to Q9. +- url: https://hcxsbx.abdm.gov.in/images/260d0dec19a681e80262.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Production.pdf + hash: sha256:c38476fb90101f13fdfea447861292718d561e1dc088ae20950b193606500d2e + fetched: '2026-09-14' + note: Onboarding providers and payers in Production, row 5 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Step 1 validations. +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Bridge Error. +verified: + status: unverified +related: + flows: + - nhcx.flow.sandbox-onboarding + - nhcx.flow.generate-and-register-certificate + sandbox: + - nhcx.sandbox.environments-and-base-urls + - nhcx.sandbox.callback-url-requirements + - nhcx.sandbox.support-contacts + - shared.sandbox.registration-and-credentials + concepts: + - nhcx.concept.participant-roles + - nhcx.concept.participant-registry + - nhcx.concept.encryption-certificate + glossary: + - shared.glossary.hfr + - shared.glossary.m1 + - shared.glossary.abha + - nhcx.glossary.irdai + - nhcx.glossary.tpa + - nhcx.glossary.payer + - nhcx.glossary.provider +--- + +# What you need before you register on the NHCX sandbox + +## In plain words + +Before your system can join the NHCX sandbox, your organisation and your software must exist in the right registries. Your software must also support basic [ABHA](../../shared/glossary/abha.md) features. + +Some steps need approval, and the reviews have no fixed turnaround time. Start them first. + +## Before you start + +Nothing. This page is the starting point. + +## What happens + +### 1. Register the organisation + +- A [provider](../glossary/provider.md) registers each facility in the Health Facility Registry ([HFR](../../shared/glossary/hfr.md)) at https://facility.abdm.gov.in/. The HFR ID becomes your registry id. Questions go to `facility@nha.gov.in`. +- A [payer](../glossary/payer.md) or [TPA](../glossary/tpa.md) uses the id issued by [IRDAI](../glossary/irdai.md) or the relevant authority. +- The mobile number on the HFR record must be current. Participant creation checks it and sends a passcode to it. + +### 2. Apply for ABDM sandbox credentials + +1. Apply at https://sandbox.abdm.gov.in/sandbox/v3/. +2. Select "Providers and Payer" and Milestone 1 as your intent. +3. Wait for review. On approval you receive a client ID and a client secret. + +The review is semi-manual. It filters out repeat requests from the same organisation, organisations missing from any registry, technology providers without a valid website, and spam. + +### 3. Build Milestone 1 + +Your software must support [Milestone 1](../../shared/glossary/m1.md). It creates an ABHA number through Aadhaar or a driving licence. It verifies an ABHA number or ABHA address at patient registration. + +### 4. Register on the NHCX sandbox + +Register at https://sandbox.abdm.gov.in/sandbox/v3/sandbox-registration with your ABDM sandbox client ID and secret. After you submit the form, NHCX sandbox roles are assigned to your client. + +### 5. Decide your role + +| Role | Code | Registry | Registry code | +|---|---|---|---| +| Provider | `10001` | HFR | `10001` | +| Payer | `10002` | Payer | `10004` | +| TPA | `10003` | Payer | `10004` | + +A wrong role and registry pair leads to access errors, rejected requests or misrouted messages. + +### 6. Prepare the technical pieces + +- An RSA key pair and an X.509 certificate. See [generate an encryption certificate](../flows/generate-and-register-certificate.md). +- A public HTTPS callback address. See [callback URL rules](callback-url-requirements.md). + +Then create your participant code. See [onboard as a participant in the sandbox](../flows/sandbox-onboarding.md). + +## How you know it worked + +You are ready to register when all of these hold: + +- Your facility has an HFR ID, or your payer holds its registry id. +- You hold an ABDM sandbox client ID and secret, and a session token call with them returns an access token. +- The NHCX sandbox registration form is submitted and roles are assigned to your client. +- You have a certificate and a reachable callback URL. + +## When it goes wrong + +- **You are waiting for sandbox approval.** The review has no fixed turnaround time, and nothing on your side speeds it up. Do not submit a second application: repeat requests are filtered out. Ask about a stalled request through the channels in [where to get help](support-contacts.md). +- **Participant creation fails the mobile number check.** The number must match the one on the HFR record for providers, or the payer record for payers. Update the registry record first. +- **"No user role found/associated for sender code."** Your client has no NHCX role yet. Confirm the sandbox registration form went through, then contact support. +- **Requests are rejected or misrouted after registration.** Check the role and registry codes you registered with. diff --git a/catalogue/nhcx/sandbox/sandbox-exit.md b/catalogue/nhcx/sandbox/sandbox-exit.md new file mode 100644 index 000000000..627eea7bc --- /dev/null +++ b/catalogue/nhcx/sandbox/sandbox-exit.md @@ -0,0 +1,134 @@ +--- +id: nhcx.sandbox.sandbox-exit +type: sandbox +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: The sandbox exit process and sign-off +summary: >- + The use cases you must show working, the bundle review, the two demonstrations + and the sign-off that let you move from testing to live claims. +sources: +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use cases 1-13. +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use cases 1-15 and response validations. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8. +- url: https://hcxsbx.abdm.gov.in/#/domain-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications.md + hash: sha256:56234dd8a55fe4eb9dd852779b22b522b04760c9bec5c263d5e9bc3ac2c6f167 + fetched: '2026-09-14' + note: Site page /domain-specifications, text as shown on the site. NHCX Sandbox Process, Step 3. +- url: https://hcxsbx.abdm.gov.in/#/introduction-NHCX/guidlines-for-participant-onboarding + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/introduction-NHCX__guidlines-for-participant-onboarding.md + hash: sha256:58aaa762f2a04565e2060658b0eda95e3cac4cbb0819b6d865f04cf53066680d + fetched: '2026-09-14' + note: Site page /introduction-NHCX/guidlines-for-participant-onboarding, text as shown on the site. Step 3 Sandbox certification. +verified: + status: unverified +related: + sandbox: + - nhcx.sandbox.going-live + - nhcx.sandbox.dummy-payer + - nhcx.sandbox.support-contacts + - nhcx.sandbox.test-participants + fhir: + - nhcx.fhir.validation + concepts: + - nhcx.concept.message-identifiers + - nhcx.concept.four-message-legs + tests: + - nhcx.test.provider-uc-01 + - nhcx.test.provider-uc-05 + - nhcx.test.provider-uc-07 + - nhcx.test.provider-uc-09 + - nhcx.test.provider-uc-13 + - nhcx.test.payer-uc-01 + - nhcx.test.payer-uc-07 + - nhcx.test.payer-uc-15 + glossary: + - nhcx.glossary.sandbox-exit + - shared.glossary.nrces + - nhcx.glossary.irdai + - shared.glossary.nha +--- + +# The sandbox exit process and sign-off + +## In plain words + +[Sandbox exit](../glossary/sandbox-exit.md) is how you prove your system works before it handles live claims. You run a fixed set of use cases for your role, send sample bundles for review, and show your system in two demonstrations. + +When all of that passes, [NHA](../../shared/glossary/nha.md) confirms your sandbox integration by email. That confirmation opens the way to production. + +## Before you start + +- You are a registered sandbox participant. See [what you need before you register](prerequisites.md). +- Your callback URL receives deliveries. See [callback URL rules](callback-url-requirements.md). +- You can run the provider use cases against the [dummy payer](dummy-payer.md). + +## What happens + +### 1. Run every use case for your role + +| # | Provider use case | You call | You receive | +|---|---|---|---| +| 1 | Get participant list | `/fetch/participants/list` | | +| 2 | Get policy | `/participant/get/policies` | | +| 3 | Get public key | `/fetch/certs` | | +| 4 | Get the auth token | `/get/session` | | +| 5 | Coverage eligibility | `/v1/coverageeligibility/check` | `/v1/coverageeligibility/on_check` | +| 6 | Insurance plan | `/v1/insuranceplan/request` | `/v1/insuranceplan/on_request` | +| 7 | Preauthorisation | `/v1/preauth/submit` | `/v1/preauth/on_submit` | +| 8 | Answer a communication request | `/v1/communication/on_request` | `/v1/communication/request` | +| 9 | Claim | `/v1/claim/submit` | `/v1/claim/on_submit` | +| 10 | Claim search | `/v1/search/submit` | `/v1/search/on_submit` | +| 11 | Acknowledge a payment notice | `/v1/paymentnotice/on_request` | `/v1/paymentnotice/request` | +| 12 | Reprocess or cancel | `/v1/task/submit` | `/v1/task/on_submit` | +| 13 | Status | `/v1/status` | `/v1/on_status` | + +A payer runs 15 use cases. Six are registry and utility calls: link, fetch and de-link ABHA policies, the participant list, the public key and the auth token. Six answer requests: eligibility, insurance plan, preauthorisation, claim, search and task. The last three raise a communication request, send a payment notice and check status. + +### 2. Meet the checks on every response + +- Validate each payload against the NRCeS profiles. +- Use different values for `x-hcx-api_call_id` and `x-hcx-correlation_id`. +- Set the response's correlation id to the API call id of the request you answer. +- Address the response to the sender of the request. +- Send an encrypted payload when you processed the request. Send a `ProtocolResponse` when you could not, for example when the payload was invalid or would not decrypt. + +### 3. Send bundles for review + +Email sample FHIR bundles to `hcx.integration@nha.gov.in`. The NRCeS team validates them. + +### 4. Demonstrate + +1. **Internal demo.** The NHA team checks your use cases. +2. **HTC demo.** A demonstration to the Health Tech Committee, run by the NRCeS, IRDAI, TCS and NHA teams. + +Request each demo by email to `hcx.integration@nha.gov.in`. Additional security testing, such as STQC or CERT-IN review, can be required. + +### 5. Receive sign-off + +After the demos and the bundle review pass, NHA sends a communication confirming your successful integration on the NHCX sandbox. + +## How you know it worked + +You hold the email from NHA confirming successful integration on the NHCX sandbox. Keep it: production access is set up after it. + +## When it goes wrong + +- **You are waiting for a demo date or for bundle review results.** Demos are scheduled after your email request, and the reviews have no fixed turnaround time. Keep testing the remaining use cases meanwhile. Follow up on the same email thread, not with a new request. +- **The bundle review sends back findings.** Fix each one, run the validator again, and resend. See [validating a bundle](../fhir/validation.md). +- **A use case fails in the demo.** Rerun it against the [dummy payer](dummy-payer.md) until the callback arrives and passes the response checks, then ask for a new slot. +- **A response is rejected for its ids.** The response's correlation id must equal the request's API call id, and its API call id must be new. diff --git a/catalogue/nhcx/sandbox/support-contacts.md b/catalogue/nhcx/sandbox/support-contacts.md new file mode 100644 index 000000000..3bb24289c --- /dev/null +++ b/catalogue/nhcx/sandbox/support-contacts.md @@ -0,0 +1,103 @@ +--- +id: nhcx.sandbox.support-contacts +type: sandbox +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Where to get help with NHCX +summary: >- + Which address to write to for each kind of question, what to put in the message, + and what to do while you wait for an answer. +sources: +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8. +- url: https://hcxsbx.abdm.gov.in/#/domain-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications.md + hash: sha256:56234dd8a55fe4eb9dd852779b22b522b04760c9bec5c263d5e9bc3ac2c6f167 + fetched: '2026-09-14' + note: Site page /domain-specifications, text as shown on the site. Guidelines for Participant Onboarding. +- url: https://hcxsbx.abdm.gov.in/images/2b7fde4358fd0a4b2086.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Code Snippets references for payload preparation.pdf + hash: sha256:cea0cfbf5897e9642eaf9a515a941b0a1de39474ea39444c9e05abe21cd9ec73 + fetched: '2026-09-14' + note: NHCX Code Snippets references for payload preparation, row 13 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Q17 and Q19. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. item 8. +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Bridge Error, resolution steps. +verified: + status: unverified +related: + sandbox: + - nhcx.sandbox.sandbox-exit + - nhcx.sandbox.prerequisites + - nhcx.sandbox.environments-and-base-urls + fhir: + - nhcx.fhir.validation + concepts: + - nhcx.concept.message-identifiers + - nhcx.concept.error-code-spaces + glossary: + - shared.glossary.nha + - shared.glossary.nrces + - shared.glossary.hfr +--- + +# Where to get help with NHCX + +## In plain words + +Different teams handle different parts of NHCX integration. Writing to the right one, with the ids needed to trace your request, gets you an answer faster. + +## Before you start + +- Check the error atom for your code first. Most error codes name their fix. See [error code spaces](../concepts/error-code-spaces.md). +- Collect your participant code, the environment, the use case, and the correlation id and API call id of the failing request. + +## What happens + +### Who to write to + +| Topic | Address | +|---|---| +| FHIR bundle validation during sandbox exit, and requests for the internal and HTC demos | `hcx.integration@nha.gov.in` | +| How to build a FHIR bundle for a use case, and the [NRCeS](../../shared/glossary/nrces.md) specifications | `nrc-help@cdac.in` | +| ABDM Milestone 1 integration | `integration.support@nha.gov.in` | +| Facility registration in [HFR](../../shared/glossary/hfr.md) | `facility@nha.gov.in` | + +### Documents + +- Integration documents: https://hcxsbx.abdm.gov.in/#/documents +- PMJAY hospital system documents: https://hcxsbx.abdm.gov.in/#/hmisdocuments + +### What to put in the message + +- Your participant code and the environment, sandbox or production. +- The use case and the path you called. +- The `x-hcx-correlation_id`, `x-hcx-api_call_id` and `x-hcx-timestamp` of the request. +- The error code and message you received, exactly as returned. +- For a bundle question, the unencrypted bundle, with personal data replaced by test values. + +## How you know it worked + +You sent the question to the address for its topic, with the ids above, and the reply refers to your request by those ids. + +## When it goes wrong + +- **You are waiting on a reply.** Replies have no fixed turnaround time. Keep testing other use cases. Do not resend the failing request in a loop: after a failure the correlation id is inactive, so each retry needs a new one. +- **The reply asks for details you did not send.** Answer on the same thread with the ids and the exact error text. +- **An error's debugging steps end with "connect with NHCX support team".** Write to the address for the use case's topic, quoting the error code. diff --git a/catalogue/nhcx/sandbox/test-participants.md b/catalogue/nhcx/sandbox/test-participants.md new file mode 100644 index 000000000..8d8841ff0 --- /dev/null +++ b/catalogue/nhcx/sandbox/test-participants.md @@ -0,0 +1,104 @@ +--- +id: nhcx.sandbox.test-participants +type: sandbox +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Test participants available in the sandbox +summary: >- + Who your system can exchange messages with in the sandbox, starting with the built-in + test payer, and how to look up any other participant. +sources: +- url: https://hcxsbx.abdm.gov.in/images/819467ec15aff13cc2a8.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Dummy Payer Implementation.pdf + hash: sha256:97335ebc4cd32c86e0c34328b2f4c526420b32a7a009208364043d6334e9e757 + fetched: '2026-09-14' + note: NHCX Dummy Payer Implementation, row 19 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Q16. +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Use cases 1 and 3. +- url: https://hcxsbx.abdm.gov.in/images/bc2efb078b98548f8e6b.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Sandbox.pdf + hash: sha256:cbd03baf428655f0305e2f60ca331f8b76700496b070c522cafcc95001710b3a + fetched: '2026-09-14' + note: Onboarding providers and payers in Sandbox, row 4 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. participant create and delete examples. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Quick Reference Card. +verified: + status: unverified +related: + sandbox: + - nhcx.sandbox.dummy-payer + - nhcx.sandbox.environments-and-base-urls + - nhcx.sandbox.sandbox-exit + endpoints: + - nhcx.endpoint.fetch-participants-list + - nhcx.endpoint.fetch-certs + concepts: + - nhcx.concept.participant-code + - nhcx.concept.encryption-certificate + tests: + - nhcx.test.provider-uc-01 + - nhcx.test.provider-uc-03 + glossary: + - nhcx.glossary.participant-code + - nhcx.glossary.payer +--- + +# Test participants available in the sandbox + +## In plain words + +In the sandbox, a provider needs a [payer](../glossary/payer.md) to send requests to. NHCX provides one: the dummy payer, participant code `1000003538@hcx`. It answers the main use cases so you can test end to end. + +Every other sandbox participant can be looked up by role with the participant list API. + +## Before you start + +- You have your own [participant code](../glossary/participant-code.md). See [onboard as a participant in the sandbox](../flows/sandbox-onboarding.md). +- You can get a session token and call the participant APIs. See [environments and base URLs](environments-and-base-urls.md). + +## What happens + +### The dummy payer + +| Item | Value | +|---|---| +| Participant code | `1000003538@hcx` | +| Use cases it answers | Insurance plan, coverage eligibility, preauthorisation, claim, payment notice, communication | +| Provider id to put in an insurance plan request | `32722` | +| Policy number to put in an insurance plan request | `100217` | + +The provider id and policy number apply only to the dummy payer. See [the dummy payer](dummy-payer.md) for how to drive its answers. + +### Looking up other participants + +1. Call `/fetch/participants/list` on the participant base to list participants by role. See [fetch participants list](../endpoints/fetch-participants-list.md). +2. Call `/fetch/certs` with the participant's code to get the certificate you encrypt for. See [fetch certificates](../endpoints/fetch-certs.md). +3. Store the certificate locally instead of fetching it for every message. + +### Codes in the documentation + +Participant codes such as `100001@sbx`, `10001@sbx` and `1000002090@hcx` appear in examples. They show the format. Use the participant list to find a live counterpart. + +## How you know it worked + +- `/fetch/certs` for `1000003538@hcx` returns an `encryption_cert` value holding a PEM certificate. +- A coverage eligibility check sent to `1000003538@hcx` produces a `/v1/coverageeligibility/on_check` callback at your endpoint. + +## When it goes wrong + +- **You sent a request to a code copied from an example.** It may not be a live participant. Look the code up with the participant list first. +- **The dummy payer does not answer a preauthorisation or claim.** It waits for a trigger from you. See [the dummy payer](dummy-payer.md). +- **The dummy payer cannot decrypt your message.** You encrypted with the wrong certificate. Fetch its certificate again with `/fetch/certs` and resend with a new correlation id. +- **A payer you expect is missing from the list.** It has not registered in the sandbox yet. Test against the dummy payer meanwhile. diff --git a/catalogue/nhcx/tests/payer-uc-01.md b/catalogue/nhcx/tests/payer-uc-01.md new file mode 100644 index 000000000..799f1f889 --- /dev/null +++ b/catalogue/nhcx/tests/payer-uc-01.md @@ -0,0 +1,126 @@ +--- +id: nhcx.test.payer-uc-01 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Payer sandbox exit use case 1: Link ABHA with policy' +summary: >- + Prove that your insurance system can link a member's health account number to + the policies they bought, so hospitals can find them. +sources: +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Table 1.1, Use case 1. +- url: https://hcxsbx.abdm.gov.in/images/539853c50347b32b9a5e.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Policy Linking and De-Linking Process.pdf + hash: sha256:420115b9a54e15fa625312a56362164d92d23dd0d6ebf9195135bb00055d1911 + fetched: '2026-09-14' + note: Policy Linking and De-Linking Process, row 8 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2, Policy Linking Process. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, item 10. +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./participant/link/abha/policy.' +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, Q3. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8, Integrator's Journey. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.participant-link-abha-policy + - nhcx.endpoint.participant-get-policies + flows: + - nhcx.flow.policy-link-and-delink + concepts: + - nhcx.concept.policy-linking + - nhcx.concept.participant-code + sandbox: + - nhcx.sandbox.sandbox-exit + tests: + - nhcx.test.payer-uc-02 + - nhcx.test.payer-uc-03 + - nhcx.test.payer-uc-06 + - nhcx.test.provider-uc-02 + errors: + - nhcx.error.nhcx-401 + glossary: + - nhcx.glossary.tpa + - nhcx.glossary.sandbox-exit +--- + +# Payer sandbox exit use case 1: Link ABHA with policy + +## In plain words + +Hospitals find a patient's policies by looking up the patient's [ABHA](../../shared/glossary/abha.md) number in the [NHCX](../../shared/glossary/nhcx.md) registry. The registry holds only the links payers write. This case proves your system writes the link when a member buys a policy. + +It is one of the fifteen payer use cases for [sandbox exit](../glossary/sandbox-exit.md). The exchange answers this call itself. + +## Before you start + +- Your payer participant exists in the sandbox registry with the payer role, and you know its [participant code](../glossary/participant-code.md). [Onboard in the sandbox](../flows/sandbox-onboarding.md) gets you there. +- You hold a current session token from [use case 6](payer-uc-06.md). +- The token comes from the client id used when your participant was created. Linking is refused under any other. +- You know your `payerid`. If a [TPA](../glossary/tpa.md) processes your claims, you also know the TPA's participant code, the `processingid`. +- You have a member's ABHA number, mobile number, member id and the products they hold. + +## What happens + +### Run the call + +1. Call [`POST /participant/link/abha/policy`](../endpoints/participant-link-abha-policy.md). + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/participant/link/abha/policy' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -d '{"requestid": "", "abhanumber": "", "mobilenumber": "", "memberid": "", "payerid": "", "processingid": "", "policies": [{"productid": "", "productname": ""}]}' +``` + +2. For an individual payer, `payerid` is your participant code. Under a TPA, `payerid` is the insurance company's code and `processingid` is the TPA's. +3. Confirm the link: run [use case 2](payer-uc-02.md) for the same ABHA number. + +### Demonstrate it + +Sign-off needs people. Book the demos once the steps above pass in your own runs. See [the sandbox exit process](../sandbox/sandbox-exit.md). + +```precondition +human: true +who: your team, with the NHA team +action: Demonstrate this use case in the internal demo, then in the Health Tech Committee (HTC) demo. +how: Email hcx.integration@nha.gov.in to request both demos. +``` + +## How you know it worked + +The pass criterion for this case: + +> Link ABHA Number to the Policy purchased by the individual at the time of policy creation at payer systems. + +What you observe: + +- You receive HTTP 200 for the link call. +- A `/participant/get/policies` lookup for the same ABHA number returns your payer. + +## When it goes wrong + +- **The link is refused although the token is valid.** The token came from another client id. Generate it with the client id used at participant creation, and confirm any mismatch by email. +- **Your insurance company moves to another TPA.** De-link the policies with [use case 3](payer-uc-03.md). Link them again with the new TPA's code as `processingid`. +- **HTTP 401 on the call.** The token has expired, or went in without the `Bearer ` prefix. See [NHCX-401](../errors/nhcx-401.md) and fetch a new token. diff --git a/catalogue/nhcx/tests/payer-uc-02.md b/catalogue/nhcx/tests/payer-uc-02.md new file mode 100644 index 000000000..f77ccd98c --- /dev/null +++ b/catalogue/nhcx/tests/payer-uc-02.md @@ -0,0 +1,106 @@ +--- +id: nhcx.test.payer-uc-02 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Payer sandbox exit use case 2: Get policy' +summary: >- + Prove that your insurance system can read back the policies linked to a member, + exactly as hospitals will see them. +sources: +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Table 1.2, Use case 2. +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./participant/get/policies; schema identifiertype.' +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, Q3. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8, Integrator's Journey. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.participant-get-policies + flows: + - nhcx.flow.policy-link-and-delink + concepts: + - nhcx.concept.policy-linking + sandbox: + - nhcx.sandbox.sandbox-exit + tests: + - nhcx.test.payer-uc-01 + - nhcx.test.payer-uc-03 + - nhcx.test.provider-uc-02 + errors: + - nhcx.error.nhcx-401 +--- + +# Payer sandbox exit use case 2: Get policy + +## In plain words + +This case proves your system can look up the policies linked to a member's [ABHA](../../shared/glossary/abha.md) number or mobile number. It is the lookup hospitals run before they send you anything, so it shows your links as [NHCX](../../shared/glossary/nhcx.md) holds them. + +It is one of the fifteen payer use cases for [sandbox exit](../glossary/sandbox-exit.md). + +## Before you start + +- Your payer participant exists in the sandbox registry with the payer role, and you know its [participant code](../glossary/participant-code.md). [Onboard in the sandbox](../flows/sandbox-onboarding.md) gets you there. +- You hold a current session token from [use case 6](payer-uc-06.md). +- You linked a member's ABHA number to a policy in [use case 1](payer-uc-01.md). + +## What happens + +### Run the call + +1. Call [`POST /participant/get/policies`](../endpoints/participant-get-policies.md). + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/participant/get/policies' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -d '{"identifiertype": "AbhaNumber", "identifiervalue": ""}' +``` + +2. Compare the result with what you linked in [use case 1](payer-uc-01.md). + +### Demonstrate it + +Sign-off needs people. Book the demos once the steps above pass in your own runs. See [the sandbox exit process](../sandbox/sandbox-exit.md). + +```precondition +human: true +who: your team, with the NHA team +action: Demonstrate this use case in the internal demo, then in the Health Tech Committee (HTC) demo. +how: Email hcx.integration@nha.gov.in to request both demos. +``` + +## How you know it worked + +The pass criterion for this case: + +> Get the list of policies for the beneficiary based on the mobile number or ABHA + +What you observe: + +- You receive HTTP 200. +- The result lists your payer for that ABHA number, matching the link you wrote. + +## When it goes wrong + +- **Nothing comes back.** The link in [use case 1](payer-uc-01.md) did not succeed, or used a different ABHA number. +- **HTTP 401 on the call.** The token has expired, or went in without the `Bearer ` prefix. See [NHCX-401](../errors/nhcx-401.md) and fetch a new token. diff --git a/catalogue/nhcx/tests/payer-uc-03.md b/catalogue/nhcx/tests/payer-uc-03.md new file mode 100644 index 000000000..b4ea0d7f6 --- /dev/null +++ b/catalogue/nhcx/tests/payer-uc-03.md @@ -0,0 +1,113 @@ +--- +id: nhcx.test.payer-uc-03 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Payer sandbox exit use case 3: De-link ABHA from policy' +summary: >- + Prove that your insurance system can remove a policy from a member's health account + link when the policy ends or moves. +sources: +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Table 1.3, Use case 3. +- url: https://hcxsbx.abdm.gov.in/images/539853c50347b32b9a5e.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Policy Linking and De-Linking Process.pdf + hash: sha256:420115b9a54e15fa625312a56362164d92d23dd0d6ebf9195135bb00055d1911 + fetched: '2026-09-14' + note: Policy Linking and De-Linking Process, row 8 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, Validation for De-Linking. +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./participant/delink/abha/policy.' +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, Q3. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8, Integrator's Journey. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.participant-delink-abha-policy + - nhcx.endpoint.participant-get-policies + flows: + - nhcx.flow.policy-link-and-delink + concepts: + - nhcx.concept.policy-linking + sandbox: + - nhcx.sandbox.sandbox-exit + tests: + - nhcx.test.payer-uc-01 + - nhcx.test.payer-uc-02 + errors: + - nhcx.error.nhcx-401 +--- + +# Payer sandbox exit use case 3: De-link ABHA from policy + +## In plain words + +Policies lapse and members change products. This case proves your system can remove a policy from a member's [ABHA](../../shared/glossary/abha.md) link in the [NHCX](../../shared/glossary/nhcx.md) registry. Once removed, hospitals no longer see it. + +It is one of the fifteen payer use cases for [sandbox exit](../glossary/sandbox-exit.md). + +## Before you start + +- Your payer participant exists in the sandbox registry with the payer role, and you know its [participant code](../glossary/participant-code.md). [Onboard in the sandbox](../flows/sandbox-onboarding.md) gets you there. +- You hold a current session token from [use case 6](payer-uc-06.md). +- You linked the policy in [use case 1](payer-uc-01.md), and you are the participant named in its `payerid` or `processingid`. +- Your token comes from that participant's client id. The exchange compares the two before it de-links. + +## What happens + +### Run the call + +1. Call [`POST /participant/delink/abha/policy`](../endpoints/participant-delink-abha-policy.md) with the products to remove. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/participant/delink/abha/policy' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -d '{"requestid": "", "payerid": "", "memberid": "", "policies": [{"productid": "", "productname": ""}]}' +``` + +2. Confirm the removal: run [use case 2](payer-uc-02.md) for the member's ABHA number. + +### Demonstrate it + +Sign-off needs people. Book the demos once the steps above pass in your own runs. See [the sandbox exit process](../sandbox/sandbox-exit.md). + +```precondition +human: true +who: your team, with the NHA team +action: Demonstrate this use case in the internal demo, then in the Health Tech Committee (HTC) demo. +how: Email hcx.integration@nha.gov.in to request both demos. +``` + +## How you know it worked + +The pass criterion for this case: + +> De-Link Policy Number from ABHA profile + +What you observe: + +- You receive HTTP 200 for the de-link call. +- A `/participant/get/policies` lookup no longer returns the removed product for that member. + +## When it goes wrong + +- **The de-link is refused with an error message.** The token's client id is not the one behind the `payerid` or `processingid` of the link. Use that participant's credentials. +- **`There is no policies with requested details`.** The product is not in the member's linked policies. Check `productid`, `productname` and `memberid` against the link. +- **HTTP 401 on the call.** The token has expired, or went in without the `Bearer ` prefix. See [NHCX-401](../errors/nhcx-401.md) and fetch a new token. diff --git a/catalogue/nhcx/tests/payer-uc-04.md b/catalogue/nhcx/tests/payer-uc-04.md new file mode 100644 index 000000000..fbb37254a --- /dev/null +++ b/catalogue/nhcx/tests/payer-uc-04.md @@ -0,0 +1,111 @@ +--- +id: nhcx.test.payer-uc-04 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Payer sandbox exit use case 4: Get participant list' +summary: >- + Prove that your insurance system can fetch the registered participants of one + role from the claims exchange. +sources: +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Table 1.4, Use case 4. +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. components.schemas.ParticipantListResponse.' +- url: https://hcxsbx.abdm.gov.in/images/b885e59891fedc7e725c.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-PARTICIPANT SERVICE_APIs Postman Collection.zip + hash: sha256:2d082f244ee41d137a62af82380dcd2d5db9ebbab66824fd54a23c506d4d9a7f + fetched: '2026-09-14' + note: AWS(Sandbox)-PARTICIPANT SERVICE_APIs Postman Collection, row 16 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Participant List request. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, Q2 and Q3; page 6, best practices. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8, Integrator's Journey. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.fetch-participants-list + concepts: + - nhcx.concept.participant-registry + - nhcx.concept.participant-code + sandbox: + - nhcx.sandbox.sandbox-exit + - nhcx.sandbox.environments-and-base-urls + tests: + - nhcx.test.payer-uc-06 + - nhcx.test.provider-uc-01 + errors: + - nhcx.error.nhcx-401 +--- + +# Payer sandbox exit use case 4: Get participant list + +## In plain words + +This case proves your system can ask [NHCX](../../shared/glossary/nhcx.md) for every participant registered under one role, such as the hospitals or other payers in the registry. + +It is one of the fifteen payer use cases for [sandbox exit](../glossary/sandbox-exit.md). The exchange answers this call itself. + +## Before you start + +- Your payer participant exists in the sandbox registry with the payer role, and you know its [participant code](../glossary/participant-code.md). [Onboard in the sandbox](../flows/sandbox-onboarding.md) gets you there. +- You hold a current session token from [use case 6](payer-uc-06.md). +- Your system can reach `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice` over HTTPS. + +## What happens + +### Run the call + +1. Call [`POST /fetch/participants/list`](../endpoints/fetch-participants-list.md) with a role name and a registration date window. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/fetch/participants/list' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -d '{"role": "", "fromdate": "", "todate": ""}' +``` + +2. Read the `participantdetails` array in the response. + +### Demonstrate it + +Sign-off needs people. Book the demos once the steps above pass in your own runs. See [the sandbox exit process](../sandbox/sandbox-exit.md). + +```precondition +human: true +who: your team, with the NHA team +action: Demonstrate this use case in the internal demo, then in the Health Tech Committee (HTC) demo. +how: Email hcx.integration@nha.gov.in to request both demos. +``` + +## How you know it worked + +The pass criterion for this case: + +> Retrieve the list of participants in the registry based on the role + +What you observe: + +- You receive HTTP 200 with a `participantdetails` array. +- Each entry carries `participantcode`, `participantname`, `address` and `state`. +- For `role` `PAYER` with a wide date window, the list includes your own participant. + +## When it goes wrong + +- **An empty array.** Widen the date window, and send values exactly as documented: trim spaces and match case. +- **HTTP 401 on the call.** The token has expired, or went in without the `Bearer ` prefix. See [NHCX-401](../errors/nhcx-401.md) and fetch a new token. diff --git a/catalogue/nhcx/tests/payer-uc-05.md b/catalogue/nhcx/tests/payer-uc-05.md new file mode 100644 index 000000000..289d99fa1 --- /dev/null +++ b/catalogue/nhcx/tests/payer-uc-05.md @@ -0,0 +1,118 @@ +--- +id: nhcx.test.payer-uc-05 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Payer sandbox exit use case 5: Get public key' +summary: >- + Prove that your insurance system can fetch a hospital's public certificate, so + it can seal its answers for that hospital. +sources: +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Table 1.5, Use case 5. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 3.3 Certificate Fetch; Section 2.4. +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./fetch/certs.' +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, Q3. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8, Integrator's Journey. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.fetch-certs + concepts: + - nhcx.concept.encryption-certificate + - nhcx.concept.jwe-envelope + sandbox: + - nhcx.sandbox.sandbox-exit + tests: + - nhcx.test.payer-uc-06 + - nhcx.test.payer-uc-07 + - nhcx.test.provider-uc-03 + troubleshooting: + - nhcx.troubleshooting.recipient-cannot-decrypt + errors: + - nhcx.error.nhcx-401 + glossary: + - nhcx.glossary.jwe + - nhcx.glossary.x509-certificate +--- + +# Payer sandbox exit use case 5: Get public key + +## In plain words + +Every answer you send through [NHCX](../../shared/glossary/nhcx.md) is sealed for one hospital, as a [JWE](../glossary/jwe.md). You seal it with that hospital's public key. This case proves your system can fetch the key from the registry, given the hospital's [participant code](../glossary/participant-code.md). + +It is one of the fifteen payer use cases for [sandbox exit](../glossary/sandbox-exit.md). + +## Before you start + +- Your payer participant exists in the sandbox registry with the payer role, and you know its [participant code](../glossary/participant-code.md). [Onboard in the sandbox](../flows/sandbox-onboarding.md) gets you there. +- You hold a current session token from [use case 6](payer-uc-06.md). +- You know the participant code of a provider in the sandbox, from [use case 4](payer-uc-04.md) or a request it sent you. + +## What happens + +### Run the call + +1. Call [`POST /fetch/certs`](../endpoints/fetch-certs.md). `participantid` is mandatory. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/fetch/certs' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -d '{"participantid": ""}' +``` + +2. Load the returned string as a public key. Try it as an [X.509 certificate](../glossary/x509-certificate.md) first, then as a SubjectPublicKeyInfo (SPKI) key. +3. Cache the key for 24 hours, keyed by participant code. + +### Demonstrate it + +Sign-off needs people. Book the demos once the steps above pass in your own runs. See [the sandbox exit process](../sandbox/sandbox-exit.md). + +```precondition +human: true +who: your team, with the NHA team +action: Demonstrate this use case in the internal demo, then in the Health Tech Committee (HTC) demo. +how: Email hcx.integration@nha.gov.in to request both demos. +``` + +## How you know it worked + +The pass criterion for this case: + +> Retrieve the public key of the receiver, that is to be used to encrypt the payload for the receiver. participant id must be mandatorily provided in the request. + +What you observe: + +- You receive HTTP 200 with a string holding a PEM X.509 certificate or an SPKI public key. +- Your system loads it as an RSA public key without error. +- An answer you seal with it is opened by the provider in [use case 7](payer-uc-07.md). + +## When it goes wrong + +- **The call is refused or the body is empty.** `participantid` is missing or misspelt. +- **The provider cannot open your answer.** The provider rotated its certificate. Fetch it again. See [the recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). +- **HTTP 401 on the call.** The token has expired, or went in without the `Bearer ` prefix. See [NHCX-401](../errors/nhcx-401.md) and fetch a new token. diff --git a/catalogue/nhcx/tests/payer-uc-06.md b/catalogue/nhcx/tests/payer-uc-06.md new file mode 100644 index 000000000..a89bbd120 --- /dev/null +++ b/catalogue/nhcx/tests/payer-uc-06.md @@ -0,0 +1,114 @@ +--- +id: nhcx.test.payer-uc-06 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Payer sandbox exit use case 6: Get the auth token' +summary: >- + Prove that your insurance system can obtain, and keep fresh, the access token + every call to the claims exchange must carry. +sources: +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2, Tables 1.6 and 2.1, Use case 6. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 3.1 Token Request. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2, items 6, 9 and 10. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, Q3; page 5, Q20. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8, Integrator's Journey. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.get-session + - nhcx.endpoint.session-token + decisions: + - nhcx.decision.session-endpoint + concepts: + - nhcx.concept.session-token + sandbox: + - nhcx.sandbox.sandbox-exit + - nhcx.sandbox.prerequisites + tests: + - nhcx.test.payer-uc-04 + - nhcx.test.provider-uc-04 + troubleshooting: + - nhcx.troubleshooting.everything-returns-401 + errors: + - nhcx.error.nhcx-401 +--- + +# Payer sandbox exit use case 6: Get the auth token + +## In plain words + +Every call to [NHCX](../../shared/glossary/nhcx.md) carries an access token. This case proves your system can obtain one with its client credentials and replace it before it expires. + +It is one of the fifteen payer use cases for [sandbox exit](../glossary/sandbox-exit.md). + +## Before you start + +- You hold your sandbox client id and client secret. See [sandbox prerequisites](../sandbox/prerequisites.md). +- Use the client id your participant was created with. Policy linking accepts only that one. +- You know which token endpoint to call. See [which session token endpoint to call](../decisions/session-endpoint.md). + +## What happens + +### Run the call + +1. Call [`POST /get/session`](../endpoints/get-session.md) with a form-encoded body: + +```text +client_id=&client_secret=&grant_type=client_credentials +``` + +2. Read `access_token` and `expires_in` from the response. +3. Send the token on every later call as the header `bearer_auth: Bearer `. +4. Schedule a refresh before `expires_in` runs out. +5. Prove the token works: run [use case 4](payer-uc-04.md) with it. + +### Demonstrate it + +Sign-off needs people. Book the demos once the steps above pass in your own runs. See [the sandbox exit process](../sandbox/sandbox-exit.md). + +```precondition +human: true +who: your team, with the NHA team +action: Demonstrate this use case in the internal demo, then in the Health Tech Committee (HTC) demo. +how: Email hcx.integration@nha.gov.in to request both demos. +``` + +## How you know it worked + +The pass criterion for this case: + +> To generate the token to authenticate the API calls + +What you observe: + +- You receive HTTP 200 with `access_token`, `expires_in` and `token_type` `Bearer`. +- A call to `/fetch/participants/list` with the token returns HTTP 200, not 401. +- Your system replaces the token before it expires, with no manual step. + +## When it goes wrong + +- **The token call itself fails.** The client id or secret is wrong, or belongs to another environment. +- **Later calls return 401.** The token expired, lacks the `Bearer ` prefix, or went in the wrong header. See [NHCX-401](../errors/nhcx-401.md) and [every NHCX call returns 401](../troubleshooting/everything-returns-401.md). diff --git a/catalogue/nhcx/tests/payer-uc-07.md b/catalogue/nhcx/tests/payer-uc-07.md new file mode 100644 index 000000000..1c26275ad --- /dev/null +++ b/catalogue/nhcx/tests/payer-uc-07.md @@ -0,0 +1,160 @@ +--- +id: nhcx.test.payer-uc-07 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Payer sandbox exit use case 7: Respond to the coverage eligibility request' +summary: >- + Prove that your insurance system can answer a hospital's cover check through the + claims exchange, correctly addressed and sealed. +sources: +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, Table 2.2, Use case 7. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet CoverageEligibility. +- url: https://hcxsbx.abdm.gov.in/coverageeligibilityhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/coverageeligibilityhcxservice.json + hash: sha256:1723a4020b1b33d0bc1d7175609f0d05e6a6a78e8b4c52041222396639ceb52c + fetched: '2026-09-14' + note: 'API specification: coverageeligibilityhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/coverageeligibility/on_check.' +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2, Error scenario and Protocol Response. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 4, Q14; page 2, Q3. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8, Integrator's Journey. +verified: + status: unverified +related: + flows: + - nhcx.flow.payer-process-a-request + - nhcx.flow.receive-a-sealed-callback + concepts: + - nhcx.concept.message-identifiers + - nhcx.concept.protocol-headers + - nhcx.concept.four-message-legs + sandbox: + - nhcx.sandbox.sandbox-exit + - nhcx.sandbox.callback-url-requirements + troubleshooting: + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.recipient-cannot-decrypt + errors: + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1003 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-401 + endpoints: + - nhcx.endpoint.coverageeligibility-on-check + - nhcx.endpoint.fetch-certs + callbacks: + - nhcx.callback.coverageeligibility-check + - nhcx.callback.error + fhir: + - nhcx.fhir.coverage-eligibility-response + - nhcx.fhir.validation + tests: + - nhcx.test.payer-uc-05 + - nhcx.test.provider-uc-05 +--- + +# Payer sandbox exit use case 7: Respond to the coverage eligibility request + +## In plain words + +A hospital asks, through [NHCX](../../shared/glossary/nhcx.md), whether a member's cover is in force. This case proves your system answers with the member's eligibility and plan details. The answer must be sealed for that hospital and addressed back to its request. + +It is one of the fifteen payer use cases for [sandbox exit](../glossary/sandbox-exit.md). + +## Before you start + +- Your payer participant exists in the sandbox registry with the payer role, and you know its [participant code](../glossary/participant-code.md). [Onboard in the sandbox](../flows/sandbox-onboarding.md) gets you there. +- You hold a current session token from [use case 6](payer-uc-06.md). +- Your registered endpoint URL takes HTTPS calls from the exchange. See [callback URL requirements](../sandbox/callback-url-requirements.md). +- You can decrypt with your own private key, and you hold the provider's public certificate from [use case 5](payer-uc-05.md). +- A sandbox provider participant sends your payer a `POST /v1/coverageeligibility/check` request. You need a provider partner, or a provider participant of your own, to send it. + +## What happens + +### Receive the request + +1. Wait for `POST /v1/coverageeligibility/check` on your registered endpoint. +2. Answer it with HTTP 202 within 30 seconds, with the acceptance body from [receive a sealed callback](../flows/receive-a-sealed-callback.md). +3. Decrypt the payload with your private key. Validate the CoverageEligibilityRequest bundle against the [NRCeS](../../shared/glossary/nrces.md) profiles. + +### Send your answer + +1. If you processed the request, build a CoverageEligibilityResponse bundle with the member's eligibility and plan details. See [the coverage eligibility response bundle](../fhir/coverage-eligibility-response.md). Validate it against the NRCeS profiles ([validating a bundle](../fhir/validation.md)). Seal it as a [JWE](../glossary/jwe.md) with the provider's public key. +2. If you could not decrypt or validate the request, prepare a `ProtocolResponse` instead. It carries the protocol headers in clear, `x-hcx-status` `response.error`, and `x-hcx-error_details` naming the fault. +3. Set the protected headers. Use a new `x-hcx-api_call_id`, different from the correlation id. Set `x-hcx-correlation_id` to the `x-hcx-api_call_id` of the request you answer. Set `x-hcx-recipient_code` to that request's `x-hcx-sender_code`, and `x-hcx-sender_code` to your participant code. Set `x-hcx-status` to `response.complete`. +4. Send the answer to `/v1/coverageeligibility/on_check`. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/hcx/v1/coverageeligibility/on_check' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -H 'Authorization: Bearer ' \ + -d '{"type": "JWEPayload", "payload": ""}' +``` + +5. NHCX answers with HTTP 202. + +### Demonstrate it + +Sign-off needs people. Book the demos once the steps above pass in your own runs. See [the sandbox exit process](../sandbox/sandbox-exit.md). + +```precondition +human: true +who: your team, with the NHA team +action: Demonstrate this use case in the internal demo, then in the Health Tech Committee (HTC) demo. +how: Email hcx.integration@nha.gov.in to request both demos. +also: Send the FHIR bundles you used to hcx.integration@nha.gov.in for validation by the NRCeS team. +``` + +## How you know it worked + +The pass criterion for this case: + +> Payer to respond with API payload which should contain the eligibility and plan details of the beneficiary for whom the details are requested for. +> +> 1. Payload should be validated against the profiles published by NRCES. +> 2. Api caller ID and Correlation ID should be different. +> 3. Correlation ID should be the API caller ID of the request that you are responding to. +> 4. Receiver code should be the same as Sender ID of the request that Payer system is responding to. + +What you observe: + +- NHCX answers your `POST /v1/coverageeligibility/on_check` with HTTP 202. +- Your `x-hcx-api_call_id` differs from your `x-hcx-correlation_id`. +- Your `x-hcx-correlation_id` equals the `x-hcx-api_call_id` of the provider's request. +- Your `x-hcx-recipient_code` equals the `x-hcx-sender_code` of the provider's request. +- The sealed payload is a CoverageEligibilityResponse bundle, and it validates against the NRCeS profiles. +- No `/v1/error` report arrives at your endpoint for your answer. + +## When it goes wrong + +- **No request reaches your endpoint.** Check it against the [callback URL requirements](../sandbox/callback-url-requirements.md). Confirm the provider addresses your participant code, or your [TPA](../glossary/tpa.md)'s processing ID. +- **The provider cannot open your answer.** You sealed it with a stale or wrong certificate. Fetch the provider's certificate again with [use case 5](payer-uc-05.md). See [the recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). +- **[NHCX-1010](../errors/nhcx-1010.md), no data for the correlation id.** Your message's `x-hcx-correlation_id` is not the `x-hcx-api_call_id` of the request you answer. +- **[NHCX-1003](../errors/nhcx-1003.md), receiver not registered.** `x-hcx-recipient_code` is wrong. Copy it from the `x-hcx-sender_code` of the request you answer. +- **[NHCX-1011](../errors/nhcx-1011.md), invalid status.** `x-hcx-status` holds a value the exchange does not accept for this message. Use `response.complete` on an answer and `request.initiated` on a request. +- **A `/v1/error` report arrives at your endpoint.** The recipient refused your message after the exchange accepted it. Read the details as [receiving /v1/error](../callbacks/error.md) describes. +- **The exchange keeps redelivering the same message.** Your endpoint did not return HTTP 202 with the acceptance body within 30 seconds. The exchange retries five times, then deletes the request. See [retries and expiry](../concepts/retries-and-expiry.md). +- **HTTP 401 on the call.** The token has expired, or went in without the `Bearer ` prefix. See [NHCX-401](../errors/nhcx-401.md) and fetch a new token. diff --git a/catalogue/nhcx/tests/payer-uc-08.md b/catalogue/nhcx/tests/payer-uc-08.md new file mode 100644 index 000000000..91528cd20 --- /dev/null +++ b/catalogue/nhcx/tests/payer-uc-08.md @@ -0,0 +1,161 @@ +--- +id: nhcx.test.payer-uc-08 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Payer sandbox exit use case 8: Respond to the insurance plan request' +summary: >- + Prove that your insurance system can answer a hospital's request for a policy's + plan through the claims exchange. +sources: +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 2-3, Tables 2.3 and 3.1, Use case 8. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Insurance Plan. +- url: https://hcxsbx.abdm.gov.in/insuranceplanhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/insuranceplanhcxservice.json + hash: sha256:03665c6e6a5c8d86e3d621ab577dd683cf13c155d5b9529f5be6ca70fef13dee + fetched: '2026-09-14' + note: 'API specification: insuranceplanhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/insuranceplan/on_request.' +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2, Error scenario and Protocol Response. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 4, Q14; page 2, Q3. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8, Integrator's Journey. +verified: + status: unverified +related: + flows: + - nhcx.flow.payer-process-a-request + - nhcx.flow.receive-a-sealed-callback + concepts: + - nhcx.concept.message-identifiers + - nhcx.concept.protocol-headers + - nhcx.concept.four-message-legs + - nhcx.concept.insurance-plan + sandbox: + - nhcx.sandbox.sandbox-exit + - nhcx.sandbox.callback-url-requirements + troubleshooting: + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.recipient-cannot-decrypt + errors: + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1003 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-401 + endpoints: + - nhcx.endpoint.insuranceplan-on-request + - nhcx.endpoint.fetch-certs + callbacks: + - nhcx.callback.insuranceplan-request + - nhcx.callback.error + fhir: + - nhcx.fhir.insurance-plan-bundle + - nhcx.fhir.validation + tests: + - nhcx.test.payer-uc-05 + - nhcx.test.provider-uc-06 +--- + +# Payer sandbox exit use case 8: Respond to the insurance plan request + +## In plain words + +A hospital asks, through [NHCX](../../shared/glossary/nhcx.md), for the plan behind a policy: what it covers, on what conditions, with which documents. This case proves your system answers with the plan, sealed for that hospital and addressed back to its request. + +It is one of the fifteen payer use cases for [sandbox exit](../glossary/sandbox-exit.md). + +## Before you start + +- Your payer participant exists in the sandbox registry with the payer role, and you know its [participant code](../glossary/participant-code.md). [Onboard in the sandbox](../flows/sandbox-onboarding.md) gets you there. +- You hold a current session token from [use case 6](payer-uc-06.md). +- Your registered endpoint URL takes HTTPS calls from the exchange. See [callback URL requirements](../sandbox/callback-url-requirements.md). +- You can decrypt with your own private key, and you hold the provider's public certificate from [use case 5](payer-uc-05.md). +- A sandbox provider participant sends your payer a `POST /v1/insuranceplan/request` request. You need a provider partner, or a provider participant of your own, to send it. + +## What happens + +### Receive the request + +1. Wait for `POST /v1/insuranceplan/request` on your registered endpoint. +2. Answer it with HTTP 202 within 30 seconds, with the acceptance body from [receive a sealed callback](../flows/receive-a-sealed-callback.md). +3. Decrypt the payload with your private key. Validate the Task bundle against the [NRCeS](../../shared/glossary/nrces.md) profiles. + +### Send your answer + +1. If you processed the request, build a bundle holding the InsurancePlan resources for the policy. See [insurance plan bundles](../fhir/insurance-plan-bundle.md). Validate it against the NRCeS profiles ([validating a bundle](../fhir/validation.md)). Seal it as a [JWE](../glossary/jwe.md) with the provider's public key. +2. If you could not decrypt or validate the request, prepare a `ProtocolResponse` instead. It carries the protocol headers in clear, `x-hcx-status` `response.error`, and `x-hcx-error_details` naming the fault. +3. Set the protected headers. Use a new `x-hcx-api_call_id`, different from the correlation id. Set `x-hcx-correlation_id` to the `x-hcx-api_call_id` of the request you answer. Set `x-hcx-recipient_code` to that request's `x-hcx-sender_code`, and `x-hcx-sender_code` to your participant code. Set `x-hcx-status` to `response.complete`. +4. Send the answer to `/v1/insuranceplan/on_request`. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/hcx/v1/insuranceplan/on_request' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -H 'Authorization: Bearer ' \ + -d '{"type": "JWEPayload", "payload": ""}' +``` + +5. NHCX answers with HTTP 202. + +### Demonstrate it + +Sign-off needs people. Book the demos once the steps above pass in your own runs. See [the sandbox exit process](../sandbox/sandbox-exit.md). + +```precondition +human: true +who: your team, with the NHA team +action: Demonstrate this use case in the internal demo, then in the Health Tech Committee (HTC) demo. +how: Email hcx.integration@nha.gov.in to request both demos. +also: Send the FHIR bundles you used to hcx.integration@nha.gov.in for validation by the NRCeS team. +``` + +## How you know it worked + +The pass criterion for this case: + +> Respond with the insurance plan details request via NHCX +> +> 1. Payload should be validated against the profiles published by NRCES. +> 2. Api caller ID and Correlation ID should be different. +> 3. Correlation ID should be the API caller ID of the request that you are responding to. +> 4. Receiver code should be the same as Sender ID of the request that Payer system is responding to. + +What you observe: + +- NHCX answers your `POST /v1/insuranceplan/on_request` with HTTP 202. +- Your `x-hcx-api_call_id` differs from your `x-hcx-correlation_id`. +- Your `x-hcx-correlation_id` equals the `x-hcx-api_call_id` of the provider's request. +- Your `x-hcx-recipient_code` equals the `x-hcx-sender_code` of the provider's request. +- The sealed payload is a bundle holding InsurancePlan resources, and it validates against the NRCeS profiles. +- No `/v1/error` report arrives at your endpoint for your answer. + +## When it goes wrong + +- **No request reaches your endpoint.** Check it against the [callback URL requirements](../sandbox/callback-url-requirements.md). Confirm the provider addresses your participant code, or your [TPA](../glossary/tpa.md)'s processing ID. +- **The provider cannot open your answer.** You sealed it with a stale or wrong certificate. Fetch the provider's certificate again with [use case 5](payer-uc-05.md). See [the recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). +- **[NHCX-1010](../errors/nhcx-1010.md), no data for the correlation id.** Your message's `x-hcx-correlation_id` is not the `x-hcx-api_call_id` of the request you answer. +- **[NHCX-1003](../errors/nhcx-1003.md), receiver not registered.** `x-hcx-recipient_code` is wrong. Copy it from the `x-hcx-sender_code` of the request you answer. +- **[NHCX-1011](../errors/nhcx-1011.md), invalid status.** `x-hcx-status` holds a value the exchange does not accept for this message. Use `response.complete` on an answer and `request.initiated` on a request. +- **A `/v1/error` report arrives at your endpoint.** The recipient refused your message after the exchange accepted it. Read the details as [receiving /v1/error](../callbacks/error.md) describes. +- **The exchange keeps redelivering the same message.** Your endpoint did not return HTTP 202 with the acceptance body within 30 seconds. The exchange retries five times, then deletes the request. See [retries and expiry](../concepts/retries-and-expiry.md). +- **HTTP 401 on the call.** The token has expired, or went in without the `Bearer ` prefix. See [NHCX-401](../errors/nhcx-401.md) and fetch a new token. diff --git a/catalogue/nhcx/tests/payer-uc-09.md b/catalogue/nhcx/tests/payer-uc-09.md new file mode 100644 index 000000000..f7ee39458 --- /dev/null +++ b/catalogue/nhcx/tests/payer-uc-09.md @@ -0,0 +1,162 @@ +--- +id: nhcx.test.payer-uc-09 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Payer sandbox exit use case 9: Respond to the preauthorization submitted' +summary: >- + Prove that your insurance system can send its preauthorisation decision back to + the hospital through the claims exchange. +sources: +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 3-4, Tables 3.2 and 4.1, Use case 9. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Preauth. +- url: https://hcxsbx.abdm.gov.in/preauthhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/preauthhcxservice.json + hash: sha256:2e8c594c51d9640ae4a576be34a5d190614918d1e7697d6718bc91c31fa66948 + fetched: '2026-09-14' + note: 'API specification: preauthhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/preauth/on_submit.' +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2, Error scenario and Protocol Response. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 4, Q14; page 2, Q3. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8, Integrator's Journey. +verified: + status: unverified +related: + flows: + - nhcx.flow.payer-process-a-request + - nhcx.flow.receive-a-sealed-callback + concepts: + - nhcx.concept.message-identifiers + - nhcx.concept.protocol-headers + - nhcx.concept.four-message-legs + sandbox: + - nhcx.sandbox.sandbox-exit + - nhcx.sandbox.callback-url-requirements + troubleshooting: + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.recipient-cannot-decrypt + errors: + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1003 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-401 + endpoints: + - nhcx.endpoint.preauth-on-submit + - nhcx.endpoint.fetch-certs + callbacks: + - nhcx.callback.preauth-submit + - nhcx.callback.error + fhir: + - nhcx.fhir.preauth-response + - nhcx.fhir.validation + tests: + - nhcx.test.payer-uc-05 + - nhcx.test.provider-uc-07 + glossary: + - nhcx.glossary.adjudication +--- + +# Payer sandbox exit use case 9: Respond to the preauthorization submitted + +## In plain words + +A hospital submits a [preauthorisation](../glossary/preauthorisation.md) through [NHCX](../../shared/glossary/nhcx.md). This case proves your system sends back the adjudicated decision, sealed for that hospital and addressed back to its request. + +It is one of the fifteen payer use cases for [sandbox exit](../glossary/sandbox-exit.md). + +## Before you start + +- Your payer participant exists in the sandbox registry with the payer role, and you know its [participant code](../glossary/participant-code.md). [Onboard in the sandbox](../flows/sandbox-onboarding.md) gets you there. +- You hold a current session token from [use case 6](payer-uc-06.md). +- Your registered endpoint URL takes HTTPS calls from the exchange. See [callback URL requirements](../sandbox/callback-url-requirements.md). +- You can decrypt with your own private key, and you hold the provider's public certificate from [use case 5](payer-uc-05.md). +- A sandbox provider participant sends your payer a `POST /v1/preauth/submit` request. You need a provider partner, or a provider participant of your own, to send it. + +## What happens + +### Receive the request + +1. Wait for `POST /v1/preauth/submit` on your registered endpoint. +2. Answer it with HTTP 202 within 30 seconds, with the acceptance body from [receive a sealed callback](../flows/receive-a-sealed-callback.md). +3. Decrypt the payload with your private key. Validate the Claim bundle against the [NRCeS](../../shared/glossary/nrces.md) profiles. + +### Send your answer + +1. If you processed the request, build a ClaimResponse bundle with the adjudicated preauthorisation. See [the preauthorisation response bundle](../fhir/preauth-response.md). Validate it against the NRCeS profiles ([validating a bundle](../fhir/validation.md)). Seal it as a [JWE](../glossary/jwe.md) with the provider's public key. +2. If you could not decrypt or validate the request, prepare a `ProtocolResponse` instead. It carries the protocol headers in clear, `x-hcx-status` `response.error`, and `x-hcx-error_details` naming the fault. +3. Set the protected headers. Use a new `x-hcx-api_call_id`, different from the correlation id. Set `x-hcx-correlation_id` to the `x-hcx-api_call_id` of the request you answer. Set `x-hcx-recipient_code` to that request's `x-hcx-sender_code`, and `x-hcx-sender_code` to your participant code. Set `x-hcx-status` to `response.complete`. +4. Send the answer to `/v1/preauth/on_submit`. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/hcx/v1/preauth/on_submit' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -H 'Authorization: Bearer ' \ + -d '{"type": "JWEPayload", "payload": ""}' +``` + +5. NHCX answers with HTTP 202. + +### Demonstrate it + +Sign-off needs people. Book the demos once the steps above pass in your own runs. See [the sandbox exit process](../sandbox/sandbox-exit.md). + +```precondition +human: true +who: your team, with the NHA team +action: Demonstrate this use case in the internal demo, then in the Health Tech Committee (HTC) demo. +how: Email hcx.integration@nha.gov.in to request both demos. +also: Send the FHIR bundles you used to hcx.integration@nha.gov.in for validation by the NRCeS team. +``` + +## How you know it worked + +The pass criterion for this case: + +> Payer to respond with API payload which should contain the adjudicated Preauthorization details. +> +> 1. The payload should be validated against the profiles published by NRCES. +> 2. Api caller ID and Correlation ID should be different. +> 3. Correlation ID should be the API caller ID of the request that you are responding to. +> 4. Receiver code should be the same as Sender ID of the request that Payer system is responding to. + +What you observe: + +- NHCX answers your `POST /v1/preauth/on_submit` with HTTP 202. +- Your `x-hcx-api_call_id` differs from your `x-hcx-correlation_id`. +- Your `x-hcx-correlation_id` equals the `x-hcx-api_call_id` of the provider's request. +- Your `x-hcx-recipient_code` equals the `x-hcx-sender_code` of the provider's request. +- The sealed payload is a ClaimResponse bundle, and it validates against the NRCeS profiles. +- No `/v1/error` report arrives at your endpoint for your answer. + +## When it goes wrong + +- **No request reaches your endpoint.** Check it against the [callback URL requirements](../sandbox/callback-url-requirements.md). Confirm the provider addresses your participant code, or your [TPA](../glossary/tpa.md)'s processing ID. +- **The provider cannot open your answer.** You sealed it with a stale or wrong certificate. Fetch the provider's certificate again with [use case 5](payer-uc-05.md). See [the recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). +- **[NHCX-1010](../errors/nhcx-1010.md), no data for the correlation id.** Your message's `x-hcx-correlation_id` is not the `x-hcx-api_call_id` of the request you answer. +- **[NHCX-1003](../errors/nhcx-1003.md), receiver not registered.** `x-hcx-recipient_code` is wrong. Copy it from the `x-hcx-sender_code` of the request you answer. +- **[NHCX-1011](../errors/nhcx-1011.md), invalid status.** `x-hcx-status` holds a value the exchange does not accept for this message. Use `response.complete` on an answer and `request.initiated` on a request. +- **A `/v1/error` report arrives at your endpoint.** The recipient refused your message after the exchange accepted it. Read the details as [receiving /v1/error](../callbacks/error.md) describes. +- **The exchange keeps redelivering the same message.** Your endpoint did not return HTTP 202 with the acceptance body within 30 seconds. The exchange retries five times, then deletes the request. See [retries and expiry](../concepts/retries-and-expiry.md). +- **HTTP 401 on the call.** The token has expired, or went in without the `Bearer ` prefix. See [NHCX-401](../errors/nhcx-401.md) and fetch a new token. diff --git a/catalogue/nhcx/tests/payer-uc-10.md b/catalogue/nhcx/tests/payer-uc-10.md new file mode 100644 index 000000000..a6c8bb199 --- /dev/null +++ b/catalogue/nhcx/tests/payer-uc-10.md @@ -0,0 +1,160 @@ +--- +id: nhcx.test.payer-uc-10 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Payer sandbox exit use case 10: Raise communication request' +summary: >- + Prove that your insurance system can ask a hospital for more documents during + a claim cycle, and receive the documents back. +sources: +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 4, Table 4.2, Use case 10. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Communication (additional docs). +- url: https://hcxsbx.abdm.gov.in/communicationhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/communicationhcxservice.json + hash: sha256:0ad58a98851158057d38d42a8327349548644c1b2f1a33b4f94acb4c1840a8a4 + fetched: '2026-09-14' + note: 'API specification: communicationhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/communication/request.' +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Error scenario. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 4, Q14; page 2, Q3. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8, Integrator's Journey. +verified: + status: unverified +related: + flows: + - nhcx.flow.payer-process-a-request + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.send-a-sealed-request + - nhcx.flow.preauth-query-response + - nhcx.flow.claim-query-response + concepts: + - nhcx.concept.message-identifiers + - nhcx.concept.protocol-headers + - nhcx.concept.four-message-legs + - nhcx.concept.queries-and-communication + sandbox: + - nhcx.sandbox.sandbox-exit + - nhcx.sandbox.callback-url-requirements + troubleshooting: + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.recipient-cannot-decrypt + errors: + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1003 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-401 + endpoints: + - nhcx.endpoint.communication-request + - nhcx.endpoint.fetch-certs + callbacks: + - nhcx.callback.communication-on-request + - nhcx.callback.error + fhir: + - nhcx.fhir.task + - nhcx.fhir.validation + tests: + - nhcx.test.payer-uc-05 + - nhcx.test.payer-uc-15 + - nhcx.test.provider-uc-08 + glossary: + - nhcx.glossary.communication-request +--- + +# Payer sandbox exit use case 10: Raise communication request + +## In plain words + +During a claim cycle your system may need more documents from the hospital before it decides. This case proves your system sends a [communication request](../glossary/communication-request.md) through [NHCX](../../shared/glossary/nhcx.md). The hospital's documents come back later on your endpoint. + +Here your system starts the exchange. It is one of the fifteen payer use cases for [sandbox exit](../glossary/sandbox-exit.md). + +## Before you start + +- Your payer participant exists in the sandbox registry with the payer role, and you know its [participant code](../glossary/participant-code.md). [Onboard in the sandbox](../flows/sandbox-onboarding.md) gets you there. +- You hold a current session token from [use case 6](payer-uc-06.md). +- Your registered endpoint URL takes HTTPS calls from the exchange. See [callback URL requirements](../sandbox/callback-url-requirements.md). +- You can decrypt with your own private key, and you hold the provider's public certificate from [use case 5](payer-uc-05.md). +- A preauthorisation or claim from a sandbox provider is with you for adjudication. You need a provider partner, or a provider participant of your own, to send it. + +## What happens + +### Send the communication request + +1. Build a Task bundle with a CommunicationRequest as a bundle component. Name the documents you need. Validate it against the [NRCeS](../../shared/glossary/nrces.md) profiles ([validating a bundle](../fhir/validation.md)). +2. Seal it as a [JWE](../glossary/jwe.md) with the provider's public key. +3. Set the protected headers. `x-hcx-sender_code` is your participant code and `x-hcx-recipient_code` is the provider's. `x-hcx-status` is `request.initiated`. Use a new `x-hcx-api_call_id`. +4. Send it. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/hcx/v1/communication/request' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -H 'Authorization: Bearer ' \ + -d '{"payload": ""}' +``` + +5. NHCX answers with HTTP 202. + +### Receive the documents + +1. Wait for `POST /v1/communication/on_request` on your registered endpoint. +2. Answer it with HTTP 202 within 30 seconds, with the acceptance body. +3. Decrypt it. The Task bundle carries a Communication with the documents attached. + +### Demonstrate it + +Sign-off needs people. Book the demos once the steps above pass in your own runs. See [the sandbox exit process](../sandbox/sandbox-exit.md). + +```precondition +human: true +who: your team, with the NHA team +action: Demonstrate this use case in the internal demo, then in the Health Tech Committee (HTC) demo. +how: Email hcx.integration@nha.gov.in to request both demos. +also: Send the FHIR bundles you used to hcx.integration@nha.gov.in for validation by the NRCeS team. +``` + +## How you know it worked + +The pass criterion for this case: + +> Raise a communication request to Provider via HCX in a claim cycle for any additional documents required from provider. +> +> API should be called by payer systems to get the additional documents from the privider. Payload will be prepared as TaskBundle having CommunicationRequest as bundle component. +> +> Payload should be validated against the profiles published by NRCES. + +What you observe: + +- NHCX answers your `POST /v1/communication/request` with HTTP 202. +- You receive `POST /v1/communication/on_request`, whose `x-hcx-correlation_id` equals your `x-hcx-api_call_id`. +- The decrypted Task bundle carries a Communication with the documents you asked for. + +## When it goes wrong + +- **[NHCX-1003](../errors/nhcx-1003.md), receiver not registered.** `x-hcx-recipient_code` is not a registered provider code. +- **The provider cannot open your answer.** You sealed it with a stale or wrong certificate. Fetch the provider's certificate again with [use case 5](payer-uc-05.md). See [the recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). +- **The provider's answer never arrives.** Check your registered endpoint against the [callback URL requirements](../sandbox/callback-url-requirements.md). Then ask where your request stands with [use case 15](payer-uc-15.md). +- **HTTP 401 on the call.** The token has expired, or went in without the `Bearer ` prefix. See [NHCX-401](../errors/nhcx-401.md) and fetch a new token. +- **The exchange keeps redelivering the same message.** Your endpoint did not return HTTP 202 with the acceptance body within 30 seconds. The exchange retries five times, then deletes the request. See [retries and expiry](../concepts/retries-and-expiry.md). diff --git a/catalogue/nhcx/tests/payer-uc-11.md b/catalogue/nhcx/tests/payer-uc-11.md new file mode 100644 index 000000000..393d86400 --- /dev/null +++ b/catalogue/nhcx/tests/payer-uc-11.md @@ -0,0 +1,169 @@ +--- +id: nhcx.test.payer-uc-11 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Payer sandbox exit use case 11: Respond to the claim submitted' +summary: >- + Prove that your insurance system can send its claim decision back to the hospital + through the claims exchange. +sources: +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 4-5, Tables 4.3 and 5.1, Use case 11. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Status Description (Protected Header). +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Claim. +- url: https://hcxsbx.abdm.gov.in/claimhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/claimhcxservice.json + hash: sha256:488eea449c6ee45dc324f4f7c095a862c7d50d0e238075846122b51b2bab4878 + fetched: '2026-09-14' + note: 'API specification: claimhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/claim/on_submit.' +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2, Error scenario and Protocol Response. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 4, Q14; page 2, Q3. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8, Integrator's Journey. +verified: + status: unverified +related: + flows: + - nhcx.flow.payer-process-a-request + - nhcx.flow.receive-a-sealed-callback + concepts: + - nhcx.concept.message-identifiers + - nhcx.concept.protocol-headers + - nhcx.concept.four-message-legs + - nhcx.concept.status-lifecycle + sandbox: + - nhcx.sandbox.sandbox-exit + - nhcx.sandbox.callback-url-requirements + troubleshooting: + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.recipient-cannot-decrypt + errors: + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1003 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-401 + endpoints: + - nhcx.endpoint.claim-on-submit + - nhcx.endpoint.fetch-certs + callbacks: + - nhcx.callback.claim-submit + - nhcx.callback.error + fhir: + - nhcx.fhir.claim-response + - nhcx.fhir.validation + tests: + - nhcx.test.payer-uc-05 + - nhcx.test.provider-uc-09 + glossary: + - nhcx.glossary.adjudication +--- + +# Payer sandbox exit use case 11: Respond to the claim submitted + +## In plain words + +A hospital submits a [claim](../glossary/claim.md) through [NHCX](../../shared/glossary/nhcx.md). This case proves your system sends back the adjudicated claim, sealed for that hospital and addressed back to its request. + +It is one of the fifteen payer use cases for [sandbox exit](../glossary/sandbox-exit.md). + +## Before you start + +- Your payer participant exists in the sandbox registry with the payer role, and you know its [participant code](../glossary/participant-code.md). [Onboard in the sandbox](../flows/sandbox-onboarding.md) gets you there. +- You hold a current session token from [use case 6](payer-uc-06.md). +- Your registered endpoint URL takes HTTPS calls from the exchange. See [callback URL requirements](../sandbox/callback-url-requirements.md). +- You can decrypt with your own private key, and you hold the provider's public certificate from [use case 5](payer-uc-05.md). +- A sandbox provider participant sends your payer a `POST /v1/claim/submit` request. You need a provider partner, or a provider participant of your own, to send it. + +## What happens + +### Receive the request + +1. Wait for `POST /v1/claim/submit` on your registered endpoint. +2. Answer it with HTTP 202 within 30 seconds, with the acceptance body from [receive a sealed callback](../flows/receive-a-sealed-callback.md). +3. Decrypt the payload with your private key. Validate the Claim bundle against the [NRCeS](../../shared/glossary/nrces.md) profiles. + +### Send your answer + +1. If you processed the request, build a ClaimResponse bundle with the adjudicated claim. See [the claim response bundle](../fhir/claim-response.md). Validate it against the NRCeS profiles ([validating a bundle](../fhir/validation.md)). Seal it as a [JWE](../glossary/jwe.md) with the provider's public key. +2. If you could not decrypt or validate the request, prepare a `ProtocolResponse` instead. It carries the protocol headers in clear, `x-hcx-status` `response.error`, and `x-hcx-error_details` naming the fault. +3. Set the protected headers. Use a new `x-hcx-api_call_id`, different from the correlation id. Set `x-hcx-correlation_id` to the `x-hcx-api_call_id` of the request you answer. Set `x-hcx-recipient_code` to that request's `x-hcx-sender_code`, and `x-hcx-sender_code` to your participant code. Set `x-hcx-status` to `response.partial` while you acknowledge or answer in part, and `response.complete` for the final decision. +4. Send the answer to `/v1/claim/on_submit`. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/hcx/v1/claim/on_submit' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -H 'Authorization: Bearer ' \ + -d '{"type": "JWEPayload", "payload": ""}' +``` + +5. NHCX answers with HTTP 202. + +### Demonstrate it + +Sign-off needs people. Book the demos once the steps above pass in your own runs. See [the sandbox exit process](../sandbox/sandbox-exit.md). + +```precondition +human: true +who: your team, with the NHA team +action: Demonstrate this use case in the internal demo, then in the Health Tech Committee (HTC) demo. +how: Email hcx.integration@nha.gov.in to request both demos. +also: Send the FHIR bundles you used to hcx.integration@nha.gov.in for validation by the NRCeS team. +``` + +## How you know it worked + +The pass criterion for this case: + +> Payer to respond with API payload which should contain the adjudicated Claim details. +> +> 1. The payload should be validated against the profiles published by NRCES. +> 2. Api caller ID and Correlation ID should be different. +> 3. Correlation ID should be the API caller ID of the request that you are responding to. +> 4. Receiver code should be the same as Sender ID of the request that Payer system is responding to. + +What you observe: + +- NHCX answers your `POST /v1/claim/on_submit` with HTTP 202. +- Your `x-hcx-api_call_id` differs from your `x-hcx-correlation_id`. +- Your `x-hcx-correlation_id` equals the `x-hcx-api_call_id` of the provider's request. +- Your `x-hcx-recipient_code` equals the `x-hcx-sender_code` of the provider's request. +- The sealed payload is a ClaimResponse bundle, and it validates against the NRCeS profiles. +- No `/v1/error` report arrives at your endpoint for your answer. +- `x-hcx-status` is `response.partial` on an interim answer and `response.complete` on the final one. + +## When it goes wrong + +- **No request reaches your endpoint.** Check it against the [callback URL requirements](../sandbox/callback-url-requirements.md). Confirm the provider addresses your participant code, or your [TPA](../glossary/tpa.md)'s processing ID. +- **The provider cannot open your answer.** You sealed it with a stale or wrong certificate. Fetch the provider's certificate again with [use case 5](payer-uc-05.md). See [the recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). +- **[NHCX-1010](../errors/nhcx-1010.md), no data for the correlation id.** Your message's `x-hcx-correlation_id` is not the `x-hcx-api_call_id` of the request you answer. +- **[NHCX-1003](../errors/nhcx-1003.md), receiver not registered.** `x-hcx-recipient_code` is wrong. Copy it from the `x-hcx-sender_code` of the request you answer. +- **[NHCX-1011](../errors/nhcx-1011.md), invalid status.** `x-hcx-status` holds a value the exchange does not accept for this message. Use `response.complete` on an answer and `request.initiated` on a request. +- **A `/v1/error` report arrives at your endpoint.** The recipient refused your message after the exchange accepted it. Read the details as [receiving /v1/error](../callbacks/error.md) describes. +- **The exchange keeps redelivering the same message.** Your endpoint did not return HTTP 202 with the acceptance body within 30 seconds. The exchange retries five times, then deletes the request. See [retries and expiry](../concepts/retries-and-expiry.md). +- **HTTP 401 on the call.** The token has expired, or went in without the `Bearer ` prefix. See [NHCX-401](../errors/nhcx-401.md) and fetch a new token. diff --git a/catalogue/nhcx/tests/payer-uc-12.md b/catalogue/nhcx/tests/payer-uc-12.md new file mode 100644 index 000000000..7997e0c92 --- /dev/null +++ b/catalogue/nhcx/tests/payer-uc-12.md @@ -0,0 +1,162 @@ +--- +id: nhcx.test.payer-uc-12 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Payer sandbox exit use case 12: Respond to search request' +summary: >- + Prove that your insurance system can answer a hospital's claim search with the + matching claim responses. +sources: +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 5, Table 5.2, Use case 12. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Search. +- url: https://hcxsbx.abdm.gov.in/searchhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/searchhcxservice.json + hash: sha256:21749dd2ba84a19c5523772da359d76293493d44b48651f1af2e6042d78fa296 + fetched: '2026-09-14' + note: 'API specification: searchhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/search/on_submit.' +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2, Error scenario and Protocol Response. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 4, Q14; page 2, Q3. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8, Integrator's Journey. +verified: + status: unverified +related: + flows: + - nhcx.flow.payer-process-a-request + - nhcx.flow.receive-a-sealed-callback + concepts: + - nhcx.concept.message-identifiers + - nhcx.concept.protocol-headers + - nhcx.concept.four-message-legs + sandbox: + - nhcx.sandbox.sandbox-exit + - nhcx.sandbox.callback-url-requirements + troubleshooting: + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.recipient-cannot-decrypt + errors: + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1003 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-401 + endpoints: + - nhcx.endpoint.search-on-submit + - nhcx.endpoint.fetch-certs + callbacks: + - nhcx.callback.search-submit + - nhcx.callback.error + fhir: + - nhcx.fhir.task + - nhcx.fhir.claim-response + - nhcx.fhir.validation + tests: + - nhcx.test.payer-uc-05 + - nhcx.test.provider-uc-10 +--- + +# Payer sandbox exit use case 12: Respond to search request + +## In plain words + +A hospital searches its claims with you through [NHCX](../../shared/glossary/nhcx.md), by claim number, date range, policy or product. This case proves your system answers with the matching claim responses, sealed and addressed back to the search. + +It is one of the fifteen payer use cases for [sandbox exit](../glossary/sandbox-exit.md). + +## Before you start + +- Your payer participant exists in the sandbox registry with the payer role, and you know its [participant code](../glossary/participant-code.md). [Onboard in the sandbox](../flows/sandbox-onboarding.md) gets you there. +- You hold a current session token from [use case 6](payer-uc-06.md). +- Your registered endpoint URL takes HTTPS calls from the exchange. See [callback URL requirements](../sandbox/callback-url-requirements.md). +- You can decrypt with your own private key, and you hold the provider's public certificate from [use case 5](payer-uc-05.md). +- A sandbox provider participant sends your payer a `POST /v1/search/submit` request. You need a provider partner, or a provider participant of your own, to send it. + +## What happens + +### Receive the request + +1. Wait for `POST /v1/search/submit` on your registered endpoint. +2. Answer it with HTTP 202 within 30 seconds, with the acceptance body from [receive a sealed callback](../flows/receive-a-sealed-callback.md). +3. Decrypt the payload with your private key. Validate the Task bundle against the [NRCeS](../../shared/glossary/nrces.md) profiles. + +### Send your answer + +1. If you processed the request, build a Task bundle whose output carries the ClaimResponse resources that match the search inputs. See [the task bundle](../fhir/task.md). Validate it against the NRCeS profiles ([validating a bundle](../fhir/validation.md)). Seal it as a [JWE](../glossary/jwe.md) with the provider's public key. +2. If you could not decrypt or validate the request, prepare a `ProtocolResponse` instead. It carries the protocol headers in clear, `x-hcx-status` `response.error`, and `x-hcx-error_details` naming the fault. +3. Set the protected headers. Use a new `x-hcx-api_call_id`, different from the correlation id. Set `x-hcx-correlation_id` to the `x-hcx-api_call_id` of the request you answer. Set `x-hcx-recipient_code` to that request's `x-hcx-sender_code`, and `x-hcx-sender_code` to your participant code. Set `x-hcx-status` to `response.complete`, or `response.partial` when you answer in part. +4. Send the answer to `/v1/search/on_submit`. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/hcx/v1/search/on_submit' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -H 'Authorization: Bearer ' \ + -d '{"type": "JWEPayload", "payload": ""}' +``` + +5. NHCX answers with HTTP 202. + +### Demonstrate it + +Sign-off needs people. Book the demos once the steps above pass in your own runs. See [the sandbox exit process](../sandbox/sandbox-exit.md). + +```precondition +human: true +who: your team, with the NHA team +action: Demonstrate this use case in the internal demo, then in the Health Tech Committee (HTC) demo. +how: Email hcx.integration@nha.gov.in to request both demos. +also: Send the FHIR bundles you used to hcx.integration@nha.gov.in for validation by the NRCeS team. +``` + +## How you know it worked + +The pass criterion for this case: + +> To respond for search requests based on the task request. It provides the ClaimResponse(s) to the given input criteria. +> +> 1. The payload should be validated against the profiles published by NRCES. +> 2. Api caller ID and Correlation ID should be different. +> 3. Correlation ID should be the API caller ID of the request that you are responding to. +> 4. Receiver code should be the same as Sender ID of the request that Payer system is responding to. + +What you observe: + +- NHCX answers your `POST /v1/search/on_submit` with HTTP 202. +- Your `x-hcx-api_call_id` differs from your `x-hcx-correlation_id`. +- Your `x-hcx-correlation_id` equals the `x-hcx-api_call_id` of the provider's request. +- Your `x-hcx-recipient_code` equals the `x-hcx-sender_code` of the provider's request. +- The sealed payload is a Task bundle carrying the matching ClaimResponse resources, and it validates against the NRCeS profiles. +- No `/v1/error` report arrives at your endpoint for your answer. +- The ClaimResponse resources match the search inputs, for example the claim number asked for. + +## When it goes wrong + +- **No request reaches your endpoint.** Check it against the [callback URL requirements](../sandbox/callback-url-requirements.md). Confirm the provider addresses your participant code, or your [TPA](../glossary/tpa.md)'s processing ID. +- **The provider cannot open your answer.** You sealed it with a stale or wrong certificate. Fetch the provider's certificate again with [use case 5](payer-uc-05.md). See [the recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). +- **[NHCX-1010](../errors/nhcx-1010.md), no data for the correlation id.** Your message's `x-hcx-correlation_id` is not the `x-hcx-api_call_id` of the request you answer. +- **[NHCX-1003](../errors/nhcx-1003.md), receiver not registered.** `x-hcx-recipient_code` is wrong. Copy it from the `x-hcx-sender_code` of the request you answer. +- **[NHCX-1011](../errors/nhcx-1011.md), invalid status.** `x-hcx-status` holds a value the exchange does not accept for this message. Use `response.complete` on an answer and `request.initiated` on a request. +- **A `/v1/error` report arrives at your endpoint.** The recipient refused your message after the exchange accepted it. Read the details as [receiving /v1/error](../callbacks/error.md) describes. +- **The exchange keeps redelivering the same message.** Your endpoint did not return HTTP 202 with the acceptance body within 30 seconds. The exchange retries five times, then deletes the request. See [retries and expiry](../concepts/retries-and-expiry.md). +- **HTTP 401 on the call.** The token has expired, or went in without the `Bearer ` prefix. See [NHCX-401](../errors/nhcx-401.md) and fetch a new token. diff --git a/catalogue/nhcx/tests/payer-uc-13.md b/catalogue/nhcx/tests/payer-uc-13.md new file mode 100644 index 000000000..255025df3 --- /dev/null +++ b/catalogue/nhcx/tests/payer-uc-13.md @@ -0,0 +1,166 @@ +--- +id: nhcx.test.payer-uc-13 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Payer sandbox exit use case 13: Send payment notice' +summary: >- + Prove that your insurance system can tell a hospital a claim was paid, through + the claims exchange, and receive its acknowledgement. +sources: +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 6, Table 6.2, Use case 13. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet PaymentNotice. +- url: https://hcxsbx.abdm.gov.in/images/c42ad170f37c987ed173.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx + hash: sha256:f56dd156c232192296082f23b1561d0ff11fd40992e6675de41c5c991d579e6d + fetched: '2026-09-14' + note: Workflow Status Sheets(with Codes), row 12 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet1, rows 17, 30, 31, 33. +- url: https://hcxsbx.abdm.gov.in/servicehcxpayment/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/servicehcxpayment.json + hash: sha256:f5c9e3728efbbeaa5e0e8083334b0ae60a05930e5a1e096ca06d40abb235d658 + fetched: '2026-09-14' + note: 'API specification: servicehcxpayment, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/paymentnotice/request.' +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Error scenario. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 4, Q14; page 2, Q3. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8, Integrator's Journey. +verified: + status: unverified +related: + flows: + - nhcx.flow.payer-process-a-request + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.payment-notice + - nhcx.flow.send-a-sealed-request + concepts: + - nhcx.concept.message-identifiers + - nhcx.concept.protocol-headers + - nhcx.concept.four-message-legs + - nhcx.concept.workflow-codes + sandbox: + - nhcx.sandbox.sandbox-exit + - nhcx.sandbox.callback-url-requirements + troubleshooting: + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.recipient-cannot-decrypt + errors: + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1003 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-401 + endpoints: + - nhcx.endpoint.paymentnotice-request + - nhcx.endpoint.fetch-certs + callbacks: + - nhcx.callback.paymentnotice-on-request + - nhcx.callback.error + fhir: + - nhcx.fhir.payment-notice + - nhcx.fhir.task + - nhcx.fhir.validation + tests: + - nhcx.test.payer-uc-05 + - nhcx.test.payer-uc-11 + - nhcx.test.provider-uc-11 + glossary: + - nhcx.glossary.payment-notice +--- + +# Payer sandbox exit use case 13: Send payment notice + +## In plain words + +When your system pays a claim, it tells the hospital with a [payment notice](../glossary/payment-notice.md) through [NHCX](../../shared/glossary/nhcx.md). The notice carries the payment date, the amount and the bank transaction reference. The hospital acknowledges it on your endpoint. + +Here your system starts the exchange. It is one of the fifteen payer use cases for [sandbox exit](../glossary/sandbox-exit.md). + +## Before you start + +- Your payer participant exists in the sandbox registry with the payer role, and you know its [participant code](../glossary/participant-code.md). [Onboard in the sandbox](../flows/sandbox-onboarding.md) gets you there. +- You hold a current session token from [use case 6](payer-uc-06.md). +- Your registered endpoint URL takes HTTPS calls from the exchange. See [callback URL requirements](../sandbox/callback-url-requirements.md). +- You can decrypt with your own private key, and you hold the provider's public certificate from [use case 5](payer-uc-05.md). +- You approved a claim from a sandbox provider in [use case 11](payer-uc-11.md). + +## What happens + +### Send the payment notice + +1. Build a Task bundle whose Task has `code` `deliver` and a PaymentNotice as input. The PaymentReconciliation carries `status`, `paymentDate`, `paymentAmount` and `paymentIdentifier`, the bank transaction reference. See [the payment notice bundle](../fhir/payment-notice.md). +2. Validate it against the [NRCeS](../../shared/glossary/nrces.md) profiles, then seal it with the provider's public key. +3. Set the protected headers. `x-hcx-recipient_code` is the provider's code and `x-hcx-status` is `request.initiated`. Use a new `x-hcx-api_call_id`. `x-hcx-workflow_id` names the payment stage: `30` initiated, `31` processed, `33` settled. +4. Send it. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/hcx/v1/paymentnotice/request' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -H 'Authorization: Bearer ' \ + -d '{"payload": ""}' +``` + +5. NHCX answers with HTTP 202. + +### Receive the acknowledgement + +1. Wait for `POST /v1/paymentnotice/on_request` on your registered endpoint. +2. Answer it with HTTP 202 within 30 seconds, with the acceptance body. +3. Decrypt it. It carries `x-hcx-workflow_id` `17`, the provider's acknowledgement. + +### Demonstrate it + +Sign-off needs people. Book the demos once the steps above pass in your own runs. See [the sandbox exit process](../sandbox/sandbox-exit.md). + +```precondition +human: true +who: your team, with the NHA team +action: Demonstrate this use case in the internal demo, then in the Health Tech Committee (HTC) demo. +how: Email hcx.integration@nha.gov.in to request both demos. +also: Send the FHIR bundles you used to hcx.integration@nha.gov.in for validation by the NRCeS team. +``` + +## How you know it worked + +The pass criterion for this case: + +> Send Payment notification/reconciliation objects to Providers via the HCX gateway +> +> API should be called by payer systems. Request will be prepared as per the specifications. +> +> Payload should be validated against the profiles published by NRCES. + +What you observe: + +- NHCX answers your `POST /v1/paymentnotice/request` with HTTP 202. +- You receive `POST /v1/paymentnotice/on_request` with `x-hcx-workflow_id` `17` and `x-hcx-status` `response.complete`. +- Its `x-hcx-correlation_id` equals your `x-hcx-api_call_id`. + +## When it goes wrong + +- **[NHCX-1003](../errors/nhcx-1003.md), receiver not registered.** `x-hcx-recipient_code` is not the provider's registered code. +- **The provider cannot open your answer.** You sealed it with a stale or wrong certificate. Fetch the provider's certificate again with [use case 5](payer-uc-05.md). See [the recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). +- **The provider's answer never arrives.** Check your registered endpoint against the [callback URL requirements](../sandbox/callback-url-requirements.md). Then ask where your request stands with [use case 15](payer-uc-15.md). +- **HTTP 401 on the call.** The token has expired, or went in without the `Bearer ` prefix. See [NHCX-401](../errors/nhcx-401.md) and fetch a new token. +- **[NHCX-1011](../errors/nhcx-1011.md), invalid status.** `x-hcx-status` holds a value the exchange does not accept for this message. Use `response.complete` on an answer and `request.initiated` on a request. +- **The exchange keeps redelivering the same message.** Your endpoint did not return HTTP 202 with the acceptance body within 30 seconds. The exchange retries five times, then deletes the request. See [retries and expiry](../concepts/retries-and-expiry.md). diff --git a/catalogue/nhcx/tests/payer-uc-14.md b/catalogue/nhcx/tests/payer-uc-14.md new file mode 100644 index 000000000..d84d7c346 --- /dev/null +++ b/catalogue/nhcx/tests/payer-uc-14.md @@ -0,0 +1,167 @@ +--- +id: nhcx.test.payer-uc-14 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Payer sandbox exit use case 14: Respond to the task request submitted' +summary: >- + Prove that your insurance system can answer a hospital's reprocess or cancel request + through the claims exchange. +sources: +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 6-7, Tables 6.3 and 7.1, Use case 14. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Reprocess. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 10.5 Response. +- url: https://hcxsbx.abdm.gov.in/taskhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/taskhcxservice.json + hash: sha256:0418eca6478dece4d72c5a49a6547d50772511f7ffaf32f901f245591ba84656 + fetched: '2026-09-14' + note: 'API specification: taskhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/task/on_submit.' +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2, Error scenario and Protocol Response. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 4, Q14; page 2, Q3. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8, Integrator's Journey. +verified: + status: unverified +related: + flows: + - nhcx.flow.payer-process-a-request + - nhcx.flow.receive-a-sealed-callback + concepts: + - nhcx.concept.message-identifiers + - nhcx.concept.protocol-headers + - nhcx.concept.four-message-legs + - nhcx.concept.reprocess-and-cancel + sandbox: + - nhcx.sandbox.sandbox-exit + - nhcx.sandbox.callback-url-requirements + troubleshooting: + - nhcx.troubleshooting.duplicate-or-mismatched-correlation + - nhcx.troubleshooting.recipient-cannot-decrypt + errors: + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1003 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-401 + endpoints: + - nhcx.endpoint.task-on-submit + - nhcx.endpoint.fetch-certs + callbacks: + - nhcx.callback.task-submit + - nhcx.callback.error + fhir: + - nhcx.fhir.task + - nhcx.fhir.claim-response + - nhcx.fhir.validation + tests: + - nhcx.test.payer-uc-05 + - nhcx.test.provider-uc-12 +--- + +# Payer sandbox exit use case 14: Respond to the task request submitted + +## In plain words + +A hospital asks you, through [NHCX](../../shared/glossary/nhcx.md), to [reprocess](../glossary/reprocess.md) or cancel a claim or preauthorisation. This case proves your system answers the task, sealed for that hospital and addressed back to its request. + +It is one of the fifteen payer use cases for [sandbox exit](../glossary/sandbox-exit.md). + +## Before you start + +- Your payer participant exists in the sandbox registry with the payer role, and you know its [participant code](../glossary/participant-code.md). [Onboard in the sandbox](../flows/sandbox-onboarding.md) gets you there. +- You hold a current session token from [use case 6](payer-uc-06.md). +- Your registered endpoint URL takes HTTPS calls from the exchange. See [callback URL requirements](../sandbox/callback-url-requirements.md). +- You can decrypt with your own private key, and you hold the provider's public certificate from [use case 5](payer-uc-05.md). +- A sandbox provider participant sends your payer a `POST /v1/task/submit` request. You need a provider partner, or a provider participant of your own, to send it. + +## What happens + +### Receive the request + +1. Wait for `POST /v1/task/submit` on your registered endpoint. +2. Answer it with HTTP 202 within 30 seconds, with the acceptance body from [receive a sealed callback](../flows/receive-a-sealed-callback.md). +3. Decrypt the payload with your private key. Validate the Task bundle against the [NRCeS](../../shared/glossary/nrces.md) profiles. + +### Send your answer + +1. If you processed the request, build a Task bundle with `status` `completed` whose output references the resulting ClaimResponse. See [the task bundle](../fhir/task.md). Validate it against the NRCeS profiles ([validating a bundle](../fhir/validation.md)). Seal it as a [JWE](../glossary/jwe.md) with the provider's public key. +2. If you could not decrypt or validate the request, prepare a `ProtocolResponse` instead. It carries the protocol headers in clear, `x-hcx-status` `response.error`, and `x-hcx-error_details` naming the fault. +3. Set the protected headers. Use a new `x-hcx-api_call_id`, different from the correlation id. Set `x-hcx-correlation_id` to the `x-hcx-api_call_id` of the request you answer. Set `x-hcx-recipient_code` to that request's `x-hcx-sender_code`, and `x-hcx-sender_code` to your participant code. Set `x-hcx-status` to `response.complete`. +4. Send the answer to `/v1/task/on_submit`. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/hcx/v1/task/on_submit' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -H 'Authorization: Bearer ' \ + -d '{"type": "JWEPayload", "payload": ""}' +``` + +5. NHCX answers with HTTP 202. + +### Demonstrate it + +Sign-off needs people. Book the demos once the steps above pass in your own runs. See [the sandbox exit process](../sandbox/sandbox-exit.md). + +```precondition +human: true +who: your team, with the NHA team +action: Demonstrate this use case in the internal demo, then in the Health Tech Committee (HTC) demo. +how: Email hcx.integration@nha.gov.in to request both demos. +also: Send the FHIR bundles you used to hcx.integration@nha.gov.in for validation by the NRCeS team. +``` + +## How you know it worked + +The pass criterion for this case: + +> To return the response for task requests such as reprocess/cancel. +> +> 1. The payload should be validated against the profiles published by NRCES. +> 2. Api caller ID and Correlation ID should be different. +> 3. Correlation ID should be the API caller ID of the request that you are responding to. +> 4. Receiver code should be the same as Sender ID of the request that Payer system is responding to. + +What you observe: + +- NHCX answers your `POST /v1/task/on_submit` with HTTP 202. +- Your `x-hcx-api_call_id` differs from your `x-hcx-correlation_id`. +- Your `x-hcx-correlation_id` equals the `x-hcx-api_call_id` of the provider's request. +- Your `x-hcx-recipient_code` equals the `x-hcx-sender_code` of the provider's request. +- The sealed payload is a Task bundle whose output references a ClaimResponse, and it validates against the NRCeS profiles. +- No `/v1/error` report arrives at your endpoint for your answer. + +## When it goes wrong + +- **No request reaches your endpoint.** Check it against the [callback URL requirements](../sandbox/callback-url-requirements.md). Confirm the provider addresses your participant code, or your [TPA](../glossary/tpa.md)'s processing ID. +- **The provider cannot open your answer.** You sealed it with a stale or wrong certificate. Fetch the provider's certificate again with [use case 5](payer-uc-05.md). See [the recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). +- **[NHCX-1010](../errors/nhcx-1010.md), no data for the correlation id.** Your message's `x-hcx-correlation_id` is not the `x-hcx-api_call_id` of the request you answer. +- **[NHCX-1003](../errors/nhcx-1003.md), receiver not registered.** `x-hcx-recipient_code` is wrong. Copy it from the `x-hcx-sender_code` of the request you answer. +- **[NHCX-1011](../errors/nhcx-1011.md), invalid status.** `x-hcx-status` holds a value the exchange does not accept for this message. Use `response.complete` on an answer and `request.initiated` on a request. +- **A `/v1/error` report arrives at your endpoint.** The recipient refused your message after the exchange accepted it. Read the details as [receiving /v1/error](../callbacks/error.md) describes. +- **The exchange keeps redelivering the same message.** Your endpoint did not return HTTP 202 with the acceptance body within 30 seconds. The exchange retries five times, then deletes the request. See [retries and expiry](../concepts/retries-and-expiry.md). +- **HTTP 401 on the call.** The token has expired, or went in without the `Bearer ` prefix. See [NHCX-401](../errors/nhcx-401.md) and fetch a new token. diff --git a/catalogue/nhcx/tests/payer-uc-15.md b/catalogue/nhcx/tests/payer-uc-15.md new file mode 100644 index 000000000..8981883a5 --- /dev/null +++ b/catalogue/nhcx/tests/payer-uc-15.md @@ -0,0 +1,138 @@ +--- +id: nhcx.test.payer-uc-15 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Payer sandbox exit use case 15: Get status' +summary: >- + Prove that your insurance system can ask the claims exchange where one of its + earlier messages stands, and read the answer. +sources: +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 7, Table 7.2, Use case 15. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Status. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Status Description (Protected Header). +- url: https://hcxsbx.abdm.gov.in/statushcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/statushcxservice.json + hash: sha256:93b6355a234ef56607427fcdfa32da4921124180c9df08ecd73c8af8955c2adf + fetched: '2026-09-14' + note: 'API specification: statushcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/status.' +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 4, Q14; page 2, Q3. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8, Integrator's Journey. +verified: + status: unverified +related: + flows: + - nhcx.flow.status-check + endpoints: + - nhcx.endpoint.status + callbacks: + - nhcx.callback.on-status + concepts: + - nhcx.concept.status-lifecycle + - nhcx.concept.message-identifiers + decisions: + - nhcx.decision.status-poll-or-wait + sandbox: + - nhcx.sandbox.sandbox-exit + - nhcx.sandbox.callback-url-requirements + tests: + - nhcx.test.payer-uc-10 + - nhcx.test.payer-uc-13 + - nhcx.test.provider-uc-13 + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1012 +--- + +# Payer sandbox exit use case 15: Get status + +## In plain words + +Messages through [NHCX](../../shared/glossary/nhcx.md) are answered later, so one can seem to vanish. This case proves your system can ask the exchange where one of its own messages stands, such as a payment notice. The answer arrives on your endpoint as the protocol headers of that message. + +It is one of the fifteen payer use cases for [sandbox exit](../glossary/sandbox-exit.md). The exchange answers this call itself. + +## Before you start + +- Your payer participant exists in the sandbox registry with the payer role, and you know its [participant code](../glossary/participant-code.md). [Onboard in the sandbox](../flows/sandbox-onboarding.md) gets you there. +- You hold a current session token from [use case 6](payer-uc-06.md). +- You sent a message earlier, for example in [use case 13](payer-uc-13.md), and stored its `x-hcx-api_call_id`. +- Your registered endpoint URL takes HTTPS calls from the exchange. See [callback URL requirements](../sandbox/callback-url-requirements.md). + +## What happens + +### Send the status request + +1. Build the status request as a [JWE](../glossary/jwe.md), as [`/v1/status`](../endpoints/status.md) describes. +2. Set the protected headers. Use a new `x-hcx-api_call_id`. Set `x-hcx-correlation_id` to the `x-hcx-api_call_id` of the message you ask about. Set `x-hcx-recipient_code` to that message's recipient, and `x-hcx-status` to `request.initiated`. +3. Send it. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/hcx/v1/status' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -H 'Authorization: Bearer ' \ + -d '{"payload": ""}' +``` + +4. NHCX answers with HTTP 202. + +### Receive the status + +1. Wait for `POST /v1/on_status` on your registered endpoint. Answer it with HTTP 202 within 30 seconds. +2. Read the protocol headers it carries. `request.queued` means the message waits at the exchange. `request.dispatched` means it reached the recipient's system. + +### Demonstrate it + +Sign-off needs people. Book the demos once the steps above pass in your own runs. See [the sandbox exit process](../sandbox/sandbox-exit.md). + +```precondition +human: true +who: your team, with the NHA team +action: Demonstrate this use case in the internal demo, then in the Health Tech Committee (HTC) demo. +how: Email hcx.integration@nha.gov.in to request both demos. +``` + +## How you know it worked + +The pass criterion for this case: + +> Retrieve the status of any request that has been triggered to NHCX +> +> Callback API should be implemented by provider systems. It should accept the payload as ProtocolHeader contains all the attributes. +> +> Payload should be validated against the profiles published by NRCES. + +What you observe: + +- NHCX answers your `POST /v1/status` with HTTP 202. +- You receive `POST /v1/on_status` carrying the protocol headers of the message you asked about. +- Your system shows the message's stage from `x-hcx-status`. + +## When it goes wrong + +- **[NHCX-1012](../errors/nhcx-1012.md), no records for the API call id.** `x-hcx-correlation_id` must be the `x-hcx-api_call_id` of a message your participant sent. +- **The status never arrives.** Check your registered endpoint against the [callback URL requirements](../sandbox/callback-url-requirements.md). +- **HTTP 401 on the call.** The token has expired, or went in without the `Bearer ` prefix. See [NHCX-401](../errors/nhcx-401.md) and fetch a new token. diff --git a/catalogue/nhcx/tests/provider-uc-01.md b/catalogue/nhcx/tests/provider-uc-01.md new file mode 100644 index 000000000..612721828 --- /dev/null +++ b/catalogue/nhcx/tests/provider-uc-01.md @@ -0,0 +1,119 @@ +--- +id: nhcx.test.provider-uc-01 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Provider sandbox exit use case 1: Get participant list' +summary: >- + Prove that your hospital system can fetch the registered participants of one role, + such as every payer, from the claims exchange. +sources: +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Table 1.1, Use case 1. +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. components.schemas.ParticipantListResponse.' +- url: https://hcxsbx.abdm.gov.in/images/b885e59891fedc7e725c.zip + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-PARTICIPANT SERVICE_APIs Postman Collection.zip + hash: sha256:2d082f244ee41d137a62af82380dcd2d5db9ebbab66824fd54a23c506d4d9a7f + fetched: '2026-09-14' + note: AWS(Sandbox)-PARTICIPANT SERVICE_APIs Postman Collection, row 16 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Participant List request. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, Q2 and Q3; page 6, best practices. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8, Integrator's Journey. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.fetch-participants-list + - nhcx.endpoint.get-session + concepts: + - nhcx.concept.participant-registry + - nhcx.concept.participant-code + flows: + - nhcx.flow.sandbox-onboarding + sandbox: + - nhcx.sandbox.sandbox-exit + - nhcx.sandbox.environments-and-base-urls + tests: + - nhcx.test.provider-uc-04 + - nhcx.test.payer-uc-04 + errors: + - nhcx.error.nhcx-401 + glossary: + - nhcx.glossary.sandbox-exit + - nhcx.glossary.participant-code +--- + +# Provider sandbox exit use case 1: Get participant list + +## In plain words + +This case proves your system can ask [NHCX](../../shared/glossary/nhcx.md) for every participant registered under one role. A provider usually asks for payers, then offers them in its payer picker. + +It is one of the thirteen provider use cases for [sandbox exit](../glossary/sandbox-exit.md). The exchange answers this call itself, so no payer takes part. + +## Before you start + +- Your provider participant exists in the sandbox registry, and you know its [participant code](../glossary/participant-code.md). [Onboard in the sandbox](../flows/sandbox-onboarding.md) gets you there. +- You hold a current session token from [use case 4](provider-uc-04.md). +- Your system can reach `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice` over HTTPS. + +## What happens + +### Run the call + +1. Call [`POST /fetch/participants/list`](../endpoints/fetch-participants-list.md) with a role and a registration date window. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/fetch/participants/list' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -d '{"role": "PAYER", "fromdate": "", "todate": ""}' +``` + +2. Read the `participantdetails` array in the response. +3. Show the returned participants in your system, for example as a payer picker. + +### Demonstrate it + +Sign-off needs people. Book the demos once the steps above pass in your own runs. See [the sandbox exit process](../sandbox/sandbox-exit.md). + +```precondition +human: true +who: your team, with the NHA team +action: Demonstrate this use case in the internal demo, then in the Health Tech Committee (HTC) demo. +how: Email hcx.integration@nha.gov.in to request both demos. +``` + +## How you know it worked + +The pass criterion for this case: + +> Retrieve the list of participants in the registry based on the role + +What you observe: + +- You receive HTTP 200 with a `participantdetails` array. +- Each entry carries `participantcode`, `participantname`, `address` and `state`. +- For `role` `PAYER` with a wide date window, the array is not empty. + +## When it goes wrong + +- **An empty array.** Widen the date window so it covers the registrations you expect. Send values exactly as documented: trim spaces and match case. +- **Every call fails, even with a new token.** You are on the wrong base URL. The participant APIs live under `participanthcxservice`. See [environments and base URLs](../sandbox/environments-and-base-urls.md). +- **HTTP 401 on the call.** The token has expired, or went in without the `Bearer ` prefix. See [NHCX-401](../errors/nhcx-401.md) and fetch a new token. diff --git a/catalogue/nhcx/tests/provider-uc-02.md b/catalogue/nhcx/tests/provider-uc-02.md new file mode 100644 index 000000000..da43d1182 --- /dev/null +++ b/catalogue/nhcx/tests/provider-uc-02.md @@ -0,0 +1,123 @@ +--- +id: nhcx.test.provider-uc-02 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Provider sandbox exit use case 2: Get policy' +summary: >- + Prove that your hospital system can look up the insurance policies a payer has + linked to a patient, before any claim work starts. +sources: +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Table 1.2, Use case 2. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, item 7. +- url: https://hcxsbx.abdm.gov.in/images/53347f5988b0ce5396f1.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_APIs to be called based on scenario.xlsx + hash: sha256:f92a30673d65dd2cc3cf09e2087c624f23f781dc4ca6b5cd8ec1825e224ac108 + fetched: '2026-09-14' + note: NHCX_APIs to be called based on scenario, row 26 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. sheet Scenarios, row 1. +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./participant/get/policies; schema identifiertype.' +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, Q3. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8, Integrator's Journey. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.participant-get-policies + - nhcx.endpoint.participant-link-abha-policy + flows: + - nhcx.flow.policy-link-and-delink + concepts: + - nhcx.concept.policy-linking + - nhcx.concept.participant-code + sandbox: + - nhcx.sandbox.sandbox-exit + tests: + - nhcx.test.provider-uc-04 + - nhcx.test.provider-uc-05 + - nhcx.test.payer-uc-01 + - nhcx.test.payer-uc-02 + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1003 +--- + +# Provider sandbox exit use case 2: Get policy + +## In plain words + +This case proves your system can find a patient's insurance policies. You look them up by the patient's [ABHA](../../shared/glossary/abha.md) number or mobile number, and [NHCX](../../shared/glossary/nhcx.md) answers from its registry. Payers write those links with [payer use case 1](payer-uc-01.md). + +It is one of the thirteen provider use cases for [sandbox exit](../glossary/sandbox-exit.md). Call it right after you register the patient. + +## Before you start + +- Your provider participant exists in the sandbox registry, and you know its [participant code](../glossary/participant-code.md). [Onboard in the sandbox](../flows/sandbox-onboarding.md) gets you there. +- You hold a current session token from [use case 4](provider-uc-04.md). +- You have the ABHA number of a beneficiary whose payer linked it to a policy through [`/participant/link/abha/policy`](../endpoints/participant-link-abha-policy.md). + +## What happens + +### Run the call + +1. Call [`POST /participant/get/policies`](../endpoints/participant-get-policies.md) with the beneficiary's identifier. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/participant/get/policies' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -d '{"identifiertype": "AbhaNumber", "identifiervalue": ""}' +``` + +2. Read the policies in the response. +3. Store the processing ID the response gives for the policy. It is the `x-hcx-recipient_code` for eligibility, preauthorisation and claim requests. Do not use the payer ID for this. + +### Demonstrate it + +Sign-off needs people. Book the demos once the steps above pass in your own runs. See [the sandbox exit process](../sandbox/sandbox-exit.md). + +```precondition +human: true +who: your team, with the NHA team +action: Demonstrate this use case in the internal demo, then in the Health Tech Committee (HTC) demo. +how: Email hcx.integration@nha.gov.in to request both demos. +``` + +## How you know it worked + +The pass criterion for this case: + +> Get the list of policies for the beneficiary based on the mobile number or ABHA + +What you observe: + +- You receive HTTP 200 listing the policies linked to that beneficiary. +- The payer that made the link appears in the result. +- Your system stores the processing ID, ready for [use case 5](provider-uc-05.md). + +## When it goes wrong + +- **No policies come back.** No payer has linked a policy to that ABHA number. Confirm the number matches the one the payer linked. +- **Later requests fail with [NHCX-1003](../errors/nhcx-1003.md).** Your system addressed the payer ID. Address the processing ID from this response instead. +- **HTTP 401 on the call.** The token has expired, or went in without the `Bearer ` prefix. See [NHCX-401](../errors/nhcx-401.md) and fetch a new token. diff --git a/catalogue/nhcx/tests/provider-uc-03.md b/catalogue/nhcx/tests/provider-uc-03.md new file mode 100644 index 000000000..58a5f86cf --- /dev/null +++ b/catalogue/nhcx/tests/provider-uc-03.md @@ -0,0 +1,127 @@ +--- +id: nhcx.test.provider-uc-03 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Provider sandbox exit use case 3: Get public key' +summary: >- + Prove that your hospital system can fetch the public certificate of the organisation + it is about to send a sealed message to. +sources: +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Table 1.3, Use case 3. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 3.3 Certificate Fetch; Section 2.4. +- url: https://hcxsbx.abdm.gov.in/images/819467ec15aff13cc2a8.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Dummy Payer Implementation.pdf + hash: sha256:97335ebc4cd32c86e0c34328b2f4c526420b32a7a009208364043d6334e9e757 + fetched: '2026-09-14' + note: NHCX Dummy Payer Implementation, row 19 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1. +- url: https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json + hash: sha256:6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63 + fetched: '2026-09-14' + note: 'API specification: participanthcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./fetch/certs.' +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, Q3. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8, Integrator's Journey. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.fetch-certs + concepts: + - nhcx.concept.encryption-certificate + - nhcx.concept.jwe-envelope + flows: + - nhcx.flow.send-a-sealed-request + sandbox: + - nhcx.sandbox.sandbox-exit + - nhcx.sandbox.dummy-payer + tests: + - nhcx.test.provider-uc-04 + - nhcx.test.provider-uc-05 + - nhcx.test.payer-uc-05 + troubleshooting: + - nhcx.troubleshooting.recipient-cannot-decrypt + errors: + - nhcx.error.nhcx-401 + - nhcx.error.payr-1001 + glossary: + - nhcx.glossary.jwe + - nhcx.glossary.x509-certificate +--- + +# Provider sandbox exit use case 3: Get public key + +## In plain words + +Every payload you send through [NHCX](../../shared/glossary/nhcx.md) is sealed for one recipient, as a [JWE](../glossary/jwe.md). You seal it with that recipient's public key. This case proves your system can fetch the key from the registry, given the recipient's [participant code](../glossary/participant-code.md). + +It is one of the thirteen provider use cases for [sandbox exit](../glossary/sandbox-exit.md). + +## Before you start + +- Your provider participant exists in the sandbox registry, and you know its [participant code](../glossary/participant-code.md). [Onboard in the sandbox](../flows/sandbox-onboarding.md) gets you there. +- You hold a current session token from [use case 4](provider-uc-04.md). +- You know the recipient's participant code. With no payer partner, use the sandbox dummy payer, `1000003538@hcx`. See [the dummy payer](../sandbox/dummy-payer.md). + +## What happens + +### Run the call + +1. Call [`POST /fetch/certs`](../endpoints/fetch-certs.md). `participantid` is mandatory. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/fetch/certs' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -d '{"participantid": "1000003538@hcx"}' +``` + +2. Load the returned string as a public key. Try it as an [X.509 certificate](../glossary/x509-certificate.md) first. If that fails, parse it as a SubjectPublicKeyInfo (SPKI) key. +3. Cache the key for 24 hours, keyed by participant code. + +### Demonstrate it + +Sign-off needs people. Book the demos once the steps above pass in your own runs. See [the sandbox exit process](../sandbox/sandbox-exit.md). + +```precondition +human: true +who: your team, with the NHA team +action: Demonstrate this use case in the internal demo, then in the Health Tech Committee (HTC) demo. +how: Email hcx.integration@nha.gov.in to request both demos. +``` + +## How you know it worked + +The pass criterion for this case: + +> Retrieve the public key of the receiver, that is to be used to encrypt the payload for the receiver. participant id must be mandatorily provided in the request. + +What you observe: + +- You receive HTTP 200 with a string holding a PEM X.509 certificate or an SPKI public key. +- Your system loads it as an RSA public key without error. +- A request you seal with it is opened by the recipient. [Use case 5](provider-uc-05.md) proves this: no decryption `ProtocolResponse` comes back. + +## When it goes wrong + +- **The call is refused or the body is empty.** `participantid` is missing or misspelt. Send the exact participant code, including its suffix. +- **The recipient cannot decrypt your message.** You sealed with a stale or wrong key. See [PAYR-1001](../errors/payr-1001.md) and [the recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). Fetch the key again when the recipient rotates its certificate. +- **HTTP 401 on the call.** The token has expired, or went in without the `Bearer ` prefix. See [NHCX-401](../errors/nhcx-401.md) and fetch a new token. diff --git a/catalogue/nhcx/tests/provider-uc-04.md b/catalogue/nhcx/tests/provider-uc-04.md new file mode 100644 index 000000000..9eb7decc3 --- /dev/null +++ b/catalogue/nhcx/tests/provider-uc-04.md @@ -0,0 +1,115 @@ +--- +id: nhcx.test.provider-uc-04 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Provider sandbox exit use case 4: Get the auth token' +summary: >- + Prove that your hospital system can obtain, and keep fresh, the access token every + call to the claims exchange must carry. +sources: +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Table 1.4, Use case 4. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 3.1 Token Request; Section 2.3. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, Q3; page 5, Q20. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2, items 6 and 9. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8, Integrator's Journey. +verified: + status: unverified +related: + endpoints: + - nhcx.endpoint.get-session + - nhcx.endpoint.session-token + - nhcx.endpoint.fetch-participants-list + decisions: + - nhcx.decision.session-endpoint + concepts: + - nhcx.concept.session-token + sandbox: + - nhcx.sandbox.sandbox-exit + - nhcx.sandbox.prerequisites + tests: + - nhcx.test.provider-uc-01 + - nhcx.test.payer-uc-06 + troubleshooting: + - nhcx.troubleshooting.everything-returns-401 + errors: + - nhcx.error.nhcx-401 +--- + +# Provider sandbox exit use case 4: Get the auth token + +## In plain words + +Every call to [NHCX](../../shared/glossary/nhcx.md) carries an access token. This case proves your system can obtain one with its client credentials and replace it before it expires. + +It is one of the thirteen provider use cases for [sandbox exit](../glossary/sandbox-exit.md). The exchange issues the token; no payer takes part. + +## Before you start + +- You hold your sandbox client id and client secret. [Sandbox prerequisites](../sandbox/prerequisites.md) covers how you get them. +- You know which token endpoint to call. See [which session token endpoint to call](../decisions/session-endpoint.md). + +## What happens + +### Run the call + +1. Call [`POST /get/session`](../endpoints/get-session.md) with a form-encoded body: + +```text +client_id=&client_secret=&grant_type=client_credentials +``` + +2. Read `access_token` and `expires_in` from the response. +3. Send the token on every later call. Participant service calls take it as `bearer_auth: Bearer `. Exchange calls take the same value on both `bearer_auth` and `Authorization`. +4. Schedule a refresh before `expires_in` runs out. Do not wait for a 401. +5. Prove the token works: run [use case 1](provider-uc-01.md) with it. + +### Demonstrate it + +Sign-off needs people. Book the demos once the steps above pass in your own runs. See [the sandbox exit process](../sandbox/sandbox-exit.md). + +```precondition +human: true +who: your team, with the NHA team +action: Demonstrate this use case in the internal demo, then in the Health Tech Committee (HTC) demo. +how: Email hcx.integration@nha.gov.in to request both demos. +``` + +## How you know it worked + +The pass criterion for this case: + +> To generate the token to authenticate NHCX API calls + +What you observe: + +- You receive HTTP 200 with `access_token`, `expires_in` and `token_type` `Bearer`. +- A call to `/fetch/participants/list` with the token returns HTTP 200, not 401. +- Your system replaces the token before it expires, with no manual step. + +## When it goes wrong + +- **The token call itself fails.** The client id or secret is wrong, or belongs to another environment. Use your sandbox credentials. +- **Later calls return 401 after a while.** The token expired. The message `Sender is not authorized to execute the operation` means the same. See [NHCX-401](../errors/nhcx-401.md). +- **Later calls return 401 at once.** The token went in without the `Bearer ` prefix, or in the wrong header. See [every NHCX call returns 401](../troubleshooting/everything-returns-401.md). diff --git a/catalogue/nhcx/tests/provider-uc-05.md b/catalogue/nhcx/tests/provider-uc-05.md new file mode 100644 index 000000000..9a816d78f --- /dev/null +++ b/catalogue/nhcx/tests/provider-uc-05.md @@ -0,0 +1,175 @@ +--- +id: nhcx.test.provider-uc-05 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Provider sandbox exit use case 5: Check the coverage eligibility' +summary: >- + Prove that your hospital system can ask a payer through the claims exchange whether + a patient's cover is in force, and handle both kinds of answer. +sources: +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2, Tables 1.5 and 2.1, Use case 5. +- url: https://hcxsbx.abdm.gov.in/images/819467ec15aff13cc2a8.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Dummy Payer Implementation.pdf + hash: sha256:97335ebc4cd32c86e0c34328b2f4c526420b32a7a009208364043d6334e9e757 + fetched: '2026-09-14' + note: NHCX Dummy Payer Implementation, row 19 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, items 7 and 8. +- url: https://hcxsbx.abdm.gov.in/coverageeligibilityhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/coverageeligibilityhcxservice.json + hash: sha256:1723a4020b1b33d0bc1d7175609f0d05e6a6a78e8b4c52041222396639ceb52c + fetched: '2026-09-14' + note: 'API specification: coverageeligibilityhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/coverageeligibility/check.' +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 4-6, Q14 and Q21. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Error scenario. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8, Integrator's Journey. +verified: + status: unverified +related: + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.four-message-legs + - nhcx.concept.coverage-eligibility-purposes + sandbox: + - nhcx.sandbox.sandbox-exit + - nhcx.sandbox.dummy-payer + - nhcx.sandbox.callback-url-requirements + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback + - nhcx.troubleshooting.recipient-cannot-decrypt + - nhcx.troubleshooting.bundle-rejected + flows: + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.send-a-sealed-request + - nhcx.flow.receive-a-sealed-callback + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.get-session + callbacks: + - nhcx.callback.coverageeligibility-on-check + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.coverage-eligibility-response + - nhcx.fhir.validation + tests: + - nhcx.test.provider-uc-02 + - nhcx.test.provider-uc-03 + - nhcx.test.provider-uc-13 + - nhcx.test.payer-uc-07 + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1003 + - nhcx.error.nhcx-1005 + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1001 + - nhcx.error.payr-1049 +--- + +# Provider sandbox exit use case 5: Check the coverage eligibility + +## In plain words + +This case proves your system can ask a [payer](../glossary/payer.md) whether a patient's cover is in force, through [NHCX](../../shared/glossary/nhcx.md). The answer comes back later, on a callback your system hosts. + +Your callback must handle two forms of answer. A sealed result arrives when the payer processed the request. A `ProtocolResponse` arrives when it could not. + +## Before you start + +- Your provider participant exists in the sandbox registry, and you know its [participant code](../glossary/participant-code.md). [Onboard in the sandbox](../flows/sandbox-onboarding.md) gets you there. +- You hold a current session token from [use case 4](provider-uc-04.md). +- You hold the recipient's public certificate from [use case 3](provider-uc-03.md), and your own private key. +- Your registered endpoint URL takes HTTPS calls from the exchange. See [callback URL requirements](../sandbox/callback-url-requirements.md). +- The recipient is the sandbox dummy payer, participant code `1000003538@hcx`, unless a payer partner answers for you. See [the dummy payer](../sandbox/dummy-payer.md). +- You have the patient's policy and the payer's processing ID from [use case 2](provider-uc-02.md). + +## What happens + +### Send the request + +1. Build a coverage eligibility request bundle for the patient, as a [FHIR](../../shared/glossary/fhir.md) collection. See [the coverage eligibility request bundle](../fhir/coverage-eligibility-request.md). Validate it against the [NRCeS](../../shared/glossary/nrces.md) profiles, as [validating a bundle](../fhir/validation.md) describes. +2. Seal it as a [JWE](../glossary/jwe.md) with the recipient's public key. [Send a sealed request](../flows/send-a-sealed-request.md) walks through the envelope. +3. Set the protected headers. `x-hcx-sender_code` is your participant code. `x-hcx-recipient_code` is the payer's processing ID, or `1000003538@hcx` for the dummy payer. `x-hcx-status` is `request.initiated`. Use a new `x-hcx-api_call_id` and a `x-hcx-correlation_id` unique to this request cycle. `x-hcx-ben-abha-id` carries the beneficiary's [ABHA](../../shared/glossary/abha.md) number. +4. Send the sealed payload. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/hcx/v1/coverageeligibility/check' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -H 'Authorization: Bearer ' \ + -d '{"payload": ""}' +``` + +5. NHCX answers with HTTP 202. Store your `x-hcx-api_call_id` against the case. + +### Receive the answer + +1. Wait for `POST /v1/coverageeligibility/on_check` on your registered endpoint. +2. Answer it with HTTP 202 within 30 seconds, with the acceptance body from [receive a sealed callback](../flows/receive-a-sealed-callback.md). +3. Read `type` in the body. `ProtocolResponse` means the payer could not process your request. Read `x-hcx-error_details` and do not decrypt. +4. Any other `type` carries a sealed `payload`. Decrypt it with your private key and parse the CoverageEligibilityResponse bundle. +5. Validate the decrypted bundle against the NRCeS profiles. + +### Demonstrate it + +Sign-off needs people. Book the demos once the steps above pass in your own runs. See [the sandbox exit process](../sandbox/sandbox-exit.md). + +```precondition +human: true +who: your team, with the NHA team +action: Demonstrate this use case in the internal demo, then in the Health Tech Committee (HTC) demo. +how: Email hcx.integration@nha.gov.in to request both demos. +also: Send the FHIR bundles you used to hcx.integration@nha.gov.in for validation by the NRCeS team. +``` + +## How you know it worked + +The pass criterion for this case: + +> To check the eligibility of a beneficiary with the payers via NHCX. +> +> Callback API should be implemented by provider systems. It should accept the payload in two forms and it will be derived based on “type” param of the response. +> +> Payload should be validated against the profiles published by NRCES. + +What you observe: + +- NHCX answers your `POST /v1/coverageeligibility/check` with HTTP 202. +- You receive `POST /v1/coverageeligibility/on_check` on your registered endpoint. +- Its `x-hcx-correlation_id` equals the `x-hcx-api_call_id` of your request. Its `x-hcx-recipient_code` is your participant code. +- Your endpoint answers it with HTTP 202 within 30 seconds. +- For a sealed answer, the decrypted payload is a CoverageEligibilityResponse bundle that validates against the NRCeS profiles. +- For a `ProtocolResponse`, your system shows the code and message from `x-hcx-error_details` and does not try to decrypt. + +## When it goes wrong + +- **The callback never arrives.** Your callback URL must use a domain name, not an IP address or port. It must run on an India-hosted server that allows the exchange's outbound addresses. See [callback URL requirements](../sandbox/callback-url-requirements.md) and [accepted, then no callback](../troubleshooting/accepted-then-no-callback.md). Then ask where the request stands with [use case 13](provider-uc-13.md). +- **HTTP 401 on the call.** The token has expired, or went in without the `Bearer ` prefix. See [NHCX-401](../errors/nhcx-401.md) and fetch a new token. +- **[NHCX-1003](../errors/nhcx-1003.md), receiver not registered.** `x-hcx-recipient_code` is wrong. Address the processing ID from [use case 2](provider-uc-02.md), not the payer ID. +- **[NHCX-1006](../errors/nhcx-1006.md), duplicate request.** You reused a correlation id. A failed request makes its correlation id inactive, so start the next cycle with a new one. +- **A `ProtocolResponse` says the payer cannot decrypt.** You sealed with a stale or wrong certificate. See [PAYR-1001](../errors/payr-1001.md) and [the recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). +- **A `ProtocolResponse` rejects the bundle.** See [PAYR-1049](../errors/payr-1049.md) and [the payer rejects your bundle](../troubleshooting/bundle-rejected.md). Validate against the NRCeS profiles before you send. +- **The exchange keeps redelivering the same message.** Your endpoint did not return HTTP 202 with the acceptance body within 30 seconds. The exchange retries five times, then deletes the request. See [retries and expiry](../concepts/retries-and-expiry.md). diff --git a/catalogue/nhcx/tests/provider-uc-06.md b/catalogue/nhcx/tests/provider-uc-06.md new file mode 100644 index 000000000..4ce232981 --- /dev/null +++ b/catalogue/nhcx/tests/provider-uc-06.md @@ -0,0 +1,176 @@ +--- +id: nhcx.test.provider-uc-06 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Provider sandbox exit use case 6: Request insurance plan details' +summary: >- + Prove that your hospital system can request a payer's plan for a policy through + the claims exchange, and handle both kinds of answer. +sources: +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 2-3, Tables 2.2 and 3.1, Use case 6. +- url: https://hcxsbx.abdm.gov.in/images/819467ec15aff13cc2a8.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Dummy Payer Implementation.pdf + hash: sha256:97335ebc4cd32c86e0c34328b2f4c526420b32a7a009208364043d6334e9e757 + fetched: '2026-09-14' + note: NHCX Dummy Payer Implementation, row 19 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Insurance Plan. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Insurance Plan. +- url: https://hcxsbx.abdm.gov.in/insuranceplanhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/insuranceplanhcxservice.json + hash: sha256:03665c6e6a5c8d86e3d621ab577dd683cf13c155d5b9529f5be6ca70fef13dee + fetched: '2026-09-14' + note: 'API specification: insuranceplanhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/insuranceplan/request.' +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, item 7. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 4-6, Q14 and Q21. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8, Integrator's Journey. +verified: + status: unverified +related: + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.four-message-legs + - nhcx.concept.insurance-plan + sandbox: + - nhcx.sandbox.sandbox-exit + - nhcx.sandbox.dummy-payer + - nhcx.sandbox.callback-url-requirements + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback + - nhcx.troubleshooting.recipient-cannot-decrypt + - nhcx.troubleshooting.bundle-rejected + flows: + - nhcx.flow.insurance-plan-request + - nhcx.flow.send-a-sealed-request + - nhcx.flow.receive-a-sealed-callback + endpoints: + - nhcx.endpoint.insuranceplan-request + - nhcx.endpoint.fetch-certs + callbacks: + - nhcx.callback.insuranceplan-on-request + fhir: + - nhcx.fhir.insurance-plan-bundle + - nhcx.fhir.task + - nhcx.fhir.validation + tests: + - nhcx.test.provider-uc-03 + - nhcx.test.provider-uc-13 + - nhcx.test.payer-uc-08 + - nhcx.test.tc-hbp-01 + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1003 + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1001 + - nhcx.error.payr-1049 + - nhcx.error.payr-1402 + - nhcx.error.payr-1405 + - nhcx.error.payr-1406 +--- + +# Provider sandbox exit use case 6: Request insurance plan details + +## In plain words + +The insurance plan tells your hospital what a policy covers, under which conditions, and with which documents. This case proves your system can request it from a payer through [NHCX](../../shared/glossary/nhcx.md). + +The plan arrives later on your callback, sealed. A `ProtocolResponse` arrives instead when the payer could not process the request. + +## Before you start + +- Your provider participant exists in the sandbox registry, and you know its [participant code](../glossary/participant-code.md). [Onboard in the sandbox](../flows/sandbox-onboarding.md) gets you there. +- You hold a current session token from [use case 4](provider-uc-04.md). +- You hold the recipient's public certificate from [use case 3](provider-uc-03.md), and your own private key. +- Your registered endpoint URL takes HTTPS calls from the exchange. See [callback URL requirements](../sandbox/callback-url-requirements.md). +- The recipient is the sandbox dummy payer, participant code `1000003538@hcx`, unless a payer partner answers for you. See [the dummy payer](../sandbox/dummy-payer.md). +- With the dummy payer, put provider id `32722` inside the bundle and use policy number `100217`. These values work only with the dummy payer. + +## What happens + +### Send the request + +1. Build a Task bundle whose Task has `code` `poll` and a policy number input, with your provider id as an optional input. See [insurance plan bundles](../fhir/insurance-plan-bundle.md). Validate it against the [NRCeS](../../shared/glossary/nrces.md) profiles, as [validating a bundle](../fhir/validation.md) describes. +2. Seal it as a [JWE](../glossary/jwe.md) with the recipient's public key. [Send a sealed request](../flows/send-a-sealed-request.md) walks through the envelope. +3. Set the protected headers. `x-hcx-sender_code` is your participant code. `x-hcx-recipient_code` is the payer's processing ID, or `1000003538@hcx` for the dummy payer. `x-hcx-status` is `request.initiated`. Use a new `x-hcx-api_call_id` and a `x-hcx-correlation_id` unique to this request cycle. `x-hcx-ben-abha-id` carries the beneficiary's [ABHA](../../shared/glossary/abha.md) number. +4. Send the sealed payload. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/hcx/v1/insuranceplan/request' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -H 'Authorization: Bearer ' \ + -d '{"payload": ""}' +``` + +5. NHCX answers with HTTP 202. Store your `x-hcx-api_call_id` against the case. + +### Receive the answer + +1. Wait for `POST /v1/insuranceplan/on_request` on your registered endpoint. +2. Answer it with HTTP 202 within 30 seconds, with the acceptance body from [receive a sealed callback](../flows/receive-a-sealed-callback.md). +3. Read `type` in the body. `ProtocolResponse` means the payer could not process your request. Read `x-hcx-error_details` and do not decrypt. +4. Any other `type` carries a sealed `payload`. Decrypt it with your private key and parse the InsurancePlan bundle. +5. Validate the decrypted bundle against the NRCeS profiles. + +### Demonstrate it + +Sign-off needs people. Book the demos once the steps above pass in your own runs. See [the sandbox exit process](../sandbox/sandbox-exit.md). + +```precondition +human: true +who: your team, with the NHA team +action: Demonstrate this use case in the internal demo, then in the Health Tech Committee (HTC) demo. +how: Email hcx.integration@nha.gov.in to request both demos. +also: Send the FHIR bundles you used to hcx.integration@nha.gov.in for validation by the NRCeS team. +``` + +## How you know it worked + +The pass criterion for this case: + +> Request insurance plan details from the Payer via HCX +> +> Callback API should be implemented by provider systems. It should accept the payload in two forms, and it will be derived based on “type” param of the response. +> +> Payload should be validated against the profiles published by NRCES. + +What you observe: + +- NHCX answers your `POST /v1/insuranceplan/request` with HTTP 202. +- You receive `POST /v1/insuranceplan/on_request` on your registered endpoint. +- Its `x-hcx-correlation_id` equals the `x-hcx-api_call_id` of your request. Its `x-hcx-recipient_code` is your participant code. +- Your endpoint answers it with HTTP 202 within 30 seconds. +- For a sealed answer, the decrypted payload is a bundle holding InsurancePlan resources that validates against the NRCeS profiles. +- For a `ProtocolResponse`, your system shows the code and message from `x-hcx-error_details` and does not try to decrypt. + +## When it goes wrong + +- **The payer says the policy or hospital is unknown.** See [PAYR-1402](../errors/payr-1402.md) and [PAYR-1405](../errors/payr-1405.md). With the dummy payer, use provider id `32722` and policy number `100217`. +- **[PAYR-1406](../errors/payr-1406.md), a request is already in progress.** Wait for the first answer before you ask again. +- **The callback never arrives.** Your callback URL must use a domain name, not an IP address or port. It must run on an India-hosted server that allows the exchange's outbound addresses. See [callback URL requirements](../sandbox/callback-url-requirements.md) and [accepted, then no callback](../troubleshooting/accepted-then-no-callback.md). Then ask where the request stands with [use case 13](provider-uc-13.md). +- **HTTP 401 on the call.** The token has expired, or went in without the `Bearer ` prefix. See [NHCX-401](../errors/nhcx-401.md) and fetch a new token. +- **[NHCX-1003](../errors/nhcx-1003.md), receiver not registered.** `x-hcx-recipient_code` is wrong. Address the processing ID from [use case 2](provider-uc-02.md), not the payer ID. +- **A `ProtocolResponse` says the payer cannot decrypt.** You sealed with a stale or wrong certificate. See [PAYR-1001](../errors/payr-1001.md) and [the recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). +- **A `ProtocolResponse` rejects the bundle.** See [PAYR-1049](../errors/payr-1049.md) and [the payer rejects your bundle](../troubleshooting/bundle-rejected.md). Validate against the NRCeS profiles before you send. diff --git a/catalogue/nhcx/tests/provider-uc-07.md b/catalogue/nhcx/tests/provider-uc-07.md new file mode 100644 index 000000000..6aec7487f --- /dev/null +++ b/catalogue/nhcx/tests/provider-uc-07.md @@ -0,0 +1,197 @@ +--- +id: nhcx.test.provider-uc-07 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Provider sandbox exit use case 7: Preauthorization submission' +summary: >- + Prove that your hospital system can send a preauthorisation to a payer through + the claims exchange, and handle both kinds of answer. +sources: +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 3-4, Tables 3.2 and 4.1, Use case 7. +- url: https://hcxsbx.abdm.gov.in/images/819467ec15aff13cc2a8.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Dummy Payer Implementation.pdf + hash: sha256:97335ebc4cd32c86e0c34328b2f4c526420b32a7a009208364043d6334e9e757 + fetched: '2026-09-14' + note: NHCX Dummy Payer Implementation, row 19 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-3, Preauth and Test Usecase Action API. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Preauth. +- url: https://hcxsbx.abdm.gov.in/preauthhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/preauthhcxservice.json + hash: sha256:2e8c594c51d9640ae4a576be34a5d190614918d1e7697d6718bc91c31fa66948 + fetched: '2026-09-14' + note: 'API specification: preauthhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/preauth/submit.' +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, items 7 and 8. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 4-6, Q14 and Q21. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Error scenario. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8, Integrator's Journey. +verified: + status: unverified +related: + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.four-message-legs + - nhcx.concept.claim-cycle + sandbox: + - nhcx.sandbox.sandbox-exit + - nhcx.sandbox.dummy-payer + - nhcx.sandbox.callback-url-requirements + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback + - nhcx.troubleshooting.recipient-cannot-decrypt + - nhcx.troubleshooting.bundle-rejected + flows: + - nhcx.flow.preauth-submit + - nhcx.flow.send-a-sealed-request + - nhcx.flow.receive-a-sealed-callback + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.dummy-payer-process-request + - nhcx.endpoint.fetch-certs + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.preauth-response + - nhcx.fhir.validation + tests: + - nhcx.test.provider-uc-05 + - nhcx.test.provider-uc-08 + - nhcx.test.provider-uc-13 + - nhcx.test.payer-uc-09 + - nhcx.test.tc-pa-01 + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1003 + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1001 + - nhcx.error.payr-1049 + glossary: + - nhcx.glossary.preauthorisation +--- + +# Provider sandbox exit use case 7: Preauthorization submission + +## In plain words + +A [preauthorisation](../glossary/preauthorisation.md) asks the payer to approve treatment before it happens. This case proves your system can submit one through [NHCX](../../shared/glossary/nhcx.md) and read the payer's decision. + +The decision arrives later on your callback, sealed. A `ProtocolResponse` arrives instead when the payer could not process the request. + +## Before you start + +- Your provider participant exists in the sandbox registry, and you know its [participant code](../glossary/participant-code.md). [Onboard in the sandbox](../flows/sandbox-onboarding.md) gets you there. +- You hold a current session token from [use case 4](provider-uc-04.md). +- You hold the recipient's public certificate from [use case 3](provider-uc-03.md), and your own private key. +- Your registered endpoint URL takes HTTPS calls from the exchange. See [callback URL requirements](../sandbox/callback-url-requirements.md). +- The recipient is the sandbox dummy payer, participant code `1000003538@hcx`, unless a payer partner answers for you. See [the dummy payer](../sandbox/dummy-payer.md). +- The patient's coverage eligibility check passed in [use case 5](provider-uc-05.md). + +## What happens + +### Send the request + +1. Build a Claim bundle with `use` `preauthorization`. See [the preauthorisation request bundle](../fhir/preauth-request.md). Validate it against the [NRCeS](../../shared/glossary/nrces.md) profiles, as [validating a bundle](../fhir/validation.md) describes. +2. Seal it as a [JWE](../glossary/jwe.md) with the recipient's public key. [Send a sealed request](../flows/send-a-sealed-request.md) walks through the envelope. +3. Set the protected headers. `x-hcx-sender_code` is your participant code. `x-hcx-recipient_code` is the payer's processing ID, or `1000003538@hcx` for the dummy payer. `x-hcx-status` is `request.initiated`. Use a new `x-hcx-api_call_id` and a `x-hcx-correlation_id` unique to this request cycle. `x-hcx-ben-abha-id` carries the beneficiary's [ABHA](../../shared/glossary/abha.md) number. +4. Send the sealed payload. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/hcx/v1/preauth/submit' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -H 'Authorization: Bearer ' \ + -d '{"payload": ""}' +``` + +5. NHCX answers with HTTP 202. Store your `x-hcx-api_call_id` against the case. + +### Make the dummy payer answer + +The dummy payer answers a preauth only when you tell it how. Call its test action API with the correlation id of your request. `action` is `Approve`, `Reject` or `Query`. See [dummy payer, act on a request](../endpoints/dummy-payer-process-request.md). + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/dummyhcxpayer/process/request' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -H 'Authorization: Bearer ' \ + -d '{"action": "Approve", "method": "Preauth", "correlationId": ""}' +``` + +### Receive the answer + +1. Wait for `POST /v1/preauth/on_submit` on your registered endpoint. +2. Answer it with HTTP 202 within 30 seconds, with the acceptance body from [receive a sealed callback](../flows/receive-a-sealed-callback.md). +3. Read `type` in the body. `ProtocolResponse` means the payer could not process your request. Read `x-hcx-error_details` and do not decrypt. +4. Any other `type` carries a sealed `payload`. Decrypt it with your private key and parse the ClaimResponse bundle. +5. Validate the decrypted bundle against the NRCeS profiles. + +### Demonstrate it + +Sign-off needs people. Book the demos once the steps above pass in your own runs. See [the sandbox exit process](../sandbox/sandbox-exit.md). + +```precondition +human: true +who: your team, with the NHA team +action: Demonstrate this use case in the internal demo, then in the Health Tech Committee (HTC) demo. +how: Email hcx.integration@nha.gov.in to request both demos. +also: Send the FHIR bundles you used to hcx.integration@nha.gov.in for validation by the NRCeS team. +``` + +## How you know it worked + +The pass criterion for this case: + +> Submit the Preauthorization request from the Provider end. +> +> Callback API should be implemented by provider systems. It should accept the payload in two forms, and it will be derived based on “type” param of the response. +> +> Payload should be validated against the profiles published by NRCES. + +What you observe: + +- NHCX answers your `POST /v1/preauth/submit` with HTTP 202. +- You receive `POST /v1/preauth/on_submit` on your registered endpoint. +- Its `x-hcx-correlation_id` equals the `x-hcx-api_call_id` of your request. Its `x-hcx-recipient_code` is your participant code. +- Your endpoint answers it with HTTP 202 within 30 seconds. +- For a sealed answer, the decrypted payload is a ClaimResponse bundle that validates against the NRCeS profiles. +- For a `ProtocolResponse`, your system shows the code and message from `x-hcx-error_details` and does not try to decrypt. +- With the dummy payer, the decision matches the `action` you sent to `/process/request`. + +## When it goes wrong + +- **Nothing arrives from the dummy payer.** It waits for your `/process/request` call. Send it with the correlation id of your preauthorisation. +- **The callback never arrives.** Your callback URL must use a domain name, not an IP address or port. It must run on an India-hosted server that allows the exchange's outbound addresses. See [callback URL requirements](../sandbox/callback-url-requirements.md) and [accepted, then no callback](../troubleshooting/accepted-then-no-callback.md). Then ask where the request stands with [use case 13](provider-uc-13.md). +- **HTTP 401 on the call.** The token has expired, or went in without the `Bearer ` prefix. See [NHCX-401](../errors/nhcx-401.md) and fetch a new token. +- **[NHCX-1003](../errors/nhcx-1003.md), receiver not registered.** `x-hcx-recipient_code` is wrong. Address the processing ID from [use case 2](provider-uc-02.md), not the payer ID. +- **[NHCX-1006](../errors/nhcx-1006.md), duplicate request.** You reused a correlation id. A failed request makes its correlation id inactive, so start the next cycle with a new one. +- **A `ProtocolResponse` says the payer cannot decrypt.** You sealed with a stale or wrong certificate. See [PAYR-1001](../errors/payr-1001.md) and [the recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). +- **A `ProtocolResponse` rejects the bundle.** See [PAYR-1049](../errors/payr-1049.md) and [the payer rejects your bundle](../troubleshooting/bundle-rejected.md). Validate against the NRCeS profiles before you send. +- **The exchange keeps redelivering the same message.** Your endpoint did not return HTTP 202 with the acceptance body within 30 seconds. The exchange retries five times, then deletes the request. See [retries and expiry](../concepts/retries-and-expiry.md). diff --git a/catalogue/nhcx/tests/provider-uc-08.md b/catalogue/nhcx/tests/provider-uc-08.md new file mode 100644 index 000000000..533ab8fa1 --- /dev/null +++ b/catalogue/nhcx/tests/provider-uc-08.md @@ -0,0 +1,185 @@ +--- +id: nhcx.test.provider-uc-08 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Provider sandbox exit use case 8: Respond to communication request received + from payer for additional documents' +summary: >- + Prove that your hospital system can receive a payer's request for more documents + and send the documents back through the claims exchange. +sources: +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 4, Table 4.2, Use case 8. +- url: https://hcxsbx.abdm.gov.in/images/819467ec15aff13cc2a8.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Dummy Payer Implementation.pdf + hash: sha256:97335ebc4cd32c86e0c34328b2f4c526420b32a7a009208364043d6334e9e757 + fetched: '2026-09-14' + note: NHCX Dummy Payer Implementation, row 19 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2, Preauth steps 2-5 and Communication. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Communication (additional docs). +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. page 6, Query flow and Table 6.2. +- url: https://hcxsbx.abdm.gov.in/communicationhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/communicationhcxservice.json + hash: sha256:0ad58a98851158057d38d42a8327349548644c1b2f1a33b4f94acb4c1840a8a4 + fetched: '2026-09-14' + note: 'API specification: communicationhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/communication/on_request.' +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2, Error scenario and Protocol Response. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 4, Q14. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8, Integrator's Journey. +verified: + status: unverified +related: + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.four-message-legs + - nhcx.concept.queries-and-communication + - nhcx.concept.message-identifiers + sandbox: + - nhcx.sandbox.sandbox-exit + - nhcx.sandbox.dummy-payer + - nhcx.sandbox.callback-url-requirements + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback + - nhcx.troubleshooting.recipient-cannot-decrypt + - nhcx.troubleshooting.bundle-rejected + flows: + - nhcx.flow.preauth-query-response + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.send-a-sealed-request + endpoints: + - nhcx.endpoint.communication-on-request + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.dummy-payer-process-request + callbacks: + - nhcx.callback.communication-request + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.task + - nhcx.fhir.validation + tests: + - nhcx.test.provider-uc-07 + - nhcx.test.payer-uc-10 + errors: + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1003 + - nhcx.error.payr-1039 + - nhcx.error.payr-1520 + glossary: + - nhcx.glossary.communication-request +--- + +# Provider sandbox exit use case 8: Respond to communication request received from payer for additional documents + +## In plain words + +A payer can pause a preauthorisation or a claim and ask your hospital for more documents. The request arrives on your endpoint as a [communication request](../glossary/communication-request.md), through [NHCX](../../shared/glossary/nhcx.md). This case proves your system receives it and sends the documents back. + +Here the payer starts the exchange. Your system answers it. + +## Before you start + +- Your provider participant exists in the sandbox registry, and you know its [participant code](../glossary/participant-code.md). [Onboard in the sandbox](../flows/sandbox-onboarding.md) gets you there. +- You hold a current session token from [use case 4](provider-uc-04.md). +- You hold the recipient's public certificate from [use case 3](provider-uc-03.md), and your own private key. +- Your registered endpoint URL takes HTTPS calls from the exchange. See [callback URL requirements](../sandbox/callback-url-requirements.md). +- The recipient is the sandbox dummy payer, participant code `1000003538@hcx`, unless a payer partner answers for you. See [the dummy payer](../sandbox/dummy-payer.md). +- You can submit a preauthorisation, as in [use case 7](provider-uc-07.md). +- You have the documents to send, ready to attach. + +## What happens + +### Get a query from the dummy payer + +1. Submit a preauthorisation to `1000003538@hcx`, as in [use case 7](provider-uc-07.md). +2. Call the dummy payer's `/process/request` with `action` `Query`, `method` `Preauth` and your correlation id. See [dummy payer, act on a request](../endpoints/dummy-payer-process-request.md). + +### Receive the communication request + +1. Wait for `POST /v1/communication/request` on your registered endpoint. +2. Answer it with HTTP 202 within 30 seconds, with the acceptance body from [receive a sealed callback](../flows/receive-a-sealed-callback.md). +3. Decrypt the payload. The Task bundle carries a CommunicationRequest naming what the payer wants. + +### Send the documents + +1. Build a Task bundle with a Communication as its input. Put each document in the Communication's `payload.contentAttachment`. Validate it against the [NRCeS](../../shared/glossary/nrces.md) profiles. +2. Seal it with the payer's public key. +3. Set the protected headers. Use a new `x-hcx-api_call_id`. Set `x-hcx-correlation_id` to the `x-hcx-api_call_id` of the communication request. Set `x-hcx-recipient_code` to its `x-hcx-sender_code`, and `x-hcx-status` to `response.complete`. +4. Send it to [`/v1/communication/on_request`](../endpoints/communication-on-request.md). + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/hcx/v1/communication/on_request' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -H 'Authorization: Bearer ' \ + -d '{"type": "JWEPayload", "payload": ""}' +``` + +5. NHCX answers with HTTP 202. +6. Wait for the final decision on `POST /v1/preauth/on_submit`, and answer it with HTTP 202 within 30 seconds. + +### Demonstrate it + +Sign-off needs people. Book the demos once the steps above pass in your own runs. See [the sandbox exit process](../sandbox/sandbox-exit.md). + +```precondition +human: true +who: your team, with the NHA team +action: Demonstrate this use case in the internal demo, then in the Health Tech Committee (HTC) demo. +how: Email hcx.integration@nha.gov.in to request both demos. +also: Send the FHIR bundles you used to hcx.integration@nha.gov.in for validation by the NRCeS team. +``` + +## How you know it worked + +The pass criterion for this case: + +> Respond to the communication Request via NHCX. This API will be called by payers to seek more details of the case submitted by providers for Preauthorization or for Claims. +> +> Encrypted payload of TaskBundle should have Comunication as input. +> +> Payload should be validated against the profiles published by NRCES. + +What you observe: + +- You receive `POST /v1/communication/request` and answer it with HTTP 202 within 30 seconds. +- NHCX answers your `POST /v1/communication/on_request` with HTTP 202. +- No `/v1/error` report arrives for your answer. +- The final decision arrives on `POST /v1/preauth/on_submit` for the same case. + +## When it goes wrong + +- **The communication request never arrives.** Check your registered endpoint against the [callback URL requirements](../sandbox/callback-url-requirements.md). With the dummy payer, confirm you sent `action` `Query`. +- **The payer refuses the documents.** A Communication needs its payload and identifier. See [PAYR-1039](../errors/payr-1039.md) and [PAYR-1520](../errors/payr-1520.md). +- **A [PMJAY](../glossary/pmjay.md) payer never sends one.** PMJAY payers raise queries on the preauthorisation or claim callback, with a workflow id. See [TC-PA-02](tc-pa-02.md). +- **[NHCX-1010](../errors/nhcx-1010.md), no data for the correlation id.** Your message's `x-hcx-correlation_id` is not the `x-hcx-api_call_id` of the request you answer. +- **[NHCX-1011](../errors/nhcx-1011.md), invalid status.** `x-hcx-status` holds a value the exchange does not accept for this message. Use `response.complete` on an answer and `request.initiated` on a request. +- **[NHCX-1003](../errors/nhcx-1003.md), receiver not registered.** `x-hcx-recipient_code` is wrong. Copy it from the `x-hcx-sender_code` of the request you answer. +- **A `/v1/error` report arrives at your endpoint.** The recipient refused your message after the exchange accepted it. Read the details as [receiving /v1/error](../callbacks/error.md) describes. +- **The exchange keeps redelivering the same message.** Your endpoint did not return HTTP 202 with the acceptance body within 30 seconds. The exchange retries five times, then deletes the request. See [retries and expiry](../concepts/retries-and-expiry.md). diff --git a/catalogue/nhcx/tests/provider-uc-09.md b/catalogue/nhcx/tests/provider-uc-09.md new file mode 100644 index 000000000..3e85f3e14 --- /dev/null +++ b/catalogue/nhcx/tests/provider-uc-09.md @@ -0,0 +1,197 @@ +--- +id: nhcx.test.provider-uc-09 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Provider sandbox exit use case 9: Claim submission' +summary: >- + Prove that your hospital system can send a claim to a payer through the claims + exchange, and handle both kinds of answer. +sources: +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 4-5, Tables 4.3 and 5.1, Use case 9. +- url: https://hcxsbx.abdm.gov.in/images/819467ec15aff13cc2a8.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Dummy Payer Implementation.pdf + hash: sha256:97335ebc4cd32c86e0c34328b2f4c526420b32a7a009208364043d6334e9e757 + fetched: '2026-09-14' + note: NHCX Dummy Payer Implementation, row 19 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-3, Claim and Test Usecase Action API. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Claim. +- url: https://hcxsbx.abdm.gov.in/claimhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/claimhcxservice.json + hash: sha256:488eea449c6ee45dc324f4f7c095a862c7d50d0e238075846122b51b2bab4878 + fetched: '2026-09-14' + note: 'API specification: claimhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/claim/submit.' +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, items 7 and 8. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 4-6, Q14 and Q21. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Error scenario. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8, Integrator's Journey. +verified: + status: unverified +related: + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.four-message-legs + - nhcx.concept.claim-cycle + sandbox: + - nhcx.sandbox.sandbox-exit + - nhcx.sandbox.dummy-payer + - nhcx.sandbox.callback-url-requirements + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback + - nhcx.troubleshooting.recipient-cannot-decrypt + - nhcx.troubleshooting.bundle-rejected + flows: + - nhcx.flow.claim-submit + - nhcx.flow.send-a-sealed-request + - nhcx.flow.receive-a-sealed-callback + endpoints: + - nhcx.endpoint.claim-submit + - nhcx.endpoint.dummy-payer-process-request + - nhcx.endpoint.fetch-certs + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + - nhcx.fhir.claim-response + - nhcx.fhir.validation + tests: + - nhcx.test.provider-uc-07 + - nhcx.test.provider-uc-11 + - nhcx.test.provider-uc-13 + - nhcx.test.payer-uc-11 + - nhcx.test.tc-cl-01 + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1003 + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1001 + - nhcx.error.payr-1049 + glossary: + - nhcx.glossary.claim +--- + +# Provider sandbox exit use case 9: Claim submission + +## In plain words + +A [claim](../glossary/claim.md) asks the payer to settle the bill after treatment. This case proves your system can submit one through [NHCX](../../shared/glossary/nhcx.md) and read the payer's decision. + +The decision arrives later on your callback, sealed. A `ProtocolResponse` arrives instead when the payer could not process the claim. + +## Before you start + +- Your provider participant exists in the sandbox registry, and you know its [participant code](../glossary/participant-code.md). [Onboard in the sandbox](../flows/sandbox-onboarding.md) gets you there. +- You hold a current session token from [use case 4](provider-uc-04.md). +- You hold the recipient's public certificate from [use case 3](provider-uc-03.md), and your own private key. +- Your registered endpoint URL takes HTTPS calls from the exchange. See [callback URL requirements](../sandbox/callback-url-requirements.md). +- The recipient is the sandbox dummy payer, participant code `1000003538@hcx`, unless a payer partner answers for you. See [the dummy payer](../sandbox/dummy-payer.md). +- You know the preauthorisation the claim settles, from [use case 7](provider-uc-07.md). + +## What happens + +### Send the request + +1. Build a Claim bundle with `use` `claim`. See [the claim request bundle](../fhir/claim-request.md). Validate it against the [NRCeS](../../shared/glossary/nrces.md) profiles, as [validating a bundle](../fhir/validation.md) describes. +2. Seal it as a [JWE](../glossary/jwe.md) with the recipient's public key. [Send a sealed request](../flows/send-a-sealed-request.md) walks through the envelope. +3. Set the protected headers. `x-hcx-sender_code` is your participant code. `x-hcx-recipient_code` is the payer's processing ID, or `1000003538@hcx` for the dummy payer. `x-hcx-status` is `request.initiated`. Use a new `x-hcx-api_call_id` and a `x-hcx-correlation_id` unique to this request cycle. `x-hcx-ben-abha-id` carries the beneficiary's [ABHA](../../shared/glossary/abha.md) number. +4. Send the sealed payload. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/hcx/v1/claim/submit' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -H 'Authorization: Bearer ' \ + -d '{"payload": ""}' +``` + +5. NHCX answers with HTTP 202. Store your `x-hcx-api_call_id` against the case. + +### Make the dummy payer answer + +The dummy payer answers a claim only when you tell it how. Call its test action API with the correlation id of your request. `action` is `Approve`, `Reject` or `Query`. See [dummy payer, act on a request](../endpoints/dummy-payer-process-request.md). + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/dummyhcxpayer/process/request' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -H 'Authorization: Bearer ' \ + -d '{"action": "Approve", "method": "Claim", "correlationId": ""}' +``` + +### Receive the answer + +1. Wait for `POST /v1/claim/on_submit` on your registered endpoint. +2. Answer it with HTTP 202 within 30 seconds, with the acceptance body from [receive a sealed callback](../flows/receive-a-sealed-callback.md). +3. Read `type` in the body. `ProtocolResponse` means the payer could not process your request. Read `x-hcx-error_details` and do not decrypt. +4. Any other `type` carries a sealed `payload`. Decrypt it with your private key and parse the ClaimResponse bundle. +5. Validate the decrypted bundle against the NRCeS profiles. + +### Demonstrate it + +Sign-off needs people. Book the demos once the steps above pass in your own runs. See [the sandbox exit process](../sandbox/sandbox-exit.md). + +```precondition +human: true +who: your team, with the NHA team +action: Demonstrate this use case in the internal demo, then in the Health Tech Committee (HTC) demo. +how: Email hcx.integration@nha.gov.in to request both demos. +also: Send the FHIR bundles you used to hcx.integration@nha.gov.in for validation by the NRCeS team. +``` + +## How you know it worked + +The pass criterion for this case: + +> Submit the Claim from the Provider end to the NHCX. +> +> Callback API should be implemented by provider systems. It should accept the payload in two forms, and it will be derived based on “type” param of the response. +> +> Payload should be validated against the profiles published by NRCES. + +What you observe: + +- NHCX answers your `POST /v1/claim/submit` with HTTP 202. +- You receive `POST /v1/claim/on_submit` on your registered endpoint. +- Its `x-hcx-correlation_id` equals the `x-hcx-api_call_id` of your request. Its `x-hcx-recipient_code` is your participant code. +- Your endpoint answers it with HTTP 202 within 30 seconds. +- For a sealed answer, the decrypted payload is a ClaimResponse bundle that validates against the NRCeS profiles. +- For a `ProtocolResponse`, your system shows the code and message from `x-hcx-error_details` and does not try to decrypt. +- With the dummy payer, the decision matches the `action` you sent to `/process/request`. + +## When it goes wrong + +- **Nothing arrives from the dummy payer.** It waits for your `/process/request` call, with `method` `Claim` and the correlation id of your claim. +- **The callback never arrives.** Your callback URL must use a domain name, not an IP address or port. It must run on an India-hosted server that allows the exchange's outbound addresses. See [callback URL requirements](../sandbox/callback-url-requirements.md) and [accepted, then no callback](../troubleshooting/accepted-then-no-callback.md). Then ask where the request stands with [use case 13](provider-uc-13.md). +- **HTTP 401 on the call.** The token has expired, or went in without the `Bearer ` prefix. See [NHCX-401](../errors/nhcx-401.md) and fetch a new token. +- **[NHCX-1003](../errors/nhcx-1003.md), receiver not registered.** `x-hcx-recipient_code` is wrong. Address the processing ID from [use case 2](provider-uc-02.md), not the payer ID. +- **[NHCX-1006](../errors/nhcx-1006.md), duplicate request.** You reused a correlation id. A failed request makes its correlation id inactive, so start the next cycle with a new one. +- **A `ProtocolResponse` says the payer cannot decrypt.** You sealed with a stale or wrong certificate. See [PAYR-1001](../errors/payr-1001.md) and [the recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). +- **A `ProtocolResponse` rejects the bundle.** See [PAYR-1049](../errors/payr-1049.md) and [the payer rejects your bundle](../troubleshooting/bundle-rejected.md). Validate against the NRCeS profiles before you send. +- **The exchange keeps redelivering the same message.** Your endpoint did not return HTTP 202 with the acceptance body within 30 seconds. The exchange retries five times, then deletes the request. See [retries and expiry](../concepts/retries-and-expiry.md). diff --git a/catalogue/nhcx/tests/provider-uc-10.md b/catalogue/nhcx/tests/provider-uc-10.md new file mode 100644 index 000000000..7762b4e1e --- /dev/null +++ b/catalogue/nhcx/tests/provider-uc-10.md @@ -0,0 +1,177 @@ +--- +id: nhcx.test.provider-uc-10 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Provider sandbox exit use case 10: Claim search' +summary: >- + Prove that your hospital system can search a payer's claim records through the + claims exchange, and handle both kinds of answer. +sources: +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 5, Tables 5.2, Use case 10. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Search. +- url: https://hcxsbx.abdm.gov.in/images/819467ec15aff13cc2a8.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Dummy Payer Implementation.pdf + hash: sha256:97335ebc4cd32c86e0c34328b2f4c526420b32a7a009208364043d6334e9e757 + fetched: '2026-09-14' + note: NHCX Dummy Payer Implementation, row 19 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1. +- url: https://hcxsbx.abdm.gov.in/searchhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/searchhcxservice.json + hash: sha256:21749dd2ba84a19c5523772da359d76293493d44b48651f1af2e6042d78fa296 + fetched: '2026-09-14' + note: 'API specification: searchhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/search/submit.' +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, items 7 and 8. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 4-6, Q14 and Q21. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Error scenario. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8, Integrator's Journey. +verified: + status: unverified +related: + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.four-message-legs + sandbox: + - nhcx.sandbox.sandbox-exit + - nhcx.sandbox.dummy-payer + - nhcx.sandbox.callback-url-requirements + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback + - nhcx.troubleshooting.recipient-cannot-decrypt + - nhcx.troubleshooting.bundle-rejected + flows: + - nhcx.flow.claim-search + - nhcx.flow.send-a-sealed-request + - nhcx.flow.receive-a-sealed-callback + endpoints: + - nhcx.endpoint.search-submit + - nhcx.endpoint.fetch-certs + callbacks: + - nhcx.callback.search-on-submit + fhir: + - nhcx.fhir.task + - nhcx.fhir.claim-response + - nhcx.fhir.validation + tests: + - nhcx.test.provider-uc-09 + - nhcx.test.provider-uc-13 + - nhcx.test.payer-uc-12 + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1003 + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1001 + - nhcx.error.payr-1049 +--- + +# Provider sandbox exit use case 10: Claim search + +## In plain words + +This case proves your system can search a payer's claim records through [NHCX](../../shared/glossary/nhcx.md). You send search criteria, such as a claim number or a date range. The matching claim responses arrive later on your callback. + +A `ProtocolResponse` arrives instead when the payer could not process the search. + +## Before you start + +- Your provider participant exists in the sandbox registry, and you know its [participant code](../glossary/participant-code.md). [Onboard in the sandbox](../flows/sandbox-onboarding.md) gets you there. +- You hold a current session token from [use case 4](provider-uc-04.md). +- You hold the recipient's public certificate from [use case 3](provider-uc-03.md), and your own private key. +- Your registered endpoint URL takes HTTPS calls from the exchange. See [callback URL requirements](../sandbox/callback-url-requirements.md). +- A payer partner answers search requests. The dummy payer answers insurance plan, coverage eligibility, preauthorisation, claim, payment notice and communication only. See [the dummy payer](../sandbox/dummy-payer.md). +- You have at least one claim with that payer, from [use case 9](provider-uc-09.md). + +## What happens + +### Send the request + +1. Build a Task bundle for the search, with your criteria as Task inputs: claim number, from date, to date, policy number or product number. See [the task bundle](../fhir/task.md). Validate it against the [NRCeS](../../shared/glossary/nrces.md) profiles, as [validating a bundle](../fhir/validation.md) describes. +2. Seal it as a [JWE](../glossary/jwe.md) with the recipient's public key. [Send a sealed request](../flows/send-a-sealed-request.md) walks through the envelope. +3. Set the protected headers. `x-hcx-sender_code` is your participant code. `x-hcx-recipient_code` is the payer's processing ID. `x-hcx-status` is `request.initiated`. Use a new `x-hcx-api_call_id` and a `x-hcx-correlation_id` unique to this request cycle. `x-hcx-ben-abha-id` carries the beneficiary's [ABHA](../../shared/glossary/abha.md) number. +4. Send the sealed payload. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/hcx/v1/search/submit' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -H 'Authorization: Bearer ' \ + -d '{"payload": ""}' +``` + +5. NHCX answers with HTTP 202. Store your `x-hcx-api_call_id` against the case. + +### Receive the answer + +1. Wait for `POST /v1/search/on_submit` on your registered endpoint. +2. Answer it with HTTP 202 within 30 seconds, with the acceptance body from [receive a sealed callback](../flows/receive-a-sealed-callback.md). +3. Read `type` in the body. `ProtocolResponse` means the payer could not process your request. Read `x-hcx-error_details` and do not decrypt. +4. Any other `type` carries a sealed `payload`. Decrypt it with your private key and parse the Task bundle, whose Task output carries the matching ClaimResponse resources. +5. Validate the decrypted bundle against the NRCeS profiles. + +### Demonstrate it + +Sign-off needs people. Book the demos once the steps above pass in your own runs. See [the sandbox exit process](../sandbox/sandbox-exit.md). + +```precondition +human: true +who: your team, with the NHA team +action: Demonstrate this use case in the internal demo, then in the Health Tech Committee (HTC) demo. +how: Email hcx.integration@nha.gov.in to request both demos. +also: Send the FHIR bundles you used to hcx.integration@nha.gov.in for validation by the NRCeS team. +``` + +## How you know it worked + +The pass criterion for this case: + +> To search the claim related information by the providers/regulatory bodies +> +> Callback API should be implemented by provider systems. It should accept the payload in two forms, and it will be derived based on “type” param of the response. +> +> Payload should be validated against the profiles published by NRCES. + +What you observe: + +- NHCX answers your `POST /v1/search/submit` with HTTP 202. +- You receive `POST /v1/search/on_submit` on your registered endpoint. +- Its `x-hcx-correlation_id` equals the `x-hcx-api_call_id` of your request. Its `x-hcx-recipient_code` is your participant code. +- Your endpoint answers it with HTTP 202 within 30 seconds. +- For a sealed answer, the decrypted payload is a Task bundle that validates against the NRCeS profiles. +- For a `ProtocolResponse`, your system shows the code and message from `x-hcx-error_details` and does not try to decrypt. +- The ClaimResponse resources in the answer match your criteria, for example your claim number. + +## When it goes wrong + +- **The callback never arrives.** Your callback URL must use a domain name, not an IP address or port. It must run on an India-hosted server that allows the exchange's outbound addresses. See [callback URL requirements](../sandbox/callback-url-requirements.md) and [accepted, then no callback](../troubleshooting/accepted-then-no-callback.md). Then ask where the request stands with [use case 13](provider-uc-13.md). +- **HTTP 401 on the call.** The token has expired, or went in without the `Bearer ` prefix. See [NHCX-401](../errors/nhcx-401.md) and fetch a new token. +- **[NHCX-1003](../errors/nhcx-1003.md), receiver not registered.** `x-hcx-recipient_code` is wrong. Address the processing ID from [use case 2](provider-uc-02.md), not the payer ID. +- **[NHCX-1006](../errors/nhcx-1006.md), duplicate request.** You reused a correlation id. A failed request makes its correlation id inactive, so start the next cycle with a new one. +- **A `ProtocolResponse` says the payer cannot decrypt.** You sealed with a stale or wrong certificate. See [PAYR-1001](../errors/payr-1001.md) and [the recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). +- **A `ProtocolResponse` rejects the bundle.** See [PAYR-1049](../errors/payr-1049.md) and [the payer rejects your bundle](../troubleshooting/bundle-rejected.md). Validate against the NRCeS profiles before you send. +- **The exchange keeps redelivering the same message.** Your endpoint did not return HTTP 202 with the acceptance body within 30 seconds. The exchange retries five times, then deletes the request. See [retries and expiry](../concepts/retries-and-expiry.md). diff --git a/catalogue/nhcx/tests/provider-uc-11.md b/catalogue/nhcx/tests/provider-uc-11.md new file mode 100644 index 000000000..437c34cfe --- /dev/null +++ b/catalogue/nhcx/tests/provider-uc-11.md @@ -0,0 +1,184 @@ +--- +id: nhcx.test.provider-uc-11 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Provider sandbox exit use case 11: Acknowledge payment notice' +summary: >- + Prove that your hospital system can receive a payer's payment notice and acknowledge + it through the claims exchange. +sources: +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 5-6, Tables 5.3 and 6.1, Use case 11. +- url: https://hcxsbx.abdm.gov.in/images/819467ec15aff13cc2a8.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Dummy Payer Implementation.pdf + hash: sha256:97335ebc4cd32c86e0c34328b2f4c526420b32a7a009208364043d6334e9e757 + fetched: '2026-09-14' + note: NHCX Dummy Payer Implementation, row 19 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 2-3, Payment Notice and trigger API. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet PaymentNotice. +- url: https://hcxsbx.abdm.gov.in/images/c42ad170f37c987ed173.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx + hash: sha256:f56dd156c232192296082f23b1561d0ff11fd40992e6675de41c5c991d579e6d + fetched: '2026-09-14' + note: Workflow Status Sheets(with Codes), row 12 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet1, row Payment Notice Recived. +- url: https://hcxsbx.abdm.gov.in/servicehcxpayment/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/servicehcxpayment.json + hash: sha256:f5c9e3728efbbeaa5e0e8083334b0ae60a05930e5a1e096ca06d40abb235d658 + fetched: '2026-09-14' + note: 'API specification: servicehcxpayment, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/paymentnotice/on_request.' +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, Q2; page 4, Q14. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2, Error scenario and Protocol Response. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8, Integrator's Journey. +verified: + status: unverified +related: + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.four-message-legs + - nhcx.concept.workflow-codes + sandbox: + - nhcx.sandbox.sandbox-exit + - nhcx.sandbox.dummy-payer + - nhcx.sandbox.callback-url-requirements + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback + - nhcx.troubleshooting.recipient-cannot-decrypt + - nhcx.troubleshooting.bundle-rejected + flows: + - nhcx.flow.payment-notice + - nhcx.flow.receive-a-sealed-callback + endpoints: + - nhcx.endpoint.paymentnotice-on-request + - nhcx.endpoint.dummy-payer-paymentnotice-init + callbacks: + - nhcx.callback.paymentnotice-request + fhir: + - nhcx.fhir.payment-notice + - nhcx.fhir.task + - nhcx.fhir.validation + tests: + - nhcx.test.provider-uc-09 + - nhcx.test.payer-uc-13 + errors: + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1011 + - nhcx.error.nhcx-1003 + glossary: + - nhcx.glossary.payment-notice +--- + +# Provider sandbox exit use case 11: Acknowledge payment notice + +## In plain words + +When a payer pays a claim, it sends your hospital a [payment notice](../glossary/payment-notice.md) through [NHCX](../../shared/glossary/nhcx.md). The notice carries the payment date, the amount and the bank transaction reference. This case proves your system receives it and sends an acknowledgement back. + +Here the payer starts the exchange. Your system answers it. + +## Before you start + +- Your provider participant exists in the sandbox registry, and you know its [participant code](../glossary/participant-code.md). [Onboard in the sandbox](../flows/sandbox-onboarding.md) gets you there. +- You hold a current session token from [use case 4](provider-uc-04.md). +- You hold the recipient's public certificate from [use case 3](provider-uc-03.md), and your own private key. +- Your registered endpoint URL takes HTTPS calls from the exchange. See [callback URL requirements](../sandbox/callback-url-requirements.md). +- The recipient is the sandbox dummy payer, participant code `1000003538@hcx`, unless a payer partner answers for you. See [the dummy payer](../sandbox/dummy-payer.md). +- You have the claim number of a claim you submitted in [use case 9](provider-uc-09.md). + +## What happens + +### Get a payment notice from the dummy payer + +1. Call the dummy payer's payment notice trigger with your participant code and the claim number. See [dummy payer, send a payment notice](../endpoints/dummy-payer-paymentnotice-init.md). + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/dummyhcxpayer/paymentNotice/init' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -H 'Authorization: Bearer ' \ + -d '{"providerId": "", "claimNumber": ""}' +``` + +### Receive the notice + +1. Wait for `POST /v1/paymentnotice/request` on your registered endpoint. +2. Answer it with HTTP 202 within 30 seconds, with the acceptance body. +3. Decrypt the payload. Store the payment date, amount and `paymentIdentifier` from the PaymentReconciliation. + +### Send the acknowledgement + +1. Build a Task bundle whose Task acknowledges the notice. See [the payment notice bundle](../fhir/payment-notice.md). Validate it against the [NRCeS](../../shared/glossary/nrces.md) profiles. +2. Seal it with the payer's public key. +3. Set the protected headers. Use a new `x-hcx-api_call_id`. Set `x-hcx-correlation_id` to the `x-hcx-api_call_id` of the notice. Set `x-hcx-recipient_code` to its `x-hcx-sender_code`. Set `x-hcx-workflow_id` to `17` and `x-hcx-status` to `response.complete`. +4. Send it to [`/v1/paymentnotice/on_request`](../endpoints/paymentnotice-on-request.md). + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/hcx/v1/paymentnotice/on_request' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -H 'Authorization: Bearer ' \ + -d '{"type": "JWEPayload", "payload": ""}' +``` + +5. NHCX answers with HTTP 202. + +### Demonstrate it + +Sign-off needs people. Book the demos once the steps above pass in your own runs. See [the sandbox exit process](../sandbox/sandbox-exit.md). + +```precondition +human: true +who: your team, with the NHA team +action: Demonstrate this use case in the internal demo, then in the Health Tech Committee (HTC) demo. +how: Email hcx.integration@nha.gov.in to request both demos. +also: Send the FHIR bundles you used to hcx.integration@nha.gov.in for validation by the NRCeS team. +``` + +## How you know it worked + +The pass criterion for this case: + +> Acknowledge the payment notification sent by the Payer. +> +> Encrypted payload of TaskBundle with Task Resource +> +> Payload should be validated against the profiles published by NRCES. + +What you observe: + +- You receive `POST /v1/paymentnotice/request` and answer it with HTTP 202 within 30 seconds. +- Your system shows the payment date, amount and bank transaction reference for the claim. +- NHCX answers your `POST /v1/paymentnotice/on_request` with HTTP 202. +- No `/v1/error` report arrives for your acknowledgement. + +## When it goes wrong + +- **The notice never arrives.** Check your registered endpoint against the [callback URL requirements](../sandbox/callback-url-requirements.md). With the dummy payer, send a claim number you submitted. +- **Your acknowledgement goes nowhere.** Build the URL as `https://apisbx.abdm.gov.in/hcx/v1/paymentnotice/on_request`, with a slash after `.in`. +- **[NHCX-1010](../errors/nhcx-1010.md), no data for the correlation id.** Your message's `x-hcx-correlation_id` is not the `x-hcx-api_call_id` of the request you answer. +- **[NHCX-1011](../errors/nhcx-1011.md), invalid status.** `x-hcx-status` holds a value the exchange does not accept for this message. Use `response.complete` on an answer and `request.initiated` on a request. +- **[NHCX-1003](../errors/nhcx-1003.md), receiver not registered.** `x-hcx-recipient_code` is wrong. Copy it from the `x-hcx-sender_code` of the request you answer. +- **A `/v1/error` report arrives at your endpoint.** The recipient refused your message after the exchange accepted it. Read the details as [receiving /v1/error](../callbacks/error.md) describes. +- **The exchange keeps redelivering the same message.** Your endpoint did not return HTTP 202 with the acceptance body within 30 seconds. The exchange retries five times, then deletes the request. See [retries and expiry](../concepts/retries-and-expiry.md). diff --git a/catalogue/nhcx/tests/provider-uc-12.md b/catalogue/nhcx/tests/provider-uc-12.md new file mode 100644 index 000000000..72c7d3424 --- /dev/null +++ b/catalogue/nhcx/tests/provider-uc-12.md @@ -0,0 +1,185 @@ +--- +id: nhcx.test.provider-uc-12 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Provider sandbox exit use case 12: Request for reprocess or cancel' +summary: >- + Prove that your hospital system can ask a payer to reprocess or cancel a claim + or preauthorisation through the claims exchange. +sources: +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 6, Table 6.2, Use case 12. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Reprocess. +- url: https://hcxsbx.abdm.gov.in/images/53347f5988b0ce5396f1.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_APIs to be called based on scenario.xlsx + hash: sha256:f92a30673d65dd2cc3cf09e2087c624f23f781dc4ca6b5cd8ec1825e224ac108 + fetched: '2026-09-14' + note: NHCX_APIs to be called based on scenario, row 26 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. sheet Scenarios, rows 9 and 12. +- url: https://hcxsbx.abdm.gov.in/images/819467ec15aff13cc2a8.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Dummy Payer Implementation.pdf + hash: sha256:97335ebc4cd32c86e0c34328b2f4c526420b32a7a009208364043d6334e9e757 + fetched: '2026-09-14' + note: NHCX Dummy Payer Implementation, row 19 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1. +- url: https://hcxsbx.abdm.gov.in/taskhcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/taskhcxservice.json + hash: sha256:0418eca6478dece4d72c5a49a6547d50772511f7ffaf32f901f245591ba84656 + fetched: '2026-09-14' + note: 'API specification: taskhcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/task/submit.' +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, items 7 and 8. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 4-6, Q14 and Q21. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8, Integrator's Journey. +verified: + status: unverified +related: + concepts: + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + - nhcx.concept.four-message-legs + - nhcx.concept.reprocess-and-cancel + sandbox: + - nhcx.sandbox.sandbox-exit + - nhcx.sandbox.dummy-payer + - nhcx.sandbox.callback-url-requirements + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback + - nhcx.troubleshooting.recipient-cannot-decrypt + - nhcx.troubleshooting.bundle-rejected + flows: + - nhcx.flow.claim-reprocess + - nhcx.flow.preauth-cancel + - nhcx.flow.send-a-sealed-request + - nhcx.flow.receive-a-sealed-callback + endpoints: + - nhcx.endpoint.task-submit + - nhcx.endpoint.fetch-certs + callbacks: + - nhcx.callback.task-on-submit + fhir: + - nhcx.fhir.task + - nhcx.fhir.validation + tests: + - nhcx.test.provider-uc-07 + - nhcx.test.provider-uc-09 + - nhcx.test.payer-uc-14 + - nhcx.test.tc-cl-03 + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1003 + - nhcx.error.nhcx-1006 + - nhcx.error.payr-1001 + - nhcx.error.payr-1049 + - nhcx.error.payr-1518 + - nhcx.error.payr-1519 + - nhcx.error.payr-1253 + - nhcx.error.payr-1257 + glossary: + - nhcx.glossary.reprocess +--- + +# Provider sandbox exit use case 12: Request for reprocess or cancel + +## In plain words + +After a rejection or a partial approval, your hospital can ask the payer to [reprocess](../glossary/reprocess.md) the case. You can also cancel a preauthorisation until the claim is raised. Both go to the payer as a Task, through [NHCX](../../shared/glossary/nhcx.md). This case proves your system sends one and reads the answer. + +A `ProtocolResponse` arrives instead when the payer could not process the task. + +## Before you start + +- Your provider participant exists in the sandbox registry, and you know its [participant code](../glossary/participant-code.md). [Onboard in the sandbox](../flows/sandbox-onboarding.md) gets you there. +- You hold a current session token from [use case 4](provider-uc-04.md). +- You hold the recipient's public certificate from [use case 3](provider-uc-03.md), and your own private key. +- Your registered endpoint URL takes HTTPS calls from the exchange. See [callback URL requirements](../sandbox/callback-url-requirements.md). +- A payer partner answers task requests. The dummy payer answers insurance plan, coverage eligibility, preauthorisation, claim, payment notice and communication only. See [the dummy payer](../sandbox/dummy-payer.md). +- A case in the right state. To reprocess, a claim that was rejected or partly approved. To cancel, a preauthorisation with no claim raised yet. + +## What happens + +### Send the request + +1. Build a Task bundle. The Task `code` is `reprocess`, `cancel`, `release` or `nullify`, as the case needs. Its `status` is `requested`, and its input carries the claim number. See [the task bundle](../fhir/task.md). Validate it against the [NRCeS](../../shared/glossary/nrces.md) profiles, as [validating a bundle](../fhir/validation.md) describes. +2. Seal it as a [JWE](../glossary/jwe.md) with the recipient's public key. [Send a sealed request](../flows/send-a-sealed-request.md) walks through the envelope. +3. Set the protected headers. `x-hcx-sender_code` is your participant code. `x-hcx-recipient_code` is the payer's processing ID. `x-hcx-status` is `request.initiated`. Use a new `x-hcx-api_call_id` and a `x-hcx-correlation_id` unique to this request cycle. `x-hcx-ben-abha-id` carries the beneficiary's [ABHA](../../shared/glossary/abha.md) number. +4. Send the sealed payload. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/hcx/v1/task/submit' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -H 'Authorization: Bearer ' \ + -d '{"payload": ""}' +``` + +5. NHCX answers with HTTP 202. Store your `x-hcx-api_call_id` against the case. + +### Receive the answer + +1. Wait for `POST /v1/task/on_submit` on your registered endpoint. +2. Answer it with HTTP 202 within 30 seconds, with the acceptance body from [receive a sealed callback](../flows/receive-a-sealed-callback.md). +3. Read `type` in the body. `ProtocolResponse` means the payer could not process your request. Read `x-hcx-error_details` and do not decrypt. +4. Any other `type` carries a sealed `payload`. Decrypt it with your private key and parse the Task bundle. +5. Validate the decrypted bundle against the NRCeS profiles. + +### Demonstrate it + +Sign-off needs people. Book the demos once the steps above pass in your own runs. See [the sandbox exit process](../sandbox/sandbox-exit.md). + +```precondition +human: true +who: your team, with the NHA team +action: Demonstrate this use case in the internal demo, then in the Health Tech Committee (HTC) demo. +how: Email hcx.integration@nha.gov.in to request both demos. +also: Send the FHIR bundles you used to hcx.integration@nha.gov.in for validation by the NRCeS team. +``` + +## How you know it worked + +The pass criterion for this case: + +> To reprocess/cancel the claims or preauthorisations, in case of rejection or partial approval provider can raise reprocess. +> +> Callback API should be implemented by provider systems. It should accept the payload in two forms, and it will be derived based on “type” param of the response. +> +> Payload should be validated against the profiles published by NRCES. + +What you observe: + +- NHCX answers your `POST /v1/task/submit` with HTTP 202. +- You receive `POST /v1/task/on_submit` on your registered endpoint. +- Its `x-hcx-correlation_id` equals the `x-hcx-api_call_id` of your request. Its `x-hcx-recipient_code` is your participant code. +- Your endpoint answers it with HTTP 202 within 30 seconds. +- For a sealed answer, the decrypted payload is a Task bundle that validates against the NRCeS profiles. +- For a `ProtocolResponse`, your system shows the code and message from `x-hcx-error_details` and does not try to decrypt. + +## When it goes wrong + +- **The payer finds no task input.** See [PAYR-1518](../errors/payr-1518.md) and [PAYR-1519](../errors/payr-1519.md). Every input needs a type and a value. +- **A cancel is refused.** The case is already cancelled, or payment has started. See [PAYR-1253](../errors/payr-1253.md) and [PAYR-1257](../errors/payr-1257.md). +- **The callback never arrives.** Your callback URL must use a domain name, not an IP address or port. It must run on an India-hosted server that allows the exchange's outbound addresses. See [callback URL requirements](../sandbox/callback-url-requirements.md) and [accepted, then no callback](../troubleshooting/accepted-then-no-callback.md). Then ask where the request stands with [use case 13](provider-uc-13.md). +- **HTTP 401 on the call.** The token has expired, or went in without the `Bearer ` prefix. See [NHCX-401](../errors/nhcx-401.md) and fetch a new token. +- **[NHCX-1003](../errors/nhcx-1003.md), receiver not registered.** `x-hcx-recipient_code` is wrong. Address the processing ID from [use case 2](provider-uc-02.md), not the payer ID. +- **[NHCX-1006](../errors/nhcx-1006.md), duplicate request.** You reused a correlation id. A failed request makes its correlation id inactive, so start the next cycle with a new one. +- **A `ProtocolResponse` says the payer cannot decrypt.** You sealed with a stale or wrong certificate. See [PAYR-1001](../errors/payr-1001.md) and [the recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md). +- **A `ProtocolResponse` rejects the bundle.** See [PAYR-1049](../errors/payr-1049.md) and [the payer rejects your bundle](../troubleshooting/bundle-rejected.md). Validate against the NRCeS profiles before you send. diff --git a/catalogue/nhcx/tests/provider-uc-13.md b/catalogue/nhcx/tests/provider-uc-13.md new file mode 100644 index 000000000..7804f7a61 --- /dev/null +++ b/catalogue/nhcx/tests/provider-uc-13.md @@ -0,0 +1,144 @@ +--- +id: nhcx.test.provider-uc-13 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'Provider sandbox exit use case 13: Get status' +summary: >- + Prove that your hospital system can ask the claims exchange where one of its earlier + requests stands, and read the answer. +sources: +- url: https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a + fetched: '2026-09-14' + note: NHCX Provider Side Use Cases- Sandbox Exit Process, row 9 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 6-7, Tables 6.3 and 7.1, Use case 13. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Status. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Status Description (Protected Header). +- url: https://hcxsbx.abdm.gov.in/statushcxservice/api-docs + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/statushcxservice.json + hash: sha256:93b6355a234ef56607427fcdfa32da4921124180c9df08ecd73c8af8955c2adf + fetched: '2026-09-14' + note: 'API specification: statushcxservice, row 23 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications. paths./v1/status.' +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 4, Q14; page 2, Q3. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8, Integrator's Journey. +verified: + status: unverified +related: + flows: + - nhcx.flow.status-check + - nhcx.flow.send-a-sealed-request + endpoints: + - nhcx.endpoint.status + - nhcx.endpoint.fetch-certs + callbacks: + - nhcx.callback.on-status + concepts: + - nhcx.concept.status-lifecycle + - nhcx.concept.protocol-headers + - nhcx.concept.message-identifiers + decisions: + - nhcx.decision.status-poll-or-wait + sandbox: + - nhcx.sandbox.sandbox-exit + - nhcx.sandbox.callback-url-requirements + tests: + - nhcx.test.provider-uc-07 + - nhcx.test.payer-uc-15 + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback + errors: + - nhcx.error.nhcx-401 + - nhcx.error.nhcx-1012 +--- + +# Provider sandbox exit use case 13: Get status + +## In plain words + +Every request through [NHCX](../../shared/glossary/nhcx.md) is answered later, so a request can seem to vanish. This case proves your system can ask the exchange where one of its own requests stands. The answer arrives on your callback as the protocol headers of that request. + +It is one of the thirteen provider use cases for [sandbox exit](../glossary/sandbox-exit.md). The exchange answers this call itself. + +## Before you start + +- Your provider participant exists in the sandbox registry, and you know its [participant code](../glossary/participant-code.md). [Onboard in the sandbox](../flows/sandbox-onboarding.md) gets you there. +- You hold a current session token from [use case 4](provider-uc-04.md). +- You sent a request earlier, for example in [use case 7](provider-uc-07.md), and stored its `x-hcx-api_call_id`. +- Your registered endpoint URL takes HTTPS calls from the exchange. See [callback URL requirements](../sandbox/callback-url-requirements.md). + +## What happens + +### Send the status request + +1. Build the status request as a [JWE](../glossary/jwe.md), as [`/v1/status`](../endpoints/status.md) describes. +2. Set the protected headers. Use a new `x-hcx-api_call_id`. Set `x-hcx-correlation_id` to the `x-hcx-api_call_id` of the request you ask about. Set `x-hcx-recipient_code` to that request's recipient, and `x-hcx-status` to `request.initiated`. `x-hcx-ben-abha-id` carries the beneficiary's [ABHA](../../shared/glossary/abha.md) number. +3. Send it. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/hcx/v1/status' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -H 'Authorization: Bearer ' \ + -d '{"payload": ""}' +``` + +4. NHCX answers with HTTP 202. + +### Receive the status + +1. Wait for `POST /v1/on_status` on your registered endpoint. Answer it with HTTP 202 within 30 seconds. +2. Read the protocol headers it carries. `x-hcx-status` names the stage. `request.queued` means the request waits at the exchange. `request.dispatched` means it reached the recipient's system. + +### Demonstrate it + +Sign-off needs people. Book the demos once the steps above pass in your own runs. See [the sandbox exit process](../sandbox/sandbox-exit.md). + +```precondition +human: true +who: your team, with the NHA team +action: Demonstrate this use case in the internal demo, then in the Health Tech Committee (HTC) demo. +how: Email hcx.integration@nha.gov.in to request both demos. +``` + +## How you know it worked + +The pass criterion for this case: + +> Retrieve the status of any request that has been triggered to NHCX +> +> Callback API should be implemented by provider systems. It should accept the payload as ProtocolHeader contains all the attributes. +> +> Payload should be validated against the profiles published by NRCES. + +What you observe: + +- NHCX answers your `POST /v1/status` with HTTP 202. +- You receive `POST /v1/on_status` carrying the protocol headers of the request you asked about. +- Your endpoint answers it with HTTP 202 within 30 seconds. +- Your system shows the request's stage from `x-hcx-status`. + +## When it goes wrong + +- **[NHCX-1012](../errors/nhcx-1012.md), no records for the API call id.** `x-hcx-correlation_id` must be the `x-hcx-api_call_id` of a request your participant sent. +- **The status never arrives.** Check your registered endpoint against the [callback URL requirements](../sandbox/callback-url-requirements.md). +- **The status stays at `request.queued`.** The recipient has not taken the request. See [accepted, then no callback](../troubleshooting/accepted-then-no-callback.md) before you resend anything. +- **HTTP 401 on the call.** The token has expired, or went in without the `Bearer ` prefix. See [NHCX-401](../errors/nhcx-401.md) and fetch a new token. diff --git a/catalogue/nhcx/tests/tc-abha-01.md b/catalogue/nhcx/tests/tc-abha-01.md new file mode 100644 index 000000000..7d961e24b --- /dev/null +++ b/catalogue/nhcx/tests/tc-abha-01.md @@ -0,0 +1,161 @@ +--- +id: nhcx.test.tc-abha-01 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'TC-ABHA-01: Validate PMJAY policy using ABHA' +summary: >- + Check that your hospital system can confirm a government scheme patient's policy + is active, using their health account number. +sources: +- url: https://hcxsbx.abdm.gov.in/images/4d333fa6ce5ef99920de.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Test Cases.xlsx + hash: sha256:0d95021974cfe81ab2e3bf66f983228a70b8fed8d7d251eb6d7eeab7354ecad2 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Test Cases, row 31 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sheet1, row TC-ABHA-01. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sections 7.3, 7.4 and 7.6. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. page 19, Biometric Authentication; page 26, 8.3.1 Validation. +- url: https://hcxsbx.abdm.gov.in/images/53347f5988b0ce5396f1.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_APIs to be called based on scenario.xlsx + hash: sha256:f92a30673d65dd2cc3cf09e2087c624f23f781dc4ca6b5cd8ec1825e224ac108 + fetched: '2026-09-14' + note: NHCX_APIs to be called based on scenario, row 26 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. sheet Scenarios, row 3. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 4-6, Q14 and Q21. +verified: + status: unverified +related: + flows: + - nhcx.flow.pmjay-patient-to-cashless + - nhcx.flow.send-a-sealed-request + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.biometric-fingerprint-iris + - nhcx.flow.biometric-face + concepts: + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.hmis-integration-architecture + - nhcx.concept.workflow-codes + - nhcx.concept.coverage-eligibility-purposes + - nhcx.concept.biometric-authentication + sandbox: + - nhcx.sandbox.test-participants + glossary: + - nhcx.glossary.pmjay + endpoints: + - nhcx.endpoint.coverageeligibility-check + - nhcx.endpoint.participant-get-policies + - nhcx.endpoint.abha-biometric-auth-init + - nhcx.endpoint.abha-biometric-auth-verify + callbacks: + - nhcx.callback.coverageeligibility-on-check + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.coverage-eligibility-response + - nhcx.fhir.validation + decisions: + - nhcx.decision.eligibility-purpose + - nhcx.decision.biometric-modality + tests: + - nhcx.test.provider-uc-02 + - nhcx.test.provider-uc-05 + - nhcx.test.tc-hbp-01 + - nhcx.test.tc-ce-01 + errors: + - nhcx.error.nhcx-1018 + - nhcx.error.payr-1005 + - nhcx.error.payr-1123 + - nhcx.error.payr-1006 + - nhcx.error.payr-1007 + - nhcx.error.payr-1101 + - nhcx.error.payr-1272 +--- + +# TC-ABHA-01: Validate PMJAY policy using ABHA + +## In plain words + +This test case checks the first exchange of a [PMJAY](../glossary/pmjay.md) admission. Your [HMIS](../../shared/glossary/hmis.md) sends a coverage eligibility request with purpose `validation` for the patient's [ABHA](../../shared/glossary/abha.md) number. The payer answers on your callback with the patient's cover and wallet position. + +It is the happy path: a linked ABHA number and an active policy. + +## Before you start + +- The test case pre-condition holds: valid ABHA, consent available. +- The beneficiary's ABHA number is linked to their PMJAY policy. [Use case 2](provider-uc-02.md) returns the policy. +- The beneficiary is authenticated, or has a signed exemption consent on record. See [fingerprint or iris authentication](../flows/biometric-fingerprint-iris.md) and [face authentication](../flows/biometric-face.md). + +```precondition +human: true +who: the beneficiary, present at the hospital, and your front desk operator +action: Authenticate the beneficiary by fingerprint, iris or face. Keep the user token it returns. +valid_for: 30 minutes. Refresh it automatically until the transaction cycle ends. +fallback: Where biometric authentication is not feasible, record an Aadhaar exemption consent signed by the beneficiary and a hospital representative. +``` + +- Your provider sandbox basics pass. You hold a session token ([use case 4](provider-uc-04.md)) and the payer's certificate ([use case 3](provider-uc-03.md)). Your callback endpoint works ([use case 5](provider-uc-05.md)). +- You address the PMJAY payer by the processing ID from [use case 2](provider-uc-02.md). + +## What happens + +| Test case field | Value | +|---|---| +| API / FHIR Resource | CoverageEligibilityRequest (validation) | +| Input Parameters | ABHA: `91-XXXX-XXXX-XXXX`, Purpose: `validation` | + +1. Build a CoverageEligibilityRequest bundle with `purpose` `validation`. Include the PMJAY member ID or ABHA number, the active Coverage, the provider and insurer Organizations, and a PractitionerRole as enterer. See [the request bundle](../fhir/coverage-eligibility-request.md). +2. Validate the bundle against the [NRCeS](../../shared/glossary/nrces.md) profiles, as [validating a bundle](../fhir/validation.md) describes. +3. Seal it as a [JWE](../glossary/jwe.md) with the PMJAY payer's public key. +4. Set the protected headers. `x-hcx-status` is `request.initiated`. Pass the biometric user token as a header parameter on the request. `x-hcx-recipient_code` is the payer's processing ID, and `x-hcx-ben-abha-id` carries the beneficiary's ABHA number. +5. Send it. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/hcx/v1/coverageeligibility/check' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -H 'Authorization: Bearer ' \ + -d '{"payload": ""}' +``` + +6. [NHCX](../../shared/glossary/nhcx.md) answers with HTTP 202. +7. Wait for `POST /v1/coverageeligibility/on_check` on your registered endpoint. Answer it with HTTP 202 within 30 seconds. +8. Decrypt the payload with your private key and read the CoverageEligibilityResponse. + +## How you know it worked + +The pass criterion for TC-ABHA-01: + +| Field | Value | +|---|---| +| Processing / validation rules | Check ABHA linkage and active policy | +| Expected output | CoverageEligibilityResponse with active coverage | +| Remarks | Happy path | + +What you observe: + +- NHCX answers your request with HTTP 202, and `/v1/coverageeligibility/on_check` arrives with a sealed payload. +- The decrypted CoverageEligibilityResponse carries `outcome` `complete`. +- `insurance[*].inforce` is `true`, and `disposition` reads as in force, for example `Policy is currently in-force`. +- The response gives the wallet position: used amount, available balance and wallet liability. + +## When it goes wrong + +- **[NHCX-1018](../errors/nhcx-1018.md), invalid ABHA number.** The exchange rejects the number's format in the header. +- **The beneficiary is not covered.** See [PAYR-1005](../errors/payr-1005.md) and [PAYR-1123](../errors/payr-1123.md). Check the ABHA number against the linked policy. +- **The policy does not exist or has expired.** See [PAYR-1006](../errors/payr-1006.md) and [PAYR-1007](../errors/payr-1007.md). +- **[PAYR-1101](../errors/payr-1101.md), invalid purpose.** Send `validation` exactly, in lower case. +- **[PAYR-1272](../errors/payr-1272.md), invalid biometric user token.** The token expired or failed. Authenticate the beneficiary again, or use the Authentication Consent questionnaire. +- **The callback never arrives.** Your callback URL must use a domain name, not an IP address or port. It must run on an India-hosted server that allows the exchange's outbound addresses. See [callback URL requirements](../sandbox/callback-url-requirements.md) and [accepted, then no callback](../troubleshooting/accepted-then-no-callback.md). Then ask where the request stands with [use case 13](provider-uc-13.md). diff --git a/catalogue/nhcx/tests/tc-ce-01.md b/catalogue/nhcx/tests/tc-ce-01.md new file mode 100644 index 000000000..55278e807 --- /dev/null +++ b/catalogue/nhcx/tests/tc-ce-01.md @@ -0,0 +1,154 @@ +--- +id: nhcx.test.tc-ce-01 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'TC-CE-01: Coverage eligibility with auth requirements' +summary: >- + Check that your hospital system can confirm a chosen package is covered and affordable, + before it asks for preauthorisation. +sources: +- url: https://hcxsbx.abdm.gov.in/images/4d333fa6ce5ef99920de.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Test Cases.xlsx + hash: sha256:0d95021974cfe81ab2e3bf66f983228a70b8fed8d7d251eb6d7eeab7354ecad2 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Test Cases, row 31 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sheet1, row TC-CE-01. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sections 7.3, 7.4 and 7.6. +- url: https://hcxsbx.abdm.gov.in/images/53347f5988b0ce5396f1.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_APIs to be called based on scenario.xlsx + hash: sha256:f92a30673d65dd2cc3cf09e2087c624f23f781dc4ca6b5cd8ec1825e224ac108 + fetched: '2026-09-14' + note: NHCX_APIs to be called based on scenario, row 26 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. sheet Scenarios, row 5. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. page 19, Biometric Authentication. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 4-6, Q14 and Q21. +verified: + status: unverified +related: + flows: + - nhcx.flow.pmjay-patient-to-cashless + - nhcx.flow.send-a-sealed-request + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.coverage-eligibility-check + - nhcx.flow.biometric-fingerprint-iris + - nhcx.flow.biometric-face + concepts: + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.hmis-integration-architecture + - nhcx.concept.workflow-codes + - nhcx.concept.coverage-eligibility-purposes + - nhcx.concept.biometric-authentication + sandbox: + - nhcx.sandbox.test-participants + glossary: + - nhcx.glossary.pmjay + - nhcx.glossary.coverage-eligibility + endpoints: + - nhcx.endpoint.coverageeligibility-check + callbacks: + - nhcx.callback.coverageeligibility-on-check + fhir: + - nhcx.fhir.coverage-eligibility-request + - nhcx.fhir.coverage-eligibility-response + - nhcx.fhir.validation + decisions: + - nhcx.decision.eligibility-purpose + tests: + - nhcx.test.tc-abha-01 + - nhcx.test.tc-hbp-01 + - nhcx.test.tc-pa-01 + errors: + - nhcx.error.payr-1032 + - nhcx.error.payr-1033 + - nhcx.error.payr-1008 + - nhcx.error.payr-1111 + - nhcx.error.payr-1114 + - nhcx.error.payr-1272 +--- + +# TC-CE-01: Coverage eligibility with auth requirements + +## In plain words + +Before a [PMJAY](../glossary/pmjay.md) preauthorisation, your [HMIS](../../shared/glossary/hmis.md) asks the payer about the exact package it plans to treat. The coverage eligibility purpose `auth-requirements` returns whether the package is covered at your hospital. It also lists the questionnaires and documents the preauthorisation needs. + +This test case checks a package the wallet can afford. + +## Before you start + +- The test case pre-condition holds: wallet available. [TC-ABHA-01](tc-abha-01.md) returned an available balance. +- You chose the package from the plan in [TC-HBP-01](tc-hbp-01.md). +- You hold a valid biometric user token for the beneficiary. + +```precondition +human: true +who: the beneficiary, present at the hospital, and your front desk operator +action: If the user token has expired, authenticate the beneficiary again by fingerprint, iris or face. +``` + +- Your provider sandbox basics pass. You hold a session token ([use case 4](provider-uc-04.md)) and the payer's certificate ([use case 3](provider-uc-03.md)). Your callback endpoint works ([use case 5](provider-uc-05.md)). +- You address the PMJAY payer by the processing ID from [use case 2](provider-uc-02.md). + +## What happens + +| Test case field | Value | +|---|---| +| API / FHIR Resource | CoverageEligibilityRequest (auth-requirements) | +| Input Parameters | Amount: `25000`, Package: `HBP-123` | + +1. Build a CoverageEligibilityRequest bundle with `purpose` `auth-requirements`. Add the package as an item: this purpose requires items. See [the request bundle](../fhir/coverage-eligibility-request.md). +2. Validate the bundle against the [NRCeS](../../shared/glossary/nrces.md) profiles, as [validating a bundle](../fhir/validation.md) describes. +3. Seal it as a [JWE](../glossary/jwe.md) with the PMJAY payer's public key. +4. Set the protected headers. `x-hcx-status` is `request.initiated`. Pass the biometric user token as a header parameter on the request. `x-hcx-recipient_code` is the payer's processing ID, and `x-hcx-ben-abha-id` carries the beneficiary's [ABHA](../../shared/glossary/abha.md) number. +5. Send it. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/hcx/v1/coverageeligibility/check' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -H 'Authorization: Bearer ' \ + -d '{"payload": ""}' +``` + +6. [NHCX](../../shared/glossary/nhcx.md) answers with HTTP 202. +7. Wait for `POST /v1/coverageeligibility/on_check` on your registered endpoint. Answer it with HTTP 202 within 30 seconds. +8. Decrypt the payload with your private key and read the CoverageEligibilityResponse. + +## How you know it worked + +The pass criterion for TC-CE-01: + +| Field | Value | +|---|---| +| Processing / validation rules | Check wallet balance and speciality rules | +| Expected output | Eligible, balance sufficient | +| Remarks | Preauth allowed | + +What you observe: + +- The decrypted CoverageEligibilityResponse carries `outcome` `complete`, and `insurance[*].inforce` is `true`. +- The item for `HBP-123` is not marked `excluded`. +- `authorizationRequired` and `authorizationSupporting` list what the preauthorisation needs. +- The available balance from [TC-ABHA-01](tc-abha-01.md) is at least `25000`, and no insufficient coverage error comes back. + +## When it goes wrong + +- **[PAYR-1033](../errors/payr-1033.md), no items for the purpose.** `auth-requirements` needs the package as an item. +- **[PAYR-1032](../errors/payr-1032.md), invalid purpose.** Send `auth-requirements` exactly. +- **[PAYR-1008](../errors/payr-1008.md), coverage amount insufficient.** The wallet cannot pay the amount. The case fails the test. +- **A rule or speciality failure.** See [PAYR-1111](../errors/payr-1111.md) and [PAYR-1114](../errors/payr-1114.md). Use the speciality code the plan gives for the package. +- **[PAYR-1272](../errors/payr-1272.md), invalid biometric user token.** Authenticate the beneficiary again. +- **The callback never arrives.** Your callback URL must use a domain name, not an IP address or port. It must run on an India-hosted server that allows the exchange's outbound addresses. See [callback URL requirements](../sandbox/callback-url-requirements.md) and [accepted, then no callback](../troubleshooting/accepted-then-no-callback.md). Then ask where the request stands with [use case 13](provider-uc-13.md). diff --git a/catalogue/nhcx/tests/tc-cl-01.md b/catalogue/nhcx/tests/tc-cl-01.md new file mode 100644 index 000000000..d6ebf15dc --- /dev/null +++ b/catalogue/nhcx/tests/tc-cl-01.md @@ -0,0 +1,164 @@ +--- +id: nhcx.test.tc-cl-01 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'TC-CL-01: Submit the claim after discharge' +summary: >- + Check that your hospital system can submit the final claim after a government + scheme patient leaves, and see the payer accept it for adjudication. +sources: +- url: https://hcxsbx.abdm.gov.in/images/4d333fa6ce5ef99920de.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Test Cases.xlsx + hash: sha256:0d95021974cfe81ab2e3bf66f983228a70b8fed8d7d251eb6d7eeab7354ecad2 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Test Cases, row 31 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sheet1, row TC-CL-01. +- url: https://hcxsbx.abdm.gov.in/images/c42ad170f37c987ed173.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx + hash: sha256:f56dd156c232192296082f23b1561d0ff11fd40992e6675de41c5c991d579e6d + fetched: '2026-09-14' + note: Workflow Status Sheets(with Codes), row 12 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet1, rows 15, 21, 25, 26, 28, 29. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 9 claims workflow, PMJAY exception and Stage 2. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 11-12, section 25 Q3 and Q7; pages 4-6, Q14 and Q21. +- url: https://hcxsbx.abdm.gov.in/images/53347f5988b0ce5396f1.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_APIs to be called based on scenario.xlsx + hash: sha256:f92a30673d65dd2cc3cf09e2087c624f23f781dc4ca6b5cd8ec1825e224ac108 + fetched: '2026-09-14' + note: NHCX_APIs to be called based on scenario, row 26 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. sheet Scenarios, row 10. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. page 19, Biometric Authentication; page 35, Claim. +verified: + status: unverified +related: + flows: + - nhcx.flow.pmjay-patient-to-cashless + - nhcx.flow.send-a-sealed-request + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.claim-submit + - nhcx.flow.biometric-fingerprint-iris + - nhcx.flow.biometric-face + concepts: + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.hmis-integration-architecture + - nhcx.concept.workflow-codes + - nhcx.concept.claim-cycle + - nhcx.concept.biometric-authentication + sandbox: + - nhcx.sandbox.test-participants + glossary: + - nhcx.glossary.pmjay + - nhcx.glossary.claim + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.claim-request + - nhcx.fhir.claim-response + - nhcx.fhir.validation + decisions: + - nhcx.decision.biometric-modality + tests: + - nhcx.test.tc-pa-01 + - nhcx.test.tc-cl-02 + - nhcx.test.provider-uc-09 + errors: + - nhcx.error.payr-1302 + - nhcx.error.payr-1301 + - nhcx.error.payr-1012 + - nhcx.error.payr-1357 + - nhcx.error.payr-1363 + - nhcx.error.payr-1366 + - nhcx.error.payr-1095 +--- + +# TC-CL-01: Submit the claim after discharge + +## In plain words + +Under [PMJAY](../glossary/pmjay.md), discharge and claim are one submission. After the patient leaves, your [HMIS](../../shared/glossary/hmis.md) submits a Claim bundle with `use` `claim` through [NHCX](../../shared/glossary/nhcx.md). It carries the final amount, within the approved amount, and the discharge documents. + +This test case checks the payer accepts the claim for adjudication. + +## Before you start + +- The test case pre-condition holds: preauth approved. You received `/v1/preauth/on_submit` with `x-hcx-workflow_id` `21`, and you hold its `preAuthRef`. +- No claim has been raised for this case yet. +- You have the documents the plan requires at claim, from [TC-HBP-01](tc-hbp-01.md). +- The beneficiary authenticated at discharge. + +```precondition +human: true +who: the beneficiary, present at discharge, and your front desk operator +action: Authenticate the beneficiary by fingerprint, iris or face at discharge. Keep the user token it returns. +fallback: Send the Authentication Consent questionnaire response in the claim instead, when biometric authentication fails. +``` + +- Your provider sandbox basics pass. You hold a session token ([use case 4](provider-uc-04.md)) and the payer's certificate ([use case 3](provider-uc-03.md)). Your callback endpoint works ([use case 5](provider-uc-05.md)). +- You address the PMJAY payer by the processing ID from [use case 2](provider-uc-02.md). + +## What happens + +| Test case field | Value | +|---|---| +| API / FHIR Resource | /claim/submit (Claim) | +| Input Parameters | ApprovedAmount: `23000`, Docs attached | + +1. Build a Claim bundle with `use` `claim`. See [the claim request bundle](../fhir/claim-request.md). Reuse the preauthorisation's claim identifier, or reference its `preAuthRef`. Keep the claimed amount within the approved `23000`. Put the discharge details in `supportingInfo` with category `DIS`, and attach the documents. +2. Validate the bundle against the [NRCeS](../../shared/glossary/nrces.md) profiles, as [validating a bundle](../fhir/validation.md) describes. +3. Seal it as a [JWE](../glossary/jwe.md) with the PMJAY payer's public key. +4. Set the protected headers. `x-hcx-workflow_id` is `15` and `x-hcx-status` is `request.initiated`. Pass the discharge user token as a header parameter on the request. `x-hcx-recipient_code` is the payer's processing ID, and `x-hcx-ben-abha-id` carries the beneficiary's [ABHA](../../shared/glossary/abha.md) number. +5. Send it. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/hcx/v1/claim/submit' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -H 'Authorization: Bearer ' \ + -d '{"payload": ""}' +``` + +6. NHCX answers with HTTP 202. +7. Wait for `POST /v1/claim/on_submit` on your registered endpoint. Answer it with HTTP 202 within 30 seconds. +8. Decrypt the payload with your private key and read the payer's answer. + +The path is described in full in [submit a claim after discharge](../flows/claim-submit.md). + +## How you know it worked + +The pass criterion for TC-CL-01: + +| Field | Value | +|---|---| +| Processing / validation rules | Match preauth & treatment details | +| Expected output | Claim accepted for adjudication | +| Remarks | Sent to workflow | + +What you observe: + +- NHCX answers your request with HTTP 202. +- You receive `/v1/claim/on_submit` with `x-hcx-workflow_id` `25` and `x-hcx-status` `response.partial`. Workflow `25` means the payer received the claim. +- Further `response.partial` updates may follow, such as `28` in process and `29` forwarded. +- The decision arrives with `response.complete`, for example `26` approved. + +## When it goes wrong + +- **[PAYR-1302](../errors/payr-1302.md), no approved preauthorisation.** Wait for workflow `21` before you claim. +- **[PAYR-1301](../errors/payr-1301.md), claim already raised.** A case takes one claim. +- **[PAYR-1012](../errors/payr-1012.md), claim above the approved amount.** Keep the claim within `23000`. +- **Discharge data is wrong.** See [PAYR-1357](../errors/payr-1357.md) and [PAYR-1095](../errors/payr-1095.md). Admission must not fall after discharge. +- **The discharge authentication is missing or invalid.** See [PAYR-1363](../errors/payr-1363.md) and [PAYR-1366](../errors/payr-1366.md). Authenticate again, or send the Authentication Consent questionnaire response. +- **The callback never arrives.** Your callback URL must use a domain name, not an IP address or port. It must run on an India-hosted server that allows the exchange's outbound addresses. See [callback URL requirements](../sandbox/callback-url-requirements.md) and [accepted, then no callback](../troubleshooting/accepted-then-no-callback.md). Then ask where the request stands with [use case 13](provider-uc-13.md). diff --git a/catalogue/nhcx/tests/tc-cl-02.md b/catalogue/nhcx/tests/tc-cl-02.md new file mode 100644 index 000000000..ff89f19d2 --- /dev/null +++ b/catalogue/nhcx/tests/tc-cl-02.md @@ -0,0 +1,146 @@ +--- +id: nhcx.test.tc-cl-02 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'TC-CL-02: Submit a claim query update' +summary: >- + Check that your hospital system can answer a payer's query on a claim with more + documents, and see the payer accept the answer. +sources: +- url: https://hcxsbx.abdm.gov.in/images/4d333fa6ce5ef99920de.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Test Cases.xlsx + hash: sha256:0d95021974cfe81ab2e3bf66f983228a70b8fed8d7d251eb6d7eeab7354ecad2 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Test Cases, row 31 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sheet1, row TC-CL-02. +- url: https://hcxsbx.abdm.gov.in/images/53347f5988b0ce5396f1.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_APIs to be called based on scenario.xlsx + hash: sha256:f92a30673d65dd2cc3cf09e2087c624f23f781dc4ca6b5cd8ec1825e224ac108 + fetched: '2026-09-14' + note: NHCX_APIs to be called based on scenario, row 26 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. sheet Scenarios, row 11. +- url: https://hcxsbx.abdm.gov.in/images/c42ad170f37c987ed173.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx + hash: sha256:f56dd156c232192296082f23b1561d0ff11fd40992e6675de41c5c991d579e6d + fetched: '2026-09-14' + note: Workflow Status Sheets(with Codes), row 12 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet1, rows 27, 28, 151. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. page 36, 8.5.2 Query updation. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 4-6, Q14 and Q21. +verified: + status: unverified +related: + flows: + - nhcx.flow.pmjay-patient-to-cashless + - nhcx.flow.send-a-sealed-request + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.claim-query-response + concepts: + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.hmis-integration-architecture + - nhcx.concept.workflow-codes + - nhcx.concept.queries-and-communication + - nhcx.concept.status-lifecycle + sandbox: + - nhcx.sandbox.test-participants + glossary: + - nhcx.glossary.pmjay + endpoints: + - nhcx.endpoint.claim-submit + callbacks: + - nhcx.callback.claim-on-submit + fhir: + - nhcx.fhir.query-update + - nhcx.fhir.claim-request + - nhcx.fhir.validation + tests: + - nhcx.test.tc-cl-01 + - nhcx.test.tc-pa-02 + errors: + - nhcx.error.payr-1303 + - nhcx.error.payr-1304 + - nhcx.error.nhcx-1006 +--- + +# TC-CL-02: Submit a claim query update + +## In plain words + +A [PMJAY](../glossary/pmjay.md) payer can send a claim back with a query. You answer by submitting the claim again with the documents asked for. It is a new claim request that keeps the old reference and uses a new correlation id. + +This test case checks the payer accepts your answer for adjudication. + +## Before you start + +- The test case pre-condition holds: claim should be submitted. [TC-CL-01](tc-cl-01.md) passed. +- The payer queried it: you received `/v1/claim/on_submit` with `x-hcx-workflow_id` `27`. You read the query remarks. +- You have the documents that answer the query. +- You hold a valid user token for the beneficiary. + +```precondition +human: true +who: the beneficiary, present at the hospital, and your front desk operator +action: If the user token has expired, authenticate the beneficiary again by fingerprint, iris or face. +``` + +- Your provider sandbox basics pass. You hold a session token ([use case 4](provider-uc-04.md)) and the payer's certificate ([use case 3](provider-uc-03.md)). Your callback endpoint works ([use case 5](provider-uc-05.md)). +- You address the PMJAY payer by the processing ID from [use case 2](provider-uc-02.md). + +## What happens + +| Test case field | Value | +|---|---| +| API / FHIR Resource | /claim/submit (Claim) | +| Input Parameters | Documents | + +1. Build the Claim bundle with `use` `claim` again. Keep the claim identifier of the original claim. Add the documents. See [query update bundles](../fhir/query-update.md). +2. Validate the bundle against the [NRCeS](../../shared/glossary/nrces.md) profiles, as [validating a bundle](../fhir/validation.md) describes. +3. Seal it as a [JWE](../glossary/jwe.md) with the PMJAY payer's public key. +4. Set the protected headers. Use a new `x-hcx-correlation_id`. `x-hcx-workflow_id` is `151` and `x-hcx-status` is `response.complete`, the pair for the claim query response stage. See [workflow codes](../concepts/workflow-codes.md). `x-hcx-recipient_code` is the payer's processing ID, and `x-hcx-ben-abha-id` carries the beneficiary's [ABHA](../../shared/glossary/abha.md) number. +5. Send it. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/hcx/v1/claim/submit' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -H 'Authorization: Bearer ' \ + -d '{"payload": ""}' +``` + +6. [NHCX](../../shared/glossary/nhcx.md) answers with HTTP 202. +7. Wait for `POST /v1/claim/on_submit` on your registered endpoint. Answer it with HTTP 202 within 30 seconds. +8. Decrypt the payload with your private key and read the payer's answer. + +The path is described in full in [answer a payer query on a claim](../flows/claim-query-response.md). + +## How you know it worked + +The pass criterion for TC-CL-02: + +| Field | Value | +|---|---| +| Processing / validation rules | Match claim & treatment details | +| Expected output | Claim Query details accepted for adjudication | +| Remarks | Sent to workflow | + +What you observe: + +- NHCX answers your request with HTTP 202. +- You receive `/v1/claim/on_submit` for the case with `x-hcx-status` `response.partial` while the payer adjudicates again. It is not a `ProtocolResponse`. +- The decision follows later with `response.complete`. + +## When it goes wrong + +- **[PAYR-1303](../errors/payr-1303.md), no active claim.** The claim identifier differs from the original. +- **[PAYR-1304](../errors/payr-1304.md), no queried claim.** Wait for workflow `27` before you answer. +- **[NHCX-1006](../errors/nhcx-1006.md), duplicate request.** You reused the original correlation id. Use a new one. +- **The payer treats it as a preauthorisation answer.** You sent workflow `19`. A claim query answer carries `151`. +- **The callback never arrives.** Your callback URL must use a domain name, not an IP address or port. It must run on an India-hosted server that allows the exchange's outbound addresses. See [callback URL requirements](../sandbox/callback-url-requirements.md) and [accepted, then no callback](../troubleshooting/accepted-then-no-callback.md). Then ask where the request stands with [use case 13](provider-uc-13.md). diff --git a/catalogue/nhcx/tests/tc-cl-03.md b/catalogue/nhcx/tests/tc-cl-03.md new file mode 100644 index 000000000..a0be01f26 --- /dev/null +++ b/catalogue/nhcx/tests/tc-cl-03.md @@ -0,0 +1,150 @@ +--- +id: nhcx.test.tc-cl-03 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'TC-CL-03: Submit a CRC task after rejection or partial payment' +summary: >- + Check that your hospital system can raise a review request after a government + scheme claim is rejected or only partly paid. +sources: +- url: https://hcxsbx.abdm.gov.in/images/4d333fa6ce5ef99920de.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Test Cases.xlsx + hash: sha256:0d95021974cfe81ab2e3bf66f983228a70b8fed8d7d251eb6d7eeab7354ecad2 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Test Cases, row 31 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sheet1, row TC-CL-03. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 6-9, sections 22 and 23; pages 4-6, Q14 and Q21. +- url: https://hcxsbx.abdm.gov.in/images/53347f5988b0ce5396f1.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_APIs to be called based on scenario.xlsx + hash: sha256:f92a30673d65dd2cc3cf09e2087c624f23f781dc4ca6b5cd8ec1825e224ac108 + fetched: '2026-09-14' + note: NHCX_APIs to be called based on scenario, row 26 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. sheet Scenarios, rows 12 and 14. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sections 10.4 and 10.5. +- url: https://hcxsbx.abdm.gov.in/images/c42ad170f37c987ed173.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx + hash: sha256:f56dd156c232192296082f23b1561d0ff11fd40992e6675de41c5c991d579e6d + fetched: '2026-09-14' + note: Workflow Status Sheets(with Codes), row 12 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet1, rows 36, 252, 253, 254. +verified: + status: unverified +related: + flows: + - nhcx.flow.pmjay-patient-to-cashless + - nhcx.flow.send-a-sealed-request + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.claim-reprocess + concepts: + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.hmis-integration-architecture + - nhcx.concept.workflow-codes + - nhcx.concept.reprocess-and-cancel + sandbox: + - nhcx.sandbox.test-participants + glossary: + - nhcx.glossary.pmjay + - nhcx.glossary.crc + - nhcx.glossary.reprocess + endpoints: + - nhcx.endpoint.task-submit + callbacks: + - nhcx.callback.task-on-submit + fhir: + - nhcx.fhir.task + - nhcx.fhir.claim-response + - nhcx.fhir.validation + tests: + - nhcx.test.tc-cl-01 + - nhcx.test.provider-uc-12 + errors: + - nhcx.error.payr-1332 + - nhcx.error.payr-1518 + - nhcx.error.payr-1519 +--- + +# TC-CL-03: Submit a CRC task after rejection or partial payment + +## In plain words + +When a [PMJAY](../glossary/pmjay.md) claim is rejected, your hospital can ask for it to be reprocessed. The Claim Review Committee ([CRC](../glossary/crc.md)) decides, and its decision is final. When a claim is paid in part, your hospital can raise an erroneous claim for the shortfall instead. + +Both go as a Task bundle on `/v1/task/submit`. This test case checks your system raises one. + +## Before you start + +- The test case pre-condition holds: claim should be rejected or partially paid. +- For a rejection: the claim decision arrived on `/v1/claim/on_submit` as rejected. +- For a partial payment: the payment notice with workflow `33`, payment cleared, arrived. You verified it and acknowledged it with workflow `17`. +- No reprocess or erroneous claim was raised for this claim before. PMJAY allows one of each, and none after a CRC decision. +- You have a supporting document that justifies the request. +- Your provider sandbox basics pass. You hold a session token ([use case 4](provider-uc-04.md)) and the payer's certificate ([use case 3](provider-uc-03.md)). Your callback endpoint works ([use case 5](provider-uc-05.md)). +- You address the PMJAY payer by the processing ID from [use case 2](provider-uc-02.md). + +## What happens + +| Test case field | Value | +|---|---| +| API / FHIR Resource | /task/submit (Task) | +| Input Parameters | Not published for TC-CL-03 | + +Use these values for the request: + +| Case | `Task.code` | `reasonCode` | Amount | +|---|---|---|---| +| Claim rejected | `reprocess` | `claimrejected` | Not sent | +| Claim partially paid | `reprocess` | `partialpayment` | The shortfall, no more | + +1. Build a Task bundle. The Task `code` is `reprocess`, system `http://terminology.hl7.org/CodeSystem/financialtaskcode`. Its `status` is `requested` and its `intent` is `order`. Set `reasonCode` from the table. Add the claim number as an input: the preauthorisation number your system generated. Attach the supporting document as `valueAttachment`. See [the task bundle](../fhir/task.md). +2. Validate the bundle against the [NRCeS](../../shared/glossary/nrces.md) profiles, as [validating a bundle](../fhir/validation.md) describes. +3. Seal it as a [JWE](../glossary/jwe.md) with the PMJAY payer's public key. +4. Set the protected headers. `x-hcx-workflow_id` is `36` and `x-hcx-status` is `request.initiated`. `x-hcx-recipient_code` is the payer's processing ID, and `x-hcx-ben-abha-id` carries the beneficiary's [ABHA](../../shared/glossary/abha.md) number. +5. Send it. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/hcx/v1/task/submit' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -H 'Authorization: Bearer ' \ + -d '{"payload": ""}' +``` + +6. [NHCX](../../shared/glossary/nhcx.md) answers with HTTP 202. +7. Wait for `POST /v1/task/on_submit` on your registered endpoint. Answer it with HTTP 202 within 30 seconds. +8. Decrypt the payload with your private key and read the Task bundle. +9. Resolve the ClaimResponse that `Task.output[0].valueReference` points to, and read it as any adjudication. + +The path is described in full in [ask the payer to reprocess a claim](../flows/claim-reprocess.md). + +## How you know it worked + +No expected output or remarks are published for TC-CL-03. Its one published rule: + +| Field | Value | +|---|---| +| Processing / validation rules | Match claim and Treatment details | +| Expected output | Not published | +| Remarks | Not published | + +What you observe: + +- NHCX answers your `POST /v1/task/submit` with HTTP 202. +- You receive `POST /v1/task/on_submit` with a sealed Task bundle. The Task `status` is `completed`. +- The Task output references a ClaimResponse for the original claim number. +- For a reprocess, `x-hcx-workflow_id` `252` means approved, `253` rejected and `254` queried. + +## When it goes wrong + +- **[PAYR-1332](../errors/payr-1332.md), invalid CRC request.** Check the claim number, reason code and that the claim is in the right state. +- **The payer finds no task input.** See [PAYR-1518](../errors/payr-1518.md) and [PAYR-1519](../errors/payr-1519.md). Every input needs a type and a value. +- **An erroneous claim is refused before payment clears.** Wait for workflow `33`, acknowledge it, then raise the request. +- **A second request for the same claim is refused.** PMJAY allows one reprocess and one erroneous claim per claim. +- **The callback never arrives.** Your callback URL must use a domain name, not an IP address or port. It must run on an India-hosted server that allows the exchange's outbound addresses. See [callback URL requirements](../sandbox/callback-url-requirements.md) and [accepted, then no callback](../troubleshooting/accepted-then-no-callback.md). Then ask where the request stands with [use case 13](provider-uc-13.md). diff --git a/catalogue/nhcx/tests/tc-hbp-01.md b/catalogue/nhcx/tests/tc-hbp-01.md new file mode 100644 index 000000000..9b9b7aa23 --- /dev/null +++ b/catalogue/nhcx/tests/tc-hbp-01.md @@ -0,0 +1,137 @@ +--- +id: nhcx.test.tc-hbp-01 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'TC-HBP-01: Fetch admissible HBP package' +summary: >- + Check that your hospital system can fetch the benefit packages the state scheme + allows at your hospital, with their rules and document needs. +sources: +- url: https://hcxsbx.abdm.gov.in/images/4d333fa6ce5ef99920de.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Test Cases.xlsx + hash: sha256:0d95021974cfe81ab2e3bf66f983228a70b8fed8d7d251eb6d7eeab7354ecad2 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Test Cases, row 31 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sheet1, row TC-HBP-01. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sections 6.4 and 6.5. +- url: https://hcxsbx.abdm.gov.in/images/53347f5988b0ce5396f1.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_APIs to be called based on scenario.xlsx + hash: sha256:f92a30673d65dd2cc3cf09e2087c624f23f781dc4ca6b5cd8ec1825e224ac108 + fetched: '2026-09-14' + note: NHCX_APIs to be called based on scenario, row 26 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. sheet Scenarios, row 2. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 4-6, Q14 and Q21. +verified: + status: unverified +related: + flows: + - nhcx.flow.pmjay-patient-to-cashless + - nhcx.flow.send-a-sealed-request + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.insurance-plan-request + concepts: + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.hmis-integration-architecture + - nhcx.concept.workflow-codes + - nhcx.concept.insurance-plan + sandbox: + - nhcx.sandbox.test-participants + glossary: + - nhcx.glossary.pmjay + - nhcx.glossary.hbp + - nhcx.glossary.sha + endpoints: + - nhcx.endpoint.insuranceplan-request + callbacks: + - nhcx.callback.insuranceplan-on-request + fhir: + - nhcx.fhir.insurance-plan-bundle + - nhcx.fhir.pmjay-insurance-plan + - nhcx.fhir.task + - nhcx.fhir.validation + tests: + - nhcx.test.tc-abha-01 + - nhcx.test.tc-ce-01 + - nhcx.test.provider-uc-06 + errors: + - nhcx.error.payr-1401 + - nhcx.error.payr-1402 + - nhcx.error.payr-1404 + - nhcx.error.payr-1405 + - nhcx.error.payr-1406 +--- + +# TC-HBP-01: Fetch admissible HBP package + +## In plain words + +[HBP](../glossary/hbp.md) packages are the treatments a [PMJAY](../glossary/pmjay.md) policy pays for, and each state sets its own. This test case fetches the insurance plan for your hospital through [NHCX](../../shared/glossary/nhcx.md). It checks that the state's packages come back, with their conditions and document requirements. + +## Before you start + +- The test case pre-condition holds: policy validated. [TC-ABHA-01](tc-abha-01.md) passed. +- Your hospital is on the payer's network for that state. The payer checks this before it answers. +- You have the policy code and your hospital's [HFR](../../shared/glossary/hfr.md) ID. The request needs both. +- Your provider sandbox basics pass. You hold a session token ([use case 4](provider-uc-04.md)) and the payer's certificate ([use case 3](provider-uc-03.md)). Your callback endpoint works ([use case 5](provider-uc-05.md)). +- You address the PMJAY payer by the processing ID from [use case 2](provider-uc-02.md). + +## What happens + +| Test case field | Value | +|---|---| +| API / FHIR Resource | InsurancePlan | +| Input Parameters | PlanId: `PMJAY-TS-001`, Provider Id: `HOSP123`, PayerID: `SHA-HARYANA` | + +1. Build a Task bundle whose Task has `code` `poll`, `status` `requested` and `intent` `order`. Add the inputs `policyNumber` and `providerId`, where `providerId` is your HFR ID. See [insurance plan bundles](../fhir/insurance-plan-bundle.md). +2. Validate the bundle against the [NRCeS](../../shared/glossary/nrces.md) profiles, as [validating a bundle](../fhir/validation.md) describes. +3. Seal it as a [JWE](../glossary/jwe.md) with the PMJAY payer's public key. +4. Set the protected headers. `x-hcx-status` is `request.initiated`. `x-hcx-recipient_code` is the payer's processing ID, and `x-hcx-ben-abha-id` carries the beneficiary's [ABHA](../../shared/glossary/abha.md) number. +5. Send it. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/hcx/v1/insuranceplan/request' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -H 'Authorization: Bearer ' \ + -d '{"payload": ""}' +``` + +6. NHCX answers with HTTP 202. +7. Wait for `POST /v1/insuranceplan/on_request` on your registered endpoint. Answer it with HTTP 202 within 30 seconds. +8. Decrypt the payload with your private key and read the insurance plan bundle. +9. Cache the plan. Fetch it again after 15 days, or when the policy changes. + +## How you know it worked + +The pass criterion for TC-HBP-01: + +| Field | Value | +|---|---| +| Processing / validation rules | Validate provide against state network hospitals | +| Expected output | InsurancePlan with all HBP packages along with inclusions and exclusions,claim conditions, document requirements | +| Remarks | State-specific HBP applied | + +What you observe: + +- The decrypted payload is a Bundle of type `collection` with InsurancePlan, Organization and Questionnaire entries. +- Packages appear under `specificCost`: `category` is the speciality and `benefit` is the package, with its cost. +- The plan carries the `claim-exclusion`, `claimCondition` and `claimSupportingInfoRequirement` extensions. +- The packages are those of the payer's state. See [the PMJAY insurance plan](../fhir/pmjay-insurance-plan.md). + +## When it goes wrong + +- **[PAYR-1401](../errors/payr-1401.md), policy not allowed for the hospital.** The hospital is not on the state network for that policy. +- **[PAYR-1402](../errors/payr-1402.md), policy not associated with a payer.** Check the policy code. +- **[PAYR-1404](../errors/payr-1404.md), no treatment under any speciality.** No packages are configured for your hospital on that policy. +- **[PAYR-1405](../errors/payr-1405.md), no enrolled hospital.** The HFR ID or sender code is not enrolled with the payer. +- **[PAYR-1406](../errors/payr-1406.md), a request is already in progress.** Wait for the first answer before you ask again. +- **The callback never arrives.** Your callback URL must use a domain name, not an IP address or port. It must run on an India-hosted server that allows the exchange's outbound addresses. See [callback URL requirements](../sandbox/callback-url-requirements.md) and [accepted, then no callback](../troubleshooting/accepted-then-no-callback.md). Then ask where the request stands with [use case 13](provider-uc-13.md). diff --git a/catalogue/nhcx/tests/tc-pa-01.md b/catalogue/nhcx/tests/tc-pa-01.md new file mode 100644 index 000000000..96a3ced16 --- /dev/null +++ b/catalogue/nhcx/tests/tc-pa-01.md @@ -0,0 +1,161 @@ +--- +id: nhcx.test.tc-pa-01 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'TC-PA-01: Submit a preauthorisation' +summary: >- + Check that your hospital system can submit a preauthorisation for a government + scheme patient and see the payer take it into its workflow. +sources: +- url: https://hcxsbx.abdm.gov.in/images/4d333fa6ce5ef99920de.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Test Cases.xlsx + hash: sha256:0d95021974cfe81ab2e3bf66f983228a70b8fed8d7d251eb6d7eeab7354ecad2 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Test Cases, row 31 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sheet1, row TC-PA-01. +- url: https://hcxsbx.abdm.gov.in/images/53347f5988b0ce5396f1.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_APIs to be called based on scenario.xlsx + hash: sha256:f92a30673d65dd2cc3cf09e2087c624f23f781dc4ca6b5cd8ec1825e224ac108 + fetched: '2026-09-14' + note: NHCX_APIs to be called based on scenario, row 26 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. sheet Scenarios, row 6. +- url: https://hcxsbx.abdm.gov.in/images/c42ad170f37c987ed173.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx + hash: sha256:f56dd156c232192296082f23b1561d0ff11fd40992e6675de41c5c991d579e6d + fetched: '2026-09-14' + note: Workflow Status Sheets(with Codes), row 12 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet1, rows 12, 20, 21, 23, 24. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. page 6, Table 6.2; page 19, Biometric Authentication. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 4-6, Q14 and Q21. +verified: + status: unverified +related: + flows: + - nhcx.flow.pmjay-patient-to-cashless + - nhcx.flow.send-a-sealed-request + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.preauth-submit + - nhcx.flow.biometric-fingerprint-iris + - nhcx.flow.biometric-face + concepts: + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.hmis-integration-architecture + - nhcx.concept.workflow-codes + - nhcx.concept.claim-cycle + - nhcx.concept.biometric-authentication + sandbox: + - nhcx.sandbox.test-participants + glossary: + - nhcx.glossary.pmjay + - nhcx.glossary.preauthorisation + endpoints: + - nhcx.endpoint.preauth-submit + - nhcx.endpoint.abha-biometric-auth-verify + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.preauth-request + - nhcx.fhir.preauth-response + - nhcx.fhir.validation + decisions: + - nhcx.decision.biometric-modality + tests: + - nhcx.test.tc-ce-01 + - nhcx.test.tc-pa-02 + - nhcx.test.tc-cl-01 + - nhcx.test.provider-uc-07 + errors: + - nhcx.error.payr-1201 + - nhcx.error.payr-1235 + - nhcx.error.payr-1254 + - nhcx.error.payr-1256 + - nhcx.error.payr-1272 + - nhcx.error.payr-1216 +--- + +# TC-PA-01: Submit a preauthorisation + +## In plain words + +A [preauthorisation](../glossary/preauthorisation.md) asks the payer to approve treatment before it happens. Under [PMJAY](../glossary/pmjay.md) it is a Claim bundle with `use` `preauthorization`, sent through [NHCX](../../shared/glossary/nhcx.md). This test case submits one with a diagnosis, treatment plan, supporting documents and doctor details. + +It passes when the payer acknowledges the case into its workflow. + +## Before you start + +- The test case pre-condition holds: eligibility successful. [TC-CE-01](tc-ce-01.md) passed for the package. +- The preauthorisation amount is no more than the balance remaining on the wallet. +- You have the treating doctor's [HPR](../../shared/glossary/hpr.md) ID. +- The beneficiary authenticated biometrically for this preauthorisation. It is mandatory before a PMJAY preauthorisation. + +```precondition +human: true +who: the beneficiary, present at the hospital, and your front desk operator +action: Authenticate the beneficiary by fingerprint, iris or face. Keep the user token it returns. +valid_for: 30 minutes. Refresh it automatically until the transaction cycle ends. +fallback: Where biometric authentication is not feasible, record an Aadhaar exemption consent signed by the beneficiary and a hospital representative. +``` + +- Your provider sandbox basics pass. You hold a session token ([use case 4](provider-uc-04.md)) and the payer's certificate ([use case 3](provider-uc-03.md)). Your callback endpoint works ([use case 5](provider-uc-05.md)). +- You address the PMJAY payer by the processing ID from [use case 2](provider-uc-02.md). + +## What happens + +| Test case field | Value | +|---|---| +| API / FHIR Resource | /preauth/submit (Claim) | +| Input Parameters | Diagnosis: `I10`, Treatment Plan, Support Documents. Doctor Details | + +1. Build a Claim bundle with `use` `preauthorization`. See [the preauthorisation request bundle](../fhir/preauth-request.md). Set the diagnosis to `I10`. Add every billable item of the treatment plan and a claim identifier. Add the supporting documents as diagnostic report (`DIA`) and clinical document (`CD`). Name the practitioner by HPR ID. +2. Validate the bundle against the [NRCeS](../../shared/glossary/nrces.md) profiles, as [validating a bundle](../fhir/validation.md) describes. +3. Seal it as a [JWE](../glossary/jwe.md) with the PMJAY payer's public key. +4. Set the protected headers. `x-hcx-workflow_id` is `12` and `x-hcx-status` is `request.initiated`. Use a new `x-hcx-correlation_id`. Pass the biometric user token as a header parameter on the request. `x-hcx-recipient_code` is the payer's processing ID, and `x-hcx-ben-abha-id` carries the beneficiary's [ABHA](../../shared/glossary/abha.md) number. +5. Send it. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/hcx/v1/preauth/submit' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -H 'Authorization: Bearer ' \ + -d '{"payload": ""}' +``` + +6. NHCX answers with HTTP 202. +7. Wait for `POST /v1/preauth/on_submit` on your registered endpoint. Answer it with HTTP 202 within 30 seconds. +8. Decrypt the payload with your private key and read the payer's answer. + +The path is described in full in [submit a preauthorisation](../flows/preauth-submit.md). + +## How you know it worked + +The pass criterion for TC-PA-01: + +| Field | Value | +|---|---| +| Processing / validation rules | Validate clinical & financial rules | +| Expected output | Preauth ID generated, status=PENDING | +| Remarks | Sent to workflow | + +What you observe: + +- NHCX answers your request with HTTP 202. +- You receive `/v1/preauth/on_submit` with `x-hcx-workflow_id` `20` and `x-hcx-status` `response.partial`. Workflow `20` means the payer received and acknowledged the preauthorisation. +- Your system shows the case as pending until the decision arrives. +- The decision arrives later on the same path: `21` approved, `23` rejected or `24` queried. + +## When it goes wrong + +- **[PAYR-1201](../errors/payr-1201.md), invalid claimed amount.** The amount exceeds what the wallet allows. Keep it within the balance from [TC-ABHA-01](tc-abha-01.md). +- **[PAYR-1235](../errors/payr-1235.md), insufficient wallet balance.** The wallet cannot pay the preauthorisation. +- **A required questionnaire response is missing.** See [PAYR-1254](../errors/payr-1254.md) and [PAYR-1256](../errors/payr-1256.md). Answer what [TC-CE-01](tc-ce-01.md) listed. +- **[PAYR-1272](../errors/payr-1272.md), invalid biometric user token.** Authenticate the beneficiary again. +- **[PAYR-1216](../errors/payr-1216.md), a case is already in progress.** The beneficiary has an open preauthorisation. +- **The callback never arrives.** Your callback URL must use a domain name, not an IP address or port. It must run on an India-hosted server that allows the exchange's outbound addresses. See [callback URL requirements](../sandbox/callback-url-requirements.md) and [accepted, then no callback](../troubleshooting/accepted-then-no-callback.md). Then ask where the request stands with [use case 13](provider-uc-13.md). diff --git a/catalogue/nhcx/tests/tc-pa-02.md b/catalogue/nhcx/tests/tc-pa-02.md new file mode 100644 index 000000000..830d2eda8 --- /dev/null +++ b/catalogue/nhcx/tests/tc-pa-02.md @@ -0,0 +1,148 @@ +--- +id: nhcx.test.tc-pa-02 +type: test +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: 'TC-PA-02: Submit a preauthorisation query update' +summary: >- + Check that your hospital system can answer a payer's query on a preauthorisation + with more documents, and see the payer accept the answer. +sources: +- url: https://hcxsbx.abdm.gov.in/images/4d333fa6ce5ef99920de.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Test Cases.xlsx + hash: sha256:0d95021974cfe81ab2e3bf66f983228a70b8fed8d7d251eb6d7eeab7354ecad2 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Test Cases, row 31 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sheet1, row TC-PA-02. +- url: https://hcxsbx.abdm.gov.in/images/53347f5988b0ce5396f1.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_APIs to be called based on scenario.xlsx + hash: sha256:f92a30673d65dd2cc3cf09e2087c624f23f781dc4ca6b5cd8ec1825e224ac108 + fetched: '2026-09-14' + note: NHCX_APIs to be called based on scenario, row 26 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. sheet Scenarios, row 8. +- url: https://hcxsbx.abdm.gov.in/images/c42ad170f37c987ed173.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx + hash: sha256:f56dd156c232192296082f23b1561d0ff11fd40992e6675de41c5c991d579e6d + fetched: '2026-09-14' + note: Workflow Status Sheets(with Codes), row 12 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. Sheet1, rows 18, 19, 24. +- url: https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf + hash: sha256:d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164 + fetched: '2026-09-14' + note: NHCX-PMJAY-HMIS Integration Guide, row 28 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. page 32, 8.4.4 Query updation. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 4-6, Q14 and Q21. +verified: + status: unverified +related: + flows: + - nhcx.flow.pmjay-patient-to-cashless + - nhcx.flow.send-a-sealed-request + - nhcx.flow.receive-a-sealed-callback + - nhcx.flow.preauth-query-response + concepts: + - nhcx.concept.pmjay-on-nhcx + - nhcx.concept.hmis-integration-architecture + - nhcx.concept.workflow-codes + - nhcx.concept.queries-and-communication + - nhcx.concept.biometric-authentication + sandbox: + - nhcx.sandbox.test-participants + glossary: + - nhcx.glossary.pmjay + endpoints: + - nhcx.endpoint.preauth-submit + callbacks: + - nhcx.callback.preauth-on-submit + fhir: + - nhcx.fhir.query-update + - nhcx.fhir.preauth-request + - nhcx.fhir.validation + tests: + - nhcx.test.tc-pa-01 + - nhcx.test.provider-uc-08 + errors: + - nhcx.error.payr-1218 + - nhcx.error.payr-1219 + - nhcx.error.payr-1234 + - nhcx.error.nhcx-1006 +--- + +# TC-PA-02: Submit a preauthorisation query update + +## In plain words + +A [PMJAY](../glossary/pmjay.md) payer can send a preauthorisation back with a query. You answer by submitting the preauthorisation again with the documents asked for. It is a new preauthorisation request that keeps the old reference and uses a new correlation id. + +This test case checks the payer accepts your answer for adjudication. + +## Before you start + +- The test case pre-condition holds: preauth should be submitted. [TC-PA-01](tc-pa-01.md) passed. +- The payer queried it: you received `/v1/preauth/on_submit` with `x-hcx-workflow_id` `24`. You read the query remarks. +- You have the documents that answer the query. +- You hold a valid biometric user token for the beneficiary. + +```precondition +human: true +who: the beneficiary, present at the hospital, and your front desk operator +action: If the user token has expired, authenticate the beneficiary again by fingerprint, iris or face. +``` + +- Your provider sandbox basics pass. You hold a session token ([use case 4](provider-uc-04.md)) and the payer's certificate ([use case 3](provider-uc-03.md)). Your callback endpoint works ([use case 5](provider-uc-05.md)). +- You address the PMJAY payer by the processing ID from [use case 2](provider-uc-02.md). + +## What happens + +| Test case field | Value | +|---|---| +| API / FHIR Resource | /preauth/submit (Claim) | +| Input Parameters | Additional Documents | + +1. Build the Claim bundle with `use` `preauthorization` again. Keep the claim identifier of the original preauthorisation. Add the additional documents. See [query update bundles](../fhir/query-update.md). +2. Validate the bundle against the [NRCeS](../../shared/glossary/nrces.md) profiles, as [validating a bundle](../fhir/validation.md) describes. +3. Seal it as a [JWE](../glossary/jwe.md) with the PMJAY payer's public key. +4. Set the protected headers. Use a new `x-hcx-correlation_id`. `x-hcx-workflow_id` is `19` and `x-hcx-status` is `response.complete`, the pair for the preauth query response stage. See [workflow codes](../concepts/workflow-codes.md). `x-hcx-recipient_code` is the payer's processing ID, and `x-hcx-ben-abha-id` carries the beneficiary's [ABHA](../../shared/glossary/abha.md) number. +5. Send it. + +```bash +curl -X POST 'https://apisbx.abdm.gov.in/hcx/v1/preauth/submit' \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json' \ + -H 'bearer_auth: Bearer ' \ + -H 'Authorization: Bearer ' \ + -d '{"payload": ""}' +``` + +6. [NHCX](../../shared/glossary/nhcx.md) answers with HTTP 202. +7. Wait for `POST /v1/preauth/on_submit` on your registered endpoint. Answer it with HTTP 202 within 30 seconds. +8. Decrypt the payload with your private key and read the payer's answer. + +The path is described in full in [answer a payer query on a preauthorisation](../flows/preauth-query-response.md). + +## How you know it worked + +The pass criterion for TC-PA-02: + +| Field | Value | +|---|---| +| Processing / validation rules | Match Preauth & treatment details | +| Expected output | Preauth Query details accepted for adjudication | +| Remarks | Sent to workflow | + +What you observe: + +- NHCX answers your request with HTTP 202. +- You receive `/v1/preauth/on_submit` with `x-hcx-workflow_id` `18` and `x-hcx-status` `response.partial`. The payer acknowledged your query response. +- The decision follows later on the same path. + +## When it goes wrong + +- **[PAYR-1218](../errors/payr-1218.md), no queried preauthorisation.** The case was not queried, or the claim identifier differs from the original. +- **[PAYR-1219](../errors/payr-1219.md), case not queried.** Wait for workflow `24` before you answer. +- **[PAYR-1234](../errors/payr-1234.md), no preauthorisation record.** Reuse the original claim identifier. +- **[NHCX-1006](../errors/nhcx-1006.md), duplicate request.** You reused the original correlation id. Use a new one. +- **The acknowledgement carries `x-hcx-status` `response.error`.** The payer could not accept the answer. Read `x-hcx-error_details` and correct the bundle. +- **The callback never arrives.** Your callback URL must use a domain name, not an IP address or port. It must run on an India-hosted server that allows the exchange's outbound addresses. See [callback URL requirements](../sandbox/callback-url-requirements.md) and [accepted, then no callback](../troubleshooting/accepted-then-no-callback.md). Then ask where the request stands with [use case 13](provider-uc-13.md). diff --git a/catalogue/nhcx/troubleshooting/accepted-then-no-callback.md b/catalogue/nhcx/troubleshooting/accepted-then-no-callback.md new file mode 100644 index 000000000..ff428e3e6 --- /dev/null +++ b/catalogue/nhcx/troubleshooting/accepted-then-no-callback.md @@ -0,0 +1,110 @@ +--- +id: nhcx.troubleshooting.accepted-then-no-callback +type: troubleshooting +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: The request was accepted with 202 and no callback arrives +summary: >- + Your request was accepted and the answer never came back. The checks that find + where it stopped, in order. +sources: +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 4-6, Q12, Q14 and Q21. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, items 7 and 8. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. Status Description (Protected Header). +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Status. +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet NHCX Error Codes, NHCX-1006. +verified: + status: unverified +related: + concepts: + - nhcx.concept.four-message-legs + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.retries-and-expiry + - nhcx.concept.message-identifiers + endpoints: + - nhcx.endpoint.status + - nhcx.endpoint.participant-get-policies + callbacks: + - nhcx.callback.error + - nhcx.callback.on-status + decisions: + - nhcx.decision.status-poll-or-wait + errors: + - nhcx.error.nhcx-1001 + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1012 + troubleshooting: + - nhcx.troubleshooting.callback-url-rejected + - nhcx.troubleshooting.recipient-cannot-decrypt + - nhcx.troubleshooting.bundle-rejected + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - nhcx.glossary.tpa +--- + +# The request was accepted with 202 and no callback arrives + +## In plain words + +Your call returned `202` and no `on_` callback has come. The `202` only means [NHCX](../../shared/glossary/nhcx.md) accepted the request. The answer travels three more legs, and any of them can stop it, so you have to find which one. + +## Before you start + +- You have the request's api call id, correlation id and timestamp. See [correlation id, API call id and workflow id](../concepts/message-identifiers.md). +- You know which leg is which. See [the four legs of every exchange](../concepts/four-message-legs.md). + +## What happens + +Work through these in order. + +1. **Did `/v1/error` receive anything?** When NHCX cannot deliver your request, the failure comes back to your `/v1/error` endpoint. Check its log before anything else. See [receiving POST /v1/error](../callbacks/error.md). +2. **Can NHCX reach your callback endpoint at all?** Domain name, India hosting, whitelisted addresses and routing all matter. See [your callback URL is rejected or never called](../troubleshooting/callback-url-rejected.md). +3. **Does your endpoint answer `202` within 30 seconds, with the acceptance body?** A slow or malformed acknowledgement counts as a failed delivery. NHCX retries five times, then deletes the request. See [the 202 acknowledgement and the 30 second rule](../concepts/synchronous-acknowledgement.md) and [gateway retries and the 24 hour expiry window](../concepts/retries-and-expiry.md). +4. **Did you address the right recipient?** When a [TPA](../glossary/tpa.md) processes the policy, `x-hcx-recipient_code` must be the `processingid` from [`/participant/get/policies`](../endpoints/participant-get-policies.md), not the payer's code. +5. **Where does the request stand?** Send one [status check](../endpoints/status.md) with the request's api call id as its correlation id. `request.queued` means it is still inside NHCX. `request.dispatched` means the recipient holds it, and a [`/v1/on_status`](../callbacks/on-status.md) callback follows. See [poll with /v1/status or wait for the callback](../decisions/status-poll-or-wait.md). +6. **Did the recipient reject it?** A recipient that cannot process your request answers with a clear-text `ProtocolResponse`, `x-hcx-status` `response.error`, instead of a sealed payload. If your handler only accepts sealed bodies, you drop it. Read `x-hcx-error_details`, then see [the recipient cannot decrypt your message](../troubleshooting/recipient-cannot-decrypt.md) or [the payer rejects your FHIR bundle](../troubleshooting/bundle-rejected.md). + +## How you know it worked + +The `on_` callback reaches your endpoint carrying the correlation id you sent. Your endpoint answers it `202` within 30 seconds, with the acceptance body, and the next request of the same kind completes the same way. + +## When it goes wrong + +Do not resubmit with the same correlation id: it is refused as a duplicate. Once you know the old cycle failed, start a new one with a new correlation id. + +If every check above passes and nothing arrives, contact NHCX support. Give the api call id, the correlation id, the timestamp and the `202` body. See [support contacts](../sandbox/support-contacts.md). + +The errors this symptom can surface: + +- [NHCX-1001](../errors/nhcx-1001.md): the receiver system is not reachable. +- [NHCX-1006](../errors/nhcx-1006.md): a request with the same correlation id already exists. +- [NHCX-1010](../errors/nhcx-1010.md): no data for the correlation id of a callback. +- [NHCX-1012](../errors/nhcx-1012.md): no records for the api call id of a status check. diff --git a/catalogue/nhcx/troubleshooting/bundle-rejected.md b/catalogue/nhcx/troubleshooting/bundle-rejected.md new file mode 100644 index 000000000..37b7cfb17 --- /dev/null +++ b/catalogue/nhcx/troubleshooting/bundle-rejected.md @@ -0,0 +1,96 @@ +--- +id: nhcx.troubleshooting.bundle-rejected +type: troubleshooting +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: The payer rejects your FHIR bundle +summary: >- + The payer opened your message and refused its content as malformed or incomplete. + The checks that find the fault in the bundle, in order. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheets Bridge Error (PAYR-1004, 1008, 1009, 1012, 1013, HFR, attachment rows) and Payer Error Codes (PAYR-1004). +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 1.3 Key Principles. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 6, best practices. +- url: https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf + hash: sha256:d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b + fetched: '2026-09-14' + note: Guide For Providers, listed on https://hcxsbx.abdm.gov.in/#/media-center, not named in the NHCX document sheet. page 8, FHIR Bundle Validation. +verified: + status: unverified +related: + concepts: + - nhcx.concept.fhir-in-nhcx + - nhcx.concept.error-code-spaces + fhir: + - nhcx.fhir.validation + - nhcx.fhir.collection-bundle + errors: + - nhcx.error.payr-1004 + - nhcx.error.payr-1008 + - nhcx.error.payr-1009 + - nhcx.error.payr-1013 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - shared.glossary.fhir + - shared.glossary.nrces + - shared.glossary.hfr +--- + +# The payer rejects your FHIR bundle + +## In plain words + +The payer decrypted your message and could not accept the [FHIR](../../shared/glossary/fhir.md) bundle inside it. The answer names the fault with a code: + +- `PAYR-1004`: the bundle is malformed, followed by error details. +- `PAYR-1008`: the bundle is invalid or cannot be parsed. +- A structural code such as `PAYR-1009`: no identifier for the patient. + +## Before you start + +- You have the full answer, including the error message and any details after the code. +- You have read [FHIR collection bundles and the NHCX claim profiles](../concepts/fhir-in-nhcx.md). +- You can run the [NRCeS](../../shared/glossary/nrces.md) validator. See [validating a bundle](../fhir/validation.md). + +## What happens + +Read the message with the code. `PAYR-1004` also means "Provider is not registered with the payer for requested policy" in the standard payer codes. The message text tells you which one you have. See [error code spaces](../concepts/error-code-spaces.md). + +Then work through these in order. + +1. **Does the bundle pass the NRCeS validator?** Run it on the exact bundle you sealed and fix what it reports first. +2. **Is the bundle shaped right?** It is a `Bundle` of type `collection`. Every resource declares its NRCeS profile in `meta.profile`. Resources reference each other as `urn:uuid:`, not by relative paths. See [the collection bundle](../fhir/collection-bundle.md). +3. **Does every resource carry its identifier and type?** The patient, the provider organisation, the payer organisation and the claim each need an identifier with a type. +4. **Is your hospital identified correctly?** Send the [HFR](../../shared/glossary/hfr.md) ID as an identifier with type code `NPI` in the provider `Organization`. It must match the registry ID recorded for you as sender. +5. **Are the attachments valid?** Each has Base64 data, a name that is not empty, and one of these content types: `application/pdf`, `application/jpg`, `application/jpeg`, `application/png`, `application/fhir+json`. +6. **Are the values clean?** Trim leading and trailing spaces. Codes are case sensitive and must match the expected values exactly. + +## How you know it worked + +The validator passes the bundle, and the payer's answer is an adjudication: a ClaimResponse or eligibility response with an outcome, not a bundle error. + +## When it goes wrong + +If the validator passes and the payer still refuses the bundle, send the bundle to `hcx.integration@nha.gov.in` for validation by the NRCeS team. Include the payer's full error message. See [support contacts](../sandbox/support-contacts.md). + +The errors this symptom can surface: + +- [PAYR-1004](../errors/payr-1004.md): the bundle is malformed. +- [PAYR-1008](../errors/payr-1008.md): the bundle is invalid or cannot be parsed. +- [PAYR-1009](../errors/payr-1009.md): no identifier for the patient. +- [PAYR-1013](../errors/payr-1013.md): no identifier for the provider organisation. diff --git a/catalogue/nhcx/troubleshooting/callback-url-rejected.md b/catalogue/nhcx/troubleshooting/callback-url-rejected.md new file mode 100644 index 000000000..485e0bf24 --- /dev/null +++ b/catalogue/nhcx/troubleshooting/callback-url-rejected.md @@ -0,0 +1,90 @@ +--- +id: nhcx.troubleshooting.callback-url-rejected +type: troubleshooting +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Your callback URL is rejected or never called +summary: >- + Your registered endpoint is refused, or saved and never called. The checks that + make it reachable, in order. +sources: +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 4-6, Q14 and Q21. +- url: https://hcxsbx.abdm.gov.in/images/260d0dec19a681e80262.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Production.pdf + hash: sha256:c38476fb90101f13fdfea447861292718d561e1dc088ae20950b193606500d2e + fetched: '2026-09-14' + note: Onboarding providers and payers in Production, row 5 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 3, Steps 3 and 4. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. NHCX Participant Registry; Transport Security. +- url: https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf + hash: sha256:b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe + fetched: '2026-09-14' + note: API Response Handling to avoid Failures, row 15 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, Error scenario. +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet NHCX Error Codes, NHCX-1001. +verified: + status: unverified +related: + concepts: + - nhcx.concept.participant-registry + - nhcx.concept.synchronous-acknowledgement + - nhcx.concept.retries-and-expiry + endpoints: + - nhcx.endpoint.participant-update + - nhcx.endpoint.v2-participant-update + - nhcx.endpoint.update-validate + sandbox: + - nhcx.sandbox.callback-url-requirements + - nhcx.sandbox.support-contacts + errors: + - nhcx.error.nhcx-1001 + troubleshooting: + - nhcx.troubleshooting.accepted-then-no-callback +--- + +# Your callback URL is rejected or never called + +## In plain words + +[NHCX](../../shared/glossary/nhcx.md) delivers requests and answers to the endpoint URL in your participant record. Either the update that sets it is refused, or it saves and nothing ever arrives. Senders see `NHCX-1001`, receiver system not reachable, when your endpoint cannot be reached. + +## Before you start + +- Your participant is active and you can call the participant update. See [the participant registry and what a participant record holds](../concepts/participant-registry.md). +- You have read [callback URL requirements](../sandbox/callback-url-requirements.md). + +## What happens + +Work through these in order. + +1. **Is the URL HTTPS and publicly reachable?** The endpoint must be HTTPS, publicly accessible and reachable from NHCX. +2. **Does it use a domain name?** Use a fully qualified domain name. An IP address or an explicit port number is not accepted. +3. **Is the server in India?** Callback servers must be hosted in India. +4. **Are the NHCX addresses allowed in?** Whitelist the NAT IPs `3.109.99.210`, `13.126.152.0` and `13.200.129.223` in your server configuration and firewall. Confirm no firewall rule blocks incoming requests from them. +5. **Did you confirm the update?** An update to your endpoint sends a passcode. The new endpoint activates only after you confirm it with [`/update/validate`](../endpoints/update-validate.md), within 24 hours. See [`POST /participant/update`](../endpoints/participant-update.md) and [`POST /v2/participant/update`](../endpoints/v2-participant-update.md). +6. **Does your application route the paths NHCX calls?** Requests arrive on the use case paths, such as `/v1/claim/on_submit`. Check that load balancers, API gateways and reverse proxies send each path to the right service and version. +7. **Does your endpoint answer fast enough?** Answer `202` within 30 seconds with the acceptance body. Otherwise NHCX retries five times, then deletes the request. See [the 202 acknowledgement and the 30 second rule](../concepts/synchronous-acknowledgement.md). + +## How you know it worked + +Your participant record shows the new endpoint as active. The next request or callback addressed to you arrives on the right path, and your endpoint answers it `202` within 30 seconds. + +## When it goes wrong + +If every check passes and nothing arrives, look at whether the request was ever sent to you. See [the request was accepted with 202 and no callback arrives](../troubleshooting/accepted-then-no-callback.md). + +If the update itself keeps failing, contact NHCX support with your participant code, the endpoint URL and the full response. See [support contacts](../sandbox/support-contacts.md). + +The error this symptom can surface: [NHCX-1001](../errors/nhcx-1001.md), the receiver system is not reachable. diff --git a/catalogue/nhcx/troubleshooting/duplicate-or-mismatched-correlation.md b/catalogue/nhcx/troubleshooting/duplicate-or-mismatched-correlation.md new file mode 100644 index 000000000..e50680397 --- /dev/null +++ b/catalogue/nhcx/troubleshooting/duplicate-or-mismatched-correlation.md @@ -0,0 +1,95 @@ +--- +id: nhcx.troubleshooting.duplicate-or-mismatched-correlation +type: troubleshooting +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Responses arrive against the wrong request +summary: >- + Answers land on the wrong case, or the exchange refuses a request as a duplicate. + The checks on your message identifiers, in order. +sources: +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, item 8. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. NHCX Protocol Headers table. +- url: https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf + hash: sha256:50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d + fetched: '2026-09-14' + note: NHCX Payer Side Use Cases- Sandbox Exit Process, row 10 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, Table 2.2 Validations. +- url: https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx + hash: sha256:25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913 + fetched: '2026-09-14' + note: NHCX Requests and Responses for UseCases, row 11 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheets CoverageEligibility and Preauth, correlation rows. +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 3, Q4. +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet NHCX Error Codes, NHCX-1006. +verified: + status: unverified +related: + concepts: + - nhcx.concept.message-identifiers + - nhcx.concept.protocol-headers + decisions: + - nhcx.decision.status-poll-or-wait + errors: + - nhcx.error.nhcx-1006 + - nhcx.error.nhcx-1010 + - nhcx.error.nhcx-1012 + - nhcx.error.payr-1516 + glossary: + - nhcx.glossary.correlation-id + - nhcx.glossary.api-call-id +--- + +# Responses arrive against the wrong request + +## In plain words + +An answer from [NHCX](../../shared/glossary/nhcx.md) is attached to the wrong case in your system. Or the exchange refuses a request as a duplicate, or refuses a callback it cannot match. All three come from how your system sets and reads the correlation id and the api call id. + +## Before you start + +- You log the `x-hcx-correlation_id` and `x-hcx-api_call_id` of every message you send and receive. +- You have read [correlation id, API call id and workflow id](../concepts/message-identifiers.md). + +## What happens + +Work through these in order. + +1. **Does each request cycle get its own correlation id?** Generate a new random 36-character identifier for every request that opens a cycle. Set it equal to that request's api call id. Never copy one from an example. See [correlation id](../glossary/correlation-id.md). +2. **Does every message in the cycle carry it unchanged?** The answer, any query and every callback in the cycle echo the correlation id of the request. The answer's own api call id is different. +3. **Is the api call id new on every call?** Generate a fresh one for every call, including retries. See [API call id](../glossary/api-call-id.md). +4. **Did you reuse a failed cycle's correlation id?** After an error, the correlation id becomes inactive. A new request with it is refused with `NHCX-1006`. Start a fresh cycle with a new id. +5. **Do you match answers by correlation id?** Store the correlation id against the case before you send. Match every incoming message on it, never on arrival order or time. +6. **If you are the payer, is the receiver right?** The receiver code of your answer is the sender code of the request you answer. + +## How you know it worked + +Every callback lands on the case whose request carried its correlation id. New requests are accepted with `202`, and your logs show no `NHCX-1006` or `NHCX-1010`. + +## When it goes wrong + +If one case's answers keep landing elsewhere after these checks, compare the correlation id in the misplaced callback with the one stored on each case. Two cases holding the same value point at a generator that repeats. A status check can confirm which request NHCX holds for an id. See [poll with /v1/status or wait for the callback](../decisions/status-poll-or-wait.md). + +The errors this symptom can surface: + +- [NHCX-1006](../errors/nhcx-1006.md): a request with the same correlation id already exists. +- [NHCX-1010](../errors/nhcx-1010.md): no data for the correlation id of a callback. +- [NHCX-1012](../errors/nhcx-1012.md): no records for an api call id. +- [PAYR-1516](../errors/payr-1516.md): no event found for the api call id and correlation id of an error response. diff --git a/catalogue/nhcx/troubleshooting/everything-returns-401.md b/catalogue/nhcx/troubleshooting/everything-returns-401.md new file mode 100644 index 000000000..85d9dcb91 --- /dev/null +++ b/catalogue/nhcx/troubleshooting/everything-returns-401.md @@ -0,0 +1,87 @@ +--- +id: nhcx.troubleshooting.everything-returns-401 +type: troubleshooting +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: Every NHCX call returns 401 +summary: >- + Every call you make is rejected as unauthorised, not only one. The checks that + rule out the token and headers, in order. +sources: +- url: https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf + hash: sha256:5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8 + fetched: '2026-09-14' + note: FAQs, row 21 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, Q3; page 5, Q20. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. pages 1-2, items 6, 9 and 10. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Section 3.1 Token Request. +- url: https://hcxsbx.abdm.gov.in/images/54d18468412741b759f3.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Authenticating with NHCX.pdf + hash: sha256:0ea90b635634844aaf8981e917cbf8b765ddd83a340f3c934883912599a62d8b + fetched: '2026-09-14' + note: Authenticating with NHCX, row 3 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1. +- url: https://hcxsbx.abdm.gov.in/images/539853c50347b32b9a5e.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Policy Linking and De-Linking Process.pdf + hash: sha256:420115b9a54e15fa625312a56362164d92d23dd0d6ebf9195135bb00055d1911 + fetched: '2026-09-14' + note: Policy Linking and De-Linking Process, row 8 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 2, Validation for De-Linking. +verified: + status: unverified +related: + concepts: + - nhcx.concept.session-token + - nhcx.concept.policy-linking + decisions: + - nhcx.decision.session-endpoint + endpoints: + - nhcx.endpoint.session-token + - nhcx.endpoint.get-session + errors: + - nhcx.error.nhcx-401 + sandbox: + - nhcx.sandbox.environments-and-base-urls + - nhcx.sandbox.support-contacts +--- + +# Every NHCX call returns 401 + +## In plain words + +Every call to [NHCX](../../shared/glossary/nhcx.md) fails with `401`, often with the message `Sender is not authorized to execute the operation`. When every endpoint fails the same way, the fault is your token or the header carrying it, not any one operation. + +## Before you start + +- More than one endpoint is failing. If one call fails while others succeed, read that call's own error instead. +- You have the full response body, not only the status code. +- You know where your system gets its token. See [which session token endpoint to call](../decisions/session-endpoint.md). + +## What happens + +Work through these in order. + +1. **Has the token expired?** This message appears when the session token has expired. Read the lifetime from the token response, `expiresIn` or `expires_in`, instead of assuming one. Fetch a new token and retry the failing call once. Retrying with the old token fails the same way. See [the session token every NHCX call carries](../concepts/session-token.md). +2. **Does the value start with `Bearer `?** The header value is the word `Bearer`, a space, then the token. A bare token gives `401`. +3. **Is the token in the header the call reads?** Send the same value in both `bearer_auth` and `Authorization`: `Bearer `. +4. **Are the token and the host from the same environment?** A sandbox token does not work against a production host, or the reverse. Compare the host you minted the token on with the host of the failing call. See [environments and base URLs](../sandbox/environments-and-base-urls.md). +5. **Is the token call itself healthy?** If minting a token fails, check the credentials and the body format for the address you call. See [`POST /api/hiecm/gateway/v3/sessions`](../endpoints/session-token.md) and [`POST /get/session`](../endpoints/get-session.md). + +## How you know it worked + +A call that was returning `401` now returns its normal response, and keeps doing so across several calls over more than one token lifetime. One success after several failures can be a token that happened to be fresh; confirm again after the next refresh. + +## When it goes wrong + +A `401` on linking or de-linking a policy, while other calls work, is a different fault. The token must come from the client ID used when the payer or TPA named in the link was created. See [linking an ABHA to an insurance policy](../concepts/policy-linking.md). + +If all five checks pass and calls still return `401`, the credentials may have been revoked or reissued. Contact NHCX support with the API you called, the time of the call and the full response body. Never send the token or the client secret. See [support contacts](../sandbox/support-contacts.md). + +The error this symptom surfaces: [NHCX-401](../errors/nhcx-401.md), user unauthorized. diff --git a/catalogue/nhcx/troubleshooting/recipient-cannot-decrypt.md b/catalogue/nhcx/troubleshooting/recipient-cannot-decrypt.md new file mode 100644 index 000000000..3408d4e57 --- /dev/null +++ b/catalogue/nhcx/troubleshooting/recipient-cannot-decrypt.md @@ -0,0 +1,93 @@ +--- +id: nhcx.troubleshooting.recipient-cannot-decrypt +type: troubleshooting +gateway: nhcx +milestone: n/a +version: nhcx-v1 +title: The recipient cannot decrypt your message +summary: >- + The payer answers that it could not open your sealed payload. The checks that + find the wrong key, form or header, in order. +sources: +- url: https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx + hash: sha256:3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76 + fetched: '2026-09-14' + note: Standard Error Codes, row 18 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. sheet Bridge Error, PAYR-1001 and PAYR-1002; sheet Payer Error Codes. +- url: https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx + hash: sha256:beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1 + fetched: '2026-09-14' + note: NHCX PMJAY Integration Handbook, row 24 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/hmisdocuments. Sections 2.1-2.4 and 3.3. +- url: https://hcxsbx.abdm.gov.in/#/technical-specifications + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md + hash: sha256:b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc + fetched: '2026-09-14' + note: Site page /technical-specifications, text as shown on the site. NHCX Protocol Headers table. +- url: https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf + file: catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf + hash: sha256:b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f + fetched: '2026-09-14' + note: Common Mistakes while implementing through NHCX, row 22 of the NHCX document sheet, listed on https://hcxsbx.abdm.gov.in/#/documents. page 1, item 4; page 2, item 7. +verified: + status: unverified +related: + concepts: + - nhcx.concept.encryption-certificate + - nhcx.concept.jwe-envelope + - nhcx.concept.protocol-headers + decisions: + - nhcx.decision.key-encryption-algorithm + - nhcx.decision.jwe-serialisation + flows: + - nhcx.flow.rotate-certificate + - nhcx.flow.generate-and-register-certificate + endpoints: + - nhcx.endpoint.fetch-certs + - nhcx.endpoint.v2-update-cert + - nhcx.endpoint.participant-update + errors: + - nhcx.error.payr-1001 + - nhcx.error.payr-1002 + sandbox: + - nhcx.sandbox.support-contacts + glossary: + - nhcx.glossary.jwe + - nhcx.glossary.x509-certificate + - nhcx.glossary.protected-header + - nhcx.glossary.tpa +--- + +# The recipient cannot decrypt your message + +## In plain words + +The payer's answer is a clear-text `ProtocolResponse` carrying `PAYR-1001`: an error occurred while decrypting the payload for the receiver code. The recipient could not open your [JWE](../glossary/jwe.md) with its private key. The fault is almost always on the sending side: the wrong certificate, the wrong algorithm or the wrong form. + +## Before you start + +- You have the `ProtocolResponse`, including `x-hcx-error_details` and the correlation id. +- You have read [your encryption certificate and the recipient's](../concepts/encryption-certificate.md). + +## What happens + +Work through these in order. + +1. **Did you seal to the recipient you addressed?** The certificate must belong to the participant in `x-hcx-recipient_code`. Fetch it with [`POST /fetch/certs`](../endpoints/fetch-certs.md), passing that code as `participantid`. When a [TPA](../glossary/tpa.md) processes the policy, that is the `processingid`. +2. **Is your cached copy stale?** Cache a fetched certificate for 24 hours at most. On `PAYR-1001`, fetch it again and resend. A recipient that rotated its key has a new certificate. +3. **Did the key import correctly?** `/fetch/certs` can return a PEM-encoded [X.509 certificate](../glossary/x509-certificate.md) or a bare SubjectPublicKeyInfo public key. Try X.509 import first, then fall back to the bare key. +4. **Are the algorithms right?** The protected header must carry `alg` `RSA-OAEP-256` and `enc` `A256GCM`. See [RSA-OAEP or RSA-OAEP-256 for the content key](../decisions/key-encryption-algorithm.md). +5. **Is the form right?** The body must be `{"payload": ""}`, a compact string with four dots. See [compact or flattened JWE serialisation](../decisions/jwe-serialisation.md). +6. **Is the [protected header](../glossary/protected-header.md) complete?** It must carry `x-hcx-sender_code`, `x-hcx-recipient_code`, `x-hcx-api_call_id`, `x-hcx-correlation_id`, `x-hcx-workflow_id`, `x-hcx-timestamp` and `x-hcx-status`, as participant codes from NHCX and fresh identifiers. + +The reverse fault has its own code. `PAYR-1002` means the payer could not seal its answer to you with the certificate registered for you. Update your registered certificate with [`POST /v2/update/cert`](../endpoints/v2-update-cert.md) or [`POST /participant/update`](../endpoints/participant-update.md). The payer fetches the new one and sends its answer. See [rotate your encryption certificate](../flows/rotate-certificate.md). + +## How you know it worked + +You resend the same content with a fresh correlation id and a fresh api call id. NHCX refuses a correlation id it already holds with [`NHCX-1006`](../errors/nhcx-1006.md), and a request that failed is retired. The answer arrives as a sealed payload on your callback, not a `ProtocolResponse`. Your own decrypter opens it with your private key. + +## When it goes wrong + +If every check passes and `PAYR-1001` persists, confirm with the recipient that its registered certificate matches the private key it decrypts with. Then contact NHCX support with the receiver code and correlation id. See [support contacts](../sandbox/support-contacts.md). + +The errors this symptom can surface: [PAYR-1001](../errors/payr-1001.md), the recipient could not decrypt your payload; and [PAYR-1002](../errors/payr-1002.md), the payer could not encrypt its answer to you. diff --git a/catalogue/openapi/.raw/nhcx-package-2026-09-15/nhcx-error.yaml b/catalogue/openapi/.raw/nhcx-package-2026-09-15/nhcx-error.yaml new file mode 100644 index 000000000..9b5e2e32e --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-package-2026-09-15/nhcx-error.yaml @@ -0,0 +1,1128 @@ +# NHCX error codes: the gateway codes, the standard payer codes and the reference payer codes. +# build-docs renders the tables in docs/06-Reference/01-Error Codes.md from this file. +# kind is the published sheet's classification, Transport or Business, on the codes the sheet classifies. +# collisions lists the codes from PAYR-1001 to PAYR-1020 that the standard sheet (Payer Error Codes) and the +# reference payer's Bridge Error sheet read differently: eighteen of the twenty. PAYR-1001 and PAYR-1002 are +# a decryption and an encryption failure on both sheets. +# note, on a code, records what the SHA HP sandbox payer sent that the sheet does not say. The observed space +# holds the one code the sandbox run met that is on none of the seven sheets. +spaces: + - id: gateway + name: Gateway + prefix: NHCX- + sent_by: The exchange + arrives: Synchronously on your own call, or on /v1/error + - id: standard-payer + name: Standard payer + prefix: PAYR-1001 to PAYR-1020 + sent_by: A payer implementing the published standard + arrives: Inside the sealed response + - id: reference-payer + name: Reference payer + prefix: PAYR-1001 to PAYR-1520 + sent_by: The PMJAY reference implementation + arrives: Inside the sealed response + - id: observed + name: Observed live + prefix: ERR-PYR- + sent_by: The PMJAY reference implementation, on none of its published sheets + arrives: Inside the sealed response +collisions: + - code: PAYR-1003 + standard_payer: Error while connecting to NHCX; the system will resend later + reference_payer: Invalid workflow requested (marked deprecated on the Bridge Error sheet) + - code: PAYR-1004 + standard_payer: Provider is not registered with the payer for the requested policy + reference_payer: Received FHIR bundle is malformed + - code: PAYR-1005 + standard_payer: Beneficiary is not a covered member for the requested policy + reference_payer: Maximum time limit exceeded in receiving the request + - code: PAYR-1006 + standard_payer: Policy does not exist + reference_payer: Invalid name in request (marked deprecated on the Bridge Error sheet) + - code: PAYR-1007 + standard_payer: Requested policy is expired + reference_payer: Invalid gender in request (marked deprecated on the Bridge Error sheet) + - code: PAYR-1008 + standard_payer: Eligible coverage amount is insufficient + reference_payer: Invalid FHIR bundle received + - code: PAYR-1009 + standard_payer: Requested items are not valid or not covered + reference_payer: No identifier found for patient component + - code: PAYR-1010 + standard_payer: Preauthorisation is required but was not obtained + reference_payer: No type found for patient component identifier + - code: PAYR-1011 + standard_payer: The prior approved package does not support enhancement + reference_payer: No identifier found for claim component + - code: PAYR-1012 + standard_payer: Claim amount is more than the preauthorisation approved amount + reference_payer: No type found for claim component identifier + - code: PAYR-1013 + standard_payer: No prior approval for the requested procedures or packages + reference_payer: No identifier found for organization component for provider + - code: PAYR-1014 + standard_payer: Date of birth is after the date of service + reference_payer: No type found for organization component identifier for provider + - code: PAYR-1015 + standard_payer: Date of service is after the date of death + reference_payer: No identifier found for organization component for payer + - code: PAYR-1016 + standard_payer: Duplicate claim submitted based on service codes and dates + reference_payer: No type found for organization component identifier for payer + - code: PAYR-1017 + standard_payer: Amount calculations are not correct + reference_payer: No task code received + - code: PAYR-1018 + standard_payer: Time limit for submission expired + reference_payer: No task reason code received + - code: PAYR-1019 + standard_payer: Requested additional information was not received in time + reference_payer: Invalid sequence received in supporting info element + - code: PAYR-1020 + standard_payer: No valid bank details found for the provider + reference_payer: Invalid category received in supporting info element +bands: + - band: NHCX-1xxx + rejected_by: The exchange, on the envelope + means: The message never reached the payer + - band: PAYR-10xx + rejected_by: Transport and bundle structure + means: An element, id, sequence or type is missing. Not a value problem + - band: PAYR-11xx + rejected_by: Coverage eligibility + means: The policy, the beneficiary or the hospital configuration + - band: PAYR-12xx + rejected_by: Preauthorisation + means: Codes, amounts, dates, sequencing and scheme rules + - band: PAYR-13xx + rejected_by: Claim + means: The same, against the approved preauthorisation + - band: PAYR-14xx + rejected_by: Insurance plan, and the scheme's outer rules + means: Empanelment, policy association, plan configuration +codes: + - code: NHCX-401 + space: gateway + kind: Business + message: User Unauthorized + - code: NHCX-1001 + space: gateway + kind: Transport + message: Receiver system is not reachable. + - code: NHCX-1002 + space: gateway + kind: Business + message: Sender not registered in NHCX. Please register in NHCX portal and try again. + - code: NHCX-1003 + space: gateway + kind: Business + message: Receiver not registered in NHCX. Please try again with valid receiver details. + - code: NHCX-1004 + space: gateway + kind: Business + message: No receiver registered in NHCX for the requested scheme. Please try again with valid receiver details for the scheme. + - code: NHCX-1005 + space: gateway + kind: Business + message: Invalid request header. Please try again with valid headers. + - code: NHCX-1006 + space: gateway + kind: Business + message: Duplicate request. Request with same correlation id already exist in the system. + - code: NHCX-1007 + space: gateway + kind: Business + message: Something went wrong while processing the request. Please check the request structure and values and try again. + - code: NHCX-1008 + space: gateway + kind: Business + message: Something went wrong while processing the request. Please try again after sometime. + - code: NHCX-1009 + space: gateway + kind: Business + message: Something went wrong while processing the request. Please check log for more details. + - code: NHCX-1010 + space: gateway + kind: Business + message: No Data with given Correlation id for call back request, please check status for more details + - code: NHCX-1011 + space: gateway + kind: Business + message: Invalid Status, please check x-hcx-status value from the protected header + - code: NHCX-1012 + space: gateway + kind: Business + message: No records found with the requested api caller id. Please try again with a valid api caller id. + - code: NHCX-1013 + space: gateway + kind: Business + message: Invalid or blank request found. + - code: NHCX-1014 + space: gateway + kind: Business + message: Unable to send protocol response to sender. + - code: NHCX-1015 + space: gateway + kind: Business + message: Invalid response received from receiver. + - code: NHCX-1016 + space: gateway + kind: Business + message: Invalid Api Action, please check the request action for this correlationId before trying again + - code: NHCX-1017 + space: gateway + kind: Business + message: Invalid response received from receiver + - code: NHCX-1018 + space: gateway + kind: Business + message: Invalid ABHA number received. ABHA number should be sent in the format XX-XXXX-XXXX-XXXX + - code: PAYR-1001 + space: standard-payer + message: Error while decrypting request. Please reprocess the request encrypting with valid certificate of the payer. + - code: PAYR-1002 + space: standard-payer + message: Error while encrypting request. Please update encryption certificate in NHCX. + - code: PAYR-1003 + space: standard-payer + message: Error while connecting to NHCX. System will try to resend the message to NHCX after some time. + - code: PAYR-1004 + space: standard-payer + message: Provider is not registered with the payer for requested policy. + - code: PAYR-1005 + space: standard-payer + message: Beneficiary is not a covered member for requested policy. Please enroll beneficiary for the policy and try again. + - code: PAYR-1006 + space: standard-payer + message: Policy does not exist. Please try with a valid policy. + - code: PAYR-1007 + space: standard-payer + message: Requested policy is expired. Please try with a valid policy. + - code: PAYR-1008 + space: standard-payer + message: Eligible coverage amount of the beneficiary for the requested policy is insufficient to process the request. + - code: PAYR-1009 + space: standard-payer + kind: Business + message: Requested items are not valid or not covered. Please try again with valid or covered items. + - code: PAYR-1010 + space: standard-payer + kind: Business + message: Preauthorization is required to process the request but was not obtained. + - code: PAYR-1011 + space: standard-payer + kind: Business + message: Enhancement request can not be processed as the prior approved package/procedure does not support enhancement. + - code: PAYR-1012 + space: standard-payer + kind: Business + message: Claim amount requested is more than the preauthorization approved amount. + - code: PAYR-1013 + space: standard-payer + kind: Business + message: No prior approval for the requested procedures/packages obtained. + - code: PAYR-1014 + space: standard-payer + kind: Business + message: Date of birth of the beneficiary can not be after date of service. + - code: PAYR-1015 + space: standard-payer + kind: Business + message: Date of service cannot be after date of death. + - code: PAYR-1016 + space: standard-payer + kind: Business + message: Duplicate claim submitted based on service codes and dates. + - code: PAYR-1017 + space: standard-payer + kind: Business + message: Amount calculations are not correct. Please verify calculated amount. + - code: PAYR-1018 + space: standard-payer + kind: Business + message: Time limit for submission expired. + - code: PAYR-1019 + space: standard-payer + kind: Business + message: Requested additional information was not received or was not received within time limit + - code: PAYR-1020 + space: standard-payer + kind: Business + message: Unable to process payment as no valid bank details found for the provider. + - code: PAYR-1001 + space: reference-payer + message: Error occurred while decrypting payload for receiver code with correlation id . + - code: PAYR-1002 + space: reference-payer + message: Error occurred while encrypting payload for receiver code with correlation id . + - code: PAYR-1003 + space: reference-payer + message: Invalid workflow requested. Hence request will not be processed further. + - code: PAYR-1004 + space: reference-payer + message: Received FHIR bundle is malformed. Please correct the bundle and try again. + - code: PAYR-1005 + space: reference-payer + message: Maximum time limit exceeded in receiving the request. Please try again. + - code: PAYR-1006 + space: reference-payer + message: Invalid name in request. Hence request will not be processed further. + - code: PAYR-1007 + space: reference-payer + message: Invalid gender in request. Hence request will not be processed further. + - code: PAYR-1008 + space: reference-payer + message: Invalid FHIR bundle received. Hence request will not be processed further. + - code: PAYR-1009 + space: reference-payer + message: No identifier found for patient component. Hence request will not be processed further. https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html + - code: PAYR-1010 + space: reference-payer + message: No type found for patient component identifier. Hence request will not be processed further. https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html + - code: PAYR-1011 + space: reference-payer + message: No identifier found for claim component. Hence request will not be processed further. + - code: PAYR-1012 + space: reference-payer + message: No type found for claim component identifier. Hence request will not be processed further. + - code: PAYR-1013 + space: reference-payer + message: No identifier found for organization component for provider. Hence request will not be processed further. + - code: PAYR-1014 + space: reference-payer + message: No type found for organization component identifier for provider. Hence request will not be processed further. + - code: PAYR-1015 + space: reference-payer + message: No identifier found for organization component for payer. Hence request will not be processed further. + - code: PAYR-1016 + space: reference-payer + message: No type found for organization component identifier for payer. Hence request will not be processed further. + - code: PAYR-1017 + space: reference-payer + message: No task code received. Hence request will not be processed further. + - code: PAYR-1018 + space: reference-payer + message: No task reason code received. Hence request will not be processed further. + - code: PAYR-1019 + space: reference-payer + message: Invalid sequence received in supporting info element. Hence request will not be processed further. + - code: PAYR-1020 + space: reference-payer + message: Invalid category received in supporting info element for sequence %s. Hence request will not be processed further. + - code: PAYR-1021 + space: reference-payer + message: Invalid code received in supporting info element for sequence %s. Hence request will not be processed further. + - code: PAYR-1023 + space: reference-payer + message: Invalid procedure category received for procedure component. Hence request will not be processed further. + - code: PAYR-1024 + space: reference-payer + message: Invalid procedure status received for procedure component. Hence request will not be processed further. + - code: PAYR-1025 + space: reference-payer + message: Invalid procedure sequence received for procedure component. Hence request will not be processed further. + - code: PAYR-1026 + space: reference-payer + message: No procedure component found for reference in claim component. Hence request will not be processed further. + - code: PAYR-1027 + space: reference-payer + message: Invalid item id found for item in claim component. Hence request will not be processed further. + - code: PAYR-1028 + space: reference-payer + message: Invalid item sequence received for item in claim component. Hence request will not be processed further. + - code: PAYR-1029 + space: reference-payer + message: Invalid bundle id received for FHIR bundle. Hence request will not be processed further. + - code: PAYR-1030 + space: reference-payer + message: Invalid questionnaire id received in FHIR bundle for questionnaire component. Hence request will not be processed further. + - code: PAYR-1031 + space: reference-payer + message: Invalid url received for bundle entry in FHIR bundle. Hence request will not be processed further. Please reach out to technical team. + - code: PAYR-1032 + space: reference-payer + message: Invalid purpose received for coverage eligibility request. Hence request will not be processed further. Please try again with valid purpose details. + - code: PAYR-1033 + space: reference-payer + message: No items received for coverage eligibility purpose. Since items are mandatory for the requested purpose, hence request will not be processed further. Please try again with valid item details. + - code: PAYR-1034 + space: reference-payer + message: Invalid procedure code received. Please try again with valid procedure details. + - code: PAYR-1035 + space: reference-payer + message: Invalid policy code received. Please try again with valid policy details. + - code: PAYR-1036 + space: reference-payer + message: Invalid attachment received in supporting info with sequence number %s. Please try again with valid attachment details as attachment value is expected. If issue is not resolved, please reach out to technical team. + - code: PAYR-1037 + space: reference-payer + message: No identifier found for communication component. Hence request will not be processed further. + - code: PAYR-1038 + space: reference-payer + message: No type found for communication component identifier. Hence request will not be processed further. + - code: PAYR-1039 + space: reference-payer + message: No payload found for communication component. Hence request will not be processed further. + - code: PAYR-1040 + space: reference-payer + message: No component found for given reference. Hence request will not be processed further. + - code: PAYR-1041 + space: reference-payer + message: No identifier found for procedure component. Hence request will not be processed further. + - code: PAYR-1042 + space: reference-payer + message: No type found for procedure component identifier. Hence request will not be processed further. + - code: PAYR-1043 + space: reference-payer + message: Date received in the request does not adhere to the NRCES date datatype format. Hence request will not be processed further. Please refere to the date format in NRCES portal. + - code: PAYR-1044 + space: reference-payer + message: Date and time received in the request does not adhere to the NRCES date datatype format. Hence request will not be processed further. Please refere to the date time format in NRCES portal. + - code: PAYR-1045 + space: reference-payer + message: Invalid quantity received for item. Hence request will not be processed further. + - code: PAYR-1046 + space: reference-payer + message: No value or timing details received for supporting info for sequence %s. Hence request will not be processed further. Please reach out to technical team. + - code: PAYR-1047 + space: reference-payer + message: Invalid reference received in supporting info with sequence number %s. Please try again with valid resource as reference value. + - code: PAYR-1048 + space: reference-payer + message: No reference resource received for supporting info with sequence number %s. Please try again with valid resource for reference value. + - code: PAYR-1049 + space: reference-payer + message: Invalid FHIR bundle received. Hence request will not be processed further. please reach out to technical team. + - code: PAYR-1050 + space: reference-payer + message: No type found for practitioner component identifier. Hence request will not be processed further. + - code: PAYR-1051 + space: reference-payer + message: No section found for composition component. Hence request will not be processed further. + - code: PAYR-1052 + space: reference-payer + message: No references found in composition section. Hence request will not be processed further. + - code: PAYR-1053 + space: reference-payer + message: Invalid reference found in child sections of composition section. Hence request will not be processed further. + - code: PAYR-1054 + space: reference-payer + message: No section content found for composition component. Hence request will not be processed further. + - code: PAYR-1055 + space: reference-payer + message: Invalid subject type found for composition component. This should be of type Patient. Hence request will not be processed further. Please try again with valid subject type for the composition. + - code: PAYR-1056 + space: reference-payer + message: Invalid contact organization found for subject in composition component. This should be of type Organization. Hence request will not be processed further. Please try again with valid data. + - code: PAYR-1057 + space: reference-payer + message: Invalid general practioner type found for subject in composition component. This should be of type Organization/Practitioner/PractitionerRole. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html + - code: PAYR-1058 + space: reference-payer + message: Invalid managing organization type found for subject in composition component. This should be of type Organization. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html + - code: PAYR-1059 + space: reference-payer + message: Invalid encounter type found for composition/observation component. This should be of type Encounter. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-DiagnosticReportRecord.html + - code: PAYR-1060 + space: reference-payer + message: No subject found for encounter in composition component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + - code: PAYR-1061 + space: reference-payer + message: Invalid subject type found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + - code: PAYR-1062 + space: reference-payer + message: No episode of care found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + - code: PAYR-1063 + space: reference-payer + message: Invalid episode of care type found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + - code: PAYR-1064 + space: reference-payer + message: No based on found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + - code: PAYR-1065 + space: reference-payer + message: Invalid based on type found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + - code: PAYR-1066 + space: reference-payer + message: No appointment found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + - code: PAYR-1067 + space: reference-payer + message: Invalid appointment type found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + - code: PAYR-1068 + space: reference-payer + message: No reason reference found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + - code: PAYR-1069 + space: reference-payer + message: Invalid reason reference type found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + - code: PAYR-1070 + space: reference-payer + message: No author found for composition component. Hence request will not be processed further. + - code: PAYR-1071 + space: reference-payer + message: Invalid author type found for composition component. This should be of type Practitioner / PractitionerRole / Organization / Patient / Device / RelatedPerson. Hence request will not be processed further. Please try again with valid author type for the composition. + - code: PAYR-1072 + space: reference-payer + message: No procedure reference received for procedure element in claim resource. Hence request will not be processed further. + - code: PAYR-1073 + space: reference-payer + message: No based on found for observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Observation.html + - code: PAYR-1074 + space: reference-payer + message: Invalid based on type found for observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Observation.html + - code: PAYR-1075 + space: reference-payer + message: No part of found for observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Observation.html + - code: PAYR-1076 + space: reference-payer + message: Invalid part of type found for observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Observation.html + - code: PAYR-1077 + space: reference-payer + message: No subject found for observation component. Hence request will not be processed further. + - code: PAYR-1078 + space: reference-payer + message: Invalid subject type found for observation component. This should be of type Patient. Hence request will not be processed further. Please try again with valid subject type for the observation. + - code: PAYR-1079 + space: reference-payer + message: No care team details received. Hence request will not be processed further. Please add the care team details and try again. + - code: PAYR-1080 + space: reference-payer + message: Invalid HPR details received for practioner resource with url %s. Hence request will not be processed further. Please try again with valid HPR id. + - code: PAYR-1081 + space: reference-payer + message: Invalid service date received for item with sequence %s in claim resource. Hence request will not be processed further. Please try again with valid item service date. + - code: PAYR-1082 + space: reference-payer + message: Invalid title received for composition for supporting info with sequence %s in claim resource. Hence request will not be processed further. Please try again with valid composition title. + - code: PAYR-1083 + space: reference-payer + message: No HPR details found for the practitioner for resource %s. Hence request will not be processed further. Please send the details in the identifier for Practitioner resource with category code as HPIN. + - code: PAYR-1084 + space: reference-payer + message: No questionnaire response resource found for url %s. Hence request will not be processed further. Please add the resources for all the references given in the FHIR bundle and try again. + - code: PAYR-1085 + space: reference-payer + message: Invalid questionnaire response resource type found in the FHIR bundle for url %s. Hence request will not be processed further. + - code: PAYR-1086 + space: reference-payer + message: No procedure resource found for url %s. Hence request will not be processed further. Please add the resources for all the references given in the FHIR bundle and try again. + - code: PAYR-1087 + space: reference-payer + message: Invalid procedure resource type found in the FHIR bundle for url %s. Hence request will not be processed further. Procedure resource type is expected. + - code: PAYR-1088 + space: reference-payer + message: Invalid composition details. + - code: PAYR-1089 + space: reference-payer + message: No billing items found. Hence request will not be processed further. Please try again with valid billing items. + - code: PAYR-1090 + space: reference-payer + message: No identifier found for coverage component. Hence request will not be processed further. + - code: PAYR-1091 + space: reference-payer + message: No type found for coverage component identifier. Hence request will not be processed further. + - code: PAYR-1092 + space: reference-payer + message: Something went wrong while processing request, kindly intiate new request + - code: PAYR-1093 + space: reference-payer + message: No subject found for encounter in composition component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + - code: PAYR-1094 + space: reference-payer + message: Invalid subject type found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + - code: PAYR-1095 + space: reference-payer + message: Invalid discharge information received for claim request. Hence request will not be processed further. Please send the discharge information in supporting info in claim resource, with category as DIS (refer - https://www.nrces.in/ndhm/fhir/r4/ValueSet-ndhm-supportinginfo-category.html), and codes in LAMA/DAMA/DTH/DTM (refer - https://www.nrces.in/ndhm/fhir/r4/ValueSet-ndhm-supportinginfo-code.html). + - code: PAYR-1096 + space: reference-payer + message: Invalid death date received for claim request. Hence request will not be processed further. Please send the death date information in supporting info in claim resource, with category as ONS (refer - https://www.nrces.in/ndhm/fhir/r4/ValueSet-ndhm-supportinginfo-category.html), and code as DTM (refer - https://www.nrces.in/ndhm/fhir/r4/ValueSet-ndhm-supportinginfo-code.html). + - code: PAYR-1097 + space: reference-payer + message: No payload found in the request. Please ensure that the request that is being sent, contains encrypted payload within the mandatory payload properties. + - code: PAYR-1098 + space: reference-payer + message: Value type received as %s for category - OTH and code - EDT for item with sequence %s in supporting info in claim resource. In supporting info list, item with category - OTH and code - EDT combination is used to get the registration date. So the registration date should be sent as timing (date or period) or as a string value, adhering to the NRCES standards, with the category - OTH and code - EDT. + - code: PAYR-1099 + space: reference-payer + message: Value type received as %s for category - ONS and code - DSDE for item with sequence %s in supporting info in claim resource. In supporting info list, item with category - ONS and code - DSDE combination is used to get the discharge date. So the discharge date should be sent as timing (date or period) or as a string value, adhering to the NRCES standards, with the category - ONS and code - DSDE. + - code: PAYR-1101 + space: reference-payer + message: Invalid purpose received as (%s) for beneficiary id (%s) from hospital id (%s). Hence no result will be returned. Please try again with a valid purpose. + - code: PAYR-1102 + space: reference-payer + message: Invalid search parameter requested. Please try again with a valid id. + - code: PAYR-1103 + space: reference-payer + message: Invalid careplan id received. Please try again with valid careplan id. + - code: PAYR-1104 + space: reference-payer + message: Multiple records found for the beneficiary. Hence request will not be processed further. + - code: PAYR-1105 + space: reference-payer + message: Hospital configuration not found. Please contact support team. + - code: PAYR-1106 + space: reference-payer + message: No details found for the requested procedures in the system. + - code: PAYR-1107 + space: reference-payer + message: No billable item received. Please try again with valid item data. + - code: PAYR-1108 + space: reference-payer + message: No details found for the requested stratification in the system. + - code: PAYR-1109 + space: reference-payer + message: No details found for the requested investigations in the system. + - code: PAYR-1110 + space: reference-payer + message: No details found for the requested implants in the system. + - code: PAYR-1111 + space: reference-payer + message: Rule failure. + - code: PAYR-1112 + space: reference-payer + message: Invalid payer id received. Please try again ith valid payer details + - code: PAYR-1113 + space: reference-payer + message: Invalid item code received as %s. Please try again with valid data + - code: PAYR-1114 + space: reference-payer + message: Invalid speciality code received as %s for item %s. Please try again with valid data. Speciality code is available as the code of the category for specific cost of plan in isurance plan + - code: PAYR-1115 + space: reference-payer + message: Invalid procedure quantity received as %s for item %s. Please try again with valid data. Item quantity should be greater than 1 + - code: PAYR-1116 + space: reference-payer + message: Hospital is not authorized to raise any case under policy %s. Hence request will not be processed further. Please connect with the support team to get the required authorization + - code: PAYR-1117 + space: reference-payer + message: No policy details found for %s. Hence request will not be processed further + - code: PAYR-1118 + space: reference-payer + message: No details found for requested items. Hence request will not be processed further + - code: PAYR-1119 + space: reference-payer + message: No payer details received for payer id %s from HCX. Please try again with valid payer details. + - code: PAYR-1120 + space: reference-payer + message: Duplicate reference id found as %s. Please try again with valid reference details. + - code: PAYR-1121 + space: reference-payer + message: No policy details found for %s for beneficiary %s. Hence request will not be processed further. + - code: PAYR-1122 + space: reference-payer + message: No policy details found for beneficiary %s. Hence request will not be processed further. + - code: PAYR-1123 + space: reference-payer + message: Beneficiary is not a covered member for requested payer. Please enroll beneficiary for applicable policy of requested payer and try again. + - code: PAYR-1201 + space: reference-payer + message: Invalid claimed amount received for case number %s. Please try again with a valid claim amount. Claimed amount should be greater than INR 0 and less than equals to balance wallet amount of the beneficiary. + - code: PAYR-1202 + space: reference-payer + message: Invalid speciality code received as %s for item %s for case number %s. Please try again with valid data. Speciality code is available as the code of the category for specific cost of plan in isurance plan. + - code: PAYR-1203 + space: reference-payer + message: Invalid speciality description received as %s for procedure %s for case number %s. Please try again with valid data. Speciality description is available as the display of the category for specific cost of plan in isurance plan. + - code: PAYR-1204 + space: reference-payer + message: Invalid procedure code received as %s for case number %s. Please try again with valid data. Procedure code is available as the code of the type for benefit component, of specific cost, of plan in isurance plan. + - code: PAYR-1205 + space: reference-payer + message: Invalid procedure description received as %s for procedure %s for case number %s. Please try again with valid data. Procedure description is available as the display of the type for benefit component, of specific cost, of plan in isurance plan. + - code: PAYR-1206 + space: reference-payer + message: Invalid procedure type received as %s for procedure %s for case number %s. Please try again with valid data. + - code: PAYR-1207 + space: reference-payer + message: Invalid procedure factor received as %s for procedure %s for case number %s. Please try again with valid data. + - code: PAYR-1208 + space: reference-payer + message: Invalid procedure quantity received as %s for item %s for case number %s. Please try again with valid data. Item quantity should be greater than 1. + - code: PAYR-1209 + space: reference-payer + message: Invalid net amount received as INR %s for item %s for case number %s. Please try again with valid data. Item net amount should be greater than INR 0. + - code: PAYR-1210 + space: reference-payer + message: Invalid procedure status received as %s for procedure %s for case number %s. Please try again with valid data. + - code: PAYR-1211 + space: reference-payer + message: Requested beneficary details and careplan details does not match any criteria for processing the case at this hospital. Please try again with valid data. + - code: PAYR-1212 + space: reference-payer + message: No previous preauthorization approved record found for the enhancement request for case number %s. Hence request will not be processed further. Please initiate a new preauthorization. + - code: PAYR-1213 + space: reference-payer + message: Existing case in progress found for case number %s. Hence enhancement request will not be accepted. Please try after the adjudication is completed for the current case. + - code: PAYR-1214 + space: reference-payer + message: No previous preauthorization approved record found for the resubmission request for case number %s. Hence request will not be processed further. Please initiate a new preauthorization. + - code: PAYR-1215 + space: reference-payer + message: Existing case in progress found for case number %s. Hence resubmission request will not be accepted. Please try after the adjudication is completed for the current case. + - code: PAYR-1216 + space: reference-payer + message: Existing case in progress found for case number %s. Hence new preauthorization request will not be accepted. + - code: PAYR-1217 + space: reference-payer + message: Previous preauthorization approved record found for the new preauthorization request for case number %s. Hence request will not be processed further. Please initiate enhancement/resubmission. + - code: PAYR-1218 + space: reference-payer + message: No queried preauthorization record found for the query update request for case number %s. Hence request will not be processed further. + - code: PAYR-1219 + space: reference-payer + message: Case number %s is not queried. Hence query updation request will not be processed further. + - code: PAYR-1220 + space: reference-payer + message: Invalid investigation description received as %s for investigation code %s for case number %s. Please try again with valid data. + - code: PAYR-1221 + space: reference-payer + message: Invalid investigation code received as %s for case number %s. Please try again with valid data. + - code: PAYR-1222 + space: reference-payer + message: Invalid investigation status received as %s for investigation %s for case number %s. Please try again with valid data. + - code: PAYR-1223 + space: reference-payer + message: Invalid investigation attachment received for investigation %s for case number %s. Please try again with valid data. + - code: PAYR-1224 + space: reference-payer + message: Invalid implant description received as %s for implant code %s for case number %s. Please try again with valid data. + - code: PAYR-1225 + space: reference-payer + message: Invalid implant code received as %s for case number %s. Please try again with valid data. + - code: PAYR-1226 + space: reference-payer + message: Invalid implant status received as %s for investigation %s for case number %s. Please try again with valid data. + - code: PAYR-1227 + space: reference-payer + message: Invalid implant attachment received for investigation %s for case number %s. Please try again with valid data. + - code: PAYR-1228 + space: reference-payer + message: Invalid implant quantity received as %s for implant %s for case number %s. Please try again with valid data. + - code: PAYR-1229 + space: reference-payer + message: Invalid implant net amount received as INR %s for implant %s for case number %s. Please try again with valid data. + - code: PAYR-1230 + space: reference-payer + message: Invalid implant unit price received as INR %s for implant %s for case number %s. Please try again with valid data. + - code: PAYR-1231 + space: reference-payer + message: Claim has already been raised for case number %s. Hence preauthorization request will not be accepted. + - code: PAYR-1232 + space: reference-payer + message: No investigation found for case number %s. Investigation details are mandatory for private hospitals. + - code: PAYR-1233 + space: reference-payer + message: Patient liability is not aplicable for the hospital and beneficiary do not have enough wallet balance with deficit amount INR %s for the requested preauthorization for case number %s. + - code: PAYR-1234 + space: reference-payer + message: No preauthorization record found for case number %s. Hence the request will not be processed. + - code: PAYR-1235 + space: reference-payer + message: Insufficient wallet balance. Hence the request will not be processed. + - code: PAYR-1236 + space: reference-payer + message: Invalid claim type (in-patient/out-patient) received. Hence the request will not be processed. + - code: PAYR-1237 + space: reference-payer + message: Beneficiary is having an active preauthorization request at %s. Hence the request will not be processed. Kindly inform %s to cancel the active preauthorization request or raise a claim to proceed with current preauthorization. + - code: PAYR-1238 + space: reference-payer + message: Beneficiary is having an active preauthorization request at this hospital with reference number %s. Hence the request will not be processed. Kindly cancel the active preauthorization request or raise a claim to proceed with current preauthorization. + - code: PAYR-1239 + space: reference-payer + message: Hospital configuration not found. Please contact support team. + - code: PAYR-1240 + space: reference-payer + message: No details found for the requested procedures in the system. + - code: PAYR-1241 + space: reference-payer + message: Invalid registration date received for case number %s. Hence the request will not be processed. + - code: PAYR-1242 + space: reference-payer + message: Invalid registration date format received for case number %s. Hence the request will not be processed. + - code: PAYR-1243 + space: reference-payer + message: Invalid admission date received for case number %s. Hence the request will not be processed. + - code: PAYR-1244 + space: reference-payer + message: Invalid admission date format received for case number %s. Hence the request will not be processed. + - code: PAYR-1245 + space: reference-payer + message: Rule failure. + note: The SHA HP sandbox sent this code as "Only one conservative procedure can be booked for a case", on an enhancement that added a second Conservative package. + - code: PAYR-1246 + space: reference-payer + message: Invalid payer id received as %s. Please try again with valid payer id. + - code: PAYR-1247 + space: reference-payer + message: Payer details for payer id %s is not received from HCX for the request. Hence the request will not be processed. + - code: PAYR-1248 + space: reference-payer + message: Invalid item code received as %s for item sequence %s case number %s. Please try again with valid data. + - code: PAYR-1249 + space: reference-payer + message: Invalid item sequence received as %s for case number %s. Please try again with valid data. + - code: PAYR-1250 + space: reference-payer + message: Requested policy %s is not listed. Please try again with valid policy code. + - code: PAYR-1251 + space: reference-payer + message: No billable treatment plan received for case number %s. Please try again with valid treatment plan data. + - code: PAYR-1252 + space: reference-payer + message: Case number %s is not in active preauthorization state with the current status of the case with the payer system is %s. Hence the preauthorization can not be cancelled. Only the cases with current status as preauthorization submitted or preauthorization approved can be cancelled. + - code: PAYR-1253 + space: reference-payer + message: Case number %s is already cancelled. Hence the preauthorization can not be cancelled again. Only the cases with current status as preauthorization submitted or preauthorization approved can be cancelled. + - code: PAYR-1254 + space: reference-payer + message: Response for STG Questionnaire id %s is mandatory for procedure code %s. Hence the preauthorization request will not be processed as the questionnaire response is not received for procedure code. + - code: PAYR-1255 + space: reference-payer + message: Case number %s is already cancelled. Hence no preauthorization request will be accepted for this case number. New preauthorization request needs to be raised with new case/reference number to proceed further. + - code: PAYR-1256 + space: reference-payer + message: Response for Authentication Consent Questionnaire is missing for case number %s. This must be sent if the biometric authentication for patient is not available. For new preauthorization request, either biometric authentication for patient or response for Authentication Consent questionnaire must be sent. Please check/update the insurance plan for the policy for the details of the questionnaire. Please adhere to the response of the coverage eligibility for auth-requirements purpose to check the mandatory documents to be attached with the request + - code: PAYR-1257 + space: reference-payer + message: Payment is initiated for case number %s. Hence the preauthorization can not be cancelled again. Only the cases with current status as preauthorization submitted or preauthorization approved can be cancelled + - code: PAYR-1258 + space: reference-payer + message: Payment is accomplished/cleared for case number %s. Hence the preauthorization can not be cancelled again. Only the cases with current status as preauthorization submitted or preauthorization approved can be cancelled + - code: PAYR-1259 + space: reference-payer + message: DOB is missing for new born for the case number (%s) with correlation id as (%s) at (%s) + - code: PAYR-1260 + space: reference-payer + message: DOB cannot be a future date for the case number (%s) with correlation id as (%s) at (%s) + - code: PAYR-1261 + space: reference-payer + message: Invalid new born details for the case number (%s) with correlation id as (%s) at (%s) + - code: PAYR-1262 + space: reference-payer + message: Gender is mandatory for the new born beneficiary + - code: PAYR-1263 + space: reference-payer + message: Documents are mandatory for the new born beneficiary + - code: PAYR-1264 + space: reference-payer + message: Documents are mandatory for the new born beneficiary + - code: PAYR-1265 + space: reference-payer + message: Documents are mandatory for the new born beneficiary + - code: PAYR-1266 + space: reference-payer + message: Documents are mandatory for the new born beneficiary + - code: PAYR-1267 + space: reference-payer + message: Beneficiary is having an active preauthorization request for new born case at this hospital with reference number %s. Hence the request will not be processed. Kindly cancel the active preauthorization request or raise a claim to proceed with current preauthorization + - code: PAYR-1268 + space: reference-payer + message: Beneficiary is having an active preauthorization request for new born case at %s. Hence the request will not be processed. Kindly inform %s to cancel the active preauthorization request or raise a claim to proceed with current preauthorization + - code: PAYR-1269 + space: reference-payer + message: Date of birth received for new born beneficiary exceeds 6 years before the current date. New born cases can be raised only for the beneficiary whose date of birth is within 6 years of current date + - code: PAYR-1270 + space: reference-payer + message: Item LM100 is not applicable for preauthorization request. This item is expected/mandated only during claim submission if the patient is discharged after/during surgery under LAMA/DAMA category for PMJAY cases. + - code: PAYR-1271 + space: reference-payer + message: No value received for link id %s for Authentication Consent Questionnaire for preauthorization request. This must be sent if the biometric authentication for patient is not available. For new preauthorization request, either biometric authentication for patient or response for Authentication Consent questionnaire must be sent. Please check/update the insurance plan for the policy for the details of the questionnaire. Please adhere to the response of the coverage eligibility for auth-requirements purpose to check the mandatory documents to be attached with the request. + - code: PAYR-1272 + space: reference-payer + message: Invalid biometric user token received. Please try again with valid valid biometric details of the beneficiary. For any issues with biometric, please try with Authentication Consent Questionnaire, details for which has been received in response for coverage eligibliity auth-requirements. + - code: PAYR-1273 + space: reference-payer + message: No questionnaire found for the received selection. Please validate the questionnaire url from insurance plan/coverage auth-requirements response. + - code: PAYR-1301 + space: reference-payer + message: Claim has already been raised for case number %s. Hence new claim request will not be accepted. + - code: PAYR-1302 + space: reference-payer + message: No preauthorization approved record found for case number %s. Hence new claim request will not be accepted. + - code: PAYR-1303 + space: reference-payer + message: No active claim record found for case number %s. Hence query updation request will not be accepted. + - code: PAYR-1304 + space: reference-payer + message: No claim queried record found for case number %s. Hence query updation request will not be accepted. + - code: PAYR-1305 + space: reference-payer + message: Invalid usecase requested for case number %s. Please try again with valid usecase. + - code: PAYR-1306 + space: reference-payer + message: No item found in preauthorization request for procedure %s with item sequence %s for case number %s. Please try again with valid items. + - code: PAYR-1307 + space: reference-payer + message: Invalid quantity requested for procedure %s with item sequence %s for case number %s. Please try again with valid quantity. + - code: PAYR-1308 + space: reference-payer + message: No item found in active claim request for procedure %s with item sequence %s for case number %s. Please try again with valid items. + - code: PAYR-1309 + space: reference-payer + message: No item found in preauthorization request for implant %s with item sequence %s for case number %s. Please try again with valid items. + - code: PAYR-1310 + space: reference-payer + message: Invalid quantity requested for implant %s with item sequence %s for case number %s. Please try again with valid quantity. + - code: PAYR-1311 + space: reference-payer + message: No item found in active claim request for implant %s with item sequence %s for case number %s. Please try again with valid items. + - code: PAYR-1312 + space: reference-payer + message: No item found in preauthorization request for investigation %s with item sequence %s for case number %s. Please try again with valid items. + - code: PAYR-1313 + space: reference-payer + message: Invalid quantity requested for investigation %s with item sequence %s for case number %s. Please try again with valid quantity. + - code: PAYR-1314 + space: reference-payer + message: No item found in active claim request for investigation %s with item sequence %s for case number %s. Please try again with valid items. + - code: PAYR-1315 + space: reference-payer + message: Rejected item found for preauthorization for procedure %s with item sequence %s for case number %s. Please try again with valid items. + - code: PAYR-1316 + space: reference-payer + message: Rejected item found for preauthorization for investigation %s with item sequence %s for case number %s. Please try again with valid items. + - code: PAYR-1317 + space: reference-payer + message: Rejected item found for preauthorization for implant %s with item sequence %s for case number %s. Please try again with valid items. + - code: PAYR-1318 + space: reference-payer + message: No requested treatment plan found for case number %s. Please try again with valid items. + - code: PAYR-1319 + space: reference-payer + message: No requested investigation plan found for case number %s. Please try again with valid items. + - code: PAYR-1320 + space: reference-payer + message: No details found for the requested investigations in the system. Hence request will not be processed. + - code: PAYR-1321 + space: reference-payer + message: Error occurred while processing the request due to invalid workflow id as (%s) + - code: PAYR-1322 + space: reference-payer + message: No active case found for the given case number. + note: The SHA HP sandbox sent this code as "Active instance found for case number", for a second request on a case while the first was still queued. The sheet's message reads the opposite way. + - code: PAYR-1323 + space: reference-payer + message: Insufficient wallet balance. Hence the request will not be processed. + - code: PAYR-1324 + space: reference-payer + message: Invalid discharge stage received for case number %s. Hence the request will not be processed. + - code: PAYR-1325 + space: reference-payer + message: Invalid admission date received for case number %s. Hence the request will not be processed. + - code: PAYR-1326 + space: reference-payer + message: Invalid discharge date received for case number %s. Hence the request will not be processed. + - code: PAYR-1327 + space: reference-payer + message: Invalid admission date format received for case number %s. Hence the request will not be processed. + - code: PAYR-1328 + space: reference-payer + message: Invalid discharge date format received for case number %s. Hence the request will not be processed. + - code: PAYR-1329 + space: reference-payer + message: Invalid registration date received for case number %s. Hence the request will not be processed. + - code: PAYR-1330 + space: reference-payer + message: Invalid registration date format received for case number %s. Hence the request will not be processed. + - code: PAYR-1331 + space: reference-payer + message: Receiver not registered in NHCX. Please try again with valid receiver details. + - code: PAYR-1332 + space: reference-payer + message: Invalid CRC request. + - code: PAYR-1333 + space: reference-payer + message: Invalid claim type (in-patient/out-patient) received. Hence the request will not be processed. + - code: PAYR-1334 + space: reference-payer + message: Hospital configuration not found. Please contact support team. + - code: PAYR-1335 + space: reference-payer + message: Invalid implant quantity received as %s for implant %s for case number %s. Please try again with valid data. + - code: PAYR-1336 + space: reference-payer + message: Invalid implant unit price received as INR %s for implant %s for case number %s. Please try again with valid data. + - code: PAYR-1337 + space: reference-payer + message: Invalid implant net amount received as INR %s for implant %s for case number %s. Please try again with valid data. + - code: PAYR-1338 + space: reference-payer + message: Invalid implant attachment received for investigation %s for case number %s. Please try again with valid data. + - code: PAYR-1339 + space: reference-payer + message: Invalid implant status received as %s for investigation %s for case number %s. Please try again with valid data. + - code: PAYR-1340 + space: reference-payer + message: Invalid investigation status received as %s for investigation %s for case number %s. Please try again with valid data. + - code: PAYR-1341 + space: reference-payer + message: Invalid investigation attachment received for investigation %s for case number %s. Please try again with valid data. + - code: PAYR-1342 + space: reference-payer + message: Existing case in progress found for case number %s. Hence new reimbursement request will not be accepted. + - code: PAYR-1343 + space: reference-payer + message: Previous reimbursement approved record found for the new reimbursement request for case number %s. Hence request will not be processed further. + - code: PAYR-1344 + space: reference-payer + message: No details found for the requested procedures in the system. + - code: PAYR-1345 + space: reference-payer + message: Invalid procedure status received as %s for procedure %s for case number %s. Please try again with valid data. + - code: PAYR-1346 + space: reference-payer + message: Invalid procedure description received as %s for procedure %s for case number %s. Please try again with valid data. + - code: PAYR-1347 + space: reference-payer + message: Invalid procedure type received as %s for procedure %s for case number %s. Please try again with valid data. + - code: PAYR-1348 + space: reference-payer + message: Invalid procedure factor received as %s for procedure %s for case number %s. Please try again with valid data. + - code: PAYR-1349 + space: reference-payer + message: Invalid procedure quantity received as %s for procedure %s for case number %s. Please try again with valid data. + - code: PAYR-1350 + space: reference-payer + message: Invalid procedure net amount received as INR %s for procedure %s for case number %s. Please try again with valid data. + - code: PAYR-1351 + space: reference-payer + message: Invalid speciality code received as %s for procedure %s for case number %s. Please try again with valid data. + - code: PAYR-1352 + space: reference-payer + message: Requested beneficary details and careplan details does not match any criteria for processing the case at this hospital. Please try again with valid data. + - code: PAYR-1353 + space: reference-payer + message: Invalid careplan id received. Please try again with valid careplan id. + - code: PAYR-1354 + space: reference-payer + message: Rule failure. + - code: PAYR-1355 + space: reference-payer + message: No details found for the requested implants in the system. Hence request will not be processed. + - code: PAYR-1356 + space: reference-payer + message: Patient liability is not aplicable for the hospital and beneficiary do not have enough wallet balance with deficit amount INR %s for the requested preauthorization for case number %s. + - code: PAYR-1357 + space: reference-payer + message: Admission date cannot be after the discharge date. Hence request will not be processed. Please correct the data and try again. + - code: PAYR-1358 + space: reference-payer + message: Registration of the patient is allowed maximum upto %s days after admission. Hence request will not be processed. Please correct the data and try again. + - code: PAYR-1359 + space: reference-payer + message: No billable treatment plan received for case number %s. Please try again with valid treatment plan data. + - code: PAYR-1360 + space: reference-payer + message: Invalid item code received as %s for item sequence %s case number %s. Please try again with valid data. + - code: PAYR-1361 + space: reference-payer + message: Invalid item sequence received as %s for case number %s. Please try again with valid data. + - code: PAYR-1362 + space: reference-payer + message: No procedure with code LM100 received with 'Requested' status for case number %s. Please try again with valid data. For PMJAY claims, if case comes under LAMA/DAMA scenario with beneficiary being discharged before surgery or during surgery, procedure with code LM100 is mandatory. Only this procedure code will be accepted for LAMA/DAMA case, and all other previous preauthorization approved items will get disqualified for the claim submission + - code: PAYR-1363 + space: reference-payer + message: Response for Authentication Consent Questionnaire is missing for case number %s. This must be sent if the biometric authentication for patient is not available during discharge. For new claim request, either biometric authentication for patient during discharge, or response for Authentication Consent questionnaire must be sent. Please check/update the insurance plan for the policy for the details of the questionnaire. + - code: PAYR-1364 + space: reference-payer + message: No value received for link id %s for Authentication Consent Questionnaire for claim request. This must be sent if the biometric authentication for patient is not available during discharge. For new claim request, either biometric authentication for patient during discharge, or response for Authentication Consent questionnaire must be sent. Please check/update the insurance plan for the policy for the details of the questionnaire. + - code: PAYR-1365 + space: reference-payer + message: Response for STG Questionnaire id %s is mandatory for procedure code %s. Hence the preauthorization request will not be processed as the questionnaire response is not received for procedure code. + - code: PAYR-1366 + space: reference-payer + message: Invalid biometric user token received. Please try again with valid biometric details of the beneficiary. For any issues with biometric, please try with Authentication Consent Questionnaire for discharge, details for which has been received in insurance plan. + - code: PAYR-1367 + space: reference-payer + message: No biometric records found for the beneficiary for %s. Please ensure correctness of biometric authentication date for the day for cyclic procedure %s. + - code: PAYR-1368 + space: reference-payer + message: "%s units of cycle information received for procedure code %s with item sequence %s. Cycle information should be sent for all the requested/processed cycles." + - code: PAYR-1369 + space: reference-payer + message: Biometric authentication cannot be performed more than once on the same date. Multiple biometric authentication information has been provided for same date for cyclic procedure %s. Hence case will not be processed. Please check and update biometric authentication execution dates and try again. + - code: PAYR-1370 + space: reference-payer + message: Received invalid start date as %s for supporting details with item sequence %s. Please try again with valid start date. + - code: PAYR-1401 + space: reference-payer + message: policy not allowed for the hospital. Please reach out to technical support team. + - code: PAYR-1402 + space: reference-payer + message: Requested policy found not be associated with any payer for insurance plan request. Hence request will not be processed. + - code: PAYR-1403 + space: reference-payer + message: Requested renewal found not be associated with requested policy for insurance plan request. Hence request will not be processed. + - code: PAYR-1404 + space: reference-payer + message: No treatment provided for policy under any speciality. Please reach out to technical support team. + - code: PAYR-1405 + space: reference-payer + message: No enrolled hospital found for HFR id or sender id . Please reach out to technical support team. + - code: PAYR-1406 + space: reference-payer + message: Existing request with correlation id %s is in progress with the payer. Hence this request will not be accepted until the execution for previous request is complete. Please wait for 15 - 60 minutes to allow the execution of previous requests. For further assistance, please reach out to technical support team. + - code: PAYR-1501 + space: reference-payer + message: Value type received as %s for category - ONS and code - PSP for item with sequence %s in supporting info in claim resource. In supporting info list, item with category - ONS and code - PSP combination is used to get the surgery date. So the surgery date should be sent as timing (date or period) or as a string value, adhering to the NRCES standards, with the category - ONS and code - PSP. + - code: PAYR-1502 + space: reference-payer + message: Value type received as %s for category - ONS and code - ADDD for item with sequence %s in supporting info in claim resource. In supporting info list, item with category - ONS and code - ADDD combination is used to get the admission date. So the admission date should be sent as timing (date or period) or as a string value, adhering to the NRCES standards, with the category - ONS and code - ADDD. + - code: PAYR-1503 + space: reference-payer + message: Value type received as %s for category - ONS and code - DTM for item with sequence %s in supporting info in claim resource. In supporting info list, item with category - ONS and code - DTM combination is used to get the death date. So the death date should be sent as timing (date or period) or as a string value, adhering to the NRCES standards, with the category - ONS and code - DTM. + - code: PAYR-1504 + space: reference-payer + message: Value type received as %s for category - NMI and code - CQD for item with sequence %s in supporting info in claim resource. In supporting info list, item with category - NMI and code - CQD combination is used to get the overall case remarks for query response. So the case remarks for query response should be sent as a string value, adhering to the NRCES standards, with the category - NMI and code - CQD. + - code: PAYR-1505 + space: reference-payer + message: Category received as %s and code received as %s for item with sequence %s in supporting info in claim resource, where the reference value redirects to Questionnaire Response resource in the FHIR bundle. To include a policy/case level Questionnaire Response, in supporting info list there should be an entry with category - INF and code - ODN , and the value as reference. This reference value should refer to a resource of Questionnaire Response in the FHIR bundle. To include response for any STG questionnaire, in supporting info list there should be an entry with category - STG, and the value as reference + - code: PAYR-1506 + space: reference-payer + message: Invalid gender received for new born patient. Please try agian with valid gender data as it is mandatory for PMJAY in new born case. Please refer to the valid gender values at https://hl7.org/fhir/R4/valueset-administrative-gender.html + - code: PAYR-1507 + space: reference-payer + message: Invalid date of birth received for new born patient. Please try agian with valid date of birth as it is mandatory for PMJAY in new born case. + - code: PAYR-1508 + space: reference-payer + message: Invalid resource received for new born patient for url %s. Please try agian with valid Patient resource for the link reference as linked Patient resource is mandatory for PMJAY in new born case + - code: PAYR-1509 + space: reference-payer + message: Invalid attachment received for new born patient. Please try agian with valid attachment as attachment is mandatory for PMJAY in new born case + - code: PAYR-1510 + space: reference-payer + message: Invalid parameter code received. Please check and try again with a valid parameter code + - code: PAYR-1511 + space: reference-payer + message: Invalid parameter value received. Please check and try again with a valid parameter value + - code: PAYR-1512 + space: reference-payer + message: Invalid resource received for patient for url %s. Please try agian with valid Patient resource for the reference + - code: PAYR-1513 + space: reference-payer + message: Invalid diagnosis received in DiagnosisComponent. In DiagnosisComponent, diagnosis should be sent as CodeableConcept. Please try agian with valid data + - code: PAYR-1514 + space: reference-payer + message: Value type received as %s for category - DIS for item with sequence %s in supporting info in claim resource. In supporting info list, item with category - DIS is used to get the discharge related information. So the discharge information should be sent as string value, with value representing discharge stage (After Surgery / Before Surgery / During Surgery), with the category - DIS and code - DTH/LAMA/DAMA/DTM + - code: PAYR-1515 + space: reference-payer + message: Invalid name received for organization resource with url %s. Name is mandatory for organization resource. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html + - code: PAYR-1516 + space: reference-payer + message: No event found for api-caller-id %s and correlation id %s for sender code %s. Hence error response willnot be accepted. + - code: PAYR-1517 + space: reference-payer + message: Invalid error structure received for NHCX error. Protocol response structure is expected, but received JWEPayloadResponse. + - code: PAYR-1518 + space: reference-payer + message: No input parameters received for task resource. Input parameters are expected for task resource, but not received. Please try again with valid data. + - code: PAYR-1519 + space: reference-payer + message: No type found for task input parameters. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html + - code: PAYR-1520 + space: reference-payer + message: Invalid resource received for communication for url %s. Please try agian with valid Communication resource for the reference. + - code: ERR-PYR-CLM-007 + space: observed + message: No prior preauthorization or claim record found for case number + note: On none of the seven sheets. The SHA HP sandbox sent it for a claim raised under a number of its own rather than the preauthorisation's. diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf new file mode 100644 index 000000000..e82fbe443 Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(PROD)_NHCX-OnBoarding APIs Postman Collection.zip b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(PROD)_NHCX-OnBoarding APIs Postman Collection.zip new file mode 100644 index 000000000..e0668c535 Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(PROD)_NHCX-OnBoarding APIs Postman Collection.zip differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-NHCX USECASE Postman Collection.zip b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-NHCX USECASE Postman Collection.zip new file mode 100644 index 000000000..bc1821981 Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-NHCX USECASE Postman Collection.zip differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-PARTICIPANT SERVICE_APIs Postman Collection.zip b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-PARTICIPANT SERVICE_APIs Postman Collection.zip new file mode 100644 index 000000000..86800224a Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-PARTICIPANT SERVICE_APIs Postman Collection.zip differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)NHCX-OnBoarding APIs Postman Collection.zip b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)NHCX-OnBoarding APIs Postman Collection.zip new file mode 100644 index 000000000..ecc3718a6 Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)NHCX-OnBoarding APIs Postman Collection.zip differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Authenticating with NHCX.pdf b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Authenticating with NHCX.pdf new file mode 100644 index 000000000..17ba3932b Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Authenticating with NHCX.pdf differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Claim.pdf b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Claim.pdf new file mode 100644 index 000000000..4b9813cb4 Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Claim.pdf differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf new file mode 100644 index 000000000..3bf209e24 Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Coverage Eligibility.pdf b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Coverage Eligibility.pdf new file mode 100644 index 000000000..6c4fa6d5b Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Coverage Eligibility.pdf differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf new file mode 100644 index 000000000..ddab1ed5a Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Implementation Guide for Adoption of FHIR in ABDM and NHCX.pdf b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Implementation Guide for Adoption of FHIR in ABDM and NHCX.pdf new file mode 100644 index 000000000..f916c514b Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Implementation Guide for Adoption of FHIR in ABDM and NHCX.pdf differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Code Snippets references for payload preparation.pdf b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Code Snippets references for payload preparation.pdf new file mode 100644 index 000000000..091266720 Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Code Snippets references for payload preparation.pdf differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Dummy Payer Implementation.pdf b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Dummy Payer Implementation.pdf new file mode 100644 index 000000000..e338053d6 Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Dummy Payer Implementation.pdf differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Notification Integration.docx b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Notification Integration.docx new file mode 100644 index 000000000..129446587 Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Notification Integration.docx differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf new file mode 100644 index 000000000..608a5ba8c Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf new file mode 100644 index 000000000..680bc2d0b Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx new file mode 100644 index 000000000..cde3d7ac1 Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Usecases.pdf b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Usecases.pdf new file mode 100644 index 000000000..52922959a Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Usecases.pdf differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Production.pdf b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Production.pdf new file mode 100644 index 000000000..3ee28244e Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Production.pdf differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Sandbox.pdf b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Sandbox.pdf new file mode 100644 index 000000000..7b467af2c Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Sandbox.pdf differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Payment.pdf b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Payment.pdf new file mode 100644 index 000000000..3b3529f9d Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Payment.pdf differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Policy Linking and De-Linking Process.pdf b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Policy Linking and De-Linking Process.pdf new file mode 100644 index 000000000..fc92d217e Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Policy Linking and De-Linking Process.pdf differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Preauthorization.pdf b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Preauthorization.pdf new file mode 100644 index 000000000..3a7205b65 Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Preauthorization.pdf differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx new file mode 100644 index 000000000..9fe8bd810 Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standards for NHCX.pdf b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standards for NHCX.pdf new file mode 100644 index 000000000..9cc55028f Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standards for NHCX.pdf differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Steps to generate encryption Certificate.pdf b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Steps to generate encryption Certificate.pdf new file mode 100644 index 000000000..4ee0ef205 Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Steps to generate encryption Certificate.pdf differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx new file mode 100644 index 000000000..d0e4702e5 Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Biometric Authentication APIs Postman Collection.zip b/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Biometric Authentication APIs Postman Collection.zip new file mode 100644 index 000000000..675396c8e Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Biometric Authentication APIs Postman Collection.zip differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Biometric Authentication Implementation Steps.docx b/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Biometric Authentication Implementation Steps.docx new file mode 100644 index 000000000..86f621688 Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Biometric Authentication Implementation Steps.docx differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/FaceAuth Postman Collection.zip b/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/FaceAuth Postman Collection.zip new file mode 100644 index 000000000..f7b0973e2 Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/FaceAuth Postman Collection.zip differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Insurance Plan IG.docx b/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Insurance Plan IG.docx new file mode 100644 index 000000000..fa0ae5f8a Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Insurance Plan IG.docx differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx b/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx new file mode 100644 index 000000000..f83bb4877 Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf b/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf new file mode 100644 index 000000000..2beb05eb8 Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Overview.pdf b/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Overview.pdf new file mode 100644 index 000000000..f407944ac Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Overview.pdf differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Test Cases.xlsx b/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Test Cases.xlsx new file mode 100644 index 000000000..28ced0147 Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Test Cases.xlsx differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_APIs to be called based on scenario.xlsx b/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_APIs to be called based on scenario.xlsx new file mode 100644 index 000000000..f5e796cc4 Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_APIs to be called based on scenario.xlsx differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_Services-Request and Response.xlsx b/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_Services-Request and Response.xlsx new file mode 100644 index 000000000..90d217d0b Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_Services-Request and Response.xlsx differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/PMJAY Hospital Migration to HMIS via NHCX.docx b/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/PMJAY Hospital Migration to HMIS via NHCX.docx new file mode 100644 index 000000000..99b5e2338 Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/PMJAY Hospital Migration to HMIS via NHCX.docx differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip b/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip new file mode 100644 index 000000000..1fc8f5795 Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/manifest.json b/catalogue/openapi/.raw/nhcx-site-2026-09-14/manifest.json new file mode 100644 index 000000000..52c5b80a4 --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/manifest.json @@ -0,0 +1,1186 @@ +{ + "site": "https://hcxsbx.abdm.gov.in", + "fetched": "2026-09-14", + "bundle": "https://hcxsbx.abdm.gov.in/main.js", + "bundle_sha256": "f2ff7f475af068080cd06a3e5eb6cde96f7ee19b78858978423f3078a4ff010a", + "sheet": "NHCX-Website_DocumentDetails.xlsx - Sheet2.csv", + "files": [ + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Usecases.pdf", + "title": "NHCX Usecases", + "sheet_index": 1, + "sheet_purpose": "High level introduction to the NHCX usecases", + "listed_on": "https://hcxsbx.abdm.gov.in/#/documents", + "url": "https://hcxsbx.abdm.gov.in/images/af8d243edcc2139a515d.pdf", + "sha256": "8709b2907a0d5a0dbb36f5e63ed8deae269e0c75372b05d71ce7380c8a0929e7", + "bytes": 134558, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standards for NHCX.pdf", + "title": "Standards for NHCX", + "sheet_index": 2, + "sheet_purpose": "Standards followed in NHCX, FHIR introduction", + "listed_on": "https://hcxsbx.abdm.gov.in/#/documents", + "url": "https://hcxsbx.abdm.gov.in/images/a80bbc714dcb8793a81a.pdf", + "sha256": "71c4d37c54dffbd217fc0e33a34d2f9ed15bfeb1b7cbfabb2052cb03a565a139", + "bytes": 4329357, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Authenticating with NHCX.pdf", + "title": "Authenticating with NHCX", + "sheet_index": 3, + "sheet_purpose": "How to generate token using ABDM API for NHCX APIs", + "listed_on": "https://hcxsbx.abdm.gov.in/#/documents", + "url": "https://hcxsbx.abdm.gov.in/images/54d18468412741b759f3.pdf", + "sha256": "0ea90b635634844aaf8981e917cbf8b765ddd83a340f3c934883912599a62d8b", + "bytes": 87043, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Sandbox.pdf", + "title": "Onboarding providers and payers in Sandbox", + "sheet_index": 4, + "sheet_purpose": "How to onboard participants for NHCX in Sandbox", + "listed_on": "https://hcxsbx.abdm.gov.in/#/documents", + "url": "https://hcxsbx.abdm.gov.in/images/bc2efb078b98548f8e6b.pdf", + "sha256": "cbd03baf428655f0305e2f60ca331f8b76700496b070c522cafcc95001710b3a", + "bytes": 136691, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Onboarding providers and payers in Production.pdf", + "title": "Onboarding providers and payers in Production", + "sheet_index": 5, + "sheet_purpose": "How to onboard participants for NHCX in Production, it includes the role & registry ENUMs & the validations imposed.", + "listed_on": "https://hcxsbx.abdm.gov.in/#/documents", + "url": "https://hcxsbx.abdm.gov.in/images/260d0dec19a681e80262.pdf", + "sha256": "c38476fb90101f13fdfea447861292718d561e1dc088ae20950b193606500d2e", + "bytes": 116517, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)NHCX-OnBoarding APIs Postman Collection.zip", + "title": "AWS(Sandbox)NHCX-OnBoarding APIs Postman Collection", + "sheet_index": 6, + "sheet_purpose": "Postman Collection to onboard participants for NHCX in Sandbox(zip)", + "listed_on": "https://hcxsbx.abdm.gov.in/#/documents", + "url": "https://hcxsbx.abdm.gov.in/images/e683dda0a8cf953abbc7.zip", + "sha256": "ca4348e8a373c54bdcabd07eff8e49a55d93cdfae65fa5008ae0d56526a769f2", + "bytes": 4293, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(PROD)_NHCX-OnBoarding APIs Postman Collection.zip", + "title": "AWS(PROD)_NHCX-OnBoarding APIs Postman Collection", + "sheet_index": 7, + "sheet_purpose": "Postman Collection to onboard participants for NHCX in Production(zip)", + "listed_on": "https://hcxsbx.abdm.gov.in/#/documents", + "url": "https://hcxsbx.abdm.gov.in/images/293a43103f575b4e7f7f.zip", + "sha256": "b96963e2eead0fe3e718eb7dd2374f1a15f0dbb1aed7197a1ceae59cefbc7214", + "bytes": 1323, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Policy Linking and De-Linking Process.pdf", + "title": "Policy Linking and De-Linking Process", + "sheet_index": 8, + "sheet_purpose": "Policy Linking & De-linking validations & API implementation details(For Payer/TPA)", + "listed_on": "https://hcxsbx.abdm.gov.in/#/documents", + "url": "https://hcxsbx.abdm.gov.in/images/539853c50347b32b9a5e.pdf", + "sha256": "420115b9a54e15fa625312a56362164d92d23dd0d6ebf9195135bb00055d1911", + "bytes": 160995, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Coverage Eligibility.pdf", + "title": "Coverage Eligibility", + "sheet_index": null, + "sheet_purpose": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/documents", + "url": "https://hcxsbx.abdm.gov.in/images/cfcbe62e8378d4f48ee6.pdf", + "sha256": "69dd680ddac44231a97276a1d735e45777d8e43b5563b7248fd367a838d9744f", + "bytes": 279321, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Preauthorization.pdf", + "title": "Preauthorization", + "sheet_index": null, + "sheet_purpose": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/documents", + "url": "https://hcxsbx.abdm.gov.in/images/3799f26f2a0b2c9a80c5.pdf", + "sha256": "75d5628e7dd8a8e1a55c4ab3836c0591088ba378a8cd498e8277d83911129439", + "bytes": 303060, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Claim.pdf", + "title": "Claim", + "sheet_index": null, + "sheet_purpose": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/documents", + "url": "https://hcxsbx.abdm.gov.in/images/064cf2e059987011e53a.pdf", + "sha256": "66290de20d57d69e681946a0101518092ca43b3775bb38997c43beb17fb38076", + "bytes": 281674, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Payment.pdf", + "title": "Payment", + "sheet_index": null, + "sheet_purpose": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/documents", + "url": "https://hcxsbx.abdm.gov.in/images/b7260763ce8270b6baac.pdf", + "sha256": "6d372cdeec0abaea66b4d267c5ee6137a01830c577360dba7699e0244e49615f", + "bytes": 275075, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Provider Side Use Cases- Sandbox Exit Process.pdf", + "title": "NHCX Provider Side Use Cases- Sandbox Exit Process", + "sheet_index": 9, + "sheet_purpose": "What all usecases have to be covered by Provider, includes details like which API has to be implemented, at whose end, which bundle to be used, which status to be used & callback Logic to be implemented.", + "listed_on": "https://hcxsbx.abdm.gov.in/#/documents", + "url": "https://hcxsbx.abdm.gov.in/images/30714ca3bc1fa2ca3ec4.pdf", + "sha256": "1098cd595c986dca11bd09f2baad78f32b85ed68cec83524b5ec189643bade6a", + "bytes": 143930, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Payer Side Use Cases- Sandbox Exit Process.pdf", + "title": "NHCX Payer Side Use Cases- Sandbox Exit Process", + "sheet_index": 10, + "sheet_purpose": "What all usecases have to be covered by Payer, includes details like which API has to be implemented, at whose end, which bundle to be used, which status to be used & callback Logic to be implemented.", + "listed_on": "https://hcxsbx.abdm.gov.in/#/documents", + "url": "https://hcxsbx.abdm.gov.in/images/bd0c2ad1d5f672c40562.pdf", + "sha256": "50be7b035a2bed658b7cbbe2e8b02444aea2cda3e3af5ed04832565c825a603d", + "bytes": 149094, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Requests and Responses for UseCases.xlsx", + "title": "NHCX Requests and Responses for UseCases", + "sheet_index": 11, + "sheet_purpose": "While creating the FHIR bundles, what are the valuesets to be used, which bundle and what values are mandatory, tab wise covered for all usecases.(excel)", + "listed_on": "https://hcxsbx.abdm.gov.in/#/documents", + "url": "https://hcxsbx.abdm.gov.in/images/c8a5a74cc38bcd46586d.xlsx", + "sha256": "25d9426cab5661180103996888855e3cef20b701862d6800ec7659855303a913", + "bytes": 56137, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Workflow Status Sheets(with Codes).xlsx", + "title": "Workflow Status Sheets(with Codes)", + "sheet_index": 12, + "sheet_purpose": "Exhaustive list of the workflow codes to be shared in protected header(excel to be updated continuously as and when there is an update)", + "listed_on": "https://hcxsbx.abdm.gov.in/#/documents", + "url": "https://hcxsbx.abdm.gov.in/images/c42ad170f37c987ed173.xlsx", + "sha256": "f56dd156c232192296082f23b1561d0ff11fd40992e6675de41c5c991d579e6d", + "bytes": 13241, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Notification Integration.docx", + "title": "NHCX Notification Integration", + "sheet_index": null, + "sheet_purpose": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/documents", + "url": "https://hcxsbx.abdm.gov.in/images/01db86335b7c226eb745.docx", + "sha256": "05908862c103522fac0dbb482f8eb6a0f8536fc12b1ae3bdb0e98615f30812aa", + "bytes": 27710, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Code Snippets references for payload preparation.pdf", + "title": "NHCX Code Snippets references for payload preparation", + "sheet_index": 13, + "sheet_purpose": "Reference Code Snippet to prepare the payload for the usecases***", + "listed_on": "https://hcxsbx.abdm.gov.in/#/documents", + "url": "https://hcxsbx.abdm.gov.in/images/2b7fde4358fd0a4b2086.pdf", + "sha256": "cea0cfbf5897e9642eaf9a515a941b0a1de39474ea39444c9e05abe21cd9ec73", + "bytes": 265421, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Implementation Guide for Adoption of FHIR in ABDM and NHCX.pdf", + "title": "Implementation Guide for Adoption of FHIR in ABDM and NHCX", + "sheet_index": 14, + "sheet_purpose": "Implementation Guide for Adoption of FHIR in ABDM and NHCX", + "listed_on": "https://hcxsbx.abdm.gov.in/#/documents", + "url": "https://hcxsbx.abdm.gov.in/images/2c3fbb4e6b09f0834f69.pdf", + "sha256": "549377c9c26b1bd23decac3a1b9e5ebedfdc8e0fe99e53ef733859b188f51366", + "bytes": 1297683, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/API Response Handling to avoid Failures.pdf", + "title": "API Response Handling to avoid Failures", + "sheet_index": 15, + "sheet_purpose": "How to handle the error scenarios? How to properly send the protocol response to successfully close the request cycle.", + "listed_on": "https://hcxsbx.abdm.gov.in/#/documents", + "url": "https://hcxsbx.abdm.gov.in/images/7e71b563b562509cca5a.pdf", + "sha256": "b65cf1ec6dc1e33c7a9e77106ff7f1892e66d943598b64809f3a677752f6efbe", + "bytes": 55346, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Standard Error Codes.xlsx", + "title": "Standard Error Codes", + "sheet_index": 18, + "sheet_purpose": "All the error codes & scenarios, each usecase wise, bridge, NHCX(excel)", + "listed_on": "https://hcxsbx.abdm.gov.in/#/documents", + "url": "https://hcxsbx.abdm.gov.in/images/5a6cd3fe4604321fd732.xlsx", + "sha256": "3ab37546fe8a60adb66c37fab8ed707db6af8e1f1acd69350f8e267bb30acd76", + "bytes": 37123, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-PARTICIPANT SERVICE_APIs Postman Collection.zip", + "title": "AWS(Sandbox)-PARTICIPANT SERVICE_APIs Postman Collection", + "sheet_index": 16, + "sheet_purpose": "Postman collection for Participant Service APIs in Sandbox(zip)", + "listed_on": "https://hcxsbx.abdm.gov.in/#/documents", + "url": "https://hcxsbx.abdm.gov.in/images/b885e59891fedc7e725c.zip", + "sha256": "2d082f244ee41d137a62af82380dcd2d5db9ebbab66824fd54a23c506d4d9a7f", + "bytes": 1386, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/AWS(Sandbox)-NHCX USECASE Postman Collection.zip", + "title": "AWS(Sandbox)-NHCX USECASE Postman Collection", + "sheet_index": 17, + "sheet_purpose": "Postman collection for Usecase APIs in Sandbox(zip)", + "listed_on": "https://hcxsbx.abdm.gov.in/#/documents", + "url": "https://hcxsbx.abdm.gov.in/images/bc1e7d077857fc0fa071.zip", + "sha256": "9d15daafa813d6d57e688fe800baa5a73d2540b8d0d12c6a1315f86a424817e4", + "bytes": 527797, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/FAQs.pdf", + "title": "FAQs", + "sheet_index": 21, + "sheet_purpose": "FAQs", + "listed_on": "https://hcxsbx.abdm.gov.in/#/documents", + "url": "https://hcxsbx.abdm.gov.in/images/ff9eae6e99c1aee8a9fd.pdf", + "sha256": "5275f391537c7a97c0d11321951eb0420bd97ed42d1b3bce241c013c4b677dd8", + "bytes": 338757, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Common Mistakes while implementing through NHCX.pdf", + "title": "Common Mistakes while implementing through NHCX", + "sheet_index": 22, + "sheet_purpose": "Commonly observed mistakes and the resolution at the integrator level", + "listed_on": "https://hcxsbx.abdm.gov.in/#/documents", + "url": "https://hcxsbx.abdm.gov.in/images/038d85cffc7df66ed1a4.pdf", + "sha256": "b4af12a432a29886e1ae4956340ff07782bba7df792380de3a408f4e5a55673f", + "bytes": 61442, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/NHCX Dummy Payer Implementation.pdf", + "title": "NHCX Dummy Payer Implementation", + "sheet_index": 19, + "sheet_purpose": "NHCX Dummy Payer Implementation Guide", + "listed_on": "https://hcxsbx.abdm.gov.in/#/documents", + "url": "https://hcxsbx.abdm.gov.in/images/819467ec15aff13cc2a8.pdf", + "sha256": "97335ebc4cd32c86e0c34328b2f4c526420b32a7a009208364043d6334e9e757", + "bytes": 278011, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/documents/Steps to generate encryption Certificate.pdf", + "title": "Steps to generate encryption Certificate", + "sheet_index": 20, + "sheet_purpose": "Steps to generate the encryption certificate(public private key pair)-(Generic)", + "listed_on": "https://hcxsbx.abdm.gov.in/#/documents", + "url": "https://hcxsbx.abdm.gov.in/images/ec361a6c3e90e766d227.pdf", + "sha256": "94605e935f05ebb49e24dee50787cb4f3f1c401983a9616a5aaabdbc302f664b", + "bytes": 115492, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Overview.pdf", + "title": "NHCX-PMJAY-HMIS Integration Overview", + "sheet_index": 27, + "sheet_purpose": "NHCX-HMIS Integration Overview", + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/b6bd99dab49a5e928ea3.pdf", + "sha256": "c95469758a25cb8aca8c47757d8b18b4dedb8b4d42669663cff7343205f77fda", + "bytes": 800968, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Integration Guide.pdf", + "title": "NHCX-PMJAY-HMIS Integration Guide", + "sheet_index": 28, + "sheet_purpose": "NHCX-HMIS Integration Guide", + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/dffb62a375449b37ad73.pdf", + "sha256": "d9cdc0997294a788f33d2e00638c787dd790ebd2a2e52be97ad024d864c2b164", + "bytes": 3511014, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX PMJAY Integration Handbook.docx", + "title": "NHCX PMJAY Integration Handbook", + "sheet_index": 24, + "sheet_purpose": "NHCX-PMJAY Integration Handbook for the HMIS", + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/28df441a1ebeb1b0db15.docx", + "sha256": "beef72eb0c33bf23952d9260c30bfe6cc28796c731f5fbd2c4168e336f2859c1", + "bytes": 7721400, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/PMJAY Hospital Migration to HMIS via NHCX.docx", + "title": "PMJAY Hospital Migration to HMIS via NHCX", + "sheet_index": null, + "sheet_purpose": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/be2e25fede3bf711f783.docx", + "sha256": "cf5c9bf1c402b214f65bbb7bd0822f3a76d8ccda9b69c7bf77ba131befef3bc6", + "bytes": 33302, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Insurance Plan IG.docx", + "title": "Insurance Plan IG", + "sheet_index": 25, + "sheet_purpose": "Implementation Guide for the Insurance Plan bundle ", + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/13093b5f9b88fe826123.docx", + "sha256": "e9c6c82b6d67fd8476d6d19a5961419beb04e3c0613533453ed1e16e2a569cc1", + "bytes": 51790, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip", + "title": "Sample FHIR bundles", + "sheet_index": 29, + "sheet_purpose": "Sample FHIR", + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip", + "sha256": "8c7b24e3022733aaf7e8f517e12c11c0e8eddd6293844a2c4f3e9700fb720dca", + "bytes": 2163389, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip", + "title": "Sample FHIR bundles: FHIR_bundles_PMJAY_ext/claim/claimresponse_withQuery.txt", + "sheet_index": 29, + "sheet_purpose": "Sample FHIR", + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip", + "sha256": "45608023f68e10fc9158b0a778bc36814251e59c3a37c68cef324371560ed649", + "bytes": 6799, + "fetched": "2026-09-14", + "member": "FHIR_bundles_PMJAY_ext/claim/claimresponse_withQuery.txt", + "note": "Stored inside the zip only. member is the path inside it, sha256 is the member." + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip", + "title": "Sample FHIR bundles: FHIR_bundles_PMJAY_ext/claim/claim_queryUpdate_req.txt", + "sheet_index": 29, + "sheet_purpose": "Sample FHIR", + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip", + "sha256": "86c36cbc8c5d052f8abe395570b2f8994b559915e0b4fed3c92b71eb5f07876d", + "bytes": 376270, + "fetched": "2026-09-14", + "member": "FHIR_bundles_PMJAY_ext/claim/claim_queryUpdate_req.txt", + "note": "Stored inside the zip only. member is the path inside it, sha256 is the member." + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip", + "title": "Sample FHIR bundles: FHIR_bundles_PMJAY_ext/claim/claim_queryUpdate_response.txt", + "sheet_index": 29, + "sheet_purpose": "Sample FHIR", + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip", + "sha256": "c8cb9c00a5eb44a63ad7be0b99ff367e95ad0729716d38049fa990f0bc759847", + "bytes": 7209, + "fetched": "2026-09-14", + "member": "FHIR_bundles_PMJAY_ext/claim/claim_queryUpdate_response.txt", + "note": "Stored inside the zip only. member is the path inside it, sha256 is the member." + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip", + "title": "Sample FHIR bundles: FHIR_bundles_PMJAY_ext/claim/claim_Request.txt", + "sheet_index": 29, + "sheet_purpose": "Sample FHIR", + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip", + "sha256": "91628ac9cba97e3223df33970213739d6ea325414d60ec51a49a38508adf6973", + "bytes": 386100, + "fetched": "2026-09-14", + "member": "FHIR_bundles_PMJAY_ext/claim/claim_Request.txt", + "note": "Stored inside the zip only. member is the path inside it, sha256 is the member." + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip", + "title": "Sample FHIR bundles: FHIR_bundles_PMJAY_ext/coverageeligibility/coveragerequest_auth-requirement.txt", + "sheet_index": 29, + "sheet_purpose": "Sample FHIR", + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip", + "sha256": "754de71819afc509479f6722941eab53d0e1147db47c6a09072dc6459d5d50f6", + "bytes": 7213, + "fetched": "2026-09-14", + "member": "FHIR_bundles_PMJAY_ext/coverageeligibility/coveragerequest_auth-requirement.txt", + "note": "Stored inside the zip only. member is the path inside it, sha256 is the member." + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip", + "title": "Sample FHIR bundles: FHIR_bundles_PMJAY_ext/coverageeligibility/coveragerequest_benefits.txt", + "sheet_index": 29, + "sheet_purpose": "Sample FHIR", + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip", + "sha256": "88c7c415c29b33a1b239c9ddf659f17a0f5456b193e42c2b20e2bf85067e62b1", + "bytes": 7204, + "fetched": "2026-09-14", + "member": "FHIR_bundles_PMJAY_ext/coverageeligibility/coveragerequest_benefits.txt", + "note": "Stored inside the zip only. member is the path inside it, sha256 is the member." + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip", + "title": "Sample FHIR bundles: FHIR_bundles_PMJAY_ext/coverageeligibility/coveragerequest_validation.txt", + "sheet_index": 29, + "sheet_purpose": "Sample FHIR", + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip", + "sha256": "ec1104e4a0d3aa155c31d163726e90ff8e8636fb3fbbd660ac74799390f567c6", + "bytes": 7206, + "fetched": "2026-09-14", + "member": "FHIR_bundles_PMJAY_ext/coverageeligibility/coveragerequest_validation.txt", + "note": "Stored inside the zip only. member is the path inside it, sha256 is the member." + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip", + "title": "Sample FHIR bundles: FHIR_bundles_PMJAY_ext/coverageeligibility/coverageresponse_auth-requirement.txt", + "sheet_index": 29, + "sheet_purpose": "Sample FHIR", + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip", + "sha256": "de92d943b0de5c42e69e1566720a53f745fbc68adb5e9fdbb36ac38b57dbda1b", + "bytes": 15747, + "fetched": "2026-09-14", + "member": "FHIR_bundles_PMJAY_ext/coverageeligibility/coverageresponse_auth-requirement.txt", + "note": "Stored inside the zip only. member is the path inside it, sha256 is the member." + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip", + "title": "Sample FHIR bundles: FHIR_bundles_PMJAY_ext/coverageeligibility/coverageresponse_benefits.txt", + "sheet_index": 29, + "sheet_purpose": "Sample FHIR", + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip", + "sha256": "79ad66be8abd5bc9c6169073c71b308f51c749382831adf82e3f8ad108e325c0", + "bytes": 15729, + "fetched": "2026-09-14", + "member": "FHIR_bundles_PMJAY_ext/coverageeligibility/coverageresponse_benefits.txt", + "note": "Stored inside the zip only. member is the path inside it, sha256 is the member." + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip", + "title": "Sample FHIR bundles: FHIR_bundles_PMJAY_ext/coverageeligibility/coverageresponse_validation.txt", + "sheet_index": 29, + "sheet_purpose": "Sample FHIR", + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip", + "sha256": "a1f4052b76ee9cf91a5a61516ae18fab680da6425c1402a6ce6a5dfb1d0f7af8", + "bytes": 16042, + "fetched": "2026-09-14", + "member": "FHIR_bundles_PMJAY_ext/coverageeligibility/coverageresponse_validation.txt", + "note": "Stored inside the zip only. member is the path inside it, sha256 is the member." + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip", + "title": "Sample FHIR bundles: FHIR_bundles_PMJAY_ext/insuranceplan/insuranceplan_request.txt", + "sheet_index": 29, + "sheet_purpose": "Sample FHIR", + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip", + "sha256": "0146c8b643d3ad9f9e49fd40dc90f9dfadea460b92640af69940220929ace4f5", + "bytes": 1269, + "fetched": "2026-09-14", + "member": "FHIR_bundles_PMJAY_ext/insuranceplan/insuranceplan_request.txt", + "note": "Stored inside the zip only. member is the path inside it, sha256 is the member." + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip", + "title": "Sample FHIR bundles: FHIR_bundles_PMJAY_ext/insuranceplan/insuranceplan_response.txt", + "sheet_index": 29, + "sheet_purpose": "Sample FHIR", + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip", + "sha256": "aefdd425f0f644d943ef0a376df46f8f573bab5c4a036e8f13d055fb53796c04", + "bytes": 21163674, + "fetched": "2026-09-14", + "member": "FHIR_bundles_PMJAY_ext/insuranceplan/insuranceplan_response.txt", + "note": "Stored inside the zip only. member is the path inside it, sha256 is the member." + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip", + "title": "Sample FHIR bundles: FHIR_bundles_PMJAY_ext/paymentNotice/paymentNotice_ack.txt", + "sheet_index": 29, + "sheet_purpose": "Sample FHIR", + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip", + "sha256": "264482d55e1b4708e0bea78d21efd7915dffd473db81f5f7d239739bbf694483", + "bytes": 3164, + "fetched": "2026-09-14", + "member": "FHIR_bundles_PMJAY_ext/paymentNotice/paymentNotice_ack.txt", + "note": "Stored inside the zip only. member is the path inside it, sha256 is the member." + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip", + "title": "Sample FHIR bundles: FHIR_bundles_PMJAY_ext/paymentNotice/payment_notice.txt", + "sheet_index": 29, + "sheet_purpose": "Sample FHIR", + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip", + "sha256": "e2ac0c7de6220126a8c38d8943d41546180e8432add3e343022f682556b68007", + "bytes": 5334, + "fetched": "2026-09-14", + "member": "FHIR_bundles_PMJAY_ext/paymentNotice/payment_notice.txt", + "note": "Stored inside the zip only. member is the path inside it, sha256 is the member." + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip", + "title": "Sample FHIR bundles: FHIR_bundles_PMJAY_ext/preauth/cancel/preauth_cancel_req.txt", + "sheet_index": 29, + "sheet_purpose": "Sample FHIR", + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip", + "sha256": "f0d8495d6d659c6579a202efe1cedf206a655a5d8598855dba60021709b6ecf4", + "bytes": 3242, + "fetched": "2026-09-14", + "member": "FHIR_bundles_PMJAY_ext/preauth/cancel/preauth_cancel_req.txt", + "note": "Stored inside the zip only. member is the path inside it, sha256 is the member." + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip", + "title": "Sample FHIR bundles: FHIR_bundles_PMJAY_ext/preauth/cancel/preauth_cancel_response.txt", + "sheet_index": 29, + "sheet_purpose": "Sample FHIR", + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip", + "sha256": "64dd25aa8aa7c3dc36901bf060e7a7a2585165ee12aa5e356a307ad1bdf35882", + "bytes": 6603, + "fetched": "2026-09-14", + "member": "FHIR_bundles_PMJAY_ext/preauth/cancel/preauth_cancel_response.txt", + "note": "Stored inside the zip only. member is the path inside it, sha256 is the member." + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip", + "title": "Sample FHIR bundles: FHIR_bundles_PMJAY_ext/preauth/enhancement/enhancement_req.txt", + "sheet_index": 29, + "sheet_purpose": "Sample FHIR", + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip", + "sha256": "3aea0a6fa0f8f0ac90be9353d22060e1efaf3e08b25d18ab1a90b780c76f47fb", + "bytes": 468672, + "fetched": "2026-09-14", + "member": "FHIR_bundles_PMJAY_ext/preauth/enhancement/enhancement_req.txt", + "note": "Stored inside the zip only. member is the path inside it, sha256 is the member." + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip", + "title": "Sample FHIR bundles: FHIR_bundles_PMJAY_ext/preauth/enhancement/enhancement_resp.txt", + "sheet_index": 29, + "sheet_purpose": "Sample FHIR", + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip", + "sha256": "f47d69cd723a0368c1d08b216946c8c38250da3487d2e78df9b04a7e2a3a5b65", + "bytes": 7979, + "fetched": "2026-09-14", + "member": "FHIR_bundles_PMJAY_ext/preauth/enhancement/enhancement_resp.txt", + "note": "Stored inside the zip only. member is the path inside it, sha256 is the member." + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip", + "title": "Sample FHIR bundles: FHIR_bundles_PMJAY_ext/preauth/preauthresponse_with_query.txt", + "sheet_index": 29, + "sheet_purpose": "Sample FHIR", + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip", + "sha256": "9c889fd48b671e48e4afe52346a6b79216ef60b063483499230c98bd1af5e006", + "bytes": 7032, + "fetched": "2026-09-14", + "member": "FHIR_bundles_PMJAY_ext/preauth/preauthresponse_with_query.txt", + "note": "Stored inside the zip only. member is the path inside it, sha256 is the member." + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip", + "title": "Sample FHIR bundles: FHIR_bundles_PMJAY_ext/preauth/preauth_request.txt", + "sheet_index": 29, + "sheet_purpose": "Sample FHIR", + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip", + "sha256": "356c05649c74c549d0648864951b59fffeee9a68a28915955f9393d1ca473ea4", + "bytes": 374611, + "fetched": "2026-09-14", + "member": "FHIR_bundles_PMJAY_ext/preauth/preauth_request.txt", + "note": "Stored inside the zip only. member is the path inside it, sha256 is the member." + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip", + "title": "Sample FHIR bundles: FHIR_bundles_PMJAY_ext/preauth/Query/preauth_queryUpdate_req.txt", + "sheet_index": 29, + "sheet_purpose": "Sample FHIR", + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip", + "sha256": "3037b415ba36b9672938c235bb7cd651d5d007677db20c6c6e0c62947e59aa88", + "bytes": 233491, + "fetched": "2026-09-14", + "member": "FHIR_bundles_PMJAY_ext/preauth/Query/preauth_queryUpdate_req.txt", + "note": "Stored inside the zip only. member is the path inside it, sha256 is the member." + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Sample FHIR bundles.zip", + "title": "Sample FHIR bundles: FHIR_bundles_PMJAY_ext/preauth/Query/preauth_response_queryUpdate_App.txt", + "sheet_index": 29, + "sheet_purpose": "Sample FHIR", + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/140dbb309d5825459a7f.zip", + "sha256": "36553446e8f53ee61e87ee418f432761c898d8568c45bf861536b6dadb0ed532", + "bytes": 6846, + "fetched": "2026-09-14", + "member": "FHIR_bundles_PMJAY_ext/preauth/Query/preauth_response_queryUpdate_App.txt", + "note": "Stored inside the zip only. member is the path inside it, sha256 is the member." + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Biometric Authentication APIs Postman Collection.zip", + "title": "Biometric Authentication APIs Postman Collection", + "sheet_index": 30, + "sheet_purpose": "Biometric Authentication APIs Postman Collection", + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/8a3940fb518ea05d34e9.zip", + "sha256": "725dc838b39beb3e3ddd2c008314323e6d5cd1c237d98875280da5218da458a4", + "bytes": 1278, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_APIs to be called based on scenario.xlsx", + "title": "NHCX_APIs to be called based on scenario", + "sheet_index": 26, + "sheet_purpose": "Roadmap for the HMIS, NHCX - APIs to be called based on scenarios", + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/53347f5988b0ce5396f1.xlsx", + "sha256": "f92a30673d65dd2cc3cf09e2087c624f23f781dc4ca6b5cd8ec1825e224ac108", + "bytes": 11206, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX_Services-Request and Response.xlsx", + "title": "NHCX_Services-Request and Response", + "sheet_index": null, + "sheet_purpose": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/cf0f8438a47633383cf8.xlsx", + "sha256": "dfcebeac29ed667656facea2be54629f33d31f8d8d5464eed3180fc1618d0787", + "bytes": 55707, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/NHCX-PMJAY-HMIS Test Cases.xlsx", + "title": "NHCX-PMJAY-HMIS Test Cases", + "sheet_index": 31, + "sheet_purpose": "NHCX-PMJAY-HMIS Test Cases", + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/4d333fa6ce5ef99920de.xlsx", + "sha256": "0d95021974cfe81ab2e3bf66f983228a70b8fed8d7d251eb6d7eeab7354ecad2", + "bytes": 53750, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/Biometric Authentication Implementation Steps.docx", + "title": "Biometric Authentication Implementation Steps", + "sheet_index": null, + "sheet_purpose": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/9f1e6b545a693d38a704.docx", + "sha256": "fac8b14bfe8d518c0e651740537b9441c501d3cf2ab0f0482a07ab9f417e43a9", + "bytes": 676168, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/hmisdocuments/FaceAuth Postman Collection.zip", + "title": "FaceAuth Postman Collection", + "sheet_index": null, + "sheet_purpose": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/images/a2f07ff8158e86e9e92a.zip", + "sha256": "f2db63f7fe272178ee57acfcfd32dbc40680d69527dc35c6724f0da2a32fcaab", + "bytes": 1685, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/media/NHCX Brochure.pdf", + "title": "NHCX Brochure", + "sheet_index": null, + "sheet_purpose": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/media-center", + "url": "https://hcxsbx.abdm.gov.in/images/ad164778cba29aca553b.pdf", + "sha256": "3d2ed90dc150f50b7aa7bbcec1cb1f75ff375a36fea1ab75fdadfa2abd0b2239", + "bytes": 478457, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf", + "title": "Guide For Providers", + "sheet_index": null, + "sheet_purpose": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/media-center", + "url": "https://hcxsbx.abdm.gov.in/images/db83dc5cbbc464d8fa15.pdf", + "sha256": "d5c8e55232cc854aa273e0bf4813db17999d7cd5f212eb84d92544b6b9f97e2b", + "bytes": 1124890, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/claimhcxservice.json", + "title": "API specification: claimhcxservice", + "sheet_index": 23, + "sheet_purpose": "Swagger Links for all the usecases and the participant service, also please note that for usecases the payload creation index 13 & 11 files are important not the swagger, for participant service API swagger is releavant.", + "listed_on": "https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications", + "url": "https://hcxsbx.abdm.gov.in/claimhcxservice/api-docs", + "sha256": "488eea449c6ee45dc324f4f7c095a862c7d50d0e238075846122b51b2bab4878", + "bytes": 18846, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/communicationhcxservice.json", + "title": "API specification: communicationhcxservice", + "sheet_index": 23, + "sheet_purpose": "Swagger Links for all the usecases and the participant service, also please note that for usecases the payload creation index 13 & 11 files are important not the swagger, for participant service API swagger is releavant.", + "listed_on": "https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications", + "url": "https://hcxsbx.abdm.gov.in/communicationhcxservice/api-docs", + "sha256": "0ad58a98851158057d38d42a8327349548644c1b2f1a33b4f94acb4c1840a8a4", + "bytes": 17418, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/coverageeligibilityhcxservice.json", + "title": "API specification: coverageeligibilityhcxservice", + "sheet_index": 23, + "sheet_purpose": "Swagger Links for all the usecases and the participant service, also please note that for usecases the payload creation index 13 & 11 files are important not the swagger, for participant service API swagger is releavant.", + "listed_on": "https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications", + "url": "https://hcxsbx.abdm.gov.in/coverageeligibilityhcxservice/api-docs", + "sha256": "1723a4020b1b33d0bc1d7175609f0d05e6a6a78e8b4c52041222396639ceb52c", + "bytes": 27781, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/insuranceplanhcxservice.json", + "title": "API specification: insuranceplanhcxservice", + "sheet_index": 23, + "sheet_purpose": "Swagger Links for all the usecases and the participant service, also please note that for usecases the payload creation index 13 & 11 files are important not the swagger, for participant service API swagger is releavant.", + "listed_on": "https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications", + "url": "https://hcxsbx.abdm.gov.in/insuranceplanhcxservice/api-docs", + "sha256": "03665c6e6a5c8d86e3d621ab577dd683cf13c155d5b9529f5be6ca70fef13dee", + "bytes": 16461, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json", + "title": "API specification: participanthcxservice", + "sheet_index": 23, + "sheet_purpose": "Swagger Links for all the usecases and the participant service, also please note that for usecases the payload creation index 13 & 11 files are important not the swagger, for participant service API swagger is releavant.", + "listed_on": "https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications", + "url": "https://hcxsbx.abdm.gov.in/participanthcxservice/api-docs", + "sha256": "6d0a2192da8160fe4b292bbdd81e937ba254bf6d27915d23907e70b82faebf63", + "bytes": 54243, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/preauthhcxservice.json", + "title": "API specification: preauthhcxservice", + "sheet_index": 23, + "sheet_purpose": "Swagger Links for all the usecases and the participant service, also please note that for usecases the payload creation index 13 & 11 files are important not the swagger, for participant service API swagger is releavant.", + "listed_on": "https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications", + "url": "https://hcxsbx.abdm.gov.in/preauthhcxservice/api-docs", + "sha256": "2e8c594c51d9640ae4a576be34a5d190614918d1e7697d6718bc91c31fa66948", + "bytes": 14617, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/searchhcxservice.json", + "title": "API specification: searchhcxservice", + "sheet_index": 23, + "sheet_purpose": "Swagger Links for all the usecases and the participant service, also please note that for usecases the payload creation index 13 & 11 files are important not the swagger, for participant service API swagger is releavant.", + "listed_on": "https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications", + "url": "https://hcxsbx.abdm.gov.in/searchhcxservice/api-docs", + "sha256": "21749dd2ba84a19c5523772da359d76293493d44b48651f1af2e6042d78fa296", + "bytes": 15602, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/servicehcxpayment.json", + "title": "API specification: servicehcxpayment", + "sheet_index": 23, + "sheet_purpose": "Swagger Links for all the usecases and the participant service, also please note that for usecases the payload creation index 13 & 11 files are important not the swagger, for participant service API swagger is releavant.", + "listed_on": "https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications", + "url": "https://hcxsbx.abdm.gov.in/servicehcxpayment/api-docs", + "sha256": "f5c9e3728efbbeaa5e0e8083334b0ae60a05930e5a1e096ca06d40abb235d658", + "bytes": 14408, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/statushcxservice.json", + "title": "API specification: statushcxservice", + "sheet_index": 23, + "sheet_purpose": "Swagger Links for all the usecases and the participant service, also please note that for usecases the payload creation index 13 & 11 files are important not the swagger, for participant service API swagger is releavant.", + "listed_on": "https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications", + "url": "https://hcxsbx.abdm.gov.in/statushcxservice/api-docs", + "sha256": "93b6355a234ef56607427fcdfa32da4921124180c9df08ecd73c8af8955c2adf", + "bytes": 10082, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/subscriptionhcxservice.json", + "title": "API specification: subscriptionhcxservice", + "sheet_index": 23, + "sheet_purpose": "Swagger Links for all the usecases and the participant service, also please note that for usecases the payload creation index 13 & 11 files are important not the swagger, for participant service API swagger is releavant.", + "listed_on": "https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications", + "url": "https://hcxsbx.abdm.gov.in/subscriptionhcxservice/api-docs", + "sha256": "0d0d4781aa96017c06c8c2533e63dd1a6b36bb2342ebb51aeefca3349d892029", + "bytes": 6362, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/taskhcxservice.json", + "title": "API specification: taskhcxservice", + "sheet_index": 23, + "sheet_purpose": "Swagger Links for all the usecases and the participant service, also please note that for usecases the payload creation index 13 & 11 files are important not the swagger, for participant service API swagger is releavant.", + "listed_on": "https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications", + "url": "https://hcxsbx.abdm.gov.in/taskhcxservice/api-docs", + "sha256": "0418eca6478dece4d72c5a49a6547d50772511f7ffaf32f901f245591ba84656", + "bytes": 18522, + "fetched": "2026-09-14" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/documents.md", + "title": "Site page /documents", + "sheet_index": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/documents", + "url": "https://hcxsbx.abdm.gov.in/#/documents", + "sha256": "b72e2be3498bf91c751dcc2da569afc7950947446b0dff00cc3b6d63fc620c6b", + "bytes": 1045, + "fetched": "2026-09-14", + "extracted_from": "https://hcxsbx.abdm.gov.in/main.js sha256:f2ff7f475af068080cd06a3e5eb6cde96f7ee19b78858978423f3078a4ff010a" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications.md", + "title": "Site page /domain-specifications", + "sheet_index": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/domain-specifications", + "url": "https://hcxsbx.abdm.gov.in/#/domain-specifications", + "sha256": "56234dd8a55fe4eb9dd852779b22b522b04760c9bec5c263d5e9bc3ac2c6f167", + "bytes": 25255, + "fetched": "2026-09-14", + "extracted_from": "https://hcxsbx.abdm.gov.in/main.js sha256:f2ff7f475af068080cd06a3e5eb6cde96f7ee19b78858978423f3078a4ff010a" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__domain-data-specifications.md", + "title": "Site page /domain-specifications/domain-data-specifications", + "sheet_index": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/domain-specifications/domain-data-specifications", + "url": "https://hcxsbx.abdm.gov.in/#/domain-specifications/domain-data-specifications", + "sha256": "d5db7e162b098b4c9555367bd64d60ba7734ceee21eee7144a49cefa4f634fd8", + "bytes": 3316, + "fetched": "2026-09-14", + "extracted_from": "https://hcxsbx.abdm.gov.in/main.js sha256:f2ff7f475af068080cd06a3e5eb6cde96f7ee19b78858978423f3078a4ff010a" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__domain-data-specifications__domain-data-models.md", + "title": "Site page /domain-specifications/domain-data-specifications/domain-data-models", + "sheet_index": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/domain-specifications/domain-data-specifications/domain-data-models", + "url": "https://hcxsbx.abdm.gov.in/#/domain-specifications/domain-data-specifications/domain-data-models", + "sha256": "ef7c35f6b8782542c703073494e0b301bcd08a2f6dda891a648eb624f5813796", + "bytes": 3430, + "fetched": "2026-09-14", + "extracted_from": "https://hcxsbx.abdm.gov.in/main.js sha256:f2ff7f475af068080cd06a3e5eb6cde96f7ee19b78858978423f3078a4ff010a" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__domain-data-specifications__domain-data-models__e-objects.md", + "title": "Site page /domain-specifications/domain-data-specifications/domain-data-models/e-objects", + "sheet_index": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/domain-specifications/domain-data-specifications/domain-data-models/e-objects", + "url": "https://hcxsbx.abdm.gov.in/#/domain-specifications/domain-data-specifications/domain-data-models/e-objects", + "sha256": "1d5d7553c709c4d237d623bc77259999f84c1b114ab51b25112cbed075352c5b", + "bytes": 7202, + "fetched": "2026-09-14", + "extracted_from": "https://hcxsbx.abdm.gov.in/main.js sha256:f2ff7f475af068080cd06a3e5eb6cde96f7ee19b78858978423f3078a4ff010a" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__domain-data-specifications__domain-data-models__implementation-guide.md", + "title": "Site page /domain-specifications/domain-data-specifications/domain-data-models/implementation-guide", + "sheet_index": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/domain-specifications/domain-data-specifications/domain-data-models/implementation-guide", + "url": "https://hcxsbx.abdm.gov.in/#/domain-specifications/domain-data-specifications/domain-data-models/implementation-guide", + "sha256": "a1ec40fb966c0149ce4a090b694fc6267a1e7024c7b46b3703e46d7ffb15fa53", + "bytes": 721, + "fetched": "2026-09-14", + "extracted_from": "https://hcxsbx.abdm.gov.in/main.js sha256:f2ff7f475af068080cd06a3e5eb6cde96f7ee19b78858978423f3078a4ff010a" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__domain-data-specifications__domain-specific-languages.md", + "title": "Site page /domain-specifications/domain-data-specifications/domain-specific-languages", + "sheet_index": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/domain-specifications/domain-data-specifications/domain-specific-languages", + "url": "https://hcxsbx.abdm.gov.in/#/domain-specifications/domain-data-specifications/domain-specific-languages", + "sha256": "282e40fb1e4482fea5145242badce2c871f93e102c44c40ebf160efda3e68316", + "bytes": 1442, + "fetched": "2026-09-14", + "extracted_from": "https://hcxsbx.abdm.gov.in/main.js sha256:f2ff7f475af068080cd06a3e5eb6cde96f7ee19b78858978423f3078a4ff010a" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__domain-data-specifications__terminologies.md", + "title": "Site page /domain-specifications/domain-data-specifications/terminologies", + "sheet_index": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/domain-specifications/domain-data-specifications/terminologies", + "url": "https://hcxsbx.abdm.gov.in/#/domain-specifications/domain-data-specifications/terminologies", + "sha256": "1cdf48ceb570f19500e672dfb1140271aca01274a1d8c3e83cad336d5a5b082d", + "bytes": 2844, + "fetched": "2026-09-14", + "extracted_from": "https://hcxsbx.abdm.gov.in/main.js sha256:f2ff7f475af068080cd06a3e5eb6cde96f7ee19b78858978423f3078a4ff010a" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__healthcare-operation-policy.md", + "title": "Site page /domain-specifications/healthcare-operation-policy", + "sheet_index": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/domain-specifications/healthcare-operation-policy", + "url": "https://hcxsbx.abdm.gov.in/#/domain-specifications/healthcare-operation-policy", + "sha256": "489dcf5d19e3de929cb5d87754482bff57a5070891cced716acf69ba01e7023b", + "bytes": 1707, + "fetched": "2026-09-14", + "extracted_from": "https://hcxsbx.abdm.gov.in/main.js sha256:f2ff7f475af068080cd06a3e5eb6cde96f7ee19b78858978423f3078a4ff010a" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__healthcare-operation-policy__access-control.md", + "title": "Site page /domain-specifications/healthcare-operation-policy/access-control", + "sheet_index": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/domain-specifications/healthcare-operation-policy/access-control", + "url": "https://hcxsbx.abdm.gov.in/#/domain-specifications/healthcare-operation-policy/access-control", + "sha256": "7c3d7b2cf396a9daaca76ade1c059a8d358d0686b7b7e041e96c5f7f239dae57", + "bytes": 3341, + "fetched": "2026-09-14", + "extracted_from": "https://hcxsbx.abdm.gov.in/main.js sha256:f2ff7f475af068080cd06a3e5eb6cde96f7ee19b78858978423f3078a4ff010a" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__healthcare-operation-policy__guidelines-event-audits.md", + "title": "Site page /domain-specifications/healthcare-operation-policy/guidelines-event-audits", + "sheet_index": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/domain-specifications/healthcare-operation-policy/guidelines-event-audits", + "url": "https://hcxsbx.abdm.gov.in/#/domain-specifications/healthcare-operation-policy/guidelines-event-audits", + "sha256": "2ad75de1a412e4f39b1a922a0d90fa8f7c76770ea55a42cb4b308d3ba534a9c7", + "bytes": 1406, + "fetched": "2026-09-14", + "extracted_from": "https://hcxsbx.abdm.gov.in/main.js sha256:f2ff7f475af068080cd06a3e5eb6cde96f7ee19b78858978423f3078a4ff010a" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__healthcare-operation-policy__guidelines-for-grienvance-redressal.md", + "title": "Site page /domain-specifications/healthcare-operation-policy/guidelines-for-grienvance-redressal", + "sheet_index": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/domain-specifications/healthcare-operation-policy/guidelines-for-grienvance-redressal", + "url": "https://hcxsbx.abdm.gov.in/#/domain-specifications/healthcare-operation-policy/guidelines-for-grienvance-redressal", + "sha256": "c223f711b5158dbc2c3d10870c3a9610c4af32681306f53593babb64ee382230", + "bytes": 5448, + "fetched": "2026-09-14", + "extracted_from": "https://hcxsbx.abdm.gov.in/main.js sha256:f2ff7f475af068080cd06a3e5eb6cde96f7ee19b78858978423f3078a4ff010a" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__healthcare-operation-policy__guidlines-beneficiary.md", + "title": "Site page /domain-specifications/healthcare-operation-policy/guidlines-beneficiary", + "sheet_index": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/domain-specifications/healthcare-operation-policy/guidlines-beneficiary", + "url": "https://hcxsbx.abdm.gov.in/#/domain-specifications/healthcare-operation-policy/guidlines-beneficiary", + "sha256": "3eee6ea210a8711f953221c91f172513d9b0dd6a33c70367833d2755443fdb08", + "bytes": 1173, + "fetched": "2026-09-14", + "extracted_from": "https://hcxsbx.abdm.gov.in/main.js sha256:f2ff7f475af068080cd06a3e5eb6cde96f7ee19b78858978423f3078a4ff010a" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/hmisdocuments.md", + "title": "Site page /hmisdocuments", + "sheet_index": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "url": "https://hcxsbx.abdm.gov.in/#/hmisdocuments", + "sha256": "495145f1020dbd2d3b33748db906cb2461c5c82a68ff2a34e88c6170d9637e6d", + "bytes": 3663, + "fetched": "2026-09-14", + "extracted_from": "https://hcxsbx.abdm.gov.in/main.js sha256:f2ff7f475af068080cd06a3e5eb6cde96f7ee19b78858978423f3078a4ff010a" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/introduction-NHCX.md", + "title": "Site page /introduction-NHCX", + "sheet_index": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/introduction-NHCX", + "url": "https://hcxsbx.abdm.gov.in/#/introduction-NHCX", + "sha256": "39f92cfaa00639c278575132b12064ff6bfd557f16f324f13d8c2ccccf6153bb", + "bytes": 8713, + "fetched": "2026-09-14", + "extracted_from": "https://hcxsbx.abdm.gov.in/main.js sha256:f2ff7f475af068080cd06a3e5eb6cde96f7ee19b78858978423f3078a4ff010a" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/introduction-NHCX__guidlines-for-participant-onboarding.md", + "title": "Site page /introduction-NHCX/guidlines-for-participant-onboarding", + "sheet_index": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/introduction-NHCX/guidlines-for-participant-onboarding", + "url": "https://hcxsbx.abdm.gov.in/#/introduction-NHCX/guidlines-for-participant-onboarding", + "sha256": "58aaa762f2a04565e2060658b0eda95e3cac4cbb0819b6d865f04cf53066680d", + "bytes": 7545, + "fetched": "2026-09-14", + "extracted_from": "https://hcxsbx.abdm.gov.in/main.js sha256:f2ff7f475af068080cd06a3e5eb6cde96f7ee19b78858978423f3078a4ff010a" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md", + "title": "Site page /technical-specifications", + "sheet_index": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/technical-specifications", + "url": "https://hcxsbx.abdm.gov.in/#/technical-specifications", + "sha256": "b2d4834fa71f26721319a8222ad44feb35467592d62a00e6c3127ac3636e96cc", + "bytes": 21482, + "fetched": "2026-09-14", + "extracted_from": "https://hcxsbx.abdm.gov.in/main.js sha256:f2ff7f475af068080cd06a3e5eb6cde96f7ee19b78858978423f3078a4ff010a" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__api-specifications.md", + "title": "Site page /technical-specifications/api-specifications", + "sheet_index": 23, + "listed_on": "https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications", + "url": "https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications", + "sha256": "4207a3dd73d3c47b0bf5feeb43b0460d0fe8dda239cc7780b3f31ce055be3a06", + "bytes": 1415, + "fetched": "2026-09-14", + "extracted_from": "https://hcxsbx.abdm.gov.in/main.js sha256:f2ff7f475af068080cd06a3e5eb6cde96f7ee19b78858978423f3078a4ff010a" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__appendix-NHCX-relay-example.md", + "title": "Site page /technical-specifications/appendix-NHCX-relay-example", + "sheet_index": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/technical-specifications/appendix-NHCX-relay-example", + "url": "https://hcxsbx.abdm.gov.in/#/technical-specifications/appendix-NHCX-relay-example", + "sha256": "388adf4d8e2d90dfb77afc4c7884c3b4f9c910a3889b7ea0e14dab66058b66fe", + "bytes": 917, + "fetched": "2026-09-14", + "extracted_from": "https://hcxsbx.abdm.gov.in/main.js sha256:f2ff7f475af068080cd06a3e5eb6cde96f7ee19b78858978423f3078a4ff010a" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol.md", + "title": "Site page /technical-specifications/open-protocol", + "sheet_index": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol", + "url": "https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol", + "sha256": "c1743dd5227b173678ad12f1ad3c240346cbea07d41877ac3acaac95ca4f6c38", + "bytes": 360, + "fetched": "2026-09-14", + "extracted_from": "https://hcxsbx.abdm.gov.in/main.js sha256:f2ff7f475af068080cd06a3e5eb6cde96f7ee19b78858978423f3078a4ff010a" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy.md", + "title": "Site page /technical-specifications/open-protocol/data-security-and-privacy", + "sheet_index": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/data-security-and-privacy", + "url": "https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/data-security-and-privacy", + "sha256": "d18658f4efbde6f370d40805d08b6f1f56fdc9c1aa7cf965294255e3cd3f01d0", + "bytes": 766, + "fetched": "2026-09-14", + "extracted_from": "https://hcxsbx.abdm.gov.in/main.js sha256:f2ff7f475af068080cd06a3e5eb6cde96f7ee19b78858978423f3078a4ff010a" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy__api-security.md", + "title": "Site page /technical-specifications/open-protocol/data-security-and-privacy/api-security", + "sheet_index": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/data-security-and-privacy/api-security", + "url": "https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/data-security-and-privacy/api-security", + "sha256": "9fe2d5a643356558131e5de801b5f325b76f80aa48e931ee6b77e088dd90a65c", + "bytes": 4398, + "fetched": "2026-09-14", + "extracted_from": "https://hcxsbx.abdm.gov.in/main.js sha256:f2ff7f475af068080cd06a3e5eb6cde96f7ee19b78858978423f3078a4ff010a" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy__audit-and-reporting.md", + "title": "Site page /technical-specifications/open-protocol/data-security-and-privacy/audit-and-reporting", + "sheet_index": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/data-security-and-privacy/audit-and-reporting", + "url": "https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/data-security-and-privacy/audit-and-reporting", + "sha256": "3805b33513ec0863294014053849d921b6fc4093d1cd0356a5e10b9eb54ef6c6", + "bytes": 1169, + "fetched": "2026-09-14", + "extracted_from": "https://hcxsbx.abdm.gov.in/main.js sha256:f2ff7f475af068080cd06a3e5eb6cde96f7ee19b78858978423f3078a4ff010a" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy__message-security-and-integrity.md", + "title": "Site page /technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity", + "sheet_index": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity", + "url": "https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity", + "sha256": "3768fd89932e4081c9e03a8695619bcaf70c641e28bb55a77eec090bb926eeb3", + "bytes": 5151, + "fetched": "2026-09-14", + "extracted_from": "https://hcxsbx.abdm.gov.in/main.js sha256:f2ff7f475af068080cd06a3e5eb6cde96f7ee19b78858978423f3078a4ff010a" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy__transport-security.md", + "title": "Site page /technical-specifications/open-protocol/data-security-and-privacy/transport-security", + "sheet_index": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/data-security-and-privacy/transport-security", + "url": "https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/data-security-and-privacy/transport-security", + "sha256": "813457cac28a0322e6a8d1ab57a8c511fcc9345498023859f9dcf381a50f717c", + "bytes": 403, + "fetched": "2026-09-14", + "extracted_from": "https://hcxsbx.abdm.gov.in/main.js sha256:f2ff7f475af068080cd06a3e5eb6cde96f7ee19b78858978423f3078a4ff010a" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__healthclaims-exchange-protocol.md", + "title": "Site page /technical-specifications/open-protocol/healthclaims-exchange-protocol", + "sheet_index": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/healthclaims-exchange-protocol", + "url": "https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/healthclaims-exchange-protocol", + "sha256": "ff4b3aa02f2aa61e2b29e50699fe16bee82c3684908bc2be0815c07b97a83371", + "bytes": 12248, + "fetched": "2026-09-14", + "extracted_from": "https://hcxsbx.abdm.gov.in/main.js sha256:f2ff7f475af068080cd06a3e5eb6cde96f7ee19b78858978423f3078a4ff010a" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__keydesign-consideration.md", + "title": "Site page /technical-specifications/open-protocol/keydesign-consideration", + "sheet_index": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/keydesign-consideration", + "url": "https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/keydesign-consideration", + "sha256": "788b0c7c5652ff8ac6696287cb7f4bc84359b5efafc8fd47ef6d2d0c0538d3e7", + "bytes": 1590, + "fetched": "2026-09-14", + "extracted_from": "https://hcxsbx.abdm.gov.in/main.js sha256:f2ff7f475af068080cd06a3e5eb6cde96f7ee19b78858978423f3078a4ff010a" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__registries.md", + "title": "Site page /technical-specifications/open-protocol/registries", + "sheet_index": null, + "listed_on": "https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/registries", + "url": "https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/registries", + "sha256": "04bf78739fa0c3807a8a5a49d8c3e004f8aba664f524d0344d7fc44c3b2baf42", + "bytes": 3091, + "fetched": "2026-09-14", + "extracted_from": "https://hcxsbx.abdm.gov.in/main.js sha256:f2ff7f475af068080cd06a3e5eb6cde96f7ee19b78858978423f3078a4ff010a" + }, + { + "file": "catalogue/openapi/.raw/nhcx-site-2026-09-14/not-on-site/External_NHCX_Payer_Service_API_Workflow_Guide.docx", + "title": "NHCX Payer Service API Workflow Guide for External Integrators", + "sheet_index": null, + "listed_on": null, + "url": null, + "sha256": "1028d480d2fabe3204301f1c1b192a0077ddfa64f7f9084b01f73e004253fdd7", + "bytes": 32637, + "fetched": "2026-09-05", + "note": "Not listed on hcxsbx.abdm.gov.in on 2026-09-14 and not named in the document sheet. Received outside the site." + } + ] +} \ No newline at end of file diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf b/catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf new file mode 100644 index 000000000..f95c6a7a2 Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/media/Guide For Providers.pdf differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/media/NHCX Brochure.pdf b/catalogue/openapi/.raw/nhcx-site-2026-09-14/media/NHCX Brochure.pdf new file mode 100644 index 000000000..c14c829bf Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/media/NHCX Brochure.pdf differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/not-on-site/External_NHCX_Payer_Service_API_Workflow_Guide.docx b/catalogue/openapi/.raw/nhcx-site-2026-09-14/not-on-site/External_NHCX_Payer_Service_API_Workflow_Guide.docx new file mode 100644 index 000000000..4baa21fa0 Binary files /dev/null and b/catalogue/openapi/.raw/nhcx-site-2026-09-14/not-on-site/External_NHCX_Payer_Service_API_Workflow_Guide.docx differ diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/documents.md b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/documents.md new file mode 100644 index 000000000..ba89cae87 --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/documents.md @@ -0,0 +1,35 @@ +# https://hcxsbx.abdm.gov.in/#/documents + + NHCX Usecases +Standards for NHCX +Authenticating with NHCX +Onboarding providers and payers in Sandbox +Onboarding providers and payers in Production +AWS(Sandbox)NHCX-OnBoarding APIs Postman Collection +AWS(PROD)_NHCX-OnBoarding APIs Postman Collection +Policy Linking and De-Linking Process +Coverage Eligibility +Preauthorization +Claim +Payment + NHCX Provider Side Use Cases- Sandbox Exit Process +NHCX Payer Side Use Cases- Sandbox Exit Process +NHCX Requests and Responses for UseCases +Workflow Status Sheets(with Codes) +th + Aug 2026 +NHCX Notification Integration +NHCX Code Snippets references for payload preparation +Implementation Guide for Adoption of FHIR in ABDM and NHCX +API Response Handling to avoid Failures +Standard Error Codes +th + Aug 2026 +AWS(Sandbox)-PARTICIPANT SERVICE_APIs Postman Collection +AWS(Sandbox)-NHCX USECASE Postman Collection +FAQs +Common Mistakes while implementing through NHCX +NHCX Dummy Payer Implementation +Steps to generate encryption Certificate +Documents +last updated on : diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications.md b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications.md new file mode 100644 index 000000000..5a07e504e --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications.md @@ -0,0 +1,298 @@ +# https://hcxsbx.abdm.gov.in/#/domain-specifications + +Domain Specifications +The primary focus of domain specifications is to establish standardized formats for data exchange terminologies (taxonomies) These specifications include the following: +Domain Data Specifications +Agreement on data exchange formats and terminologies (taxonomies) is essential for domain specifications. These specifications would mainly include: +Domain data models: + are schema definitions of domain resources such as claims, providers, payers, policies, etc., and metadata specifications. The domain models are encoded using FHIR version 4 and published by National Resource Center for EHR Standards, CDAC. Please refer to the link. +https://nrces.in/ndhm/fhir/r4/hcx-profile.html +Metadata Specifications: + Metadata is data about data, which is associated with an object, document, or dataset for the purpose of describing, administering, ensuring technical functionality, and preserving the data. In the context of health claims, metadata specifications mainly involve coding systems and suggested values for key claim attributes such as disease codes, procedure codes, diagnostic codes, and billing-related codes (e.g. room rent, ICU charges, etc.) +To achieve this objective, in compliance with the main design principles outlined in the National Health Claims Exchange - Open Specifications, the following key design guidelines are recommended. +Key design considerations for FHIR profiles of NHCX +Base resource profiling +Profiling of the base resources is done to set minimum expectations for the Providers, Insurers and TPAs, to exchange financial and clinical information. +Re-use and Refer to existing ABDM FHIR Resources. +Published as part of the existing +FHIR Implementation Guide for ABDM. +Data Structure +FHIR Bundle resource has been adopted for encapsulation of the data shared across NHCX APIs. A Bundle can carry a collection of resources meeting certain criteria as part of any service operation. +The Bundle type ‘collection’ is identified to be suitable for NHCX. Bundle type collection allows all the FHIR requisite resources and provides claim cycle specific information flow like Eligibility check, pre-auth request, Claims request, etc. +The resources can be included directly as entries and no further/meta information is needed. +Focused NHCX Resources: +Preauth +Preauth Response +Claim +Claim Response +Coverage Eligibility Request +Coverage Eligibility Response +InsurancePlan +Payment Notice +Payment Reconciliation +Task +Stakeholder Consultation +Inputs from Domain Experts, Healthcare Providers, and Technical Experts for the design and development of the profiles. +Feedback from the vibrant community of implementors from India including the FHIR India Community and NHCX Community. +Involvement of expert bodies/organizations such as IRDAI. +Domain Data Models +Domain Data refers to structured information that is specific to a particular field or industry, in this case, healthcare and health claims processing. It encompasses all relevant data required to manage and exchange information within a domain. In the context of health claims, domain data includes essential information for processing claims, such as patient records, diagnosis, procedures, and payment details. +Components of Domain Data in Health Claims: +Patient Information: +Includes personal details like name, age, gender, and identification numbers (e.g., insurance ID). +Claims Information: +Data regarding the claim, such as claim number, date of submission, and status. - Diagnosis Codes: Medical coding systems (like ICD) used to identify and classify patient illnesses or conditions. +Procedure Codes: +Codes representing medical procedures or treatments provided to the patient, often following standards like CPT (Current Procedural Terminology). +Billing Information: +Data related to costs incurred, such as hospital charges, procedure costs, room rent, and other expenses. +Provider Details: +Information about the healthcare provider or facility submitting the claim, including credentials and authorization. +Payer Details: +Information regarding the insurance company or payer responsible for processing and reimbursing the claim. +Policy Information: +Details about the patient’s health insurance policy, including coverage limits, terms, and exclusions. +Metadata: +Additional details like timestamps, status codes, and audit logs related to claim processing. +Bundle Structure +In healthcare data exchange, a Bundle is a structured collection of resources grouped for transmission as a single unit. In the context of FHIR (Fast Healthcare Interoperability Resources), a Bundle is a container that holds multiple FHIR resources, allowing them to be transmitted or stored together. Each entry in the bundle represents a different FHIR resource, and the entire bundle is treated as a single message or dataset. +Types of Bundles: +Document Bundle: Contains a collection of resources that form a clinical document. +Message Bundle: Represents a set of resources used to form a message. +Transaction Bundle: Used for creating or updating multiple resources in a single transaction. +Collection Bundle: Holds an unordered set of resources, where the order doesn't matter. +Structure of a Bundle: +Bundletype: Specifies the type of bundle, e.g., "document," "message," "transaction," or "collection." +Entry: Contains an unordered list of FHIR resources. +Request/Response: Information about the HTTP action (for transactions). In the example you mentioned, an e-claim Bundle follows the "collection" type, where each entry in the bundle contains resources necessary for processing health claims. +For example, in a CoverageEligibilityRequest, the bundle would contain the corresponding FHIR resource for that specific action, which would be processed by the recipient system accordingly. +Reference: +The FHIR standard defines the Bundle resource and its usage. You can read more about it here in the FHIR R4 documentation. This structure ensures that different systems can interpret and process the bundled resources efficiently, whether they are handling health claims, eligibility checks, or other healthcare-related transactions. +Domain Headers +All data objects must be encrypted and transmitted securely within the API request body, ensuring that the actual payload is inaccessible to the NHCX gateways. However, providers and payers may share specific information with the NHCX gateways through fields available in the API request body. This information is sent as key-value pairs in the “domain_header” section of the request body and is stored by NHCX gateways for auditing and reporting purposes. +Each data object must define the specific values to be included in the “domain_header“of the API request body, adhering to the protocols outlined in the domain specifications. The domain headers serve as metadata and are essential for protocol-level operations such as auditing, but they do not carry sensitive health or claim-related data, which is protected within the encrypted payload. These fields must follow the naming convention x-NHCX- - for consistency across different implementations. For further reference, you can consult the domain specifications provided in the FHIR HCX profile: HCX Domain Specification +Implementation Guide +An Implementation Guide (IG) is published to assist ecosystem implementers in developing flow-specific payloads based on the FHIR specification for use within the NHCX ecosystem. This guide provides a set of rules and guidelines on how FHIR resources should be used, supported by detailed documentation to clarify and facilitate their proper implementation. The IG is designed to ensure that all stakeholders, including payers, providers, and other participants, can build and validate their content against the entire implementation guide. The guide also provides resources to validate payloads, ensuring they adhere to the established standards and protocols. The expanded profiles and structures of FHIR bundles and resources, as required for NHCX, can be accessed via the following link: +NHCX FHIR Profile. +This guide serves as a key resource for understanding how to implement and utilize FHIR resources in compliance with the NHCX protocols, supporting interoperability and seamless communication across the healthcare ecosystem. +Terminologies (Code sets or Metadata standards) +To achieve semantic interoperability, it is essential to incorporate established and widely accepted terminology and coding systems in NHCX data standards. These terminologies ensure that healthcare information is uniformly understood across different systems and stakeholders. In many HL7 standards, including FHIR, these terminologies are represented through concepts and codes, providing a necessary vocabulary and ontological framework for resources. They are used to define document types, element codes, and clinical coding systems such as procedure and diagnosis codes. In the context of FHIR, data standards often rely on Code Systems and ValueSets for consistent reference and usage. Code Systems define sets of concepts, and ValueSets define which codes from those systems can be used in a particular context. Adopting these will require agreement on their references and usages. NHCX follows domain-specific guidelines that align with the broader ABDM interoperability framework, ensuring uniformity across implementations. The table below lists key code systems and value sets proposed by the National Health Authority (NHA), and these terminologies are suggested to have "preferred" or "example" binding strengths, following FHIR Terminology binding strength definitions. +Terminology Name Term +FHIR Value Set link +Insurance Company Owners +coverageeligibilityrequest.insurer +Procedure Type +claim.procedure.type +Procedure Code +claim.procedure.procedure +Denial Codes +claimresponse.item.adjudication.reason +Procedure Modifiers +claim.item.modifier +Service Categories +claim.item.category +Service Codes +claim.item.productOrService +Medical Speciality Type +practitionerRole.speciality +Health Service Provider role +claim.careTeam.role +These terminologies ensure that the data is encoded in a standard manner, enabling smooth communication and processing between the various systems participating in the health claims exchange ecosystem. For more details on the code sets and their usage, you can explore the +FHIR Value Sets and Code Systems + used in NHCX. +Operational Guidlines +For a successful data exchange, it is important to have clear guidelines regarding various activities involved in onboarding entities on the NHCX ecosystem. These guidelines are essential to establish trust among all participants. The following are the areas are addressed: +Onboarding +Defaulting/Deboarding policies +Access control policies - These policies will determine the roles of each participant and their access to different parts of the data. This will also impact the visibility and access to domain-specific attributes that are included in the data structures defined by the data exchange. +Business SLAs +Service rating policies - The parameters and mechanisms for rating each participant's (actor) performance in the data exchange. +For the claims data exchange to be successful, it is important to have the trust and cooperation of all players in the ecosystem. Therefore, the policies that govern the exchange should aim to enable and gain the trust of the ecosystem. To achieve this, the following guidelines are recommended: +Participation and disqualification rules should be clearly defined and transparent. +Data exchange protocols/specifications should follow the principle of minimalism and be continuously improved over time. +Access Controls +The National Health Claims Exchange ecosystem involves participating systems with different roles. These roles are based on the base set of organization roles defined in HL7 specifications, and they are further qualified using namespaced coding to fit the claims exchange process.The following are the roles that participating systems may possess: +provider: Health Service Provider +payer: Insurance service provider +agency.tpa: Third party administrator acting on behalf of the payer. This role is expected to behave like a payer from the data exchange perspective. +agency.regulator: Regulatory bodies like IRDAI and IIB +research: Research groups, etc. +member.isnp: eCommerce platforms facilitating insurance adoption +agency.sponsor: Scheme owners of specific programs, e.g., NHA for Ayushman Bharat +HIE/HIO.NHCX: Other NHCXs +The corresponding access rights and scenarios for each role are described in the following table. +Role +Allowed actions +Comments +provider +Eligibility check +Send request +Receive response +Pre Auth +Send request +Receive response +Claims Request +Send request +Receive response +Payment +Receive Notice +Send Acknowledgement +Search/Status +Pre Auth +Claims Status +Providers can make search/status requests for multiple requests that originated from them. +payer/ agency.tpa +Eligibility check +Receive request +Send response +Pre Auth +Receive request +Send response +Claims Request +Receive request +Send response +Payment +Send Notice +Receive Acknowledgement +Search/Status +Payment confirmation +Payers can make search/status requests for multiple payment notices that originated from them. +agency.regulator +Search +Claims +Data exchange switch will forward the search request to all payers who are expected to return the claims data in the proposed FHIR structure as per regulator’s policies. +research +Eligibility check +Receive request +Send response +Search +Pre Auths - aggregate and/or anonymised +Claims - aggregate and/or anonymised +All data exhausts for these roles would only have aggregate and anonymised data. Key aggregations for eligibility requests, preauthentication, claims and payments information will need to be further defined. +member.isnp +Eligibility check +Receive request +Send response +Search +Pre Auths - aggregate and/or anonymised +Claims - aggregate and/or anonymised +Claims - Individual claims data as per beneficiary consent +As facilitators of insurance eCommerce, it is proposed to provide ISNPs access to the data available to research role as well as individual beneficiary queries (preauth, claims) based on beneficiary consent. This consent flow is expected to work with existing consent management infrastructure and ISNPs are expected to submit the acquired consent as part of the domain header. +agency.sponsor +As planners of the insurance schemes, sponsors are proposed to be given access equivalent to payer role. +HIE/HIO.NHCX +As an NHCX this participant is expected to play different roles as per the need of the use case. However, due to the data privacy and security measures prescribed in the Open Protocol, it will not be able to view the actual payload. +Guidelines for Participant Onboarding +Pre-requisites +Step 1: +Registration with Health Facility Registry (HFR) +Please visit +https://facility.abdm.gov.in/ + to complete the facility registration process. Please write to facility@nha.gov.in in case of any question on this step. +Step 2: +Apply on ABDM sandbox by filling in the registration form. The pre-requisite for NHCX is ABHA creation and verification. This implies that you must also complete the milestone M1 integration process. Firstly, apply for sandbox registration: +https://sandbox.abdm.gov.in/sandbox/v3/ +Step 3: +M1 Integration process under ABDM It is mandatory for your software to be enabled with M1 functionalities. +Documentation on ABDM Milestone: +https://sandbox.abdm.gov.in/sandbox/v3/new-documentation?doc=getting-started +https://sandbox.abdm.gov.in/sandbox/v3/new-documentation?doc=Milestone_one +https://sandbox.abdm.gov.in/sandbox/v3/new-documentation?doc=postman_collections +https://sandbox.abdm.gov.in/sandbox/v3/new-documentation?doc=ABDM_M3_V1 +Please follow our test cases for M1 and postman collection: +https://sandbox.abdm.gov.in/sandbox/v3/new-documentation?doc=TestCases +https://sandbox.abdm.gov.in/sandbox/v3/new-documentation?doc=postman_collections +Please visit Webinars 17 and 18 for detailed M1 integration at: +https://sandbox.abdm.gov.in/sandbox/v3/webinars +Link: +https://sandbox.abdm.gov.in/sandbox/v3/sandbox-registration +Further information: +https://sandbox.abdm.gov.in/sandbox/v3/new-documentation?doc=ABDMSandboxSignup +Integration support team will guide you if you encounter any roadblocks in the process. Please reach out to: +integration.support@nha.gov.in +After this step, the integrator can start with NHCX integration. +NHCX Onboarding +This section provides guidelines and an approach for participant onboarding in an NHCX ecosystem. As mentioned in the Access Control section above, there are different types of participants that need onboarding into an NHCX registry. +The onboarding process for NHCX is a two-step process, which is outlined below: +Sandbox - for compliance testing and certification +Go Live on live instance +Sections below provide a high-level process for each of these steps +1. NHCX Sandbox Process +The main objective of the sandbox is to assist the ecosystem in testing their individual components against communication standards and obtaining certification to become part of the system. Participants who complete the sandbox process successfully can use their certification to access the NHCX production environment. +Below are the steps for integrating, testing, and launching with the assistance of the sandbox: +Step 1: +Registration to access the NHCX sandbox, participants must submit an online application expressing their interest through the online portal + https://sandbox.abdm.gov.in. +Their applications are verified by conducting basic checks against the information provided. Some requests may not meet the requirements for sandbox access, such as multiple requests from the same participant, unregistered participants, Technology service providers without a valid website, and spam applications, among others, and will have to be filtered out. This process will be partially manual. Participants who pass the verification process will be added to the NHCX sandbox and provided with the necessary credentials (sandbox Client ID and secret key) to access the sandbox environment. +The client ID and client secret obtained from the sandbox ABDM portal during Milestone 1 integration must be used to generate an access token. Headers for reference- Api - +https://dev.abdm.gov.in/gateway/v0.5/sessions +This access token will be passed in headers of the: +https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice +/participant/create +After this you need to hit +https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice +/participant/create + api to generate the participant code for your respective registryid (client_id). +The same process will be followed if you are onboarding as a Payer / Provider. +Step 2: +Technology development: API integration and testing This step involves integrating the participants' claim processing applications with the NHCX sandbox to ensure compliance with NHCX standards and building any missing pieces on their side to use the NHCX APIs required for their planned workflows. +The sandbox website provides documentation and suggestions regarding software libraries, tools, and example implementations for encryption, FHIR resource generation, code generation, and other complex parts of the NHCX protocol. The sandbox portal provides participants with all necessary help to get started and complete API integration. +Please visit +https://hcxsbx.abdm.gov.in/#/documents + the use case documents for provider & payer are present in the website and can be downloaded. +Step 3: +Sandbox Certification: All participants must fulfill a set of functional (FHIR bundle validation, functional testing of key use cases) and security tests/flows applicable to them. The functional testing will be done on two levels- first with the internal NHCX team and final will be the HTC demo. After testing the system against the applicable test cases, participants must submit their test results, including the application's usage of and interaction with NHCX APIs, to the Sandbox Operator for review and approval. Upon successful review, the sandbox will issue a successful completion certificate. Participants can use this certificate to onboard the production environments of NHCX operators. +2. Go Live Process +Once the participant obtains the sandbox certification from the affiliated NHCX, they can apply for onboarding to the NHCX production environment. The following are the key steps in the onboarding process: +Step 1: Role Assignment in Production: +The appropriate role (payer/provider) will be assigned after the successful completion of the sandbox exit process. +Provider onboarding +Hospital nodal officer enroll the entity details in HFR +Details includes Entity Name, Entity HFR Id, Entity Address, Role as PROVIDER, Bridge Id(Provided by Software Vendor), public certificate for encryption or any other information required by the authority and upon successful registration, ABDM Gateway team will issue client credentials to access NHCX APIs with role as “PROVIDER”. +HMIs will register the Hospital into the NHCX registry. +Once the data is received by NHCX, NHCX system also verify the HFR Id by calling HFR registry APIs to validate the details provided during registration. +Once the data is verified by NHCX, the Hospital will be issued the participant code from the NHCX system. +Payer Onboarding +Insurance or TPA nodal officer enroll the entity details in NHA/IRDAI portal as PAYER/TPA +Details includes Entity Name, Entity Registry Id, Entity Address, Role as payer/TPA, Bridge Id(Provided by Software provider), public certificate for encryption or any other information required by the authority +IRDAI/NHA officer scrutiny the information provided by the payer and take an action. +Upon approval of the enrolment form, NHA portal/IRDAI portal register the participant by calling the register APIs. +Once the data is received by NHCX, NHCX system also verify the registry information by calling appropriate registry APIs. +Once the data is verified by NHCX, a communication will be sent to ABDM Gateway team to issue client credentials to access NHCX APIs with role as “PAYER” or” TPA” as per the request. +Step 2: Provisioning of production credentials: +Upon meeting the requirements, participants will be accessing Client ID and secret credentials (which will be the same as what you received in Production ABDM M1). It is the responsibility of participants to safeguard the secret credentials and immediately report any breaches to the NHCX Operators. +Step 3: NHCX Registration: +If a participant is already registered in the ABDM Health Facility registry/ IRDAI registry, they should have the option to use HFR/ IRDAI authentication to register in the NHCX registry. Follow the link for the detailed process of onboarding providers and payers in the system. +Step 4: Go-Live +Participants must prepare their application for go-live in their respective environments after obtaining the production credentials. NHCX recommends conducting the necessary training for staff and planning for change management before going live in production, preferably after a pilot with a small set of clients. +Deboarding scenarios +Deboarding of any participant will be done as and when the competent authority inactivates / blacklist the entity, this can be both voluntary deboarding (business is shut) as well as involuntary deboarding (malpractice or non-compliance) by the competent authority. + + +## Links on this page + +- https://nrces.in/ndhm/fhir/r4/hcx-profile.html +- https://nrces.in/ndhm/fhir/r4/index.html +- https://nrces.in/preview/ndhm/fhir/r4/hcx-profile.html +- https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-CoverageEligibilityRequestBundle.html +- https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-ClaimBundle.html +- https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Claim.html +- https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-ClaimResponse.html +- https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Claim-definitions.html#Claim +- https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-PractitionerRole-definitions.html +- https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Claim-definitions.html +- https://nrces.in/preview/ndhm/fhir/r4/ValueSet-ndhm-benefitcategory.html +- https://facility.abdm.gov.in/ +- https://sandbox.abdm.gov.in/sandbox/v3/ +- https://sandbox.abdm.gov.in/sandbox/v3/new-documentation?doc=getting-started +- https://sandbox.abdm.gov.in/sandbox/v3/new-documentation?doc=Milestone_one +- https://sandbox.abdm.gov.in/sandbox/v3/new-documentation?doc=postman_collections +- https://sandbox.abdm.gov.in/sandbox/v3/new-documentation?doc=ABDM_M3_V1 +- https://sandbox.abdm.gov.in/sandbox/v3/new-documentation?doc=TestCases +- https://sandbox.abdm.gov.in/sandbox/v3/webinars +- https://sandbox.abdm.gov.in/sandbox/v3/sandbox-registration +- https://sandbox.abdm.gov.in/sandbox/v3/new-documentation?doc=ABDMSandboxSignup +- https://sandbox.abdm.gov.in +- https://dev.abdm.gov.in/gateway/v0.5/sessions +- https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/participant/create +- https://hcxsbx.abdm.gov.in/#/documents diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__domain-data-specifications.md b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__domain-data-specifications.md new file mode 100644 index 000000000..f9115d7ac --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__domain-data-specifications.md @@ -0,0 +1,30 @@ +# https://hcxsbx.abdm.gov.in/#/domain-specifications/domain-data-specifications + +Domain Data Specifications +The most significant aspect of domain specification would be agreement on formats for data exchange and terminologies (taxonomies) being used in those data models. These would mainly include: +Domain data model - Schema definition of domain resources like Claims, Providers, Payors, Policies, etc. Domain models are encoded using FHIRV4 and published by NRECS,CDAC. +Metadata specifications - Metadata is data about data, data associated with an object, a document, or a dataset for purposes of description, administration, technical functionality, and preservation. For the context of claims, this would mainly involve coding systems and suggested values for key claim attributes like disease codes, procedure codes, diagnostic codes, billing-related codes (e.g. room rent, ICU charges, etc.), etc. +In order to achieve this, in line with the key design principles detailed in +National Health Claims Exchange - Open Specifications, +following key design guidelines are proposed: +Key Design Considerations +Data specifications should be broken down to simpler fundamental units as far as possible. +In order to leverage existing knowledge and resources and provide wider interoperability, data specifications should extend/ reuse/ adopt international/ national models wherever available/applicable. In order to follow this in claims context, data specification should leverage resources as follows: +Leverage HL7/FHIR R4 specifications wherever possible +Leverage NRCES FHIR specifications where base FHIR specs need contextualization to the Indian context +Create minimal extensions needed in case both base FHIR and NRCES specs are not enough to support the use case +FHIR Document profiles appropriate for the protocol should be created composed of base FHIR resources +Data specifications should be created with the principle of minimalism and inclusivity. In order to achieve this: +Specs should permissive cardinalities as much as possible. E.g. they should require minimal mandatory fields to enable maximal inclusion. As a thumb rule, wherever unsure of the cardinality of an attribute, the most permissible one should be used. +Specs should use permissive terminologies/code binding strength as much as possible. E.g. in the +FHIR terminology +construct (Section 4.1.5), if there’s a conflict in choosing between “extensible” and “preferred” strengths for a coding system, “preferred” should be chosen. +Data specifications should be extensible i.e. they should allow a way to capture extra information that was not initially included during the model design. To achieve this: +It may provide a simple map of key-value pairs. Future versions of the data model may choose to create mandatory/optional names attributes in the data models after researching the wider applicability of such fields. +Data specifications should allow for namespacing in field names to indicate the source/reason/category of the extended fields. +It is recommended that all timestamps be captured in ISO-8601 format e.g. 2020-08-15T17:02:53.495+05:30. APIs may define display format property to indicate the human-readable format most suitable for display. + + +## Links on this page + +- https://www.hl7.org/fhir/terminologies.html diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__domain-data-specifications__domain-data-models.md b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__domain-data-specifications__domain-data-models.md new file mode 100644 index 000000000..069cc2ee8 --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__domain-data-specifications__domain-data-models.md @@ -0,0 +1,46 @@ +# https://hcxsbx.abdm.gov.in/#/domain-specifications/domain-data-specifications/domain-data-models + +Domain Data Models +The domain data model consists of the electronic claim (e-claim) objects (a.k.a. eObjects) that are designed to capture the required information essential for processing a health claim transaction. The e-claim objects, being machine -eadable, facilitate the flow of data exchange between different systems and data processing in health claim transactions without the need for human intervention. +Guidelines for eObjects +Bundle Structure +All e-claim objects will be modelled as FHIR bundles of type "document", with "bundle.composition.type" specifying the type of bundle. +The first resource in the bundle shall be a “Composition” resource followed by a series of other resources referenced from the “Composition” resource. The elements “type”, “category” and “section” in the “Composition” shall be used to define the purpose and set the context of the document. +For example, the data packet for a coverage eligibility check request will be a bundle with “bundle.composition.type” as “Coverage Eligibility Check” and the bundle will have a “CoverageEligibilityRequest” FHIR resource embedded in it. +CoverageEligibilityRequest Document +type = “document” +composition +type = “Coverage Eligibility Check Bundle” +section : cardinality (1..1) +code = “Insurance Record” +entry : cardinality (1..1) +reference : “CoverageEligibilityRequest” +CoverageEligibilityRequest FHIR resource + Patient FHIR resource + Coverage FHIR resource +Any other resources referenced in the CoverageEligibilityRequest resource +Identifiers: +For any resources requiring identifiers (e.g. Patient.identifier), naming systems have to be defined and agreed upon within the affinity domain to be specified in the “identifier.system” element to namespace the identifier value. This can allow an entity or resource to be referenced against system-specific identifiers. For example, a patient may be referenced as: +{ +"resourceType": "Patient", +"identifier": [ +{ +"system": "https://ndhm.gov.in/patients", +"value": "hinapatel@ndhm" +} +, +{ +"system": "https://pmjay.gov.in/beneficiaries", +"value": "QWRT23456" +} +] +} +For some identifiers, “identifier.type” can be used to provide additional information. +“identifier.use” can be used to indicate what/where/how a particular identifier might be used for. + Example: +Resources +For external entities like patients, organisations, practitioners, etc, a reference alone is enough unless additional information is required to be passed. For example, patient address & other demographics. +Domain Header +All eObjects shall be encrypted and sent in the API request body and cannot be accessed by the NHCX gateways. However, there is a provision in the API request body for providers and payers to share certain eObjects' related information with the NHCX gateway. This information can be sent in the domain_header part of the request body (as key-value pairs) which can be accessed and stored by NHCX gateways for auditing and reporting purposes. Each eObject shall define the domain header values that are to be sent in the API request body. +Search Parameters +In addition to the workflow APIs for claim processing workflows, NHCX also defines APIs for searching eObjects. To support the search APIs, all eObjects will define the search request parameters. diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__domain-data-specifications__domain-data-models__e-objects.md b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__domain-data-specifications__domain-data-models__e-objects.md new file mode 100644 index 000000000..8b8aa7d53 --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__domain-data-specifications__domain-data-models__e-objects.md @@ -0,0 +1,200 @@ +# https://hcxsbx.abdm.gov.in/#/domain-specifications/domain-data-specifications/domain-data-models/e-objects + +eObjects +This version of the NHCX specification defines the domain model specifications required for the following eObjects: +Coverage Eligibility Request and Coverage Eligibility Response +Claim Request and Claim Response: These objects will be used for both Pre-Authorization and Claim use cases (and for Pre-Determination also in future). +Payment Notice and Payment Reconciliation +As mentioned in the design considerations for domain specification, the eObjects leverage HL7/FHIR4 specification and extend it, wherever required. +Coverage Eligibility Request +As per the design considerations and guidelines listed in the previous sections, the coverage eligibility request payload has to be created as an FHIR document bundle. The bundle should have the following resources: +Resource +Description +Composition +type: + should be a code representing Coverage Eligibility Request document type. +section: + The document shall have one section with a single entry having reference to CoverageEligibilityRequest resource. +structure definition: +CoverageEligibilityRequest Document +CoverageEligibilityRequest +The document must contain a CoverageEligibilityRequest resource. +FHIR Profile: +link +structure definition: +CoverageEligibilityRequest +Patient +The document should contain a Patient resource with minimal required information about the patient (refer to rows #38-42 in the “ +CoverageEligibilityRequest +” sheet). +FHIR Profile details: +Patient resources should mandatorily have an NDHM identifier. +Patient resources can also have a hospital Id (Medical record number). +Patient resources can also have an insurance id (PMJAY ID). +Patient resources can also have employee IDs and other business identifiers. +Structure Definition: +Patient +Coverage +The document should contain one or more Coverage resources with minimal information of the policy about which the information is requested (refer to row#30 in the “ +CoverageEligibilityRequest +” sheet). FHIR Profile details: +Coverage resources should mandatorily have an identifier for the policy ID issued by the insurer. +Structure definition : +Coverage +Domain Headers: +Key +Description +Search Parameters: +Key +Description +Coverage Eligibility Response +Resource +Description +Composition +type: + should be a code representing Coverage Eligibility Request document type. +section: + The document shall have one section with a single entry having reference to CoverageEligibilityRequest resource. +structure definition: +CoverageEligibilityRequest Document +CoverageEligibilityRequest +The document must contain a CoverageEligibilityRequest resource. +FHIR Profile: +link +structure definition: +CoverageEligibilityRequest +Coverage +The document should contain one or more Coverage resources with minimal information of the policy about which the information is requested (refer to row#30 in the “ +CoverageEligibilityRequest +” sheet). FHIR Profile details: +Coverage resources should mandatorily have an identifier for the policy ID issued by the insurer. +Structure definition : +Coverage +Domain Headers: +Key +Description +Search Parameters: +Key +Description +Claim Request +Claim object is used by providers to submit pre-authorization and claim requests to the payers. The same eObject can be used for both these use cases and the usage can be differentiated by the value of “claim.use” element. The value of this element should be set as +“preauthorization” + for Pre-Authorization requests and as +“claim” + for Claim requests. +Resource +Description +Composition +type: + should be a code representing Coverage Eligibility Request document type. +section: + The document shall have one section with a single entry having reference to CoverageEligibilityRequest resource. +structure definition: +CoverageEligibilityRequest Document +CoverageEligibilityRequest +The document must contain a CoverageEligibilityRequest resource. +FHIR Profile: +link +structure definition: +CoverageEligibilityRequest +Patient +The document should contain a Patient resource with minimal required information about the patient (refer to rows #38-42 in the “ +CoverageEligibilityRequest +” sheet). +FHIR Profile details: +Patient resources should mandatorily have an NDHM identifier. +Patient resources can also have a hospital Id (Medical record number). +Patient resources can also have an insurance id (PMJAY ID). +Patient resources can also have employee IDs and other business identifiers. +Structure Definition: +Patient +Coverage +The document should contain one or more Coverage resources with minimal information of the policy about which the information is requested (refer to row#30 in the “ +CoverageEligibilityRequest +” sheet). FHIR Profile details: +Coverage resources should mandatorily have an identifier for the policy ID issued by the insurer. +Structure definition : +Coverage +Encounter +Details of the Encounters during which this Claim was created or to which the creation of this Claim is associated. +FHIR Profile: +link +Structure Definition: +Encounter +Condition +Details of the health conditions relevant to this Claim request. +FHIR Profile: +link +Structure Definition: +Condition +Signature resources +List of signatures by Hospital, Doctor and Patient associated with this Claim request. +Structure Definition: +Signature +Domain Headers: +Key +Description +Usage +“preauthorization” or “claim”, to indicate the use case this eObject is being used for. +Search Parameters: +Key +Description +Claim Response +ClaimResponse object is used by payers to send the response for pre-authorization and claim requests to the providers. The same eObject can be used for both these use cases and the usage can be differentiated by the value of “ClaimResponse.use” element. The value of this element should be set as “ +preauthorization +” for Pre-Authorization responses and as “ +claim +” for Claim responses. +Resource +Description +Composition +type: + should be a code representing Coverage Eligibility Request document type. +section: + The document shall have one section with a single entry having reference to CoverageEligibilityRequest resource. +structure definition: +CoverageEligibilityRequest Document +Claim Response +The document must contain a ClaimResponse resource. +FHIR Profile: +Link +Structure Definition: +ClaimResponse +Domain Headers: +Key +Description +Usage +“preauthorization” or “claim”, to indicate the use case this eObject is being used for. +Search Parameters: +Key +Description +Payment Notice +Resource +Description +Composition +type: + should be a code representing Payment Notice document type. +section: + The document shall have one section with a single entry having reference to PaymentNotice resource. +PaymentNotice +The document must contain a PaymentNotice resource. +FHIR Profile: +link +Structure Definition: +PaymentNotice +PaymentReconciliation +The document should contain a PaymentReconciliation resource with information about the payment related to this payment notice. +FHIR Profile: +link +Structure Definition: +PaymentReconciliation +Domain Headers: +Key +Description +Search Parameters: +Key +Description +previous +   Domain Data Models +next +Implementation Guide   diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__domain-data-specifications__domain-data-models__implementation-guide.md b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__domain-data-specifications__domain-data-models__implementation-guide.md new file mode 100644 index 000000000..a21957944 --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__domain-data-specifications__domain-data-models__implementation-guide.md @@ -0,0 +1,12 @@ +# https://hcxsbx.abdm.gov.in/#/domain-specifications/domain-data-specifications/domain-data-models/implementation-guide + +Implementation Guide +To assist implementers in the ecosystem to create flow specific payload defined in FHIR spec applicable in NHCX, an implementation guide (IG) defining a set of rules about how FHIR resources are used (or should be used), with associated documentation to support and clarify the usage will be created. +Such a publication can be used to validate content against the implementation guide as a whole. +The extended profiles and structures of the FHIR bundles and resources to be used in NHCX are available +here. + + +## Links on this page + +- https://www.nrces.in/ndhm/fhir/r4/index.html diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__domain-data-specifications__domain-specific-languages.md b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__domain-data-specifications__domain-specific-languages.md new file mode 100644 index 000000000..e5c2be1a6 --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__domain-data-specifications__domain-specific-languages.md @@ -0,0 +1,19 @@ +# https://hcxsbx.abdm.gov.in/#/domain-specifications/domain-data-specifications/domain-specific-languages + +Domain Specific Languages (DSLs) +There are two key DSLs being considered for the Health Claims Exchange - Policy Markup Language (PML) and Bill Markup Language (BML). These are currently work in progress and are expected to be released in the later version of NHCX specifications after substantial proof of concept development with various members of domain working groups. +Policy Markup Language (PML) +The purpose of policy markup language is to provide a DSL to payers such that the policies can be encoded in machine readable format, thereby helping with the automation of eligibility check and adjudication processes. +Bill Markup Language (BML) +The purpose of bill markup language is to provide a DSL to payers such that the supporting bills can be parsed as machine readable structured data, thereby helping with the automation of adjudication processes. +Questions for Consultation +Question 1 +The section above refers to adopting appropriate DSLs for policy and bills. Kindly suggest your views on the useability of such domain-specific language and provide prior examples. +Question 2 +Are there any existing solutions that have been used/experimented with? Please provide examples. + Instructions to send responses to the consultation questions are available +here. +previous +   Terminologies +next +Health Care Operation Policies   diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__domain-data-specifications__terminologies.md b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__domain-data-specifications__terminologies.md new file mode 100644 index 000000000..daaf0a27d --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__domain-data-specifications__terminologies.md @@ -0,0 +1,53 @@ +# https://hcxsbx.abdm.gov.in/#/domain-specifications/domain-data-specifications/terminologies + +Terminologies (Code sets or Metadata standards) +To achieve semantic interoperability, it is recommended that NHCX data standards incorporate well established and suitable terminology and coding systems. +In various HL7 standards (including FHIR), these are expressed as Concepts and codes and forms essential vocabulary, ontological binding for resources used to describe document types/categories, element codes and clinical coding like procedure codes, diagnosis codes etc. The data standards defined using FHIR resources and types usually will require agreement on references and usages, through agreed Code Systems and codes, typically manifested through ValueSets. +Guidlines +For Clinical resources (e.g. Condition, Procedure, Observations) - please refer to the guidance issued by NRCeS. +In India, SNOMED-CT is free for use by all as Clinical Terminology, while ICD codes are used for classifications. +Labs typically use LOINC codes +For other code/concepts in the FHIR based data standards, we would recommend guidelines +If any attributes are marked as “required” - then, use of the codes defined in the value sets +If it is marked as “preferred” or “extensible” - then, users are encouraged to draw from the specified codes for interoperability purposes, unless deemed appropriate within the affinity domain. +If marked as “example” - then the domain must agree and define a value set for usage. +ValueSet may be created derived from existing sets, either composed/included from the base or expanded. +For insurance claim domain specific element attributes (e.g. Claim.type) - the domain may define and establish value sets, as suitable in India’s context. +For the broader ABDM interoperability and conformance, NHCX would align/inherit domain specific guidelines. +The table below lists the code systems/value sets proposed by current domain working groups. Based on the above guidelines, we are proposing them to be “preferred” or “example” binding strengths as per +FHIR Terminology binding strength definitions (Section 4.1.5). +Terminology Name +FHIR Value Set link +Proposed Binding Strength +Insurance Company Owners (coverageeligibilityrequest.insurer) +link +Preferred +Procedure Type (claim.procedure.type) +link +Example +Procedure Code (claim.procedure.procedureCode) +link +Example +Denial Codes (claimresponse.item.adjudication.reason) +link +Preferred +Procedure Modifiers (claim.item.modifier) +link +Example +Service Categories (claim.item.category) +link +Example +Service Codes (claim.item.productOrService) +link +Preferred +Medical Speciality Type (practitionerRole.speciality) +link +Preferred +Health Service Provider role (claim.careTeam.role) +link +Example + + +## Links on this page + +- https://www.hl7.org/fhir/terminologies.html diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__healthcare-operation-policy.md b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__healthcare-operation-policy.md new file mode 100644 index 000000000..58eff38d1 --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__healthcare-operation-policy.md @@ -0,0 +1,19 @@ +# https://hcxsbx.abdm.gov.in/#/domain-specifications/healthcare-operation-policy + +Healthcare Operations Policies +A thriving data exchange requires clear rules of engagement on various activities in the data exchange to ensure trust from all actors. The key list of policy candidates to be addressed is: +Onboarding + Defaulting/Deboarding policies +Access control (Data sharing) policies - which actor plays what role and gets to see which parts of data. These policies will then affect the visibility and access to domain specific attributes that will typically travel in the body of the data structures defined by the data exchange. + Business SLAs +Service rating policies - What would be the parameters and mechanisms to rate each type of actor on the data exchange. +The success of the data exchange will depend on trust and willing participation from its ecosystem players. Therefore, to ensure the success of the claims data exchange, its governing policies need to focus on enabling the ecosystem and gaining its trust. To ensure this, the following key policy design guidelines are recommended: +Key Design Considerations +Policies should focus on enabling the ecosystem rather than monitoring or controlling it +Policy formulation should be done as an open consultative process to foster trust in policies +Rules of participation and disqualification should be transparently laid out +They should follow the principle of minimalism and be evolved over a period of time +Keeping these guidelines in mind, the following key policies guidelines are provided for the purpose of wider consultation as part of version 1: +Access control (Roles) + Participant onboarding/deboarding + Beneficiary Authentication process diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__healthcare-operation-policy__access-control.md b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__healthcare-operation-policy__access-control.md new file mode 100644 index 000000000..721ee35d9 --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__healthcare-operation-policy__access-control.md @@ -0,0 +1,89 @@ +# https://hcxsbx.abdm.gov.in/#/domain-specifications/healthcare-operation-policy/access-control + +Access Controls +Participating systems in the Claims information exchange ecosystem may possess one or more of the following roles. These roles are based on the base set of organisation roles defined in hl7 specifications +here. +Namespaced coding is used to further qualify the role in the context of the claims exchange process. + provider: + Health Service Provider + payer: + Insurance service provider + agency.tpa: + Third party administrator acting on behalf of the payer. In the current version, this role is expected to behave like a payer from the data exchange perspective. + agency.regulator: + IRDAI and IIB like regulatory bodies. + research: + Research groups, etc. + member.isnp: + eCommerce platforms facilitating insurance adoption + agency.sponsor: + Scheme owners of specific programs, e.g. NHA for Ayushman Bharat + HIE/HIO.NHCX: + Other NHCXs +The following table further describes these roles for their corresponding access rights and scenarios for version 1 of the claims exchange process: +Role +Allowed actions +Comments +provider +Eligibility check +Send request +Receive response +Pre Auth +Send request +Receive response +Claims Request +Send request +Receive response +Payment +Receive Notice +Send Acknowledgement +Search/Status +Pre Auth +Claims Status +Providers can make search/status requests for multiple requests that originated from them. +payer/ agency.tpa +Eligibility check +Receive request +Send response +Pre Auth +Receive request +Send response +Claims Request +Receive request +Send response +Payment +Send Notice +Receive Acknowledgement +Search/Status +Payment confirmation +Payers can make search/status requests for multiple payment notices that originated from them. +agency.regulator +Search +Claims +Data exchange switch will forward the search request to all payers who are expected to return the claims data in the proposed FHIR structure as per regulator’s policies. +research +Eligibility check +Receive request +Send response +Search +Pre Auths - aggregate and/or anonymised +Claims - aggregate and/or anonymised +All data exhausts for these roles would only have aggregate and anonymised data. Key aggregations for eligibility requests, preauthentication, claims and payments information will need to be further defined. +member.isnp +Eligibility check +Receive request +Send response +Search +Pre Auths - aggregate and/or anonymised +Claims - aggregate and/or anonymised +Claims - Individual claims data as per beneficiary consent +As facilitators of insurance eCommerce, it is proposed to provide ISNPs access to the data available to research role as well as individual beneficiary queries (preauth, claims) based on beneficiary consent. This consent flow is expected to work with existing consent management infrastructure and ISNPs are expected to submit the acquired consent as part of the domain header. +agency.sponsor +As planners of the insurance schemes, sponsors are proposed to be given access equivalent to payer role. +HIE/HIO.NHCX +As an NHCX this participant is expected to play different roles as per the need of the use case. However, due to the data privacy and security measures prescribed in the Open Protocol, it will not be able to view the actual payload. + + +## Links on this page + +- https://www.hl7.org/fhir/valueset-organization-role.html diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__healthcare-operation-policy__guidelines-event-audits.md b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__healthcare-operation-policy__guidelines-event-audits.md new file mode 100644 index 000000000..776a2b691 --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__healthcare-operation-policy__guidelines-event-audits.md @@ -0,0 +1,11 @@ +# https://hcxsbx.abdm.gov.in/#/domain-specifications/healthcare-operation-policy/guidelines-event-audits + +Guidelines for Event Audits +All events (claim request created, claim forwarded, data requested, authorisation, payment, etc) in the claims flow and corresponding system requests and responses between Provider TMS/Beneficiary apps, HCPs, and Payer TMS must be digitally signed and logged to ensure immutability, non-tamperability, and non-repudiability. +The NHCX needs to persist the logs for a configurable (as prescribed by the law of the land) period of time so that they can be retrieved when necessary and this audit trail must be made transparently available to the customer. To ensure integrity, logs should be append-only and should not be allowed to be edited. +Next Steps +This section proposes a high-level approach that can be adopted for event audit policies for an NHCX ecosystem. More deliberation is needed to arrive at model policies that can then be readily extended to be adopted by the ecosystem. Domain working groups will continue to work on developing a detailed approach for event audit policy formulation as well as a model policy for easy adoption. These documents will be released for public consultation in time for an initial pilot of the NHCX ecosystem. +previous +   Guidelines for Grievance Redressal +next +Guidelines for Beneficiary Authentication by Providers/Payors   diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__healthcare-operation-policy__guidelines-for-grienvance-redressal.md b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__healthcare-operation-policy__guidelines-for-grienvance-redressal.md new file mode 100644 index 000000000..9fee4896e --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__healthcare-operation-policy__guidelines-for-grienvance-redressal.md @@ -0,0 +1,50 @@ +# https://hcxsbx.abdm.gov.in/#/domain-specifications/healthcare-operation-policy/guidelines-for-grienvance-redressal + +Guidelines for Grievance Redressal +While the actual grievance redressal policy for an NHCX ecosystem would be drafted by its operator and agreed upon by its participants, this section outlines key design guidelines and an overall approach to arrive at such a policy. These guidelines and approach are aligned with earlier thinking from IRDAI in its publication +Re: GUIDELINES FOR GRIEVANCE REDRESSAL BY INSURANCE COMPANIES, +however, these are now envisioned to cover grievance from any actor of the ecosystem with respect to other actors. +Key Policy Design Guidelines +Final operational policies for grievance redressal are expected to be drafted by the NHCX operators as these may change over time based on the need of the ecosystem and use cases under consideration. However, to make the policies consistent and effective, the following key grievance policy design guidelines are proposed: +Each NHCX operator must publish a dispute/grievance resolution policy to allow digital initiation, routing and tracking of the grievances of any of the participants. +The policy should clearly list out all the grievances that would be addressed under it and mechanism to resolve grievances that are not covered under it. +The policy should require all participating actors to set up nodal governance bodies contactable at the digital and physical communication mechanisms provided as part of onboarding. These communication details are made available to all participants using the read access to the registry. +As part of the participant registry, the NHCX instance also publishes the details of its governance body. +The policy should publish the types and priority of the grievances handled by each type/role of the participant including any required as per prevailing regulations. +The policy should publish SLA for each grievance type including any required as per prevailing regulations. +The policy should be versioned, required to be signed by new members at the time of onboarding and any change has to be proactively informed to all existing network participants. +The policy should require ample due diligence cycle to address the grievance and review the redressal before responding back to the requester +The policy should allow for the reopening of the grievances +The policy should allow for escalation to the network operator in case the requestor does not feel satisfied with the resolution. Escalated grievances should follow accelerated timelines for resolution. +The policy should clearly layout review and resolution criteria for a grievance to be escalated and the approach the operator would take to reach a resolution. +The policy should include ways of keeping requesters informed about the latest status and any additional requirements to help address the grievance. +Proposed Approach for Policy Formulation +Drafting and evolving an efficient and truly implementable policy for grievance resolution would need active participation from the NHCX ecosystem. Keeping this in mind, the following high level approach is proposed in line with the overall +Approach for Open Specifications: +Like with the specifications so far, constitute a new working group for Dispute Resolution policies. +The working group contextualises and adopts the open specifications design principles and high level approach as detailed in + NHCX - Cover note + for the dispute resolution context. +The working group drafts a model policy in accordance with the above principles and in line with the detailed approach from step 2 above. +The principles, detailed approach and model dispute resolution policy draft is versioned and released for public consultation. +The domain working group deliberates the feedback and enhances principles/model policy as needed. +NHCX Operators adopt the model policy according to the needs of their network +Further enhancements, e.g. for new use cases, changes in approach, improvements in model policy due to on-ground observations undergo steps 3-6 and result in a newer version of the artefacts (principles, approach or model policy). +Next Steps +This section proposes a high-level approach that can be adopted for grievance redressal policies for an NHCX ecosystem. More deliberation is needed to arrive at model policies that can then be readily extended to be adopted by the ecosystem. Domain working groups will continue to work on developing a detailed approach for grievance redressal policy formulation as well as a model policy for easy adoption. These documents will be released for public consultation in time for an initial pilot of the NHCX ecosystem. +Questions for Consultation +Question 1 +Beyond what’s being proposed as a guideline, what areas and roles do you think NHCX as the data exchange gateway should play in grievance redressal? +Question 2 +While the working groups will further deliberate on details, according to you what should be the mechanism of the grievance redressal on the network? What should be the key grievances that need to be honored between network participants? How should escalations work? + Instructions to send responses to the consultation questions are available +here. +previous +   Guidelines for Participant Onboarding +next +Guidelines for Event audits   + + +## Links on this page + +- https://www.policyholder.gov.in/uploads/CEDocuments/Guidelines%20on%20Grievance%20Redressal.pdf diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__healthcare-operation-policy__guidlines-beneficiary.md b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__healthcare-operation-policy__guidlines-beneficiary.md new file mode 100644 index 000000000..ce218861f --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/domain-specifications__healthcare-operation-policy__guidlines-beneficiary.md @@ -0,0 +1,10 @@ +# https://hcxsbx.abdm.gov.in/#/domain-specifications/healthcare-operation-policy/guidlines-beneficiary + +Guidelines for Beneficiary Authentication by Providers/Payors +Aadhaar Digital eKYC API +Authentication of beneficiaries by providers on provider TMS/beneficiary APP. +The Provider TMS system will support Aadhar eKYC open API integration for beneficiary authentication using Aadhar. All the govt schemes and most of the private providers may use Aadhar based KYC process for verification of the beneficiary in their TMS system. +Aadhaar Authentication (mobile OTP/biometric) +Authentication of beneficiaries by providers on provider TMS/beneficiary APP +The Provider TMS system will use Aadhaar based authentication (Aadhar integrated Mobile OTP based authentication, biometric based authentication) for authentication of a beneficiary to initiate the claim transaction in the provider TMS system. All provider systems that are enrolled with ABDM will have biometric devices for validation and creation of the health ID. +The payer TMS system and NHCX will integrate the Aadhar authentication open API for verification of the beneficiary ID during the claim validation stage. diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/hmisdocuments.md b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/hmisdocuments.md new file mode 100644 index 000000000..373ff98aa --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/hmisdocuments.md @@ -0,0 +1,56 @@ +# https://hcxsbx.abdm.gov.in/#/hmisdocuments + +NHCX-PMJAY-HMIS Integration +Context: Current Challenges with TMS-Based PMJAY Workflow +PMJAY claims processing is currently dependent on the TMS 2.0 Provider System, irrespective of hospitals having their own Hospital Management Information Systems (HMIS). Challenges include: +Duplication of data entry: +Parallel data entry in hospital HMIS and TMS increases administrative workload and the risk of errors. +Lack of System Interoperability: +Poor interoperability prevents seamless exchange of beneficiary, clinical, and claims data across systems. +Single-System Dependency: +Exclusive reliance on a single provider system impacts scalability and operational flexibility. +Restricted Innovation and Customisation: +System constraints restrict innovation and flexibility for hospitals and technology partners. +Solution: Transition to ABDM-Enabled HMIS Integrated with NHCX +Benefits: What this means for PMJAY-empanelled Hospitals +PMJAY Workflow Embedded in Hospital Operations: +PMJAY cases can be handled as part of routine hospital workflows within HMIS, rather than as a separate, portal-driven activity. Hospital PMJAY operations are no longer impacted by portal downtime, access constraints, or concurrent user limitations. +Availability of Structured Data: +Availability of structured data enable automation of Pre-Auth/Claim resulting in low processing cost and time. This will reduce manual errors and improve the data quality (enabling basic requirement for use of any AI model) as well as aid in fraud control. +Improved Internal Audit and Financial Management: +All PMJAY-related clinical and financial records reside within hospital systems, simplifying audits, internal reviews, and compliance. PMJAY claims data flows natively into hospital billing and accounting systems, improving reconciliation and financial reporting. +Simplified Training and User Management: +Staff require training on a single system instead of managing separate user roles and workflows across HMIS and TMS. +NHCX-PMJAY-HMIS Key Differences +Item +Description +Utilising the Insurance Plan Response +The PMJAY scheme extensively uses the InsurancePlan FHIR bundle, which is configured at the hospital level and serves as a key reference for scheme operations. As this configuration drives several downstream workflows, it is critical for enabling subsequent steps in the pre-authorisation and claims lifecycle. +Biometric authentication of the Beneficiary +The PMJAY scheme mandates biometric authentication of a beneficiary during registration, treatment and discharge. This is an additional API that has to be implemented. +Structured data exchange +For a HMIS to process PMJAY claims, it is mandatory to send supporting health information in ABDM-defined structured Health Information Types. +Query flow +The PMJAY payer does not use the Communication API for queries. Instead, a query is raised by the payer with the relevant workflow ID for preauth/claim which has to be responded to by the provider with the relevant workflow ID (preauth/claim bundle structure remains the same). +API Flows +NHCX normal flow +NHCX-PMJAY-HMIS flow +Get Insurance Plan +Same +Get Policy +Same +Coverage eligibility check +Same +Pre-Auth +Same (but before pre-auth need to do mandatory biometric authentication of beneficiary). +Communication Request +Communication API is not used. Instead, a query is raised by the payer with the relevant workflow ID for preauth/claim which has to be responded to by the provider with the relevant workflow ID. +Claim Submission +Same +Payment Notice +Same +Status Check +Same +NHCX-PMJAY-HMIS Go-Live Process +Supporting documents +last updated on : diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/introduction-NHCX.md b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/introduction-NHCX.md new file mode 100644 index 000000000..4fb6e2f91 --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/introduction-NHCX.md @@ -0,0 +1,112 @@ +# https://hcxsbx.abdm.gov.in/#/introduction-NHCX + +Introduction to NHCX +The National Health Claims Exchange operates in a manner similar to internet and email exchange networks. It facilitates the transfer of data packets in FHIR standard format from one point to another (destination). Just as routing switches or email gateways ensure that messages are sent and received with the appropriate levels of consistency, security, privacy, and durability, the National Health Claims Exchange serves as a protocol for exchanging claims related information among various parties, including payers, providers, beneficiaries, regulators, and observers. +Visualization of NHCX across multiple Provider or Payer Apps +NHCX Objectives +Expanded Insurance Coverage: +We have introduced new claim types, such as outpatient department (OPD) services and pharmacy expenses, to broaden the scope of insurance policies. +Enhanced Claims Processing: +We have minimized receivable cycles and promoted the acceptance of cashless claims, particularly in smaller healthcare facilities. +Drove Insurance Innovation: +We have enabled the development of new processes and rules for automated adjudication, while implementing measures to control fraud and prevent abuse. +Standardized Claims Procedures: +We have established a uniform claims process to lower operational costs and foster trust between payers and providers through a transparent, rule-based system. +Improved Patient Experience: +We are focused on enhancing the overall patient experience by ensuring timely and efficient claims management. +NHCX Use Cases +Use Cases +Provider +Payer +Get Provider/Payer details +Provider requests payer details; NHCX validates and returns details +Payer requests provider details; NHCX validates and returns details +Eligibility Check +Provider submits request; NHCX validates and forwards it to payer; Payer process and returns status +Payer receives request from provider and processes it +Pre- Authorization +Provider submits requests; NHCX validates and forwards it to payer; Payer reviews and provides decision +Payer receives request and provides approval or denial decision +Claim Submission +Provider submits claims; NHCX validates and forwards to payer; Payer process and determines reimbursements +Payer receives claims, reviews them, and determines reimbursement +Payment Notification +Payer process claim and notifies provider of status +Payer processes claim and notifies provider of status +Claim Reprocessing +Provider submits request; NHCX validates and forwards to payer; payer reviews and provides revised decision +Payer receives requests and provides revised decision +NHCX Specifications +The National Health Authority (NHA) publishes the specifications for NHCX. These specifications define a set of minimal requirements and definitions that serve as a standard for every aspect of the envisioned claims data exchange. +Here's what the specifications aim to achieve: +Interoperability: +Ensure different systems (Provider/Payer) can work together seamlessly. +Regulations and Policies: +Define the necessary regulations and policies for the system. +Technology Choice: +Allow participants to choose the technology and solutions that best fit their needs. +The design principles behind the specifications are: +Open : +Promote vendor neutrality and facilitate technology use by being open and published under a permissive license (e.g., Creative Commons or MIT). This allows for wider participation and fosters innovation. +Evolvable and Extendable : +Adapt to changing needs over time and allow for customization within specific contexts (payer-specific rules/protocols) while maintaining overall interoperability. +Minimalistic and Inclusive : +Be easy to understand and avoid restricting innovation or hindering participation. +Data Privacy and Security : +Ensure strong data privacy and security measures are in place. This includes mechanisms like tamperproof audit trails and digital signatures for tracking data access and updates. +Unbundled : +Break down the complexity of the system into manageable pieces for easier implementation. This allows for modular use of specifications to address different needs. +Open Protocol for Claims Data Exchange (Health Claims Transfer Protocol) : +This open protocol, similar to HTTP or SMTP, defines key aspects of claims exchange +- +Authentication: +Verifies participants (Payer, Provider, Regulator, Observer, etc.). +- +Request/Response Message Syntax: +Defines the format of messages exchanged, including headers, body content (mandatory vs. optional fields), transport constraints, etc. +Supported Methods (APIs) : +Defines available functions within the system. +Response Codes : +Provides standardized response codes for different scenarios. +Data Security and Privacy : +Ensures secure, authentic, and non-repudiable message exchange. This includes encryption for data security beyond standard protocols and message signing for verification. +Domain Data Specifications +These specifications define the format and meaning of elements in request/response objects used for claim exchange. They leverage existing domain standards like FHIR, SNOMED CT, and ICD-11. Key focus areas include: + Domain data model : +Defines a schema for entities like Claims, Policies, Payments, Providers, and Payers using FHIRv4 standards as published by NRCES, GoI. This data model encodes information for each entity in a standardized format (e.g., ClaimBundle, ClaimResponseBundle, CoverageEligibilityBundle, CoverageEligibilityResponseBundle). +More details can be found here: +https://www.nrces.in/ndhm/fhir/r4/hcx-profile.html + Metadata Specifications (Value Sets) : + Defines additional information describing data elements, including coding systems and suggested values for important claim attributes such as disease codes, procedure codes, diagnostic codes, billing codes, etc. This information is used for data description, administration, functionality, and preservation. More details can be found here: +https://nrces.in/preview/ndhm/fhir/r4/ValueSet-ndhm-supportinginfo-category.html +Operational Guidelines +Following are policies for participation in the health claims exchange ecosystem: +Onboarding guidelines: + Entities (Provider/Payers) must follow specific procedures to join the National Health Claims Exchange. These procedures include requirements related to protocol adherence, compliance reviews, and review frequency. +Deboarding guidelines: + Entities may be blocked or rejected from the National Health Claims Exchange due to violations related to technical service level agreements (SLAs), protocol versions, message security, or privacy. +Access Control guidelines: + Access may be controlled based on the roles of individuals within an entity. Entities may need to obtain consent for accessing APIs and data attributes. +Exchange operation guidelines +Entity Responsibilities: The guidelines outline the responsibilities of each entity within the NHCX ecosystem. +Operational Reports and Dashboards: Regular reports and dashboards are required to monitor the exchange's operations. +Audit Checklist and Frequency: A standardized audit checklist must be followed, and audits must be conducted at specified intervals. +Governance Framework for National Health Exchange (NHCX) +Desc: +To ensure the success of the claims network, the NHA is establishing clear and well-defined specifications that foster a shared understanding among diverse stakeholders in the healthcare system. These specifications are being universally accepted by all insurance participants to form a common foundation for the NHCX network. The NHA envisions a governance approach for open specifications aligned with the key principles of the National Digital Health Blueprint, which will be further articulated as NHCX specifications. +Governance Approach and Process: +The NHA is developing and maintaining standards through a transparent, adaptable, and consultative process. This process involves: +Inclusive and Consultative Process: Engaging widely inclusive and committed groups to contribute to ideas, perspectives, and networks. +Engagement with NRCES: The NHA is collaborating with the National Resource Centre for EHR standards (NRCES) to develop specifications. This includes representation from all sectors of the healthcare industry, such as: +Insurance Providers +Third-Party Administrators (TPAs) +Patient groups +Provider Associations +Regulatory Bodies +Public Accessibility: Specifications are made publicly available and maintained in GitHub repository by authorized person of NHA. + + +## Links on this page + +- https://www.nrces.in/ndhm/fhir/r4/hcx-profile.html +- https://nrces.in/preview/ndhm/fhir/r4/ValueSet-ndhm-supportinginfo-category.html diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/introduction-NHCX__guidlines-for-participant-onboarding.md b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/introduction-NHCX__guidlines-for-participant-onboarding.md new file mode 100644 index 000000000..b4de12f1a --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/introduction-NHCX__guidlines-for-participant-onboarding.md @@ -0,0 +1,65 @@ +# https://hcxsbx.abdm.gov.in/#/introduction-NHCX/guidlines-for-participant-onboarding + +Guidelines for Participant Onboarding +While the actual onboarding/deboarding process for an NHCX ecosystem would be drafted by its operator and agreed upon by its participants, this section outlines key design guidelines and an overall approach to arrive at such a policy. +A list of different kinds of participants who would need onboarding into an NHCX registry is provided in the +Access Control +section above. Onboarding onto the NHCX is envisioned as a two step process: +Sandbox - for compliance testing and certification +Go Live on live instances +Sections below provide high level guidelines for each of these steps. +Sandbox Process +The key goal of the sandbox is to help the ecosystem test its specific components against the communication standards, and get certified to become a part of the system. Once a participant successfully completes the sandbox process, they can use the certification to get onboarded to the NHCX production environment with the necessary access. +NHCX operator(s) may nominate or list Sandbox operator(s) whose certification will be considered valid for onboarding to their platforms. +The following are the steps to integrate, test and launch with the help of sandbox. +Step 1: Registration +The participants submit +an online application +to express their interest to access the NHCX sandbox. The requests from different participants are verified to see if the participant is eligible to participate in the sandbox environment by doing basic checks against the details provided in the application form. +There may be requests that would not satisfy the conditions required for the sandbox access such as multiple requests from the same participant, participants not registered with any registry, TSPs without a valid website, spam applications, etc., which would prove to be redundant and may have to be filtered. This process would be semi-manual. +On successful verification, the approved participants are added to the NHCX sandbox and provisioned with the necessary credentials to access the sandbox environment. +Step 2: API integration and testing +In this step, the participants integrate their respective claim processing applications with the sandbox NHCX. This is to aid the developments as well as ensure that their applications are compliant with the NHCX standards and build all the missing pieces on their side to use the set of NHCX APIs necessary for their planned workflows. +Sandbox website would also include documentation and suggestions regarding the software libraries, tools and example implementations for encryption, FHIR resource generation, code generation and other new/complex parts of the NHCX protocol. The sandbox portal would ensure that the participants are provided with all the necessary help to get started and complete the API integration. +Step 3: Sandbox certification +All participants are expected to fulfil a set of functional and security tests/flows applicable to them. +Based on affiliate NHCX policies, the sandbox may necessitate additional security testing and reviews like STQC or CERT-IN. Suggestive pointers on infrastructural requirements for security testing clearance can be found in this +document. +Once the system is ready and tested against the applicable test cases, the participant will be required to submit their test results including the application's usage of and interaction with NHCX APIs to the Sandbox Operator for review and approval. +On successful review, the sandbox will issue a successful completion certificate valid for a configured period of time. This certificate can be used by the participant to get onboarded to the production environments of the NHCX operators. +Go Live process +After obtaining the affiliated sandbox certification, the participant would have to apply for onboarding into the NHCX production environment. This process will consist of the following key steps: +Step 1: Registration on NHCX +In this step, interested participants will be required to go through the onboarding process with the NHCX. NHCX operators are expected to provide a choice of registration flows with the following high level guidelines: +If the participants are registered in the NDHM Health Facility registry, then they should be allowed to use HFR authentication as a means to register in the NHCX registry, if they choose to do so. +If the participants are not registered in the ABDM Health facility registry then the participant should be allowed to use alternate means of verification like +Option to complete the ABDM HFR process and use the resultant credentials. +Authentication/Certificates/documents from IRDA or equivalent such agency identified and clearly stated in NHCX’s onboarding policy. +Summary details of the NHCX application duly filled. This application form will be more detailed, requiring more details of the participant including contact numbers, company registration details, and other details as needed in the NHCX registry. +Step 2: Review of Sandbox certification +A final round of approval for application go-live will be sought from the internal team at NHCX. Applicants will be required to share Functional and security testing certificates issued by the affiliate sandbox environment. +Step 3: Provisioning of production credentials +Once these requirements are met, the participant id along with the production access secret credentials will be provided. Participants are expected to keep the secret credentials safe and report any compromises at the earliest to the NHCX operators. +Step 4: Go-Live +The application is now expected to be prepared for go-live in respective participant ends. All the participants are advised to plan the change management at their end and conduct necessary training for their staff before going live in production NHCX, preferably after piloting with a small set of clients. +Deboarding scenarios +This section lists some of the deboarding scenarios that may be considered as part of the final deboarding policies by the NHCX operators: +Involuntary deboarding of a participant initiated by Regulator/Legal Authority. Few examples: +Suspension/Deactivation of a provider by a regulator for fraudulent activity. +Suspension/Deactivation of a TPA or a Payer by IRDA +Involuntary deboarding of a participant (mostly TSPs) initiated by NHCX. Few cases: +Serious violation of NHCX policies (e.g. grave SLA violation repeatedly) +Hacking attempts made by participants for unauthorized access, after an investigation by NHCX +Bad or irresponsible behaviour from participants if it significantly impacts the stability and performance of the NHCX (like frequent bursts of requests beyond authorised rate limits). +Voluntary deboarding of participants. Few examples: +A provider or payer shifting to another NHCX +A provider or payer shuts down their business +A provider or payer merges with another entity listed on the exchange +Please note that while the above list suggests a few of the scenarios for potential deboarding of a participant, this process should be treated with utmost care and an elaborate warning mechanism should be kept in place whenever the deboarding is not voluntary. +In addition, to provide a fair chance of appeal, the grievance redressal process on NHCX is expected to provide grievance mechanisms to handle appeal against deboarding of a participant + + +## Links on this page + +- https://sandbox.abdm.gov.in/ +- https://sandbox.abdm.gov.in/documents/NDHM_Secure_Application_Development-Reference_Document.pdf diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md new file mode 100644 index 000000000..bf89344a2 --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications.md @@ -0,0 +1,441 @@ +# https://hcxsbx.abdm.gov.in/#/technical-specifications + +Technical Specifications +The technical specifications outline the digital architecture required to implement the health claims network, including detailed protocols for data exchange, authentication mechanism, and digital network management policies. These specifications establish the framework for interoperability, secure communication, and system governance across all participants. +Open Protocol for Health Claims Data Exchange +The Open Protocol, outlined in the Key Specifications, serves as the technological backbone for the Health Claims Data Exchange. The following sections detail the critical components of the protocol, designed in alignment with the architectural principles specified in the National Health Claims Exchange (NHCX) Open Specifications. +Key design elements considered for the protocol development include: +Asynchronous Information Exchange: +The protocol supports asynchronous data exchange to accommodate the large scale and non-linear processes prevalent in the healthcare industry. +Federated Deployment: +It facilitates the federated deployment of multiple interconnected NHCX systems, allowing for decentralized control while maintaining interoperability across the ecosystem. +Data Security and Privacy: +The protocol ensures the protection of sensitive information by segregating data from personally identifiable information (PII) during transmission between applications. It also supports encryption and auditing of data exchanges to maintain security and integrity. +Unique Message Identifiers: +Ecosystem partners can generate unique identifiers for each message exchange, enabling efficient tracking and management of individual transactions. +Business Flow Support: +The protocol allows for the transmission of multiple related messages that form part of a single business process, adhering to the requirements of different business scenarios. +Integration with Existing Registries: +It permits the utilization of existing registries for key entities such as beneficiaries, providers, and payers, while offering flexibility for specific use cases. +Use Case Extensibility: +The protocol is designed to be extensible, allowing it to adapt to the specific requirements of various programs or schemes. For example, the PMJAY scheme may require additional data elements for pre-authorization or claims processing as per its guidelines. +This open protocol ensures seamless, secure, and scalable communication within the health claims ecosystem, supporting the varied needs of all stakeholders. +National Health Claims Exchange (NHCX) Protocols +The exchange platform serves as the central routing engine, managing the flow of data between healthcare providers and other National Health Claims Exchange (NHCX) participants. It receives, validates, and processes data, ensuring it meets required formats and security standards. The platform handles data transformation when necessary, ensuring compatibility across systems, and securely routes the information to the appropriate recipients. In the case of errors, it manages retries or re-routing, maintaining a seamless exchange of data while ensuring compliance with regulations. +Key building blocks include: +Exchange Protocol: Defines message flow terminologies. +Message Structure: Specifies message formats and structures. +API Structure: Outlines APIs for data exchange between entities. +Error Handling: Details error codes and descriptions for message processing +Exchange Protocol Terminology +Request: +The sender initiates the process by sending a message containing the necessary payload, following the protocol's message structure. +Response: +The recipient of the request responds with relevant payload defined by the protocol. +NHCX Systems: +These are runtimes on the NHCX platform that function as message receivers and forwarders on behalf of both senders and receivers. Depending on the use case, either the sender or receiver may participate in the process. For example, in the case of cashless claims, providers will be the senders in the Check Eligibility, PreAuth, and Claim Submission use cases, with payers acting as the recipients. Meanwhile, in the Payment Notice use case, payers will be the senders and providers will be the recipients. +Message: +The NHCX protocol facilitates the transfer of a Message that includes both a protocol header and content (payload and domain headers) as per the use case. The protocol header is a set of attributes that carries information necessary for NHCX to reliably forward the message to its destination. +The content of the message has two parts: +Domain Headers: +This includes domain or use case specific information that is not required for transportation but provides additional information about the payload (such as the payload type). +Payload: +The domain object defined for the relevant use case. Typically, this data is encrypted using the recipient's key to ensure that NHCX systems cannot view it. +Senders and Receivers: +In the information exchange, two systems are involved and referred to as Senders and Receivers. +Message Flow +Step +Action +1. Sender to NHCX +The sender sends the initial message to its preferred NHCX instance. +NHCX validates the sender and recipient statuses. +NHCX responds with an acknowledgment to the sender. +NHCX forwards the message to the end recipient or the next NHCX in the chain. +NHCX to Receiver +Finally, NHCX verifies the recipient's status. +NHCX carries out necessary checks and transmits the message to the recipient. +The recipient confirms receipt of the message. +3. Receiver to NHCX +The receiver sends the response message to its chosen NHCX instance. +NHCX verifies the recipient and sender statuses. +NHCX carries out necessary signature verifications and sends an acknowledgment to the recipient. +NHCX forwards the acknowledgment to the sender or the next NHCX in the chain. +4. NHCX to Sender +NHCX verifies the sender's status. +Then, NHCX forwards the response message to the sender. +The sender acknowledges receipt of the response message. +Message flow from NHCX to Sender +Message flow between NHCX and multiple recipients - Forward approach +Query Flow +Message Structure +Overview +NHCX messages are designed to ensure secure and reliable communication by separating use case-specific information from generic transport and domain-specific headers. This structure is like JWE tokens defined in RFC7516. Refer +link +for more information. +Key Components include: +Protected Headers ( +rotected Headers = Registered JOSE headers + NHCX Protocol Headers + NHCX Domain Headers +) +Payload ( +Encrypted Domain Data +) +Protected Header +JOSE Headers: +These follow the JSON Web Encryption header format specified in RFC7516. +For initial NHCX implementations, NHA proposes using alg:RSA-OAEP and enc: A256GCM. +NHCX Protocol Headers: +These act as private headers, adhering to section 4.3 of RFC7516. +Each attribute begins with "x-NHCX-" to maintain clarity and avoid naming conflicts. +Name +Description +Type +Addition Properties +x-hcx-sender_code +Registry code of the sender (e.g. provider or payer) +String +Mandatory +x-hcx-api_call_id +Sender generated unique id for each originating request unique for each call. +String +Mandatory +x-hcx-recipient_code +Registry code of the recipient (e.g. provider or payer) +String +Mandatory +x-hcx-request_id +Sender generated unique id for each originating request. +String +Optional +x-hcx-correlation_id +Unique id of the conversation (a collection of related messages). It may be chosen as the message_id of in the original sender’s (initiator’s) system. For return messages (asynchronous responses) responders are expected to populate with the one in the request. +String +Mandatory +x-hcx-workflow_id +Workflow id depicts the current process/state of the case. It may span over a series of message exchanges for a given transaction. +String +Optional +x-hcx-timestamp +Unix timestamp of the message while sending +datetime +Mandatory +x-hcx-debug_flag +Request to the server to include debug information. Useful in the time of integration testing and prod debugging. However, server(s) may choose to ignore this flag based on their policy. +ENUM +Error +Info +Debug +Optional +x-hcx-ben-abha-id +ABHA ID of the subscriber/member(beneficiary) +String +Mandatory +x-hcx-status +Operational status of the message. Depending on the leg of the message it would be: +Initiator's Status +request.initiated +Responder's Status + response.complete + response.partial + response.error +String +Mandatory +x-hcx-error_details +Expected to be used for providing details of the status. It Will be especially useful in scenarios where Operational status indicates an irrecoverable error. Key elements of this object are: +Code: + error, info, debug code from the system - expected to be namespaced for better readability +Message: + Short description of the detail +Trace: + Long description supporting the Code +JSON Object - E.g. +{ +error.code: “bad.input”, error.message: “Provider code not found”, trace: “” +} +Optional +x-hcx-debug_details +Expected to be used for providing details of the status. It Will be especially useful in debugging scenarios Key elements of this object are: +Code: + error, info, debug code from the system - expected to be namespaced for better readability +Message: + Short description of the detail +Trace: + Long description supporting the Code +JSON Object - E.g. +{ +error.code: “bad.input”, error.message: “Provider code not found”, trace: “” +} +Optional +Status Description (Protected Header): +request.initiated : + Initiator will send this status to initiate the request cycle. +request.queued : + When the request is queued at NHCX system, ready to be picked up for processing.(NHCX Internal) +request.dispatched : + When the request has successfully reached the receipient's system.(NHCX Internal) +request.stopped : + When the request has stopped completely after failure attempts to reach receipient. (NHCX Internal) +response.complete : + Responder will send this status to close the complete request cycle while sending final response. +response.partial : + Responder will use this status for partial response or to acknowledge the request. +response.error : + Incase the request is rejected or any error encountered. +NHCX Domain Headers: +Domain data specifications define these headers using a JSON object that maps domain-specific values. +For instance, in claims use cases, these headers might include the total claimed amount and a list of procedures. +All parameter names follow the format x-NHCX- -, where: + is a concise identifier (less than 16 characters) representing the use case, ideally aligned with the API URI path. + is a short name (less than 32 characters) for the specific parameter. +Therefore; Protected Headers = Registered JOSE headers + NHCX Protocol Headers + NHCX Domain Headers +Payload +Domain data specifications define the use case-specific payload. This payload is base64 encoded and encrypted using JSON web encryption (as outlined in the JOSE header). +Example: In cashless claims scenarios, the payload could be an FHIRV4 bundle of the appropriate type, encrypted according to relevant message security standards. +Signatures: +JWE inherently provides integrity protection for both the encrypted payload and protected headers using Authenticated Encryption with Associated Data (AEAD) mechanisms (as defined in RFC7516). Therefore, additional signatures are not necessary. +API Structure +Overview +The NHCX API structure adheres to a specific pattern for message exchange within the HCP (Health Care Provider) ecosystem. This structure is defined by the underlying protocol definition and message structure. +The expected format for API calls is as follows: +://// +transport_protocol: +Always https for secure communication. +server_address: +The address of the server handling the API call (either an NHCX instance or a payer/provider system). +protocol_version: +Indicates the version of the API for compatibility and future updates. +resource_name: +Specifies the domain resource being targeted (e.g., "claims" or "coverage eligibility"). +action: +Defines the intended operation within the resource context. +on_action: +Represents the response callback from the receiving system to the original message. +Based on this pattern, the following APIs have been designed and deployed in the sandbox environment for the cashless use case. Detailed description for each API is provided separate annexure. +S.No +Use Case +API End Point +Flow +Coverage Eligibility +/coverageeligibility/check +provider->NHCX->payer +Coverage Eligibility +/coverageeligibility/on_check +payer->NHCX->provider +Preauthorisation +/preauth/submit +provider->NHCX->payer +Preauthorisation +/preauth/on_submit +payer->NHCX->provider +Predetermination +/predetermination/submit +provider->NHCX->payer +Predetermination +/predetermination/on_submit +payer->NHCX->provider +Claim +/claim/submit +provider->NHCX->payer +Claim +/claim/on_submit +payer->NHCX->provider +Request Additional Attachments +/communication/request +payer->NHCX->provider +Send Attachments +/communication/on_request +provider->NHCX->payer +Payment +/paymentnotice/request +payer->NHCX->provider +Payment +/paymentnotice/on_request +provider->NHCX->payer +Status Check +/hcx/status +provider->NHCX,Payer->NHCX +Status Check +/NHCX/on_status +provider->NHCX,Payer->NHCX +Reprocess +/task/submit +provider->NHCX->payer +Reprocess +/task/on_submit +payer->NHCX->provider +Search +/search/submit +NHA->NHCX->Payer +Search +/search/on_submit +payer->NHCX->NHA +Error Handling +Overview +NHCX provides detailed guidelines for handling protocol-related errors, including their categorization, standardization, and asynchronous response mechanisms, especially when errors originate at the recipient end. Both the NHCX gateway and participant systems (primarily recipient systems) are required to validate specific conditions and raise appropriate error codes and details. +Follow the +link +to know more. +There are two main categories of errors: +Gateway Errors: +These occur during protocol header validation by the NHCX gateway before processing the message. The gateway responds to the caller with error codes, either synchronously in the HTTP response to the API call or asynchronously in the callback API. +Recipient Errors: +These errors are encountered by recipient systems. They must be responded to the NHCX and then to the sender asynchronously. +NHCX Participant Registry +NHCX registries serve as the definitive source of participant information on the platform. These registries may be expanded by integrating with existing registries within the healthcare ecosystem, such as the National Health Facility Registry provided by the NHA. The enrollment of participants in the registry is governed by procedure determined by NHA and Insurance regulatory and Development Authority of India (IRDAI). +The benefits of leveraging an existing registry include: +A single source of truth for all entities at the source registry. +The NHCX participant registry only needs to maintain supplementary information specific to its use case. +Enhanced interoperability across systems. +Aligned with the key design principles, NHCX registries are simplified, self-maintaining, support non-repudiability, accessible through OpenAPI’s, extensible, and designed with data privacy and security in mind. +Each registry on the NHCX platform provides the following APIs: +Create +Update +Delete +Search +Name +Description +Type +Addition Properties +participant_code +Machine-readable unique identifier of the participant, generated by the NHCX instance. +String +Mandatory +Unique across installations - namespaced as participant_code@NHCX_instance_code +registry_code +Health Facility Registry code or Payer Registry for the participant - used to validate and link the participant based on the role selected. +String +Optional +participant_name +A human-readable name for the participant +String +Mandatory +Unique within the NHCX instance context +roles +Roles assigned to the participant as per the definition in the domain specifications. This will be used for access control. +String +Mandatory +address +The physical address of the participant including its geolocation +JSON structure +Optional +email +Email ids for claims related communication +String +Optional +Maximum 3 +phone +Landline number of the participant +String +Optional +Maximum 3 +mobile +Mobile number for claims related communication +String +Mandatory +Minimum 1 +Maximum 3 +status +Current status of the participant on the instance. Can be: +Created (Not verified yet) +Active +Inactive +Blocked +String +Mandatory +signing_cert_path +URI/file path to the JWT signing certificate +String +Optional +encryption_cert +URI/file path to encryption certificate +String +Mandatory +endpoint_url +Default endpoint to make API calls +String +Mandatory +payment_details +Default payment details: +UPI ID, or +Ac Number + IFSC Code +JSON Structure +Optional +Data Security and Privacy in Claims Processing +Ensuring the privacy and security of data +involved in claims processing, which includes personal and health information, is crucial. This document outlines various approaches to achieve this goal: +Transport Security (HTTPS): +All communication between participants and the National Health Claims Exchange (NHCX) must use +HTTPS (Hypertext Transfer Protocol Secure). +This ensures a secure communication channel in both development (sandbox) and production environments. +Message Security and Integrity (Encryption): +To protect sensitive information, the data payload is encrypted using a public key (certificate) specific to the final recipient. This key is established during participant onboarding. +The encryption standard used is +JSON Web Encryption (RFC7516) +API Security (Authentication and Authorization): +A security mechanism using +API keys + is employed for authentication and authorization between participant systems and the NHCX gateway. +These API keys are generated using +JSON Web Tokens (JWT tokens) + defined in +RFC7519 +. Follow +link +to know more. +All generated tokens have an expiration time set by NHCX instances. +Participant systems obtain API keys from the NHCX gateway and include them in the "Authorization" HTTP header when making API calls. +In summary, a layered approach is taken to data security: +A secure communication channel is established using HTTPS. +Data payloads are encrypted using public key cryptography. +API keys with expiration times control access to the system. +This ensures comprehensive data security and privacy throughout the claims processing exchange. +Securing NHCX Gateway APIs +Each participant system, such as providers and payers, must obtain an API key from the NHCX gateway to authenticate itself to the gateway. The participant system should include the API key in the "Authorization" HTTP header when making any API call to the NHCX gateway. +Obtaining an API Key: +To access NHCX Gateway APIs, participant systems must first obtain an API key. After verifying and onboarding a participant, the NHCX instance provides the participant with a client ID and client secret. +Client ID: +This unique identifier represents the participant in the participant registry. +Client Secret: +A secret value used for authentication. +Request-Body: +{ +"client_id": "client_id received by the participant", +"client_secret": "client_secret received by the participant" +} +To get an API key, the participant system calls the /gateway/v0.5/sessions endpoint with the provided client ID and client secret. Upon successful validation, the gateway instance returns an API token. +Response-Body: +{ +"access_token": "the API key, a JWT access token", +"issued_token_type": "urn:ietf:params:oauth:token-type:access_token", +"token_type": "Bearer", +"expires_in": 300 +} +Revoking API Keys: +NHCX instances can revoke an API key by generating a new client secret. The participant system must then obtain a new API key using the updated client secret. +Securing Participant System APIs +NHCX instances utilize self-generated JWT tokens to secure participant system APIs. These tokens contain the following components: +Header: + Specifies the token type (JWT) and algorithm (RS256). +Payload: +Includes claims such as: +jti: A unique identifier for the token. +ss: The NHCX instance identifier. +sub: The NHCX instance identifier. +iat: The issuance time. +exp: The expiration time. +Signature: +A digital signature computed using the NHCX instance's private key. +Audit and Reporting +NHCX must record every received API call, including unencrypted information like domain headers, signature and encryption algorithm details, sender and recipient information, and signature verification status. +Deployed NHCX systems will have the following features for auditing: +Reporting: +They generate reports for various actors, including payers, providers, beneficiaries, regulators, and observers. Each system publishes a list of supported reports and their level of detail. +API Access: +Audit information stored by NHCX instances is accessible through an API, allowing participating systems to query the audit log related to their transactions. + + +## Links on this page + +- https://datatracker.ietf.org/doc/html/rfc7516 +- https://hcxsbx.abdm.gov.in/#/documents +- https://datatracker.ietf.org/doc/html/rfc7516#section-5 +- https://www.rfc-editor.org/rfc/rfc7519 diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__api-specifications.md b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__api-specifications.md new file mode 100644 index 000000000..ba190db79 --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__api-specifications.md @@ -0,0 +1,35 @@ +# https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications + +API Specifications +S.No +Use Case +API End Point +Coverage Eligibility +Preauthorisation +Claim +Request Additional Attachments +Payment +Status Check +Reprocess +Search +Insurance Plan +Communication +Participant +Notifications +Link + + +## Links on this page + +- https://hcxsbx.abdm.gov.in/coverageeligibilityhcxservice/swagger-ui-custom.html +- https://hcxsbx.abdm.gov.in/preauthhcxservice/swagger-ui-custom.html +- https://hcxsbx.abdm.gov.in/claimhcxservice/swagger-ui-custom.html +- https://hcxsbx.abdm.gov.in/communicationhcxservice/swagger-ui-custom.html +- https://hcxsbx.abdm.gov.in/servicehcxpayment/swagger-ui-custom.html +- https://hcxsbx.abdm.gov.in/statushcxservice/swagger-ui-custom.html +- https://hcxsbx.abdm.gov.in/taskhcxservice/swagger-ui-custom.html +- https://hcxsbx.abdm.gov.in/searchhcxservice/swagger-ui-custom.html +- https://hcxsbx.abdm.gov.in/insuranceplanhcxservice/swagger-ui/index.html?configUrl=/insuranceplanhcxservice/api-docs/swagger-config#/V1.0%20APIs-Payer%20side/insuranceplanRequestPost +- https://hcxsbx.abdm.gov.in/communicationhcxservice/swagger-ui/index.html?configUrl=/communicationhcxservice/api-docs/swagger-config +- https://hcxsbx.abdm.gov.in/participanthcxservice/swagger-ui/index.html?configUrl=/participanthcxservice/api-docs/swagger-config +- https://hcxsbx.abdm.gov.in/subscriptionhcxservice/swagger-ui/index.html diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__appendix-NHCX-relay-example.md b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__appendix-NHCX-relay-example.md new file mode 100644 index 000000000..d685c2555 --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__appendix-NHCX-relay-example.md @@ -0,0 +1,13 @@ +# https://hcxsbx.abdm.gov.in/#/technical-specifications/appendix-NHCX-relay-example + +Appendix A - NHCX Relay example +Potential multi NHCX scenario +Scenarios for Cross gateway exchange +The cross gateway communication will be required in the following scenarios - +When a provider is onboarded in a gateway instance but the payer for that health policy scheme is registered in another gateway instance. +If a beneficiary enrolled in health policy took treatment in a network hospital in another state and that hospital is onboarded in a different gateway instance than the payer. +For top-up cases, the providers and payers are registered in different gateway instances and in such scenarios primary insurance is handled by one payer in one gateway instance but the secondary insurance is handled by another payer registered in a different gateway instance. +previous +   Audit and Reporting +next +Domain Specifications   diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol.md b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol.md new file mode 100644 index 000000000..395045648 --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol.md @@ -0,0 +1,5 @@ +# https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol + +Open Protocol +Technology backbone for the National Health Claims Exchange +As described in Key Specifications, Open protocol deals with the technology backbone for the Health Claims Data Exchange. Sections below define the key elements of the proposed Health Claims Data Exchange Protocol. diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy.md b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy.md new file mode 100644 index 000000000..b8545818c --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy.md @@ -0,0 +1,8 @@ +# https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/data-security-and-privacy + +Data Security and Privacy +Details of mechanisms to ensure data security and privacy +Given the sensitive nature of the information involved during claims processing - personal details, health-related information, etc., it is imperative that the data is kept secure during the exchange process (security if data while stored at sender and receiver is expected to be as per the prevailing data security regulation of the data storage). +There are many language specific libraries available that can help you implement the required encryption/signing/verification that is described above. +In order to achieve this, various approaches are defined in the +subsequent sections. diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy__api-security.md b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy__api-security.md new file mode 100644 index 000000000..95756c782 --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy__api-security.md @@ -0,0 +1,77 @@ +# https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/data-security-and-privacy/api-security + +API Security +Details of API security to ensure authenticated and authorised access to APIs +The protocol defines an API key-based security for authentication and authorization of the API calls between the participating systems and the NHCX gateway. NHCX instances have to generate the API keys in the form of JWT tokens ( + RFC7519 +) and shall mandatorily set an expiry time for all the generated tokens. +In future versions, NHCX instances may support JWTs issued by other system identity providers, e.g. Health Facility Registry's IDP. +Securing NHCX Gateway APIs +All participant systems (e.g.: providers, payers) should obtain an API key from the NHCX gateway with which it identifies itself to the gateway. When calling any API on the NHCX gateway, the participant system should pass the API key as part of the 'Authorization' http header. +Steps to obtain the API key: +After a successful verification and onboarding of a participant system onto the participant registry, the NHCX instance managing the registry shall share the following details via email, SMS, or both with the participant system: +client_id: + this is the identifier of the participant in the participant registry. +client_secret: + a unique secret is generated for the participant by the NHCX instance. The client_secret value shall be stored in the participant registry in an encrypted format and shall not be sent in the registry APIs. +The participant system follow the APIs to can call '/token/generate' API along with the client_id and client_secret they have received to obtain the API key. +POST https://dev.abdm.gov.in/gateway/v0.5/sessions +Content-Type: application/json +Request-Body: +{ +"client_id": "client_id received by the participant", +"client_secret": "client_secret received by the participant" +} +NHCX instance would respond with the API token upon successful validation of the client_id and client_secret values: +HTTP/1.1 200 OK +Content-Type: application/json +Cache-Control: no-cache, no-store +Response-Body: +{ +"access_token": "the API key, a JWT access token", +"issued_token_type": "urn:ietf:params:oauth:token-type:access_token", +"token_type": "Bearer", +"expires_in": 300 +} +JWT Token Structure: +API keys are expected to be in JWT format and signed as per JSON web signature (RFC7515). The API key should have three elements separated by periods (.): BASE64URL(UTF8(JOSE Header)), BASE64URL(JWS Payload), and BASE64URL(JWS Signature). +JOSE Header should be a JSON with the following values: +{ +"typ":"JWT", +"alg":"HS256" +} +JWS Payload should be a claim set containing the mandatory claims + jti, iss, sub, iat +and +exp. +jti - unique identifier for the JWT + iss - NHCX instance identifier + sub - client_id of the participant + iat - unix timestamp at which the JWT is issued +exp - the expiration time after which the JWT must not be accepted for processing +JWS Signature must be computed in the manner defined for HS256 algorithm over the input ASCII(BASE64URL(UTF8(JOSE Header)) || '.' || BASE64URL(JWS Payload)) using the client_secret value of the participant. +Revoking API Keys +NHCX instances can revoke the API key of a participant by generating a new client_secret and updating it in the participant registry. The participant system has to generate a new API key by calling the ‘/token/generate’ API with the new client_secret value. +Securing Participant System APIs +NHCX instances while making the calls to the participant system will use a self-generated JWT token with the following elements: +JOSE Header should be a JSON with the following values: +{ +"typ":"JWT", +"alg":"RS256" +} +JWS Payload should be a claim set containing the mandatory claims j + jti, iss, sub, iat +and +exp. +jti - unique identifier for the JWT +iss - NHCX instance identifier +sub - same as iss claim, NHCX instance identifier +iat - unix timestamp at which the JWT is issued +exp - the expiration time after which the JWT must not be accepted for processing +JWS Signature must be computed in the manner defined for RS256 algorithm over the input ASCII(BASE64URL(UTF8(JOSE Header)) || '.' || BASE64URL(JWS Payload)) using the private key of the NHCX instance. +Participant systems should validate the API key signature using the public key of the NHCX instance. + + +## Links on this page + +- https://datatracker.ietf.org/doc/html/rfc7519 diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy__audit-and-reporting.md b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy__audit-and-reporting.md new file mode 100644 index 000000000..0e6c14881 --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy__audit-and-reporting.md @@ -0,0 +1,10 @@ +# https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/data-security-and-privacy/audit-and-reporting + +Audit and Reporting +Overview of audit requirements +NHCX instances are expected to log each API call received along with the non encrypted details (domain headers, sig/enc algorithm details, sender & recipient details) and status of signature verification. +Key Requirements: +NHCX instances should provide reports against the audit logs for different actors - payors, providers, beneficiaries, regulators, observers. Each NHCX instance shall publish the list of reports supported by that instance and also define the level/details of information in each report. +The audit information stored should be made available through an API, so that the participating systems can query the audit log related to them. +Each NHCX instance shall define an archival policy for retention & deletion of audit logs. The policy shall also define the process for accessing the logs after archival, if the NHCX instance has support for it. +It is recommended for NHCX instances to have a configuration to control the amount of information that gets stored in the audit logs. diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy__message-security-and-integrity.md b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy__message-security-and-integrity.md new file mode 100644 index 000000000..cd3117043 --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy__message-security-and-integrity.md @@ -0,0 +1,63 @@ +# https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity + +Message Security and Integrity +Use of JWE to ensure payload security and integrity +TO ensure that sensitive information in the actual domain objects is not accessible even to the NHCX, protocol requires the payload defined by the domain data specifications to be encrypted using a separate asymmetric encryption key of the final recipient established at the time of participant onboarding into the registry. API then carries the encrypted value of the payload. The payload encryption is expected to be performed using JSON web encryption +RFC7516 +as per algorithm and enclosed values fixed in the protected headers section above. At this point in time, no unprotected headers are envisioned in the NHCX protocol. We also do not envision multiple recipient delivery in the current version of the NHCX protocol. +Message Encryption +The high-level steps to encrypt the payload using the public key of the final recipient are: +Find out the public key of the recipient through registry lookup on NHCX. +Let JWE protected header be = BASE64URL(UTF8((Registered JOSE headers) U (NHCX Protocol Headers) U (NHCX Domain Headers)). Please note that initial version of NHCX protocol requires following JOSE headers: +{ +"alg":"RSA-OAEP","enc":"A256GCM" +} +Generate a random Content Encryption Key (CEK) as per the encryption algorithm. +Encrypt the CEK with the recipient's public key using the RSAES-OAEP algorithm to produce the JWE Encrypted Key. + Base64url-encode the JWE Encrypted Key. + Generate a random JWE Initialization Vector. + Base64url-encode the JWE Initialization Vector. +Let the Additional Authenticated Data encryption parameter be +ASCII(BASE64URL(UTF8(JWE Protected Header))). +Perform authenticated encryption on the plaintext with the AES GCM algorithm using the CEK as the encryption key, the JWE Initialization Vector, and the Additional Authenticated Data value, requesting a 128-bit Authentication Tag output. +Base64url-encode the ciphertext. + Base64url-encode the Authentication Tag +Assemble the final representation in flattened JSON serialization (Section 7.2.2 of RFC7516): +{ +"protected":"", +"encrypted_key":"", +"aad":"", +"iv":"", +"ciphertext":"", +"tag":"" +} +Message Decryption +The high-level steps to decrypt and verify the integrity of the payload using the private key of the final recipient are: +From the received JSON serialized JWE token, Base64url decode the encoded representations of the JWE Protected Header (protected), the JWE Encrypted Key (encrypted_key), the JWE Initialization Vector (iv), the JWE Ciphertext (ciphertext), the JWE Authentication Tag (tag), and the JWE AAD (aad), following the restriction that no line breaks, whitespace, or other additional characters have been used. +Verify that the octet sequence resulting from decoding the encoded JWE Protected Header is a UTF-8-encoded representation of a completely valid JSON object conforming to +RFC 7159 +; let the JWE Protected Header be this JSON object +Let the JOSE Header be the JWE Protected Header. Verify that the resulting JOSE Header does not contain duplicate Header Parameter names. +Determine the Key Management Mode employed by the algorithm specified by the "alg" (algorithm) Header Parameter. +Verify that the JWE uses a key known to the recipient. +Decrypt the JWE Encrypted Key to produce the CEK. The CEK MUST have a length equal to that required for the content-encryption algorithm. +Compute the Encoded Protected Header value BASE64URL(UTF8(JWE Protected Header)). This protected header is (Registered JOSE headers) U (NHCX Protocol Headers) U (NHCX Domain Headers). +Let the Additional Authenticated Data encryption parameter be ASCII(Encoded Protected Header). +Decrypt the JWE Ciphertext using the CEK, the JWE Initialization Vector, the Additional Authenticated Data value, and the JWE Authentication Tag (which is the Authentication Tag input to the calculation) using the specified content-encryption algorithm, returning the decrypted plaintext and validating the JWE Authentication Tag in the manner specified for the algorithm, rejecting the input without emitting any decrypted output if the JWE Authentication Tag is incorrect. +Participating systems are expected to follow best practices guidelines as in +RFC8725 +to ensure the security of the payload. +It is recommended to rotate these encryption keys once every year and mechanisms implemented for the providers/payers/NHCX to intimate the ecosystem about the potential compromise of the keys. +Here is a sample of the set of libraries that you can explore: +Nimbus + NaCl + Libgcrypt + PyNaCl + TweetNaCl + + +## Links on this page + +- https://datatracker.ietf.org/doc/html/rfc7516 +- https://datatracker.ietf.org/doc/html/rfc7159 +- https://datatracker.ietf.org/doc/html/rfc8725 diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy__transport-security.md b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy__transport-security.md new file mode 100644 index 000000000..821762386 --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__data-security-and-privacy__transport-security.md @@ -0,0 +1,5 @@ +# https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/data-security-and-privacy/transport-security + +Transport Security +TLS as default mode of communication +All communications between National Health Claims Exchange(s) and participating entities are expected to be done using Transport Layer Security. Therefore all APIs are expected to work only as HTTPS in the production environments. diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__healthclaims-exchange-protocol.md b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__healthclaims-exchange-protocol.md new file mode 100644 index 000000000..d9e1ad1fc --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__healthclaims-exchange-protocol.md @@ -0,0 +1,202 @@ +# https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/healthclaims-exchange-protocol + +National Health Claims Exchange (NHCX) Protocol +Building blocks of the National Health Claims Exchange protocol +As indicated in the +overall message flow diagram, + the exchange platform will be the routing engine that will be responsible for receiving the data from either participant (provider, payor, another NHCX instance, ...), and performing necessary validations, and forwarding it to the intended recipients. +Terminology +Request - + Initiation of the flow by the sender by passing relevant payload in the message structure defined by this protocol. Requests may travel from Sender to the Receiver through a relay of NHCX instances. +Response - +Response/reply by the recipient of the request by passing relevant response payload defined by this protocol. Responses may also travel from the “original request message” recipient to the “original request message” sender through a relay of NHCX instances. The key difference here is that a response is always sent as an earlier event received from the NHCX instance. +NHCX instance - + A runtime of the NHCX platform that performs the role of message receiving and forwarding on behalf of senders and receivers. Based on the use case, any participating party may act as the sender (thereby a requester), or a receiver (thereby a recipient). E.g. for the cashless claims use cases defined so far - Providers will be the senders in case of CheckEligibility, PreAuth and ClaimSubmission use cases (and the payers will be recipients), while Payers will be the sanders in case of PaymentNotice (and the providers will be recipients). +Message - + NHCX protocol transfers a Message that contains a transport envelope and the content as per the use case. +Transport envelop is a set attribute that carries the transport information for NHCX to reliably forward the message to the destination +Content would have two parts: +Business headers - any domain or use case specific information which may not be necessary for the transportation but allows more information about the payload, e.g. type of the payload +Payload - Domain object defined for the pertinent use case. Usually, this data will be encrypted using the recipient's key to ensure that NHCX instances cannot view this data +Senders and Receivers - Two systems participating in the information exchange. They may also be referred to as client/server as per current industry terminology. E.g. Provider(s) are senders in claims flow use case, and Payor(s) are senders in Payment Notice use case in the flow diagram above. +Overall Message Flow Diagram +NHCX protocol is designed for the exchanges to work in an asynchronous manner (like SMTP), therefore each use case will be completed in a cycle of messages as shown below: +Exchange Protocol +Sender to NHCX (Leg 1) +The sender + (originator of the communication) sends the initial message to its preferred NHCX instance. +NHCX validates the status of the sender and the next intended recipient (maybe another NHCX instance) on its registries. +NHCX then performs required signature verifications etc before responding with an acknowledgement to the sender. +It then forwards it to either the end recipient (if registered with the same instance) or the next NHCX in the chain. +Steps 1 and 7 in the above diagram as examples of this leg. +NHCX to Receiver (Leg 2) +Final NHCX in the relay chain (could be the original NHCX itself) checks the status of the recipient on its registries, +performs needed verifications and forwards the message to the recipient. +The recipient acknowledges the receipt of the message. +Steps 3 and 9 in the above diagram as examples of this leg. +Receiver to NHCX (Leg 3) +The recipient + (receiver of the original request message) sends the response message to its preferred NHCX instance. +NHCX validates the status of the recipient and original sender (maybe another NHCX instance) on its registries. +NHCX then performs required signature verifications etc before responding with an acknowledgement to the recipient. +It then forwards it to either the initial sender (if registered with the same instance) or the next NHCX in the chain. +Steps 4 and 10 in the above diagram as examples of this leg. +NHCX to Sender (Leg 4) +Final NHCX in the relay chain (could be the original NHCX itself) checks the status of the original sender on its registries, +Performs needed verifications and forwards the response message to the sender. +The sender acknowledges the receipt of the response message. +Steps 6 and 12 in the above diagram as examples of this leg. +Relays +In case Sender and receiver are listed/registered on different NHCX instances, there may be relays between the NHCXs. Steps 2, 5, 8 and 11 in the above diagram may involve such relays. Relay Architecture will be finalised after finalising the NHCX registry by NHA. +Message Structure +To facilitate safe, secure, and reliable message exchanges through NHCX, its message payload needs to be designed in a manner that separates the actual use case-specific information (payload) from transport and generic domain-specific information (headers). To achieve this, NHCX messages can be structured in line with +JWE tokens +as below (value in bracket are the corresponding JSON keys as per JWE): +Registered JOSE Headers +JSON Web encryption header as per +RFC7516. +For NHCX V1, this is proposed to be fixed to: +{ +"alg":"RSA-OAEP","enc":"A256GCM" +} +NHCX Protocol Headers +Used as private headers as per +RFC7516. +section 4.3. Please note that all the parameter names are appended with “x-NHCX-” to avoid a collision. +The following table provides the protocol related header elements in the claims exchange: +Name +Description +Type +Addition Properties +x-NHCX-sender_code +Registry code of the sender (e.g. provider or payer) +String +Mandatory +x-NHCX-recipient_code +Registry code of the recipient (e.g. provider or payer) +String +Mandatory +x-NHCX-request_id +Sender generated unique id for each originating request. +String +Mandatory +x-NHCX-correlation_id +Unique id of the conversation (a collection of related messages). It may be chosen as the message_id of in the original sender’s (initiator’s) system. For return messages (asynchronous responses) responders are expected to populate with the one in the request. +String +Mandatory +x-NHCX-workflow_id +Unique id of workflow that may span over a series of message exchanges, e.g. an eligibility check, a preauth and then claims submission for a patient may be linked with such an id from the providers initiate a request on check eligibility +String +Optional +x-NHCX-timestamp +Unix timestamp of the message while sending +datetime +Mandatory +x-NHCX-debug_flag +Request to the server to include debug information. Useful in the time of integration testing and prod debugging. However, server(s) may choose to ignore this flag based on their policy. +ENUM +Error +Info +Debug +Optional +x-NHCX-status +Operational status of the message. Depending on the leg of the message it would be: +request.initiate +request.retry + response.success + response.fail + response.sender_not_supported + response.unhandled + response.request_retry +String +Mandatory +x-NHCX-error_details +Expected to be used for providing details of the status. It Will be especially useful in scenarios where Operational status indicates an irrecoverable error. Key elements of this object are: +Code: + error, info, debug code from the system - expected to be namespaced for better readability +Message: + Short description of the detail +Trace: + Long description supporting the Code +JSON Object - E.g. +{ +error.code: “bad.input”, error.message: “Provider code not found”, trace: “” +} +Optional +x-NHCX-debug_details +Expected to be used for providing details of the status. It Will be especially useful in debugging scenarios Key elements of this object are: +Code: + error, info, debug code from the system - expected to be namespaced for better readability +Message: + Short description of the detail +Trace: + Long description supporting the Code +JSON Object - E.g. +{ +error.code: “bad.input”, error.message: “Provider code not found”, trace: “” +} +Optional +NHCX Domain Headers +JSON object containing a map of domain-specific header values as proposed in domain data specifications. E.g. For claims use cases, domain specs may decide to populate the total claimed amount, list of diagnostics/procedures. Please note that all such parameter names must follow the naming convention x-NHCX- +- +, where +use_case_name = short name (< 16 chars) given to the use case by domain working group, it is advisable to keep it the same as the one in API’s URI path +Parameter_name = short name (<32 chars) given to the parameter +Therefore the protected headers will be: +Protected Headers = (Registered JOSE headers) U (NHCX Protocol Headers) U (NHCX Domain Headers) +Payload +Use case-specific base64 encoded, encrypted payload as defined in +Domain Data specifications. +This can be thought of as a private claim in JWT terminology. JSON web encryption as defined in +RFC7516 +to be used for encrypting the payload with “alg” and “enc” as defined in the JOSE header above. +E.g. In the current cashless claims scenario, domain working groups have decided the payload to be an FHIR bundle of the appropriate type. Therefore the payload will be an encrypted FHIR bundle as defined in the domain data specs. +Signatures +As per +RFC7516 +, cryptographic mechanisms used in JWE encrypts and provides integrity protection to encrypted payload and protected headers using Authenticated Encryption with Associated Data (AEAD), hence additional signatures are not needed for message integrity protection. +API Structure +Based on the above protocol definition and the message structure, each use case API in the HCP ecosystem is expected to follow the following pattern for the onward and return journey of the use case message: +:////, where +transport_protocol - for NHCX V1 purpose it will always be https +server_address is the address of the server on which the API is called (an NHCX for payor/provider or a payor/provider/NHCX for an NHCX) +protocol_version - API version for the current protocol to help support protocol transitions +resource_name is the name of the domain resource that the API is serving. E.g. for cashless claims, it may be “claims”, “coverage eligibility”, etc. based on the use case. +action is the action sought within the context of that resource +on_action represents the callback from the receiving system for responding to the original message +Keeping this pattern in mind, in the current cashless use case following APIs are expected to be supported. +Please note that search APIs are expected to support search parameters as detailed in the +Domain Data specifications +. For FHIR based entities this is expected to be clearly published in the corresponding implementation guides. Visibility and availability of the attributes in the search result payloads are also expected to be defined in domain data specifications. +CoverageEligibility +Eligibility check +/coverageeligibility/check (provider->NHCX, NHCX->payor) +/coverageeligibility/on_check (payor->NHCX, NHCX->provider) +Claims +PreAuth submission +/preauth/submit (provider->NHCX, NHCX->payor) +/preauth/on_submit (payor->NHCX, NHCX->provider) +PreAuth Search +/preauth/search (provider->NHCX, NHCX->payor) +/preauth/on_search (payor->NHCX, NHCX->provider) +Claim submission +/claim/submit (provider->NHCX, NHCX->payor) +/claim/on_submit (payor->NHCX, NHCX->provider) +Claims Search (Also supports status search) +/claim/search (provider|regulator|auditor->NHCX, NHCX->payor) +/claim/on_search (payor->NHCX, NHCX->provider|regulator|auditor) +Payments +Payment notice and acknowledgement +/paymentnotice/request (payor>NHCX, NHCX->provider-) +/paymentnotice/on_request (provider->NHCX, NHCX->payor) +Payment Search (Also supports status search) +/paymentnotice/search (provider->NHCX, NHCX->payor) +/paymentnotice/on_search (payor->NHCX, NHCX->provider) +Following + OpenAPI 3.0 specification + details these APIs in detail. + + +## Links on this page + +- https://datatracker.ietf.org/doc/html/rfc7516 diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__keydesign-consideration.md b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__keydesign-consideration.md new file mode 100644 index 000000000..456e7afd9 --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__keydesign-consideration.md @@ -0,0 +1,17 @@ +# https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/keydesign-consideration + +Key Design Considerations +List of considerations to ensure adherence to the listed design principles +In order to fulfil architectural principles listed in +National Health Claims Exchange - Open Specifications, +the protocol needs to consider the following key design elements: +The protocol must be designed to support the asynchronous exchange of information to support the scale and asynchronous nature of processes in the industry +The protocol must support the federated deployment of multiple NHCX instances. +In order to ensure the security and privacy of sensitive data +The protocol must allow for separation of transport (and any other common information) from sensitive information in the respective flows. +The protocol must provide for encryption, signing, and auditing of relevant information. +The protocol should allow creating unique identifiers for each message exchange. +The protocol should allow related multiple messages that are part of a single business flow. +The protocol should allow using existing registries for key entities - beneficiary, provider, and payor with a facility to extend them for the specific use case. +The protocol should be designed to allow for the inclusion of the new types of use cases. +The protocol should be designed to allow extending a use case as per the need of the use case/program (for example, a particular government scheme or innovative health financing solution may need different information about the beneficiary, provider, or intervention) diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__registries.md b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__registries.md new file mode 100644 index 000000000..793b9a023 --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/pages/technical-specifications__open-protocol__registries.md @@ -0,0 +1,86 @@ +# https://hcxsbx.abdm.gov.in/#/technical-specifications/open-protocol/registries + +Registries +NHCX registries will act as a source of truth for participant information on the platform. These may be extended from/link to already existing registries in the ecosystem, e.g. registry may extend from National Health Facility Registry provided by NHA. The benefit of extending from an existing registry would be: +Easy maintenance of base data at the source registry +The extended registry only needs to maintain additional/supplementary information pertaining to its use case +Better interoperability +Keeping with the key design principles listed above, registries on NHCX will strive to be minimalistic, self-maintainable, support non-repudiability, accessible through OpenAPIs, Extensible and evolvable, and designs for data privacy and security. All registries on the NHCX platform will minimally provide the following APIs: +Create +Update +Delete +Search +Please note that onboarding of the actors in the registry will take place through workflows defined by domain groups and may change over time, therefore the access to the data modification APIs would be controlled by the NHCX instance provider and used as part of the onboarding process. +Participating Organisations/Systems Registry +This registry stores key details about the participants on the exchange who can exchange data through it. It may link with data on the HFR registry and will have fields necessary to facilitate claims data exchange with providers. Proposed attributes of the registry are: +Name +Description +Type +Addition Properties +participant_code +Machine-readable unique identifier of the participant, generated by the NHCX instance. +String +Mandatory +Unique across installations - namespaced as participant_code@NHCX_instance_code +registry_code +Health Facility Registry code or Payer Registry for the participant - used to validate and link the participant based on the role selected. +String +Optional +participant_name +A human-readable name for the participant +String +Mandatory +Unique within the NHCX instance context +roles +Roles assigned to the participant as per the definition in the domain specifications. This will be used for access control. +String +Mandatory +address +The physical address of the participant including its geolocation +JSON structure +Optional +email +Email ids for claims related communication +String +Optional +Maximum 3 +phone +Landline number of the participant +String +Optional +Maximum 3 +mobile +Mobile number for claims related communication +String +Mandatory +Minimum 1 +Maximum 3 +status +Current status of the participant on the instance. Can be: +Created (Not verified yet) +Active +Inactive +Blocked +String +Mandatory +signing_cert_path +URI/file path to the JWT signing certificate +String +Optional +encryption_cert +URI/file path to encryption certificate +String +Mandatory +endpoint_url +Default endpoint to make API calls +String +Mandatory +payment_details +Default payment details: +UPI ID, or +Ac Number + IFSC Code +JSON Structure +Optional +Following +OpenAPI 3.0 document +describes these registries and the associated APIs. diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/claimhcxservice.json b/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/claimhcxservice.json new file mode 100644 index 000000000..f0e518b83 --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/claimhcxservice.json @@ -0,0 +1 @@ +{"openapi":"3.1.0","info":{"title":"NHCX - Claim APIs","description":"The National Health Claims Exchange (NHCX) is a digital","termsOfService":"http://swagger.io/terms/","license":{"name":"Apache 2.0","url":"http://springdoc.org"},"version":"1.0.0"},"servers":[{"url":"/claimhcxservice","description":"Default Server URL"}],"paths":{"/v1/delete":{"post":{"tags":["Internal troubleshooting - APIs"],"operationId":"deleteRecordsWithCorrelationAndAction","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteRecord"}}},"required":true},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SuccessResponse"}}}},"400":{"description":"Request Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Requested resource was not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/v1/claim/submit":{"post":{"tags":["V1.0 APIs-Payer side"],"description":"This API is for providers to submit claim requests (and resubmit updated request) to HCX gateway and for HCX gateway to route the same request to payors.

Payload for this API has to be created as per the [ClaimBundle](https://nrces.in/ndhm/fhir/r4/StructureDefinition/ClaimBundle) defined in HCX Specification and serialized as per the [guidelines](https://hcxsbx.abdm.gov.in/#/technical-specifications) in HCX Specifications.","operationId":"claimSubmitPost","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JWEPayload"}}},"required":true},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"400":{"description":"Request Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"404":{"description":"Requested resource was not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/v1/claim/on_submit":{"post":{"tags":["V1.0 APIs-Provider side"],"description":"This is the callback API on HCX gateways and on Provider systems which will be called by Payor systems and HCX gateways to return the response for Claim requests.

Payload for this API has to be created as per the [ClaimResponseBundle](https://nrces.in/ndhm/fhir/r4/StructureDefinition/ClaimResponseBundle) defined in HCX Specifications and serialized as per the [guidelines](https://hcxsbx.abdm.gov.in/#/technical-specifications) in HCX Specifications.","operationId":"claimOnSubmitPost","requestBody":{"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/JWEPayloadResponse"},{"$ref":"#/components/schemas/ProtocolResponse"}]}}},"required":true},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"400":{"description":"Request Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"404":{"description":"Requested resource was not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/internal/v1/claim/submit":{"post":{"tags":["V1.0 APIs-Payer side"],"description":"This API is for providers to submit claim requests (and resubmit updated request) to HCX gateway and for HCX gateway to route the same request to payors.

Payload for this API has to be created as per the [ClaimBundle](https://nrces.in/ndhm/fhir/r4/StructureDefinition/ClaimBundle) defined in HCX Specification and serialized as per the [guidelines](https://hcxsbx.abdm.gov.in/#/technical-specifications) in HCX Specifications.","operationId":"claimSubmitPostInternal","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JWEPayload"}}},"required":true},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"400":{"description":"Request Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"404":{"description":"Requested resource was not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/internal/v1/claim/on_submit":{"post":{"tags":["V1.0 APIs-Provider side"],"description":"This is the callback API on HCX gateways and on Provider systems which will be called by Payor systems and HCX gateways to return the response for Claim requests.

Payload for this API has to be created as per the [ClaimResponseBundle](https://nrces.in/ndhm/fhir/r4/StructureDefinition/ClaimResponseBundle) defined in HCX Specifications and serialized as per the [guidelines](https://hcxsbx.abdm.gov.in/#/technical-specifications) in HCX Specifications.","operationId":"claimOnSubmitPostInternal","requestBody":{"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/JWEPayloadResponse"},{"$ref":"#/components/schemas/ProtocolResponse"}]}}},"required":true},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"400":{"description":"Request Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"404":{"description":"Requested resource was not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}}},"security":[{"bearer_auth":[]}]}}},"components":{"schemas":{"DeleteRecord":{"type":"object","properties":{"correlationid":{"type":"string"},"action":{"type":"string"}}},"Error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}},"StatusResponseObject":{"type":"object","properties":{"sender_code":{"type":"string"},"recipient_code":{"type":"string"},"entity_type":{"type":"string","enum":["coverageeligibility","predetermination","preauth","claim","task","payment","insuranceplan"]},"protocol_status":{"type":"string","enum":["request.queued","request.error","request.dispatched"]}}},"SuccessResponse":{"type":"object","properties":{"timestamp":{"type":"string"},"api_call_id":{"type":"string","format":"uuid"},"correlation_id":{"type":"string","format":"uuid"},"result":{"$ref":"#/components/schemas/StatusResponseObject"},"error":{"$ref":"#/components/schemas/Error"}}},"ErrorResponse":{"type":"object","description":"This is a response to the ClaimForm API call","properties":{"timestamp":{"type":"string","format":"date-time"},"api_call_id":{"type":"string","format":"uuid"},"correlation_id":{"type":"string","format":"uuid"},"error":{"$ref":"#/components/schemas/Error"}}},"JWEPayload":{"type":"object","description":"All the HCX protocol APIs require the request body to sent in JWE format (as defined in [RFC-7516](https://datatracker.ietf.org/doc/html/rfc7516)).","properties":{"payload":{"type":"string","description":"The paylod should be a JWE token containing the following elements. 1. Protected headers (**protected**) - A set of attributes that provide transport, security, message integrity and summary information about the message being exchanged. Refer to the ProtectedHeader schema definition below for details. 2. JWE element (**encrypted_key**) - Content Encryption Key. Refer to the EncryptedKey schema definition below for details. 3. JWE element (**iv**) - Initialisation Vector for the algorithm. Refer to the InitializationVector schema definition below for details. 4. JWE element (**aad**) - Additional authentication data. Refer to AAD schema definition below for details. 5. Encrypted Payload (**ciphertext**) - Payload containing the relevant domain entity (eObject) as prescribed for the use case by the domain specifications. This needs to be encrypted so that HCX cannot read this. Refer to CipherText schema definition below for more details. 6. Authentication tag (**tag**) - Digital signature on the protected header and the payload of the message to ensure its integrity. Refer to AuthenticationTag schema definition below for more details. Detailed steps on how to construct the JWE token are provided in this [section](https://docs.pmjay.gov.in/hcx-specifications/hcx-technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity#message-encryption) of the HCX specifications.","example":"eyJlbmMiOiJBMjU2R0NNIiwKImFsZyI6IlJTQS1PQUVQIiwKIngtaGN4LXNlbmRlcl9jb2RlIjoiMS00ZGMzZTA4OC1hMzEzLTQ0YWItYWZhMS0wMjIyOTU5Y2I3NWIiLAoieC1oY3gtcmVjaXBpZW50X2NvZGUiOiIxLTkzZjkwOGJhLWI1NzktNDUzZS04YjJhLTU2MDIyYWZhZDI3NSIsCiJ4LWhjeC1yZXF1ZXN0X2lkIjoiMjZiMTA2MGMtMWU4My00NjAwLTk2MTItZWEzMWUwY2E1MDkxIiwKIngtaGN4LWNvcnJlbGF0aW9uX2lkIjoiNWU5MzRmOTAtMTExZC00ZjBiLWIwMTYtYzIyZDgyMDY3NGUxIiwKIngtaGN4LXRpbWVzdGFtcCI6IjIwMjEtMTAtMjdUMjA6MzU6NTIuNjM2KzA1MzAiLAoieC1oY3gtc3RhdHVzIjoicmVxdWVzdC5pbml0aWF0ZSIsCiJ4LWhjeC13b3JrZmxvd19pZCI6IjVlOTM0ZjkwLTExMWQtNGYwYi1iMDE2LWMyMmQ4MjA2NzRlMiIsCiJ4LWhjeC1kZWJ1Z19mbGFnIjoiSW5mbyIsCiJ4LWhjeC1lcnJvcl9kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCAidHJhY2UiOiAiIn0sCiJ4LWhjeC1kZWJ1Z19kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCJ0cmFjZSI6IiJ9LAoiandzX2hlYWRlciI6eyJ0eXAiOiJKV1QiLCAiYWxnIjoiUlMyNTYifSwKImp3ZV9oZWFkZXIiOnsiYWxnIjoiUlNBLU9BRVAiLCJlbmMiOiJBMjU2R0NNIn0KfQ==.6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.AxY8DCtDaGlsbGljb3RoZQ.KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.Mz-VPPyU4RlcuYv1IwIvzw"}},"required":["payload"]},"StatusSuccessResponse":{"type":"object","properties":{"timestamp":{"type":"string"},"api_call_id":{"type":"string","format":"uuid"},"correlation_id":{"type":"string","format":"uuid"},"result":{"$ref":"#/components/schemas/StatusResponseObject"},"error":{"$ref":"#/components/schemas/Error"}}},"ClaimOnSubmitBody":{"discriminator":{"propertyName":"type"},"properties":{"type":{"type":"string"}},"required":["type"]},"DomainHeaders":{"type":"object","description":"JSON object containing a map of domain-specific header values as proposed in domain data specifications. E.g. For claims use cases, domain specs may decide to populate the total claimed amount, list of diagnostics/procedures.","properties":{"use_case_name":{"type":"string"},"amt_processed":{"type":"string"}}},"JWEPayloadResponse":{"allOf":[{"$ref":"#/components/schemas/ClaimOnSubmitBody"},{"type":"object","properties":{"payload":{"type":"string","description":"The paylod should be a JWE token containing the following elements. 1. Protected headers (**protected**) - A set of attributes that provide transport, security, message integrity and summary information about the message being exchanged. Refer to the ProtectedHeader schema definition below for details. 2. JWE element (**encrypted_key**) - Content Encryption Key. Refer to the EncryptedKey schema definition below for details. 3. JWE element (**iv**) - Initialisation Vector for the algorithm. Refer to the InitializationVector schema definition below for details. 4. JWE element (**aad**) - Additional authentication data. Refer to AAD schema definition below for details. 5. Encrypted Payload (**ciphertext**) - Payload containing the relevant domain entity (eObject) as prescribed for the use case by the domain specifications. This needs to be encrypted so that HCX cannot read this. Refer to CipherText schema definition below for more details. 6. Authentication tag (**tag**) - Digital signature on the protected header and the payload of the message to ensure its integrity. Refer to AuthenticationTag schema definition below for more details. Detailed steps on how to construct the JWE token are provided in this [section](https://docs.pmjay.gov.in/hcx-specifications/hcx-technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity#message-encryption) of the HCX specifications.","example":"eyJlbmMiOiJBMjU2R0NNIiwKImFsZyI6IlJTQS1PQUVQIiwKIngtaGN4LXNlbmRlcl9jb2RlIjoiMS00ZGMzZTA4OC1hMzEzLTQ0YWItYWZhMS0wMjIyOTU5Y2I3NWIiLAoieC1oY3gtcmVjaXBpZW50X2NvZGUiOiIxLTkzZjkwOGJhLWI1NzktNDUzZS04YjJhLTU2MDIyYWZhZDI3NSIsCiJ4LWhjeC1yZXF1ZXN0X2lkIjoiMjZiMTA2MGMtMWU4My00NjAwLTk2MTItZWEzMWUwY2E1MDkxIiwKIngtaGN4LWNvcnJlbGF0aW9uX2lkIjoiNWU5MzRmOTAtMTExZC00ZjBiLWIwMTYtYzIyZDgyMDY3NGUxIiwKIngtaGN4LXRpbWVzdGFtcCI6IjIwMjEtMTAtMjdUMjA6MzU6NTIuNjM2KzA1MzAiLAoieC1oY3gtc3RhdHVzIjoicmVxdWVzdC5pbml0aWF0ZSIsCiJ4LWhjeC13b3JrZmxvd19pZCI6IjVlOTM0ZjkwLTExMWQtNGYwYi1iMDE2LWMyMmQ4MjA2NzRlMiIsCiJ4LWhjeC1kZWJ1Z19mbGFnIjoiSW5mbyIsCiJ4LWhjeC1lcnJvcl9kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCAidHJhY2UiOiAiIn0sCiJ4LWhjeC1kZWJ1Z19kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCJ0cmFjZSI6IiJ9LAoiandzX2hlYWRlciI6eyJ0eXAiOiJKV1QiLCAiYWxnIjoiUlMyNTYifSwKImp3ZV9oZWFkZXIiOnsiYWxnIjoiUlNBLU9BRVAiLCJlbmMiOiJBMjU2R0NNIn0KfQ==.6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.AxY8DCtDaGlsbGljb3RoZQ.KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.Mz-VPPyU4RlcuYv1IwIvzw"}}}],"description":"All the HCX protocol APIs require the request body to sent in JWE format (as defined in [RFC-7516](https://datatracker.ietf.org/doc/html/rfc7516)).","required":["payload"]},"ProtocolHeaderXhcxdebugDetails":{"type":"object","description":"Expected to be used for providing details of the status. Will be specially useful in debugging scenarios.","properties":{"code":{"type":"string"},"message":{"type":"string"},"trace":{"type":"string"}}},"ProtocolHeaderXhcxerrorDetails":{"type":"object","description":"Expected to be used for providing details of the status. Will be specially useful in scenarios where operational status indicates irrecoverable error.","properties":{"code":{"type":"string"},"message":{"type":"string"},"trace":{"type":"string"}}},"ProtocolResponse":{"allOf":[{"$ref":"#/components/schemas/ClaimOnSubmitBody"},{"type":"object","properties":{"x-hcx-sender_code":{"type":"string","description":"Registry code of the sender (e.g. provider or payer)","example":"PROVIDER01@HCX01"},"x-hcx-recipient_code":{"type":"string","description":"Registry code of the recipient (e.g. provider or payer)","example":"PAYOR01@HCX01"},"x-hcx-api_call_id":{"type":"string","format":"uuid","description":"Sender generated unique id for each originating request. All senders (providers & payors) must generate and set a unique value to the x-hcx-api_call_id protocol header in all the API calls to the HCX gateway."},"x-hcx-correlation_id":{"type":"string","format":"uuid","description":"Unique id for all messages (requests & responses) that are involved in processing of one cycle (like coverage eligibility, pre-auth, claim, or payment notice cycle). The participant system sending the originating request of the cycle must set the x-hcx-correlation_id in the initial API call and the HCX gateway shall forward the same correlation id to the recipient of the request. The recipient must set the same correlation id in the response API call and in other API calls related to the original request (e.g. communication request, forward/redirect requests). And the same correlation id must be sent in all subsequent API calls (related to the same cycle). In case of status API call, this header should have the correlation id of the request for which the status is being requested for."},"x-hcx-workflow_id":{"type":"string","description":"Unique id for one complete workflow that spans over a series of cycles and message exchanges within the context of an admission/case. This is an optional header that can be set by providers to the same value for all requests (coverage eligibility check, preauth, claim, etc) related to a single admission/case. And when the workflow_id is sent by the originating provider, all other participant systems (payors) must set the same workflow id in all API calls (responses, forwards/redirects, payment notices, etc) related to the workflow."},"x-hcx-timestamp":{"type":"string","description":"Unix timestamp when the request is sent.","example":1629057611000},"x-hcx-debug_flag":{"type":"string","description":"Request to the server to include debug information. Useful in the time of integration testing and prod debugging. However server(s) may choose to ignore this flag based on their policy.","enum":["Error","Info","Debug"]},"x-hcx-status":{"type":"string","description":"Operational status of the message. Depending on the leg of the message, it would be one of the defined values in the enum.","enum":["request.initiated","request.processed","request.queued","request.error","request.stopped","request.dispatched","response.complete","response.error","response.partial","response.redirect"]},"x-hcx-redirect_to":{"type":"string"},"x-hcx-error_details":{"$ref":"#/components/schemas/ProtocolHeaderXhcxerrorDetails"},"x-hcx-debug_details":{"$ref":"#/components/schemas/ProtocolHeaderXhcxdebugDetails"},"x-hcx-domain-header":{"$ref":"#/components/schemas/DomainHeaders"},"x-hcx-entity-type":{"type":"string","enum":["coverageeligibility","predetermination","preauth","claim","task","payment","insuranceplan"]},"x-hcx-ben-abha-id":{"type":"string"}}}],"description":"Object to be returned as payload of the callback API (on_* APIs) in case there are any protocol related errors while processing the request or send a redirection instruction to the original sender of the request.","required":["x-hcx-api_call_id","x-hcx-correlation_id","x-hcx-recipient_code","x-hcx-sender_code","x-hcx-timestamp"]}}}} \ No newline at end of file diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/communicationhcxservice.json b/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/communicationhcxservice.json new file mode 100644 index 000000000..0c53a4b08 --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/communicationhcxservice.json @@ -0,0 +1 @@ +{"openapi":"3.1.0","info":{"title":"NHCX - Communication APIs","description":"The National Health Claims Exchange (NHCX) is a digital","termsOfService":"http://swagger.io/terms/","license":{"name":"Apache 2.0","url":"http://springdoc.org"},"version":"1.0.0"},"servers":[{"url":"/communicationhcxservice","description":"Default Server URL"}],"paths":{"/v1/communication/request":{"post":{"tags":["V1.0 APIs-Provider side"],"description":"This API is for payors to raise a communication requests to HCX gateway and for HCX gateway to route the same request to providers during the claims cycle.

Payload for this API has to be created as per the Communication Request Document defined in [HCX Specifications] (https://www.hl7.org/fhir/communicationrequest.html) and serialized as per the [guidelines](https://hcxsbx.abdm.gov.in/#/technical-specifications) in HCX Specifications.","operationId":"communicationRequestPost","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JWEPayload"}}},"required":true},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"400":{"description":"Request Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"404":{"description":"Requested resource was not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/v1/communication/on_request":{"post":{"tags":["V1.0 APIs-Payer side"],"description":"This is the callback API on HCX gateways and on Payor systems which will be called by Provider systems and HCX gateways to return the response for Communication requests.

Payload for this API has to be created as per the Communication defined in [HCX Specifications] (https://www.hl7.org/fhir/communication.html) and serialized as per the [guidelines](https://hcxsbx.abdm.gov.in/#/technical-specifications) in HCX Specifications.","operationId":"communicationOnRequestPost","requestBody":{"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/JWEPayloadResponse"},{"$ref":"#/components/schemas/ProtocolResponse"}]}}},"required":true},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"400":{"description":"Request Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"404":{"description":"Requested resource was not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/internal/v1/communication/request":{"post":{"tags":["V1.0 APIs-Provider side"],"description":"This API is for payors to raise a communication requests to HCX gateway and for HCX gateway to route the same request to providers during the claims cycle.

Payload for this API has to be created as per the Communication Request Document defined in [HCX Specifications] (https://www.hl7.org/fhir/communicationrequest.html) and serialized as per the [guidelines](https://hcxsbx.abdm.gov.in/#/technical-specifications) in HCX Specifications.","operationId":"communicationRequestPostInternal","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JWEPayload"}}},"required":true},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"400":{"description":"Request Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"404":{"description":"Requested resource was not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/internal/v1/communication/on_request":{"post":{"tags":["V1.0 APIs-Payer side"],"description":"This is the callback API on HCX gateways and on Payor systems which will be called by Provider systems and HCX gateways to return the response for Communication requests.

Payload for this API has to be created as per the Communication defined in [HCX Specifications] (https://www.hl7.org/fhir/communication.html) and serialized as per the [guidelines](https://hcxsbx.abdm.gov.in/#/technical-specifications) in HCX Specifications.","operationId":"communicationOnRequestPostInternal","requestBody":{"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/JWEPayloadResponse"},{"$ref":"#/components/schemas/ProtocolResponse"}]}}},"required":true},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"400":{"description":"Request Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"404":{"description":"Requested resource was not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}}},"security":[{"bearer_auth":[]}]}}},"components":{"schemas":{"JWEPayload":{"type":"object","description":"All the HCX protocol APIs require the request body to sent in JWE format (as defined in [RFC-7516](https://datatracker.ietf.org/doc/html/rfc7516)).","properties":{"payload":{"type":"string","description":"The paylod should be a JWE token containing the following elements. 1. Protected headers (**protected**) - A set of attributes that provide transport, security, message integrity and summary information about the message being exchanged. Refer to the ProtectedHeader schema definition below for details. 2. JWE element (**encrypted_key**) - Content Encryption Key. Refer to the EncryptedKey schema definition below for details. 3. JWE element (**iv**) - Initialisation Vector for the algorithm. Refer to the InitializationVector schema definition below for details. 4. JWE element (**aad**) - Additional authentication data. Refer to AAD schema definition below for details. 5. Encrypted Payload (**ciphertext**) - Payload containing the relevant domain entity (eObject) as prescribed for the use case by the domain specifications. This needs to be encrypted so that HCX cannot read this. Refer to CipherText schema definition below for more details. 6. Authentication tag (**tag**) - Digital signature on the protected header and the payload of the message to ensure its integrity. Refer to AuthenticationTag schema definition below for more details. Detailed steps on how to construct the JWE token are provided in this [section](https://docs.pmjay.gov.in/hcx-specifications/hcx-technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity#message-encryption) of the HCX specifications.","example":"eyJlbmMiOiJBMjU2R0NNIiwKImFsZyI6IlJTQS1PQUVQIiwKIngtaGN4LXNlbmRlcl9jb2RlIjoiMS00ZGMzZTA4OC1hMzEzLTQ0YWItYWZhMS0wMjIyOTU5Y2I3NWIiLAoieC1oY3gtcmVjaXBpZW50X2NvZGUiOiIxLTkzZjkwOGJhLWI1NzktNDUzZS04YjJhLTU2MDIyYWZhZDI3NSIsCiJ4LWhjeC1yZXF1ZXN0X2lkIjoiMjZiMTA2MGMtMWU4My00NjAwLTk2MTItZWEzMWUwY2E1MDkxIiwKIngtaGN4LWNvcnJlbGF0aW9uX2lkIjoiNWU5MzRmOTAtMTExZC00ZjBiLWIwMTYtYzIyZDgyMDY3NGUxIiwKIngtaGN4LXRpbWVzdGFtcCI6IjIwMjEtMTAtMjdUMjA6MzU6NTIuNjM2KzA1MzAiLAoieC1oY3gtc3RhdHVzIjoicmVxdWVzdC5pbml0aWF0ZSIsCiJ4LWhjeC13b3JrZmxvd19pZCI6IjVlOTM0ZjkwLTExMWQtNGYwYi1iMDE2LWMyMmQ4MjA2NzRlMiIsCiJ4LWhjeC1kZWJ1Z19mbGFnIjoiSW5mbyIsCiJ4LWhjeC1lcnJvcl9kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCAidHJhY2UiOiAiIn0sCiJ4LWhjeC1kZWJ1Z19kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCJ0cmFjZSI6IiJ9LAoiandzX2hlYWRlciI6eyJ0eXAiOiJKV1QiLCAiYWxnIjoiUlMyNTYifSwKImp3ZV9oZWFkZXIiOnsiYWxnIjoiUlNBLU9BRVAiLCJlbmMiOiJBMjU2R0NNIn0KfQ==.6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.AxY8DCtDaGlsbGljb3RoZQ.KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.Mz-VPPyU4RlcuYv1IwIvzw"}},"required":["payload"]},"Error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}},"StatusResponseObject":{"type":"object","properties":{"sender_code":{"type":"string"},"recipient_code":{"type":"string"},"entity_type":{"type":"string","enum":["coverageeligibility","predetermination","preauth","claim","task","payment","communication","insuranceplan"]},"protocol_status":{"type":"string","enum":["request.queued","request.error","request.dispatched"]}}},"StatusSuccessResponse":{"type":"object","properties":{"timestamp":{"type":"string"},"api_call_id":{"type":"string","format":"uuid"},"correlation_id":{"type":"string","format":"uuid"},"result":{"$ref":"#/components/schemas/StatusResponseObject"},"error":{"$ref":"#/components/schemas/Error"}}},"CommunicationOnRequestBody":{"discriminator":{"propertyName":"type"},"properties":{"type":{"type":"string"}},"required":["type"]},"DomainHeaders":{"type":"object","description":"JSON object containing a map of domain-specific header values as proposed in domain data specifications. E.g. For claims use cases, domain specs may decide to populate the total claimed amount, list of diagnostics/procedures.","properties":{"use_case_name":{"type":"string"},"amt_processed":{"type":"string"}}},"JWEPayloadResponse":{"allOf":[{"$ref":"#/components/schemas/CommunicationOnRequestBody"},{"type":"object","properties":{"payload":{"type":"string","description":"The paylod should be a JWE token containing the following elements. 1. Protected headers (**protected**) - A set of attributes that provide transport, security, message integrity and summary information about the message being exchanged. Refer to the ProtectedHeader schema definition below for details. 2. JWE element (**encrypted_key**) - Content Encryption Key. Refer to the EncryptedKey schema definition below for details. 3. JWE element (**iv**) - Initialisation Vector for the algorithm. Refer to the InitializationVector schema definition below for details. 4. JWE element (**aad**) - Additional authentication data. Refer to AAD schema definition below for details. 5. Encrypted Payload (**ciphertext**) - Payload containing the relevant domain entity (eObject) as prescribed for the use case by the domain specifications. This needs to be encrypted so that HCX cannot read this. Refer to CipherText schema definition below for more details. 6. Authentication tag (**tag**) - Digital signature on the protected header and the payload of the message to ensure its integrity. Refer to AuthenticationTag schema definition below for more details. Detailed steps on how to construct the JWE token are provided in this [section](https://docs.pmjay.gov.in/hcx-specifications/hcx-technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity#message-encryption) of the HCX specifications.","example":"eyJlbmMiOiJBMjU2R0NNIiwKImFsZyI6IlJTQS1PQUVQIiwKIngtaGN4LXNlbmRlcl9jb2RlIjoiMS00ZGMzZTA4OC1hMzEzLTQ0YWItYWZhMS0wMjIyOTU5Y2I3NWIiLAoieC1oY3gtcmVjaXBpZW50X2NvZGUiOiIxLTkzZjkwOGJhLWI1NzktNDUzZS04YjJhLTU2MDIyYWZhZDI3NSIsCiJ4LWhjeC1yZXF1ZXN0X2lkIjoiMjZiMTA2MGMtMWU4My00NjAwLTk2MTItZWEzMWUwY2E1MDkxIiwKIngtaGN4LWNvcnJlbGF0aW9uX2lkIjoiNWU5MzRmOTAtMTExZC00ZjBiLWIwMTYtYzIyZDgyMDY3NGUxIiwKIngtaGN4LXRpbWVzdGFtcCI6IjIwMjEtMTAtMjdUMjA6MzU6NTIuNjM2KzA1MzAiLAoieC1oY3gtc3RhdHVzIjoicmVxdWVzdC5pbml0aWF0ZSIsCiJ4LWhjeC13b3JrZmxvd19pZCI6IjVlOTM0ZjkwLTExMWQtNGYwYi1iMDE2LWMyMmQ4MjA2NzRlMiIsCiJ4LWhjeC1kZWJ1Z19mbGFnIjoiSW5mbyIsCiJ4LWhjeC1lcnJvcl9kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCAidHJhY2UiOiAiIn0sCiJ4LWhjeC1kZWJ1Z19kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCJ0cmFjZSI6IiJ9LAoiandzX2hlYWRlciI6eyJ0eXAiOiJKV1QiLCAiYWxnIjoiUlMyNTYifSwKImp3ZV9oZWFkZXIiOnsiYWxnIjoiUlNBLU9BRVAiLCJlbmMiOiJBMjU2R0NNIn0KfQ==.6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.AxY8DCtDaGlsbGljb3RoZQ.KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.Mz-VPPyU4RlcuYv1IwIvzw"}}}],"description":"All the HCX protocol APIs require the request body to sent in JWE format (as defined in [RFC-7516](https://datatracker.ietf.org/doc/html/rfc7516)).","required":["payload"]},"ProtocolHeaderXhcxdebugDetails":{"type":"object","description":"Expected to be used for providing details of the status. Will be specially useful in debugging scenarios.","properties":{"code":{"type":"string"},"message":{"type":"string"},"trace":{"type":"string"}}},"ProtocolHeaderXhcxerrorDetails":{"type":"object","description":"Expected to be used for providing details of the status. Will be specially useful in scenarios where operational status indicates irrecoverable error.","properties":{"code":{"type":"string"},"message":{"type":"string"},"trace":{"type":"string"}}},"ProtocolResponse":{"allOf":[{"$ref":"#/components/schemas/CommunicationOnRequestBody"},{"type":"object","properties":{"x-hcx-sender_code":{"type":"string","description":"Registry code of the sender (e.g. provider or payer)","example":"PROVIDER01@HCX01"},"x-hcx-recipient_code":{"type":"string","description":"Registry code of the recipient (e.g. provider or payer)","example":"PAYOR01@HCX01"},"x-hcx-api_call_id":{"type":"string","format":"uuid","description":"Sender generated unique id for each originating request. All senders (providers & payors) must generate and set a unique value to the x-hcx-api_call_id protocol header in all the API calls to the HCX gateway."},"x-hcx-correlation_id":{"type":"string","format":"uuid","description":"Unique id for all messages (requests & responses) that are involved in processing of one cycle (like coverage eligibility, pre-auth, claim, or payment notice cycle). The participant system sending the originating request of the cycle must set the x-hcx-correlation_id in the initial API call and the HCX gateway shall forward the same correlation id to the recipient of the request. The recipient must set the same correlation id in the response API call and in other API calls related to the original request (e.g. communication request, forward/redirect requests). And the same correlation id must be sent in all subsequent API calls (related to the same cycle). In case of status API call, this header should have the correlation id of the request for which the status is being requested for."},"x-hcx-workflow_id":{"type":"string","description":"Unique id for one complete workflow that spans over a series of cycles and message exchanges within the context of an admission/case. This is an optional header that can be set by providers to the same value for all requests (coverage eligibility check, preauth, claim, etc) related to a single admission/case. And when the workflow_id is sent by the originating provider, all other participant systems (payors) must set the same workflow id in all API calls (responses, forwards/redirects, payment notices, etc) related to the workflow."},"x-hcx-timestamp":{"type":"string","description":"Unix timestamp when the request is sent.","example":1629057611000},"x-hcx-debug_flag":{"type":"string","description":"Request to the server to include debug information. Useful in the time of integration testing and prod debugging. However server(s) may choose to ignore this flag based on their policy.","enum":["Error","Info","Debug"]},"x-hcx-status":{"type":"string","description":"Operational status of the message. Depending on the leg of the message, it would be one of the defined values in the enum.","enum":["request.initiated","request.processed","request.queued","request.error","request.stopped","request.dispatched","response.complete","response.error","response.partial","response.redirect"]},"x-hcx-redirect_to":{"type":"string"},"x-hcx-error_details":{"$ref":"#/components/schemas/ProtocolHeaderXhcxerrorDetails"},"x-hcx-debug_details":{"$ref":"#/components/schemas/ProtocolHeaderXhcxdebugDetails"},"x-hcx-domain-header":{"$ref":"#/components/schemas/DomainHeaders"},"x-hcx-entity-type":{"type":"string","enum":["coverageeligibility","predetermination","preauth","claim","task","payment","communication","insuranceplan"]},"x-hcx-ben-abha-id":{"type":"string"}}}],"description":"Object to be returned as payload of the callback API (on_* APIs) in case there are any protocol related errors while processing the request or send a redirection instruction to the original sender of the request.","required":["x-hcx-api_call_id","x-hcx-correlation_id","x-hcx-recipient_code","x-hcx-sender_code","x-hcx-timestamp"]}}}} \ No newline at end of file diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/coverageeligibilityhcxservice.json b/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/coverageeligibilityhcxservice.json new file mode 100644 index 000000000..408ede37c --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/coverageeligibilityhcxservice.json @@ -0,0 +1 @@ +{"openapi":"3.1.0","info":{"title":"NHCX - Coverage Eligibility APIs","description":"The National Health Claims Exchange (NHCX) is a digital","termsOfService":"http://swagger.io/terms/","license":{"name":"Apache 2.0","url":"http://springdoc.org"},"version":"1.0.0"},"servers":[{"url":"/coverageeligibilityhcxservice","description":"Default Server URL"}],"paths":{"/v1/coverageeligibility/on_check":{"post":{"tags":["V1.0 APIs-Provider side"],"description":"This API is for payors to send the response for a coverage eligibility request to the providers. In case of a successful scenario, this API payload should contain the eligibility and plan details of the beneficiary for whom the details are requested for. Payors should send the following details as the request payload in the coverage eligibility response API: 1. A set of header attributes that provide transport, security, message integrity and summary information about the message being exchanged. This information is used by the HCX gateway for routing the request and auditing purposes. 2. If the coverage eligibility request is successfully processed, payor should send a CoverageEligibilityResponse domain entity as prescribed for the use case by the [domain specifications](https://nrces.in/ndhm/fhir/r4/StructureDefinition/CoverageEligibilityResponseBundle). This needs to be encrypted so that HCX cannot read this and can be decrypted & processed only by the intended recipient. 4. In case of errors, the Coverage Eligibility Response API payload should contain the error details. In a successful coverage eligibility reponse scenario, the domain payload should contain a [CoverageEligibilityResponse ](https://nrces.in/ndhm/fhir/r4/StructureDefinition/CoverageEligibilityResponseBundle) resource as per [HCX FHIR profile definitions]. In case of errors, the error details should be sent in the following manner: - Basic details about the error must be sent as part of the header attributes. HCX gateway shall read and store this information for audit & search purposes. Following header attributes should be used for sending the error details: - **x-hcx-status** should be set to **response.fail**. - **x-hcx-error_details** attribute should be set with the appropriate error code, message and trace details (if available). - In case where there are clinical, patient or business related errors, the payor should send exact details of the error to the recipient. These details should not be shared with the HCX gateway and hence, should be sent in encrypted form. Payor should embed the error details within the CoverageEligibilityResponse resource that is sent as part of the request body. The CoverageEligibilityResponse or Communication FHIR resource created as per the HCX FHIR profile should be encrypted and sent in the request body and HCX gateway shall not be able to read the contents of the FHIR response . The request body (header attributes and the FHIR resources) should be sent in the form of a JWE token ([RFC-7516](https://datatracker.ietf.org/doc/html/rfc7516)) using the steps defined in [HCX specs](https://hcxsbx.abdm.gov.in/#/technical-specifications). Note: Refer to the JWEPayload schema definition for details & structure of the JWE token that has to be sent as the request body in this API. The response to this API could be one of the following: 1. A successful accepted response from the HCX gateway if the strucuture of the request payload is valid and the validation of open attributes (protocol headers) is successful. Upon successful validation, HCX gateway forwards the same request to the intended recipient asynchronously. 2. An error response if any of the validations fail.","operationId":"coverageeligibilityOnCheckPost","requestBody":{"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/JWEPayloadResponse"},{"$ref":"#/components/schemas/ProtocolResponse"}]}}},"required":true},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"400":{"description":"Request Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"404":{"description":"Requested resource was not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/v1/coverageeligibility/check":{"post":{"tags":["V1.0 APIs-Payer side"],"description":"This API is for providers to check the eligibility of a beneficiary with the payors via HCX. This API should be used to request whether the patient's coverage is in force, whether it is valid at this or specified date, and/or for requesting the benefits & plan details associated with the coverage. Providers should send the following details in the request body while making a call for coverage eligibility check: 1. A set of header attributes that provide transport, security, message integrity and summary information about the message being exchanged. This information is used by the HCX gateway for routing the request and auditing purposes. 2. Domain payload containing the CoverageEligibilityRequest domain entity as prescribed for the use case by the [domain specifications](https://nrces.in/ndhm/fhir/r4/StructureDefinition/CoverageEligibilityRequestBundle). This needs to be encrypted so that HCX cannot read this and can be decrypted & processed only by the intended recipient. The domain payload should be a [CoverageEligibilityRequest ](https://nrces.in/ndhm/fhir/r4/StructureDefinition/CoverageEligibilityRequestBundle) resource as per [HCX FHIR profile definitions] (an extension of HL7 FHIR). The CoverageEligibilityRequest FHIR resource created as per the HCX FHIR profile should be sent in the request body in encrypted form and HCX gateway shall not be able to read the contents of the domain payload. Overall, the request body (header attributes and the FHIR resource) should be sent in the form of a JWE token ([RFC-7516](https://datatracker.ietf.org/doc/html/rfc7516)) using the steps defined in [HCX specs](https://hcxsbx.abdm.gov.in/#/technical-specifications). Note: Refer to the JWEPayload schema definition below for details & structure of the JWE token that has to be sent as the request body in this API. The response to this API could be one of the following: 1. A successful accepted response from the HCX gateway if the strucuture of the request is valid and the validation of open attributes (protocol headers) is successful. Upon successful validation, HCX gateway forwards the same request to the intended recipient asynchronously. 2. An error response if any of the validations fail. If the request is successfully accepted by the HCX gateway and forwarded to the recipient (i.e. the payor), the provider (who made the Coverage Eligibility Request API call) should expect the response via a call back to Coverage Eligibility Response API asynchronously. The response API payload may either contain the requested coverage details or error details in case of any errors during processing. An alternate scenario is when the Payor might respond with a redirect instruction asking the Provider to submit the same request to another Payor.","operationId":"coverageeligibilityCheckPost","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JWEPayload"}}},"required":true},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"400":{"description":"Request Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"404":{"description":"Requested resource was not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/internal/v1/coverageeligibility/on_check":{"post":{"tags":["V1.0 APIs-Provider side"],"description":"This API is for payors to send the response for a coverage eligibility request to the providers. In case of a successful scenario, this API payload should contain the eligibility and plan details of the beneficiary for whom the details are requested for. Payors should send the following details as the request payload in the coverage eligibility response API: 1. A set of header attributes that provide transport, security, message integrity and summary information about the message being exchanged. This information is used by the HCX gateway for routing the request and auditing purposes. 2. If the coverage eligibility request is successfully processed, payor should send a CoverageEligibilityResponse domain entity as prescribed for the use case by the [domain specifications](https://nrces.in/ndhm/fhir/r4/StructureDefinition/CoverageEligibilityResponseBundle). This needs to be encrypted so that HCX cannot read this and can be decrypted & processed only by the intended recipient. 4. In case of errors, the Coverage Eligibility Response API payload should contain the error details. In a successful coverage eligibility reponse scenario, the domain payload should contain a [CoverageEligibilityResponse ](https://nrces.in/ndhm/fhir/r4/StructureDefinition/CoverageEligibilityResponseBundle) resource as per [HCX FHIR profile definitions]. In case of errors, the error details should be sent in the following manner: - Basic details about the error must be sent as part of the header attributes. HCX gateway shall read and store this information for audit & search purposes. Following header attributes should be used for sending the error details: - **x-hcx-status** should be set to **response.fail**. - **x-hcx-error_details** attribute should be set with the appropriate error code, message and trace details (if available). - In case where there are clinical, patient or business related errors, the payor should send exact details of the error to the recipient. These details should not be shared with the HCX gateway and hence, should be sent in encrypted form. Payor should embed the error details within the CoverageEligibilityResponse resource that is sent as part of the request body. The CoverageEligibilityResponse or Communication FHIR resource created as per the HCX FHIR profile should be encrypted and sent in the request body and HCX gateway shall not be able to read the contents of the FHIR response . The request body (header attributes and the FHIR resources) should be sent in the form of a JWE token ([RFC-7516](https://datatracker.ietf.org/doc/html/rfc7516)) using the steps defined in [HCX specs](https://hcxsbx.abdm.gov.in/#/technical-specifications). Note: Refer to the JWEPayload schema definition for details & structure of the JWE token that has to be sent as the request body in this API. The response to this API could be one of the following: 1. A successful accepted response from the HCX gateway if the strucuture of the request payload is valid and the validation of open attributes (protocol headers) is successful. Upon successful validation, HCX gateway forwards the same request to the intended recipient asynchronously. 2. An error response if any of the validations fail.","operationId":"coverageeligibilityOnCheckPostInternal","requestBody":{"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/JWEPayloadResponse"},{"$ref":"#/components/schemas/ProtocolResponse"}]}}},"required":true},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"400":{"description":"Request Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"404":{"description":"Requested resource was not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/internal/v1/coverageeligibility/check":{"post":{"tags":["V1.0 APIs-Payer side"],"description":"This API is for providers to check the eligibility of a beneficiary with the payors via HCX. This API should be used to request whether the patient's coverage is in force, whether it is valid at this or specified date, and/or for requesting the benefits & plan details associated with the coverage. Providers should send the following details in the request body while making a call for coverage eligibility check: 1. A set of header attributes that provide transport, security, message integrity and summary information about the message being exchanged. This information is used by the HCX gateway for routing the request and auditing purposes. 2. Domain payload containing the CoverageEligibilityRequest domain entity as prescribed for the use case by the [domain specifications](https://nrces.in/ndhm/fhir/r4/StructureDefinition/CoverageEligibilityRequestBundle). This needs to be encrypted so that HCX cannot read this and can be decrypted & processed only by the intended recipient. The domain payload should be a [CoverageEligibilityRequest ](https://nrces.in/ndhm/fhir/r4/StructureDefinition/CoverageEligibilityRequestBundle) resource as per [HCX FHIR profile definitions] (an extension of HL7 FHIR). The CoverageEligibilityRequest FHIR resource created as per the HCX FHIR profile should be sent in the request body in encrypted form and HCX gateway shall not be able to read the contents of the domain payload. Overall, the request body (header attributes and the FHIR resource) should be sent in the form of a JWE token ([RFC-7516](https://datatracker.ietf.org/doc/html/rfc7516)) using the steps defined in [HCX specs](https://hcxsbx.abdm.gov.in/#/technical-specifications). Note: Refer to the JWEPayload schema definition below for details & structure of the JWE token that has to be sent as the request body in this API. The response to this API could be one of the following: 1. A successful accepted response from the HCX gateway if the strucuture of the request is valid and the validation of open attributes (protocol headers) is successful. Upon successful validation, HCX gateway forwards the same request to the intended recipient asynchronously. 2. An error response if any of the validations fail. If the request is successfully accepted by the HCX gateway and forwarded to the recipient (i.e. the payor), the provider (who made the Coverage Eligibility Request API call) should expect the response via a call back to Coverage Eligibility Response API asynchronously. The response API payload may either contain the requested coverage details or error details in case of any errors during processing. An alternate scenario is when the Payor might respond with a redirect instruction asking the Provider to submit the same request to another Payor.","operationId":"coverageeligibilityCheckPostInternal","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JWEPayload"}}},"required":true},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"400":{"description":"Request Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"404":{"description":"Requested resource was not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}}},"security":[{"bearer_auth":[]}]}}},"components":{"schemas":{"CoverageeligibilityOnCheckBody":{"discriminator":{"propertyName":"type"},"properties":{"type":{"type":"string"}},"required":["type"]},"DomainHeaders":{"type":"object","description":"JSON object containing a map of domain-specific header values as proposed in domain data specifications. E.g. For claims use cases, domain specs may decide to populate the total claimed amount, list of diagnostics/procedures.","properties":{"use_case_name":{"type":"string"},"amt_processed":{"type":"string"}}},"JWEPayloadResponse":{"allOf":[{"$ref":"#/components/schemas/CoverageeligibilityOnCheckBody"},{"type":"object","properties":{"payload":{"type":"string","description":"The paylod should be a JWE token containing the following elements. 1. Protected headers (**protected**) - A set of attributes that provide transport, security, message integrity and summary information about the message being exchanged. Refer to the ProtectedHeader schema definition below for details. 2. JWE element (**encrypted_key**) - Content Encryption Key. Refer to the EncryptedKey schema definition below for details. 3. JWE element (**iv**) - Initialisation Vector for the algorithm. Refer to the InitializationVector schema definition below for details. 4. JWE element (**aad**) - Additional authentication data. Refer to AAD schema definition below for details. 5. Encrypted Payload (**ciphertext**) - Payload containing the relevant domain entity (eObject) as prescribed for the use case by the domain specifications. This needs to be encrypted so that HCX cannot read this. Refer to CipherText schema definition below for more details. 6. Authentication tag (**tag**) - Digital signature on the protected header and the payload of the message to ensure its integrity. Refer to AuthenticationTag schema definition below for more details. Detailed steps on how to construct the JWE token are provided in this [section](https://docs.pmjay.gov.in/hcx-specifications/hcx-technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity#message-encryption) of the HCX specifications.","example":"eyJlbmMiOiJBMjU2R0NNIiwKImFsZyI6IlJTQS1PQUVQIiwKIngtaGN4LXNlbmRlcl9jb2RlIjoiMS00ZGMzZTA4OC1hMzEzLTQ0YWItYWZhMS0wMjIyOTU5Y2I3NWIiLAoieC1oY3gtcmVjaXBpZW50X2NvZGUiOiIxLTkzZjkwOGJhLWI1NzktNDUzZS04YjJhLTU2MDIyYWZhZDI3NSIsCiJ4LWhjeC1yZXF1ZXN0X2lkIjoiMjZiMTA2MGMtMWU4My00NjAwLTk2MTItZWEzMWUwY2E1MDkxIiwKIngtaGN4LWNvcnJlbGF0aW9uX2lkIjoiNWU5MzRmOTAtMTExZC00ZjBiLWIwMTYtYzIyZDgyMDY3NGUxIiwKIngtaGN4LXRpbWVzdGFtcCI6IjIwMjEtMTAtMjdUMjA6MzU6NTIuNjM2KzA1MzAiLAoieC1oY3gtc3RhdHVzIjoicmVxdWVzdC5pbml0aWF0ZSIsCiJ4LWhjeC13b3JrZmxvd19pZCI6IjVlOTM0ZjkwLTExMWQtNGYwYi1iMDE2LWMyMmQ4MjA2NzRlMiIsCiJ4LWhjeC1kZWJ1Z19mbGFnIjoiSW5mbyIsCiJ4LWhjeC1lcnJvcl9kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCAidHJhY2UiOiAiIn0sCiJ4LWhjeC1kZWJ1Z19kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCJ0cmFjZSI6IiJ9LAoiandzX2hlYWRlciI6eyJ0eXAiOiJKV1QiLCAiYWxnIjoiUlMyNTYifSwKImp3ZV9oZWFkZXIiOnsiYWxnIjoiUlNBLU9BRVAiLCJlbmMiOiJBMjU2R0NNIn0KfQ==.6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.AxY8DCtDaGlsbGljb3RoZQ.KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.Mz-VPPyU4RlcuYv1IwIvzw"}}}],"description":"All the HCX protocol APIs require the request body to sent in JWE format (as defined in [RFC-7516](https://datatracker.ietf.org/doc/html/rfc7516)).","required":["payload"]},"ProtocolHeaderXhcxdebugDetails":{"type":"object","description":"Expected to be used for providing details of the status. Will be specially useful in debugging scenarios.","properties":{"code":{"type":"string"},"message":{"type":"string"},"trace":{"type":"string"}}},"ProtocolHeaderXhcxerrorDetails":{"type":"object","description":"Expected to be used for providing details of the status. Will be specially useful in scenarios where operational status indicates irrecoverable error.","properties":{"code":{"type":"string"},"message":{"type":"string"},"trace":{"type":"string"}}},"ProtocolResponse":{"allOf":[{"$ref":"#/components/schemas/CoverageeligibilityOnCheckBody"},{"type":"object","properties":{"x-hcx-sender_code":{"type":"string","description":"Registry code of the sender (e.g. provider or payer)","example":"PROVIDER01@HCX01"},"x-hcx-recipient_code":{"type":"string","description":"Registry code of the recipient (e.g. provider or payer)","example":"PAYOR01@HCX01"},"x-hcx-api_call_id":{"type":"string","format":"uuid","description":"Sender generated unique id for each originating request. All senders (providers & payors) must generate and set a unique value to the x-hcx-api_call_id protocol header in all the API calls to the HCX gateway."},"x-hcx-correlation_id":{"type":"string","format":"uuid","description":"Unique id for all messages (requests & responses) that are involved in processing of one cycle (like coverage eligibility, pre-auth, claim, or payment notice cycle). The participant system sending the originating request of the cycle must set the x-hcx-correlation_id in the initial API call and the HCX gateway shall forward the same correlation id to the recipient of the request. The recipient must set the same correlation id in the response API call and in other API calls related to the original request (e.g. communication request, forward/redirect requests). And the same correlation id must be sent in all subsequent API calls (related to the same cycle). In case of status API call, this header should have the correlation id of the request for which the status is being requested for."},"x-hcx-workflow_id":{"type":"string","description":"Unique id for one complete workflow that spans over a series of cycles and message exchanges within the context of an admission/case. This is an optional header that can be set by providers to the same value for all requests (coverage eligibility check, preauth, claim, etc) related to a single admission/case. And when the workflow_id is sent by the originating provider, all other participant systems (payors) must set the same workflow id in all API calls (responses, forwards/redirects, payment notices, etc) related to the workflow."},"x-hcx-timestamp":{"type":"string","description":"Unix timestamp when the request is sent.","example":1629057611000},"x-hcx-debug_flag":{"type":"string","description":"Request to the server to include debug information. Useful in the time of integration testing and prod debugging. However server(s) may choose to ignore this flag based on their policy.","enum":["Error","Info","Debug"]},"x-hcx-status":{"type":"string","description":"Operational status of the message. Depending on the leg of the message, it would be one of the defined values in the enum.","enum":["request.initiated","request.processed","request.queued","request.error","request.stopped","request.dispatched","response.complete","response.error","response.partial","response.redirect"]},"x-hcx-redirect_to":{"type":"string"},"x-hcx-error_details":{"$ref":"#/components/schemas/ProtocolHeaderXhcxerrorDetails"},"x-hcx-debug_details":{"$ref":"#/components/schemas/ProtocolHeaderXhcxdebugDetails"},"x-hcx-domain-header":{"$ref":"#/components/schemas/DomainHeaders"},"x-hcx-entity-type":{"type":"string","enum":["coverageeligibility","predetermination","preauth","claim","task","payment","insuranceplan"]},"x-hcx-ben-abha-id":{"type":"string"}}}],"description":"Object to be returned as payload of the callback API (on_* APIs) in case there are any protocol related errors while processing the request or send a redirection instruction to the original sender of the request.","required":["x-hcx-api_call_id","x-hcx-correlation_id","x-hcx-recipient_code","x-hcx-sender_code","x-hcx-timestamp"]},"Error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}},"StatusResponseObject":{"type":"object","properties":{"sender_code":{"type":"string"},"recipient_code":{"type":"string"},"entity_type":{"type":"string","enum":["coverageeligibility","predetermination","preauth","claim","task","payment","insuranceplan"]},"protocol_status":{"type":"string","enum":["request.queued","request.error","request.dispatched"]}}},"StatusSuccessResponse":{"type":"object","properties":{"timestamp":{"type":"string"},"api_call_id":{"type":"string","format":"uuid"},"correlation_id":{"type":"string","format":"uuid"},"result":{"$ref":"#/components/schemas/StatusResponseObject"},"error":{"$ref":"#/components/schemas/Error"}}},"JWEPayload":{"type":"object","description":"All the HCX protocol APIs require the request body to sent in JWE format (as defined in [RFC-7516](https://datatracker.ietf.org/doc/html/rfc7516)).","properties":{"payload":{"type":"string","description":"The paylod should be a JWE token containing the following elements. 1. Protected headers (**protected**) - A set of attributes that provide transport, security, message integrity and summary information about the message being exchanged. Refer to the ProtectedHeader schema definition below for details. 2. JWE element (**encrypted_key**) - Content Encryption Key. Refer to the EncryptedKey schema definition below for details. 3. JWE element (**iv**) - Initialisation Vector for the algorithm. Refer to the InitializationVector schema definition below for details. 4. JWE element (**aad**) - Additional authentication data. Refer to AAD schema definition below for details. 5. Encrypted Payload (**ciphertext**) - Payload containing the relevant domain entity (eObject) as prescribed for the use case by the domain specifications. This needs to be encrypted so that HCX cannot read this. Refer to CipherText schema definition below for more details. 6. Authentication tag (**tag**) - Digital signature on the protected header and the payload of the message to ensure its integrity. Refer to AuthenticationTag schema definition below for more details. Detailed steps on how to construct the JWE token are provided in this [section](https://docs.pmjay.gov.in/hcx-specifications/hcx-technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity#message-encryption) of the HCX specifications.","example":"eyJlbmMiOiJBMjU2R0NNIiwKImFsZyI6IlJTQS1PQUVQIiwKIngtaGN4LXNlbmRlcl9jb2RlIjoiMS00ZGMzZTA4OC1hMzEzLTQ0YWItYWZhMS0wMjIyOTU5Y2I3NWIiLAoieC1oY3gtcmVjaXBpZW50X2NvZGUiOiIxLTkzZjkwOGJhLWI1NzktNDUzZS04YjJhLTU2MDIyYWZhZDI3NSIsCiJ4LWhjeC1yZXF1ZXN0X2lkIjoiMjZiMTA2MGMtMWU4My00NjAwLTk2MTItZWEzMWUwY2E1MDkxIiwKIngtaGN4LWNvcnJlbGF0aW9uX2lkIjoiNWU5MzRmOTAtMTExZC00ZjBiLWIwMTYtYzIyZDgyMDY3NGUxIiwKIngtaGN4LXRpbWVzdGFtcCI6IjIwMjEtMTAtMjdUMjA6MzU6NTIuNjM2KzA1MzAiLAoieC1oY3gtc3RhdHVzIjoicmVxdWVzdC5pbml0aWF0ZSIsCiJ4LWhjeC13b3JrZmxvd19pZCI6IjVlOTM0ZjkwLTExMWQtNGYwYi1iMDE2LWMyMmQ4MjA2NzRlMiIsCiJ4LWhjeC1kZWJ1Z19mbGFnIjoiSW5mbyIsCiJ4LWhjeC1lcnJvcl9kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCAidHJhY2UiOiAiIn0sCiJ4LWhjeC1kZWJ1Z19kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCJ0cmFjZSI6IiJ9LAoiandzX2hlYWRlciI6eyJ0eXAiOiJKV1QiLCAiYWxnIjoiUlMyNTYifSwKImp3ZV9oZWFkZXIiOnsiYWxnIjoiUlNBLU9BRVAiLCJlbmMiOiJBMjU2R0NNIn0KfQ==.6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.AxY8DCtDaGlsbGljb3RoZQ.KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.Mz-VPPyU4RlcuYv1IwIvzw"}},"required":["payload"]}}}} \ No newline at end of file diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/insuranceplanhcxservice.json b/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/insuranceplanhcxservice.json new file mode 100644 index 000000000..50c0c6928 --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/insuranceplanhcxservice.json @@ -0,0 +1 @@ +{"openapi":"3.1.0","info":{"title":"NHCX - Insurance Plan APIs","description":"The National Health Claims Exchange (NHCX) is a digital","termsOfService":"http://swagger.io/terms/","license":{"name":"Apache 2.0","url":"http://springdoc.org"},"version":"1.0.0"},"servers":[{"url":"/insuranceplanhcxservice","description":"Default Server URL"}],"paths":{"/v1/insuranceplan/request":{"post":{"tags":["V1.0 APIs-Payer side"],"description":"This API is for providers to get the insuranceplan via HCX gateway and for HCX gateway to route the same request to payors. Payload for this API has to be created as per the TaskBundle.","operationId":"insuranceplanRequestPost","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JWEPayload"}}},"required":true},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"400":{"description":"Request Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"404":{"description":"Requested resource was not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/v1/insuranceplan/on_request":{"post":{"tags":["V1.0 APIs-Provider side"],"description":"This is the callback API on HCX gateways and on Provider systems which will be called by Payor systems and HCX gateways to return the response for insuranceplan requests. Payload for this API has to be created as per the InsuranceplanBundle.","operationId":"insuranceplanOnRequestPost","requestBody":{"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/JWEPayloadResponse"},{"$ref":"#/components/schemas/ProtocolResponse"}]}}},"required":true},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"400":{"description":"Request Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"404":{"description":"Requested resource was not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/internal/v1/insuranceplan/request":{"post":{"tags":["V1.0 APIs-Payer side"],"description":"This API is for providers to get the insuranceplan via HCX gateway and for HCX gateway to route the same request to payors. Payload for this API has to be created as per the TaskBundle.","operationId":"insuranceplanRequestPostInternal","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JWEPayload"}}},"required":true},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"400":{"description":"Request Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"404":{"description":"Requested resource was not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/internal/v1/insuranceplan/on_request":{"post":{"tags":["V1.0 APIs-Provider side"],"description":"This is the callback API on HCX gateways and on Provider systems which will be called by Payor systems and HCX gateways to return the response for insuranceplan requests. Payload for this API has to be created as per the InsuranceplanBundle.","operationId":"insuranceplanOnRequestPostInternal","requestBody":{"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/JWEPayloadResponse"},{"$ref":"#/components/schemas/ProtocolResponse"}]}}},"required":true},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"400":{"description":"Request Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"404":{"description":"Requested resource was not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}}},"security":[{"bearer_auth":[]}]}}},"components":{"schemas":{"JWEPayload":{"type":"object","description":"All the HCX protocol APIs require the request body to sent in JWE format (as defined in [RFC-7516](https://datatracker.ietf.org/doc/html/rfc7516)).","properties":{"payload":{"type":"string","description":"The paylod should be a JWE token containing the following elements. 1. Protected headers (**protected**) - A set of attributes that provide transport, security, message integrity and summary information about the message being exchanged. Refer to the ProtectedHeader schema definition below for details. 2. JWE element (**encrypted_key**) - Content Encryption Key. Refer to the EncryptedKey schema definition below for details. 3. JWE element (**iv**) - Initialisation Vector for the algorithm. Refer to the InitializationVector schema definition below for details. 4. JWE element (**aad**) - Additional authentication data. Refer to AAD schema definition below for details. 5. Encrypted Payload (**ciphertext**) - Payload containing the relevant domain entity (eObject) as prescribed for the use case by the domain specifications. This needs to be encrypted so that HCX cannot read this. Refer to CipherText schema definition below for more details. 6. Authentication tag (**tag**) - Digital signature on the protected header and the payload of the message to ensure its integrity. Refer to AuthenticationTag schema definition below for more details. Detailed steps on how to construct the JWE token are provided in this [section](https://docs.pmjay.gov.in/hcx-specifications/hcx-technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity#message-encryption) of the HCX specifications.","example":"eyJlbmMiOiJBMjU2R0NNIiwKImFsZyI6IlJTQS1PQUVQIiwKIngtaGN4LXNlbmRlcl9jb2RlIjoiMS00ZGMzZTA4OC1hMzEzLTQ0YWItYWZhMS0wMjIyOTU5Y2I3NWIiLAoieC1oY3gtcmVjaXBpZW50X2NvZGUiOiIxLTkzZjkwOGJhLWI1NzktNDUzZS04YjJhLTU2MDIyYWZhZDI3NSIsCiJ4LWhjeC1yZXF1ZXN0X2lkIjoiMjZiMTA2MGMtMWU4My00NjAwLTk2MTItZWEzMWUwY2E1MDkxIiwKIngtaGN4LWNvcnJlbGF0aW9uX2lkIjoiNWU5MzRmOTAtMTExZC00ZjBiLWIwMTYtYzIyZDgyMDY3NGUxIiwKIngtaGN4LXRpbWVzdGFtcCI6IjIwMjEtMTAtMjdUMjA6MzU6NTIuNjM2KzA1MzAiLAoieC1oY3gtc3RhdHVzIjoicmVxdWVzdC5pbml0aWF0ZSIsCiJ4LWhjeC13b3JrZmxvd19pZCI6IjVlOTM0ZjkwLTExMWQtNGYwYi1iMDE2LWMyMmQ4MjA2NzRlMiIsCiJ4LWhjeC1kZWJ1Z19mbGFnIjoiSW5mbyIsCiJ4LWhjeC1lcnJvcl9kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCAidHJhY2UiOiAiIn0sCiJ4LWhjeC1kZWJ1Z19kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCJ0cmFjZSI6IiJ9LAoiandzX2hlYWRlciI6eyJ0eXAiOiJKV1QiLCAiYWxnIjoiUlMyNTYifSwKImp3ZV9oZWFkZXIiOnsiYWxnIjoiUlNBLU9BRVAiLCJlbmMiOiJBMjU2R0NNIn0KfQ==.6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.AxY8DCtDaGlsbGljb3RoZQ.KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.Mz-VPPyU4RlcuYv1IwIvzw"}},"required":["payload"]},"Error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}},"StatusResponseObject":{"type":"object","properties":{"sender_code":{"type":"string"},"recipient_code":{"type":"string"},"entity_type":{"type":"string","enum":["coverageeligibility","predetermination","preauth","claim","task","payment","insuranceplan"]},"protocol_status":{"type":"string","enum":["request.queued","request.error","request.dispatched"]}}},"StatusSuccessResponse":{"type":"object","properties":{"timestamp":{"type":"string"},"api_call_id":{"type":"string","format":"uuid"},"correlation_id":{"type":"string","format":"uuid"},"result":{"$ref":"#/components/schemas/StatusResponseObject"},"error":{"$ref":"#/components/schemas/Error"}}},"DomainHeaders":{"type":"object","description":"JSON object containing a map of domain-specific header values as proposed in domain data specifications. E.g. For claims use cases, domain specs may decide to populate the total claimed amount, list of diagnostics/procedures.","properties":{"use_case_name":{"type":"string"},"amt_processed":{"type":"string"}}},"InsuranceplanOnRequestBody":{"discriminator":{"propertyName":"type"},"properties":{"type":{"type":"string"}},"required":["type"]},"JWEPayloadResponse":{"allOf":[{"$ref":"#/components/schemas/InsuranceplanOnRequestBody"},{"type":"object","properties":{"payload":{"type":"string","description":"The paylod should be a JWE token containing the following elements. 1. Protected headers (**protected**) - A set of attributes that provide transport, security, message integrity and summary information about the message being exchanged. Refer to the ProtectedHeader schema definition below for details. 2. JWE element (**encrypted_key**) - Content Encryption Key. Refer to the EncryptedKey schema definition below for details. 3. JWE element (**iv**) - Initialisation Vector for the algorithm. Refer to the InitializationVector schema definition below for details. 4. JWE element (**aad**) - Additional authentication data. Refer to AAD schema definition below for details. 5. Encrypted Payload (**ciphertext**) - Payload containing the relevant domain entity (eObject) as prescribed for the use case by the domain specifications. This needs to be encrypted so that HCX cannot read this. Refer to CipherText schema definition below for more details. 6. Authentication tag (**tag**) - Digital signature on the protected header and the payload of the message to ensure its integrity. Refer to AuthenticationTag schema definition below for more details. Detailed steps on how to construct the JWE token are provided in this [section](https://docs.pmjay.gov.in/hcx-specifications/hcx-technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity#message-encryption) of the HCX specifications.","example":"eyJlbmMiOiJBMjU2R0NNIiwKImFsZyI6IlJTQS1PQUVQIiwKIngtaGN4LXNlbmRlcl9jb2RlIjoiMS00ZGMzZTA4OC1hMzEzLTQ0YWItYWZhMS0wMjIyOTU5Y2I3NWIiLAoieC1oY3gtcmVjaXBpZW50X2NvZGUiOiIxLTkzZjkwOGJhLWI1NzktNDUzZS04YjJhLTU2MDIyYWZhZDI3NSIsCiJ4LWhjeC1yZXF1ZXN0X2lkIjoiMjZiMTA2MGMtMWU4My00NjAwLTk2MTItZWEzMWUwY2E1MDkxIiwKIngtaGN4LWNvcnJlbGF0aW9uX2lkIjoiNWU5MzRmOTAtMTExZC00ZjBiLWIwMTYtYzIyZDgyMDY3NGUxIiwKIngtaGN4LXRpbWVzdGFtcCI6IjIwMjEtMTAtMjdUMjA6MzU6NTIuNjM2KzA1MzAiLAoieC1oY3gtc3RhdHVzIjoicmVxdWVzdC5pbml0aWF0ZSIsCiJ4LWhjeC13b3JrZmxvd19pZCI6IjVlOTM0ZjkwLTExMWQtNGYwYi1iMDE2LWMyMmQ4MjA2NzRlMiIsCiJ4LWhjeC1kZWJ1Z19mbGFnIjoiSW5mbyIsCiJ4LWhjeC1lcnJvcl9kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCAidHJhY2UiOiAiIn0sCiJ4LWhjeC1kZWJ1Z19kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCJ0cmFjZSI6IiJ9LAoiandzX2hlYWRlciI6eyJ0eXAiOiJKV1QiLCAiYWxnIjoiUlMyNTYifSwKImp3ZV9oZWFkZXIiOnsiYWxnIjoiUlNBLU9BRVAiLCJlbmMiOiJBMjU2R0NNIn0KfQ==.6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.AxY8DCtDaGlsbGljb3RoZQ.KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.Mz-VPPyU4RlcuYv1IwIvzw"}}}],"description":"All the HCX protocol APIs require the request body to sent in JWE format (as defined in [RFC-7516](https://datatracker.ietf.org/doc/html/rfc7516)).","required":["payload"]},"ProtocolHeaderXhcxdebugDetails":{"type":"object","description":"Expected to be used for providing details of the status. Will be specially useful in debugging scenarios.","properties":{"code":{"type":"string"},"message":{"type":"string"},"trace":{"type":"string"}}},"ProtocolHeaderXhcxerrorDetails":{"type":"object","description":"Expected to be used for providing details of the status. Will be specially useful in scenarios where operational status indicates irrecoverable error.","properties":{"code":{"type":"string"},"message":{"type":"string"},"trace":{"type":"string"}}},"ProtocolResponse":{"allOf":[{"$ref":"#/components/schemas/InsuranceplanOnRequestBody"},{"type":"object","properties":{"x-hcx-sender_code":{"type":"string","description":"Registry code of the sender (e.g. provider or payer)","example":"PROVIDER01@HCX01"},"x-hcx-recipient_code":{"type":"string","description":"Registry code of the recipient (e.g. provider or payer)","example":"PAYOR01@HCX01"},"x-hcx-api_call_id":{"type":"string","format":"uuid","description":"Sender generated unique id for each originating request. All senders (providers & payors) must generate and set a unique value to the x-hcx-api_call_id protocol header in all the API calls to the HCX gateway."},"x-hcx-correlation_id":{"type":"string","format":"uuid","description":"Unique id for all messages (requests & responses) that are involved in processing of one cycle (like coverage eligibility, pre-auth, claim, or payment notice cycle). The participant system sending the originating request of the cycle must set the x-hcx-correlation_id in the initial API call and the HCX gateway shall forward the same correlation id to the recipient of the request. The recipient must set the same correlation id in the response API call and in other API calls related to the original request (e.g. communication request, forward/redirect requests). And the same correlation id must be sent in all subsequent API calls (related to the same cycle). In case of status API call, this header should have the correlation id of the request for which the status is being requested for."},"x-hcx-workflow_id":{"type":"string","description":"Unique id for one complete workflow that spans over a series of cycles and message exchanges within the context of an admission/case. This is an optional header that can be set by providers to the same value for all requests (coverage eligibility check, preauth, claim, etc) related to a single admission/case. And when the workflow_id is sent by the originating provider, all other participant systems (payors) must set the same workflow id in all API calls (responses, forwards/redirects, payment notices, etc) related to the workflow."},"x-hcx-timestamp":{"type":"string","description":"Unix timestamp when the request is sent.","example":1629057611000},"x-hcx-debug_flag":{"type":"string","description":"Request to the server to include debug information. Useful in the time of integration testing and prod debugging. However server(s) may choose to ignore this flag based on their policy.","enum":["Error","Info","Debug"]},"x-hcx-status":{"type":"string","description":"Operational status of the message. Depending on the leg of the message, it would be one of the defined values in the enum.","enum":["request.initiated","request.processed","request.queued","request.error","request.stopped","request.dispatched","response.complete","response.error","response.partial","response.redirect"]},"x-hcx-redirect_to":{"type":"string"},"x-hcx-error_details":{"$ref":"#/components/schemas/ProtocolHeaderXhcxerrorDetails"},"x-hcx-debug_details":{"$ref":"#/components/schemas/ProtocolHeaderXhcxdebugDetails"},"x-hcx-domain-header":{"$ref":"#/components/schemas/DomainHeaders"},"x-hcx-entity-type":{"type":"string","enum":["coverageeligibility","predetermination","preauth","claim","task","payment","insuranceplan"]},"x-hcx-ben-abha-id":{"type":"string"}}}],"description":"Object to be returned as payload of the callback API (on_* APIs) in case there are any protocol related errors while processing the request or send a redirection instruction to the original sender of the request.","required":["x-hcx-api_call_id","x-hcx-correlation_id","x-hcx-recipient_code","x-hcx-sender_code","x-hcx-timestamp"]}}}} \ No newline at end of file diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json b/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json new file mode 100644 index 000000000..2a7aed467 --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/participanthcxservice.json @@ -0,0 +1 @@ +{"openapi":"3.1.0","info":{"title":"Health Claim Exchange APIs","description":"The Health Claims Exchange (HCX) is a digital infrastructure designed to enable automated, data-driven management of health insurance claims in an open ecosystem. These API specifications enable all actors to interact with the HCX.","termsOfService":"http://swagger.io/terms/","license":{"name":"Apache 2.0","url":"http://springdoc.org"},"version":"1.1.0"},"servers":[{"url":"/participanthcxservice","description":"Default Server URL"}],"paths":{"/v2/update/cert":{"post":{"tags":["Registry APIs"],"description":"This API is used update public certificate for participant .","operationId":"updateCertV2","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCertV2"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateCertV2"}}}},"400":{"description":"Client Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/v2/participant/update":{"post":{"tags":["Registry APIs"],"description":"This API is to update a participant's information in the registry. participant_code must be mandatorily provided in the request.","operationId":"participantCertAndBridgeUpdate","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantCertUpdateRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantCertUpdateResp"}}}},"400":{"description":"Client Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/v2/participant/link/abha/policy/init":{"post":{"tags":["Registry APIs"],"description":"This API is to link abha policy with a participants in the registry.","operationId":"participantLinkAbhaPolicyV2Init","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantLinkAbhaRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantLinkAbhaResponse"}}}},"400":{"description":"Client Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/v2/participant/hementity/create":{"post":{"tags":["Registry APIs"],"description":"This API is to create a participant in the registry. API generates a unique participant code and returns the code in the response on successfule creation of participant.","operationId":"participantHEMCreatePostV2","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantCreateBodyV2"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantCreateResponseV2"}}}},"400":{"description":"Client Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/v2/participant/create":{"post":{"tags":["Registry APIs"],"description":"This API is to create a participant in the registry. API generates a unique participant code and returns the code in the response on successfule creation of participant.","operationId":"participantCreatePostV2","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantCreateV2Request"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantCreateV2Resp"}}}},"400":{"description":"Client Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/update/abhanumber":{"post":{"tags":["Retrieving API"],"description":"This API is to update the abha number in ABHA_AUTH_TRANSACTION table.","operationId":"updateAbhaNumberController","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAbhaRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAbhaResponse"}}}},"400":{"description":"Client Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAbhaResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAbhaResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAbhaResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/product/link":{"post":{"tags":["Retrieving API"],"description":"This API is to list products by the payers/insurance companies.","operationId":"linkProductDetails","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductLinkRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantCreateResponse"}}}},"400":{"description":"Client Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/product/getowner":{"post":{"tags":["Retrieving API"],"description":"This API is to generate the product Id and product Name.","operationId":"getOwnerByProductDetails","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductOwnerRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantCreateResponse"}}}},"400":{"description":"Client Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/product/delink":{"post":{"tags":["Retrieving API"],"description":"This API is to de-link products by the payers/insurance companies.","operationId":"delinkProductDetails","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ProductLinkRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantCreateResponse"}}}},"400":{"description":"Client Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/participant/update":{"post":{"tags":["Registry APIs"],"description":"This API is to update a participant's information in the registry. participant_code must be mandatorily provided in the request.","operationId":"participantUpdatePost","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantUpdateBody"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"string","enum":["100 CONTINUE","101 SWITCHING_PROTOCOLS","102 PROCESSING","103 EARLY_HINTS","103 CHECKPOINT","200 OK","201 CREATED","202 ACCEPTED","203 NON_AUTHORITATIVE_INFORMATION","204 NO_CONTENT","205 RESET_CONTENT","206 PARTIAL_CONTENT","207 MULTI_STATUS","208 ALREADY_REPORTED","226 IM_USED","300 MULTIPLE_CHOICES","301 MOVED_PERMANENTLY","302 FOUND","302 MOVED_TEMPORARILY","303 SEE_OTHER","304 NOT_MODIFIED","305 USE_PROXY","307 TEMPORARY_REDIRECT","308 PERMANENT_REDIRECT","400 BAD_REQUEST","401 UNAUTHORIZED","402 PAYMENT_REQUIRED","403 FORBIDDEN","404 NOT_FOUND","405 METHOD_NOT_ALLOWED","406 NOT_ACCEPTABLE","407 PROXY_AUTHENTICATION_REQUIRED","408 REQUEST_TIMEOUT","409 CONFLICT","410 GONE","411 LENGTH_REQUIRED","412 PRECONDITION_FAILED","413 PAYLOAD_TOO_LARGE","413 REQUEST_ENTITY_TOO_LARGE","414 URI_TOO_LONG","414 REQUEST_URI_TOO_LONG","415 UNSUPPORTED_MEDIA_TYPE","416 REQUESTED_RANGE_NOT_SATISFIABLE","417 EXPECTATION_FAILED","418 I_AM_A_TEAPOT","419 INSUFFICIENT_SPACE_ON_RESOURCE","420 METHOD_FAILURE","421 DESTINATION_LOCKED","422 UNPROCESSABLE_ENTITY","423 LOCKED","424 FAILED_DEPENDENCY","425 TOO_EARLY","426 UPGRADE_REQUIRED","428 PRECONDITION_REQUIRED","429 TOO_MANY_REQUESTS","431 REQUEST_HEADER_FIELDS_TOO_LARGE","451 UNAVAILABLE_FOR_LEGAL_REASONS","500 INTERNAL_SERVER_ERROR","501 NOT_IMPLEMENTED","502 BAD_GATEWAY","503 SERVICE_UNAVAILABLE","504 GATEWAY_TIMEOUT","505 HTTP_VERSION_NOT_SUPPORTED","506 VARIANT_ALSO_NEGOTIATES","507 INSUFFICIENT_STORAGE","508 LOOP_DETECTED","509 BANDWIDTH_LIMIT_EXCEEDED","510 NOT_EXTENDED","511 NETWORK_AUTHENTICATION_REQUIRED"]}}}},"400":{"description":"Client Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/participant/search":{"post":{"tags":["Registry APIs"],"description":"This API is to search for participants in the registry. API returns list of participants matching the input criteria.","operationId":"participantSearchPost","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantSearchReq"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantSearchResponse"}}}},"400":{"description":"Client Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/participant/link/abha/policy":{"post":{"tags":["Registry APIs"],"description":"This API is to link abha policy with a participants in the registry.","operationId":"participantLinkAbhaPolicy","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantLinkAbhaRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantLinkAbhaResponse"}}}},"400":{"description":"Client Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/participant/getProductIdName":{"post":{"tags":["Retrieving API"],"description":"This API is to generate the product Id and product Name.","operationId":"participantCreatePost","requestBody":{"content":{"application/json":{"schema":{"type":"string"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantCreateResponse"}}}},"400":{"description":"Client Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/participant/get/policies":{"post":{"tags":["Registry APIs"],"description":"This API is used fetch the list of Policies details for participant .","operationId":"getParticipantGetPolicies","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FetchParticipantPoliciesRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantListResponse"}}}},"400":{"description":"Client Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/participant/details":{"post":{"tags":["Registry APIs"],"description":"This API is to search for participants in the registry. API returns list of participants matching the input criteria.","operationId":"participantV2SearchPost","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantSearchReq"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantSearchResponse"}}}},"400":{"description":"Client Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/participant/delink/abha/policy":{"post":{"tags":["Registry APIs"],"description":"This API is to delink abha policy with a participants in the registry.","operationId":"participantDeLinkAbhaPolicy","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantDeLinkAbhaRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantDeLinkAbhaResponse"}}}},"400":{"description":"Client Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/participant/create":{"post":{"tags":["Registry APIs"],"description":"This API is to create a participant in the registry. API generates a unique participant code and returns the code in the response on successfule creation of participant.","operationId":"participantCreatePost_1","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantCreateBody"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantCreateResponse"}}}},"400":{"description":"Client Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/get/session":{"post":{"tags":["Registry APIs"],"description":"This API is for internal use and will fetch config path .","operationId":"getSession","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantSessionResponse"}}}},"400":{"description":"Client Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/get/linked/registry/mst":{"post":{"tags":["Registry APIs"],"description":"This API is for internal use and will fetch get linked registry .","operationId":"getLinkedRegistryMst","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"string"}}}},"400":{"description":"Client Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/fetch/participants/list":{"post":{"tags":["Registry APIs"],"description":"This API is to update a participant's information in the registry. participant_code must be mandatorily provided in the request.","operationId":"fetchParticipantByRoleAndState","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FetchParticipantRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantListResponse"}}}},"400":{"description":"Client Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/fetch/certs":{"post":{"tags":["Registry APIs"],"description":"This API will fetch certificate . participant id must be mandatorily provided in the request.","operationId":"fetchCerts","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantCertRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"string","enum":["100 CONTINUE","101 SWITCHING_PROTOCOLS","102 PROCESSING","103 EARLY_HINTS","103 CHECKPOINT","200 OK","201 CREATED","202 ACCEPTED","203 NON_AUTHORITATIVE_INFORMATION","204 NO_CONTENT","205 RESET_CONTENT","206 PARTIAL_CONTENT","207 MULTI_STATUS","208 ALREADY_REPORTED","226 IM_USED","300 MULTIPLE_CHOICES","301 MOVED_PERMANENTLY","302 FOUND","302 MOVED_TEMPORARILY","303 SEE_OTHER","304 NOT_MODIFIED","305 USE_PROXY","307 TEMPORARY_REDIRECT","308 PERMANENT_REDIRECT","400 BAD_REQUEST","401 UNAUTHORIZED","402 PAYMENT_REQUIRED","403 FORBIDDEN","404 NOT_FOUND","405 METHOD_NOT_ALLOWED","406 NOT_ACCEPTABLE","407 PROXY_AUTHENTICATION_REQUIRED","408 REQUEST_TIMEOUT","409 CONFLICT","410 GONE","411 LENGTH_REQUIRED","412 PRECONDITION_FAILED","413 PAYLOAD_TOO_LARGE","413 REQUEST_ENTITY_TOO_LARGE","414 URI_TOO_LONG","414 REQUEST_URI_TOO_LONG","415 UNSUPPORTED_MEDIA_TYPE","416 REQUESTED_RANGE_NOT_SATISFIABLE","417 EXPECTATION_FAILED","418 I_AM_A_TEAPOT","419 INSUFFICIENT_SPACE_ON_RESOURCE","420 METHOD_FAILURE","421 DESTINATION_LOCKED","422 UNPROCESSABLE_ENTITY","423 LOCKED","424 FAILED_DEPENDENCY","425 TOO_EARLY","426 UPGRADE_REQUIRED","428 PRECONDITION_REQUIRED","429 TOO_MANY_REQUESTS","431 REQUEST_HEADER_FIELDS_TOO_LARGE","451 UNAVAILABLE_FOR_LEGAL_REASONS","500 INTERNAL_SERVER_ERROR","501 NOT_IMPLEMENTED","502 BAD_GATEWAY","503 SERVICE_UNAVAILABLE","504 GATEWAY_TIMEOUT","505 HTTP_VERSION_NOT_SUPPORTED","506 VARIANT_ALSO_NEGOTIATES","507 INSUFFICIENT_STORAGE","508 LOOP_DETECTED","509 BANDWIDTH_LIMIT_EXCEEDED","510 NOT_EXTENDED","511 NETWORK_AUTHENTICATION_REQUIRED"]}}}},"400":{"description":"Client Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/fetch/certs/path":{"post":{"tags":["Registry APIs"],"description":"This API will fetch certificate . participant id must be mandatorily provided in the request.","operationId":"fetchCertsPath","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantCertRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"string","enum":["100 CONTINUE","101 SWITCHING_PROTOCOLS","102 PROCESSING","103 EARLY_HINTS","103 CHECKPOINT","200 OK","201 CREATED","202 ACCEPTED","203 NON_AUTHORITATIVE_INFORMATION","204 NO_CONTENT","205 RESET_CONTENT","206 PARTIAL_CONTENT","207 MULTI_STATUS","208 ALREADY_REPORTED","226 IM_USED","300 MULTIPLE_CHOICES","301 MOVED_PERMANENTLY","302 FOUND","302 MOVED_TEMPORARILY","303 SEE_OTHER","304 NOT_MODIFIED","305 USE_PROXY","307 TEMPORARY_REDIRECT","308 PERMANENT_REDIRECT","400 BAD_REQUEST","401 UNAUTHORIZED","402 PAYMENT_REQUIRED","403 FORBIDDEN","404 NOT_FOUND","405 METHOD_NOT_ALLOWED","406 NOT_ACCEPTABLE","407 PROXY_AUTHENTICATION_REQUIRED","408 REQUEST_TIMEOUT","409 CONFLICT","410 GONE","411 LENGTH_REQUIRED","412 PRECONDITION_FAILED","413 PAYLOAD_TOO_LARGE","413 REQUEST_ENTITY_TOO_LARGE","414 URI_TOO_LONG","414 REQUEST_URI_TOO_LONG","415 UNSUPPORTED_MEDIA_TYPE","416 REQUESTED_RANGE_NOT_SATISFIABLE","417 EXPECTATION_FAILED","418 I_AM_A_TEAPOT","419 INSUFFICIENT_SPACE_ON_RESOURCE","420 METHOD_FAILURE","421 DESTINATION_LOCKED","422 UNPROCESSABLE_ENTITY","423 LOCKED","424 FAILED_DEPENDENCY","425 TOO_EARLY","426 UPGRADE_REQUIRED","428 PRECONDITION_REQUIRED","429 TOO_MANY_REQUESTS","431 REQUEST_HEADER_FIELDS_TOO_LARGE","451 UNAVAILABLE_FOR_LEGAL_REASONS","500 INTERNAL_SERVER_ERROR","501 NOT_IMPLEMENTED","502 BAD_GATEWAY","503 SERVICE_UNAVAILABLE","504 GATEWAY_TIMEOUT","505 HTTP_VERSION_NOT_SUPPORTED","506 VARIANT_ALSO_NEGOTIATES","507 INSUFFICIENT_STORAGE","508 LOOP_DETECTED","509 BANDWIDTH_LIMIT_EXCEEDED","510 NOT_EXTENDED","511 NETWORK_AUTHENTICATION_REQUIRED"]}}}},"400":{"description":"Client Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/V2/participant/link/abha/policy":{"post":{"tags":["Registry APIs"],"description":"This API is to link abha policy with a participants in the registry.","operationId":"participantLinkAbhaPolicyV2","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantLinkAbhaRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantLinkAbhaResponse"}}}},"400":{"description":"Client Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/V2/participant/get/policies":{"post":{"tags":["Registry APIs"],"description":"This API is used fetch the list of Policies details for participant .","operationId":"getParticipantGetPoliciesV2","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/FetchParticipantPoliciesRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantListResponse"}}}},"400":{"description":"Client Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/V2/participant/delink/abha/policy":{"post":{"tags":["Registry APIs"],"description":"This API is to delink abha policy with a participants in the registry.","operationId":"participantDeLinkAbhaPolicyV2","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantDeLinkAbhaRequest"}}},"required":true},"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantDeLinkAbhaResponse"}}}},"400":{"description":"Client Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/validate":{"get":{"tags":["Registry APIs"],"description":"This API is to validate approval from participant for participant creation","operationId":"particiapntValidate","parameters":[{"name":"passcode","in":"query","required":true,"schema":{"type":"string"}},{"name":"transactionId","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"string"}}}},"400":{"description":"Client Error","content":{"application/json":{"schema":{"type":"string"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"type":"string"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"type":"string","enum":["100 CONTINUE","101 SWITCHING_PROTOCOLS","102 PROCESSING","103 EARLY_HINTS","103 CHECKPOINT","200 OK","201 CREATED","202 ACCEPTED","203 NON_AUTHORITATIVE_INFORMATION","204 NO_CONTENT","205 RESET_CONTENT","206 PARTIAL_CONTENT","207 MULTI_STATUS","208 ALREADY_REPORTED","226 IM_USED","300 MULTIPLE_CHOICES","301 MOVED_PERMANENTLY","302 FOUND","302 MOVED_TEMPORARILY","303 SEE_OTHER","304 NOT_MODIFIED","305 USE_PROXY","307 TEMPORARY_REDIRECT","308 PERMANENT_REDIRECT","400 BAD_REQUEST","401 UNAUTHORIZED","402 PAYMENT_REQUIRED","403 FORBIDDEN","404 NOT_FOUND","405 METHOD_NOT_ALLOWED","406 NOT_ACCEPTABLE","407 PROXY_AUTHENTICATION_REQUIRED","408 REQUEST_TIMEOUT","409 CONFLICT","410 GONE","411 LENGTH_REQUIRED","412 PRECONDITION_FAILED","413 PAYLOAD_TOO_LARGE","413 REQUEST_ENTITY_TOO_LARGE","414 URI_TOO_LONG","414 REQUEST_URI_TOO_LONG","415 UNSUPPORTED_MEDIA_TYPE","416 REQUESTED_RANGE_NOT_SATISFIABLE","417 EXPECTATION_FAILED","418 I_AM_A_TEAPOT","419 INSUFFICIENT_SPACE_ON_RESOURCE","420 METHOD_FAILURE","421 DESTINATION_LOCKED","422 UNPROCESSABLE_ENTITY","423 LOCKED","424 FAILED_DEPENDENCY","425 TOO_EARLY","426 UPGRADE_REQUIRED","428 PRECONDITION_REQUIRED","429 TOO_MANY_REQUESTS","431 REQUEST_HEADER_FIELDS_TOO_LARGE","451 UNAVAILABLE_FOR_LEGAL_REASONS","500 INTERNAL_SERVER_ERROR","501 NOT_IMPLEMENTED","502 BAD_GATEWAY","503 SERVICE_UNAVAILABLE","504 GATEWAY_TIMEOUT","505 HTTP_VERSION_NOT_SUPPORTED","506 VARIANT_ALSO_NEGOTIATES","507 INSUFFICIENT_STORAGE","508 LOOP_DETECTED","509 BANDWIDTH_LIMIT_EXCEEDED","510 NOT_EXTENDED","511 NETWORK_AUTHENTICATION_REQUIRED"]}}}}},"security":[{"bearer_auth":[]}]}},"/v2/participant/link/abha/policy/validate":{"get":{"tags":["Registry APIs"],"description":"This API is to link abha policy with a participants in the registry.","operationId":"participantLinkAbhaPolicyV2Validate","parameters":[{"name":"passcode","in":"query","required":true,"schema":{"type":"string"}},{"name":"transactionId","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ParticipantLinkAbhaResponse"}}}},"400":{"description":"Client Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/update/validate":{"get":{"tags":["Registry APIs"],"description":"This API is to validate approval from participant for participant Update","operationId":"particiapntUpdateValidate","parameters":[{"name":"passcode","in":"query","required":true,"schema":{"type":"string"}},{"name":"transactionId","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"string"}}}},"400":{"description":"Client Error","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Resource not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}},"security":[{"bearer_auth":[]}]}}},"components":{"schemas":{"UpdateCertV2":{"type":"object","properties":{"participantId":{"type":"string","minLength":1},"certificate":{"type":"string","minLength":1}},"required":["certificate","participantId"]},"Error":{"type":"object","properties":{"code":{"type":"string","description":"error code from the system - expected to be namespaced for better readability"},"message":{"type":"string","description":"Short description of the error"},"trace":{"type":"string","description":"Long description supporting the Code"}}},"ErrorResponse":{"type":"object","description":"This is a response to the ClaimForm API call","properties":{"timestamp":{"type":"string","description":"Unix timestamp when the response is sent.","example":1629057611000},"error":{"$ref":"#/components/schemas/Error"}},"required":["error","timestamp"]},"ParticipantCertUpdateRequest":{"type":"object","properties":{"participantcode":{"type":"string","minLength":1},"encryptioncert":{"type":"string"},"endpointurl":{"type":"string"}},"required":["participantcode"]},"ParticipantCertUpdateResp":{"type":"object","properties":{"participant_code":{"type":"string"},"status":{"type":"string"},"transactionid":{"type":"string"}}},"ParticipantLinkAbhaRequest":{"type":"object","properties":{"requestid":{"type":"string","format":"uuid"},"abhanumber":{"type":"string","maxLength":14,"minLength":14},"mobilenumber":{"type":"string"},"memberid":{"type":"string","minLength":1},"payerid":{"type":"string","minLength":1},"policies":{"type":"array","items":{"$ref":"#/components/schemas/ProductData"},"maxItems":2147483647,"minItems":1},"processingid":{"type":"string"}},"required":["abhanumber","memberid","payerid","policies","requestid"]},"ProductData":{"type":"object","properties":{"productid":{"type":"string","minLength":1},"productname":{"type":"string","minLength":1}},"required":["productid","productname"]},"ErrorMessage":{"type":"object","properties":{"errorcode":{"type":"string"},"errordescription":{"type":"string"}}},"ParticipantLinkAbhaResponse":{"type":"object","properties":{"result":{"type":"string"},"errormessage":{"$ref":"#/components/schemas/ErrorMessage"}}},"BankDetails":{"type":"object","properties":{"facilitybankaccountname":{"type":"string","minLength":1},"authorizedsignatoryname":{"type":"string","minLength":1},"bankaccountnumber":{"type":"string","minLength":1},"ifsccode":{"type":"string","minLength":1},"bankname":{"type":"string","minLength":1},"bankbranchname":{"type":"string","minLength":1},"bankaddress":{"type":"string","minLength":1},"micrcode":{"type":"string","minLength":1},"accounttype":{"type":"string","minLength":1},"upiid":{"type":"string"},"paymenttype":{"type":"string"},"mailid":{"type":"string"}},"required":["accounttype","authorizedsignatoryname","bankaccountnumber","bankaddress","bankbranchname","bankname","facilitybankaccountname","ifsccode","micrcode"]},"HospitalDoctorDetails":{"type":"object","description":"Doctor Details","properties":{"registrationnumber":{"type":"string","example":198456},"name":{"type":"string","example":"Dr. Sayantan Chatterjee"},"qualificfation":{"type":"string","example":"MD, General Physician"},"contactnumber":{"type":"string","example":9073951324},"specialities":{"type":"array","example":9073951324,"items":{"type":"string"}},"hprid":{"type":"string","example":"779-9999-6555"}}},"IncentiveRequest":{"type":"object","properties":{"incentivecode":{"type":"string","example":"A|B|C"},"status":{"type":"integer","format":"int32","example":"1|0"},"effectivestartdate":{"type":"string","example":"01/01/2024","maxLength":30,"minLength":10},"effectiveenddate":{"type":"string","example":"01/01/2024","maxLength":50,"minLength":10},"specialitycode":{"type":"string","example":"BM|GM"},"incentivecodedesc":{"type":"string","example":"A|B|C"},"incentivevalue":{"type":"string","example":110.0},"type":{"type":"string"}},"required":["effectiveenddate","effectivestartdate"]},"ParticipantCreateBodyV2":{"type":"object","properties":{"linked_registry_codes":{"type":"array","description":"Identifier of the participant in other registries. Each identifier shall be in a “normalised” notation having the structure “identifier@registry”, where registry is a unique code for the registry system and identifier is the unique id of the participant in that registry system. e.g. - facility001@hfr, to link the provider record to HFR record. The list of supported registry codes (e.g. hfr, rohini, etc) should be a configuration at the HCX instance level.","items":{"type":"string"}},"participant_name":{"type":"string","description":"Human readable name for the participant","minLength":1},"scheme_code":{"type":"string","description":"name/code of the scheme provided by the payor. scheme_code is mandatory for all participants with role “payer”. If the payer wishes to use a single entry for all its schemes, the scheme_code value should be set to “default”.","minLength":1},"state":{"type":"string","minLength":1},"district":{"type":"string","minLength":1},"parent_entity_id":{"type":"string"},"entityid":{"type":"string","minLength":1},"bankdetails":{"$ref":"#/components/schemas/BankDetails"},"taxdetails":{"$ref":"#/components/schemas/TaxDetails"},"tdsexcemptiondetailslist":{"type":"array","items":{"$ref":"#/components/schemas/TdsExcemptionDetails"}},"participantcode":{"type":"string","example":"HS1315","minLength":1},"hospitaltype":{"type":"string","example":"G | C","minLength":1},"incentiveCode":{"type":"string","example":1001,"minLength":1},"incentivecodedescription":{"type":"string","example":1001},"incentivevalue":{"type":"string","example":1001},"doctors":{"type":"array","items":{"$ref":"#/components/schemas/HospitalDoctorDetails"}},"hospitalbedstrength":{"type":"string","minLength":1},"lab_yn":{"type":"string","minLength":1},"gstcode":{"type":"string"},"registryid":{"type":"string"},"roles":{"type":"array","description":"Roles assigned to the participant as per the definition in the domain specifications. This will be used for access control.","example":"payer","items":{"type":"string","enum":["10001","10002","10003","10005","10009","10010","10006","10007","10008","10004"]}},"specialityList":{"type":"array","items":{"type":"string"}},"address":{"type":"object","additionalProperties":{},"description":"Physical address of the facility including its geolocation"},"primaryEmail":{"type":"string","description":"Primary email id for claims related communication."},"additionalEmail":{"type":"array","description":"Additional/alternative email ids of the participant. Maximum of 3 email addresses are allowed.","items":{"type":"string"},"maxItems":3,"minItems":0},"phone":{"type":"array","description":"Landline numbers of the provider. Maximum of 3 landline numbers are allowed.","example":["080 40004000"],"items":{"type":"string"},"maxItems":3,"minItems":0},"primaryMobile":{"type":"string","description":"Primary mobile number for claims related communication.","example":9899912323,"minLength":1},"additionalMobile":{"type":"array","description":"Additional/alternate mobile numbers of the participant.","example":["9100091000","9899912323"],"items":{"type":"string"},"maxItems":3,"minItems":0},"signing_cert_path":{"type":"string","description":"uri/file path to signing certificate"},"encryption_cert":{"type":"string","description":"uri/file path to encryption certificate"},"endpoint_url":{"type":"string","description":"Default endpoint to make API calls"},"payment_details":{"type":"object","additionalProperties":{},"description":"Default payment details (UPI or A/C Number + IFSC Code)"},"auth_applicable":{"type":"string"},"morthlite":{"type":"string"},"tier":{"type":"string"},"accrediationtype":{"type":"string"},"incentivedetails":{"type":"array","items":{"$ref":"#/components/schemas/IncentiveRequest"}},"hfrid":{"type":"string"}},"required":["bankdetails","district","encryption_cert","endpoint_url","entityid","hospitalbedstrength","hospitaltype","incentiveCode","lab_yn","participant_name","participantcode","primaryEmail","primaryMobile","roles","scheme_code","specialityList","state"]},"TaxDetails":{"type":"object","properties":{"pannumber":{"type":"string","minLength":1},"tannumber":{"type":"string","minLength":1},"gstnumber":{"type":"string","minLength":1}},"required":["gstnumber","pannumber","tannumber"]},"TdsExcemptionDetails":{"type":"object","properties":{"tdsexemptionapplication":{"type":"string"},"validfrom":{"type":"string","example":"2024-06-01"},"validtill":{"type":"string","example":"2024-06-01"},"tdspercent":{"type":"string"},"exempttdsapplicablerate":{"type":"string"},"exemptamount":{"type":"string"},"tdsexemptyn":{"type":"string"},"deductortype":{"type":"string"},"exemptremarks":{"type":"string"}}},"ParticipantCreateResponseV2":{"type":"object","properties":{"status":{"type":"string"},"hospitalid":{"type":"string"}}},"ParticipantCreateV2Request":{"type":"object","properties":{"registrytype":{"type":"string","minLength":1},"registryid":{"type":"string","minLength":1},"scheme_code":{"type":"string"},"role":{"type":"array","description":"Roles assigned to the participant as per the definition in the domain specifications. This will be used for access control.","example":"payer","items":{"type":"string","enum":["10001","10002","10003","10005","10009","10010","10006","10007","10008","10004"]}},"endpointurl":{"type":"string","description":"Default endpoint to make API calls"},"mobilenumber":{"type":"string","maxLength":13,"minLength":10,"pattern":"^(0|[1-9][0-9]*)$"},"email":{"type":"string","format":"email","minLength":1}},"required":["email","endpointurl","mobilenumber","registryid","registrytype","role"]},"ParticipantCreateV2Resp":{"type":"object","properties":{"participantid":{"type":"string"},"facilityname":{"type":"string"},"facilitycontact":{"type":"string"},"facilityemail":{"type":"string"},"transactionid":{"type":"string"},"error":{"$ref":"#/components/schemas/Error"}}},"UpdateAbhaRequest":{"type":"object","properties":{"dummyAbha":{"type":"string"},"realAbha":{"type":"string"}}},"UpdateAbhaResponse":{"type":"object","properties":{"successMessage":{"type":"string"},"errorMessage":{"type":"string"}}},"ProductLinkRequest":{"type":"object","properties":{"productid":{"type":"string","example":"PMJAY/MP/S"},"productname":{"type":"string","example":"PMJAY for SECC HR"},"participantcode":{"type":"string","example":"103@hcx"}},"required":["participantcode","productid","productname"]},"ParticipantCreateResponse":{"type":"object","properties":{"participant_code":{"type":"string","description":"Machine generated/readable unique identifier of the participant on the HCX instance.","example":"pcpt01@HCX01"}}},"ProductOwnerRequest":{"type":"object","properties":{"productid":{"type":"string","example":"PMJAY/MP/S"}}},"ParticipantUpdateBody":{"type":"object","properties":{"participant_code":{"type":"string","description":"Unique identifier of the participant/scheme on the HCX instance","example":"pcpt01@HCX01"},"linked_registry_codes":{"type":"array","description":"Identifier of the participant in other registries. Each identifier shall be in a “normalised” notation having the structure “identifier@registry”, where registry is a unique code for the registry system and identifier is the unique id of the participant in that registry system. e.g. - facility001@hfr, to link the provider record to HFR record. The list of supported registry codes (e.g. hfr, rohini, etc) should be a configuration at the HCX instance level.","items":{"type":"string"}},"participant_name":{"type":"string","description":"Human readable name for the participant"},"scheme_code":{"type":"string","description":"name/code of the scheme provided by the payor. scheme_code is mandatory for all participants with role “payer”. If the payer wishes to use a single entry for all its schemes, the scheme_code value should be set to “default”."},"roles":{"type":"array","description":"Roles assigned to the participant as per the definition in the domain specifications. This will be used for access control.","example":"payer","items":{"type":"string","enum":["10001","10002","10003","10005","10009","10010","10006","10007","10008","10004"]}},"address":{"type":"object","additionalProperties":{},"description":"Physical address of the facility including its geolocation"},"primaryEmail":{"type":"string","description":"Primary email id for claims related communication."},"additionalEmail":{"type":"array","description":"Additional/alternative email ids of the participant. Maximum of 3 email addresses are allowed.","items":{"type":"string"},"maxItems":3,"minItems":0},"phone":{"type":"array","description":"Landline numbers of the provider. Maximum of 3 landline numbers are allowed.","example":["080 40004000"],"items":{"type":"string"},"maxItems":3,"minItems":0},"primaryMobile":{"type":"string","description":"Primary mobile number for claims related communication.","example":9899912323},"additionalMobile":{"type":"array","description":"Additional/alternate mobile numbers of the participant.","example":["9100091000","9899912323"],"items":{"type":"string"},"maxItems":3,"minItems":0},"status":{"type":"array","description":"Current status of the participant on the instance","items":{"type":"string","enum":["Created","Active","InActive","Blocked"]}},"signing_cert_path":{"type":"string","description":"uri/file path to signing certificate"},"encryption_cert":{"type":"string","description":"uri/file path to encryption certificate"},"endpoint_url":{"type":"string","description":"Default endpoint to make API calls"},"payment_details":{"type":"object","additionalProperties":{},"description":"Default payment details (UPI or A/C Number + IFSC Code)"}},"required":["participant_code","roles"]},"ParticipantSearchReq":{"type":"object","properties":{"participant_code":{"type":"string","example":"XXXX@hcx","minLength":1}},"required":["participant_code"]},"ParticipantSearchRequest":{"type":"object","properties":{"participant_code":{"type":"string","description":"Unique identifier of the participant on the HCX instance","example":"pcpt01@HCX01"},"linked_registry_codes":{"type":"array","description":"Identifier of the participant in other registries. Each identifier shall be in a “normalised” notation having the structure “identifier@registry”, where registry is a unique code for the registry system and identifier is the unique id of the participant in that registry system. e.g. - facility001@hfr, to link the provider record to HFR record. The list of supported registry codes (e.g. hfr, rohini, etc) should be a configuration at the HCX instance level.","items":{"type":"string"}},"participant_name":{"type":"string","description":"Human readable name for the participant"},"scheme_code":{"type":"string","description":"name/code of the scheme provided by the payor. scheme_code is mandatory for all participants with role “payer”. If the payer wishes to use a single entry for all its schemes, the scheme_code value should be set to “default”."},"roles":{"type":"array","description":"Roles assigned to the participant as per the definition in the domain specifications. This will be used for access control.","example":"payer","items":{"type":"string","enum":["10001","10002","10003","10005","10009","10010","10006","10007","10008","10004"]}},"address":{"type":"object","additionalProperties":{},"description":"Physical address of the facility including its geolocation"},"primaryEmail":{"type":"string","description":"Primary email id for claims related communication."},"additionalEmail":{"type":"array","description":"Additional/alternative email ids of the participant. Maximum of 3 email addresses are allowed.","items":{"type":"string"},"maxItems":3,"minItems":0},"phone":{"type":"array","description":"Landline numbers of the provider. Maximum of 3 landline numbers are allowed.","example":["080 40004000"],"items":{"type":"string"},"maxItems":3,"minItems":0},"primaryMobile":{"type":"string","description":"Primary mobile number for claims related communication.","example":9899912323},"additionalMobile":{"type":"array","description":"Additional/alternate mobile numbers of the participant.","example":["9100091000","9899912323"],"items":{"type":"string"},"maxItems":3,"minItems":0},"status":{"type":"array","description":"Current status of the participant on the instance","items":{"type":"string","enum":["Created","Active","InActive","Blocked"]}},"signing_cert_path":{"type":"string","description":"uri/file path to signing certificate"},"encryption_cert":{"type":"string","description":"uri/file path to encryption certificate"},"endpoint_url":{"type":"string","description":"Default endpoint to make API calls"},"payment_details":{"type":"object","additionalProperties":{},"description":"Default payment details (UPI or A/C Number + IFSC Code)"}}},"ParticipantSearchResponse":{"type":"object","properties":{"timestamp":{"type":"string","description":"Unix timestamp when the request is sent","example":1629057611000},"participants":{"type":"array","description":"List of participants matching with the input search criteria","items":{"$ref":"#/components/schemas/ParticipantSearchRequest"}}},"required":["participants","timestamp"]},"FetchParticipantPoliciesRequest":{"type":"object","properties":{"identifiertype":{"type":"string","example":"MobileNo | AbhaNumber | MemberId ","minLength":1},"identifiervalue":{"type":"string","example":8127853678,"minLength":1}},"required":["identifiertype","identifiervalue"]},"ParticipantDetails":{"type":"object","properties":{"participantcode":{"type":"string"},"participantname":{"type":"string"},"address":{"type":"string"},"state":{"type":"string"}}},"ParticipantListResponse":{"type":"object","properties":{"participantdetails":{"type":"array","items":{"$ref":"#/components/schemas/ParticipantDetails"}}}},"ParticipantDeLinkAbhaRequest":{"type":"object","properties":{"requestid":{"type":"string","format":"uuid"},"payerid":{"type":"string","minLength":1},"memberid":{"type":"string","minLength":1},"policies":{"type":"array","items":{"$ref":"#/components/schemas/ProductData"},"maxItems":2147483647,"minItems":1},"processingid":{"type":"string"}},"required":["memberid","payerid","policies","requestid"]},"ParticipantDeLinkAbhaResponse":{"type":"object","properties":{"result":{"type":"string"},"errormessage":{"$ref":"#/components/schemas/ErrorMessage"}}},"ParticipantCreateBody":{"type":"object","properties":{"linked_registry_codes":{"type":"array","description":"Identifier of the participant in other registries. Each identifier shall be in a “normalised” notation having the structure “identifier@registry”, where registry is a unique code for the registry system and identifier is the unique id of the participant in that registry system. e.g. - facility001@hfr, to link the provider record to HFR record. The list of supported registry codes (e.g. hfr, rohini, etc) should be a configuration at the HCX instance level.","items":{"type":"string"},"maxItems":2147483647,"minItems":1},"participant_name":{"type":"string","description":"Human readable name for the participant","minLength":1},"scheme_code":{"type":"string","description":"name/code of the scheme provided by the payor. scheme_code is mandatory for all participants with role “payer”. If the payer wishes to use a single entry for all its schemes, the scheme_code value should be set to “default”."},"state":{"type":"string"},"district":{"type":"string"},"registryid":{"type":"string","minLength":1},"roles":{"type":"array","description":"Roles assigned to the participant as per the definition in the domain specifications. This will be used for access control.","example":"payer","items":{"type":"string","enum":["10001","10002","10003","10005","10009","10010","10006","10007","10008","10004"]}},"address":{"type":"object","additionalProperties":{},"description":"Physical address of the facility including its geolocation"},"primaryEmail":{"type":"string","format":"email","description":"Primary email id for claims related communication.","minLength":1},"additionalEmail":{"type":"array","description":"Additional/alternative email ids of the participant. Maximum of 3 email addresses are allowed.","items":{"type":"string"},"maxItems":3,"minItems":0},"phone":{"type":"array","description":"Landline numbers of the provider. Maximum of 3 landline numbers are allowed.","example":["080 40004000"],"items":{"type":"string"},"maxItems":3,"minItems":0},"primaryMobile":{"type":"string","description":"Primary mobile number for claims related communication.","example":9899912323,"maxLength":10,"minLength":10,"pattern":"^(0|[1-9][0-9]*)$"},"additionalMobile":{"type":"array","description":"Additional/alternate mobile numbers of the participant.","example":["9100091000","9899912323"],"items":{"type":"string"},"maxItems":3,"minItems":0},"signing_cert_path":{"type":"string","description":"uri/file path to signing certificate","maxLength":100,"minLength":0},"encryption_cert":{"type":"string","description":"uri/file path to encryption certificate"},"endpoint_url":{"type":"string","description":"Default endpoint to make API calls"},"payment_details":{"type":"object","additionalProperties":{},"description":"Default payment details (UPI or A/C Number + IFSC Code)"}},"required":["encryption_cert","endpoint_url","linked_registry_codes","participant_name","primaryEmail","primaryMobile","registryid","roles"]},"ParticipantSessionResponse":{"type":"object","properties":{"accessToken":{"type":"string"}}},"FetchParticipantRequest":{"type":"object","properties":{"role":{"type":"string","minLength":1},"fromdate":{"type":"string","example":"09/05/2023","minLength":1},"todate":{"type":"string","example":"10/05/2023","minLength":1},"entitytype":{"type":"string"}},"required":["fromdate","role","todate"]},"ParticipantCertRequest":{"type":"object","properties":{"participantid":{"type":"string","minLength":1}},"required":["participantid"]}}}} \ No newline at end of file diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/preauthhcxservice.json b/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/preauthhcxservice.json new file mode 100644 index 000000000..42b5197e0 --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/preauthhcxservice.json @@ -0,0 +1 @@ +{"openapi":"3.1.0","info":{"title":"NHCX - Preauthorisation APIs","description":"The National Health Claims Exchange (NHCX) is a digital","termsOfService":"http://swagger.io/terms/","license":{"name":"Apache 2.0","url":"http://springdoc.org"},"version":"1.0.0"},"servers":[{"url":"/preauthhcxservice","description":"Default Server URL"}],"paths":{"/v1/preauth/submit":{"post":{"tags":["V1.0 APIs-Payer side"],"description":"This API is for providers to submit pre-authorization requests (and resubmit updated request) to HCX gateway and for HCX gateway to route the same request to payors.

Payload for this API has to be created as per the [ClaimBundle](https://nrces.in/ndhm/fhir/r4/StructureDefinition/ClaimBundle) defined in HCX Specifications and serialized as per the [guidelines](https://hcxsbx.abdm.gov.in/#/technical-specifications) in HCX Specifications.","operationId":"preauthSubmitPost","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JWEPayload"}}},"required":true},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"400":{"description":"Request Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"404":{"description":"Requested resource was not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/v1/preauth/on_submit":{"post":{"tags":["V1.0 APIs-Provider side"],"description":"This is the callback API on HCX gateways and on Provider systems which will be called by Payor systems and HCX gateways to return the response for Pre-Authorization requests.

Payload for this API has to be created as per the [ClaimResponseBundle ](https://nrces.in/ndhm/fhir/r4/StructureDefinition/ClaimResponseBundle) defined in HCX Specifications and serialized as per the [guidelines](https://hcxsbx.abdm.gov.in/#/technical-specifications) in HCX Specifications.","operationId":"preauthOnSubmitPost","requestBody":{"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/JWEPayloadResponse"},{"$ref":"#/components/schemas/ProtocolResponse"}]}}},"required":true},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"400":{"description":"Request Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"404":{"description":"Requested resource was not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}}},"security":[{"bearer_auth":[]}]}}},"components":{"schemas":{"JWEPayload":{"type":"object","description":"All the HCX protocol APIs require the request body to sent in JWE format (as defined in [RFC-7516](https://datatracker.ietf.org/doc/html/rfc7516)).","properties":{"payload":{"type":"string","description":"The paylod should be a JWE token containing the following elements. 1. Protected headers (**protected**) - A set of attributes that provide transport, security, message integrity and summary information about the message being exchanged. Refer to the ProtectedHeader schema definition below for details. 2. JWE element (**encrypted_key**) - Content Encryption Key. Refer to the EncryptedKey schema definition below for details. 3. JWE element (**iv**) - Initialisation Vector for the algorithm. Refer to the InitializationVector schema definition below for details. 4. JWE element (**aad**) - Additional authentication data. Refer to AAD schema definition below for details. 5. Encrypted Payload (**ciphertext**) - Payload containing the relevant domain entity (eObject) as prescribed for the use case by the domain specifications. This needs to be encrypted so that HCX cannot read this. Refer to CipherText schema definition below for more details. 6. Authentication tag (**tag**) - Digital signature on the protected header and the payload of the message to ensure its integrity. Refer to AuthenticationTag schema definition below for more details. Detailed steps on how to construct the JWE token are provided in this [section](https://docs.pmjay.gov.in/hcx-specifications/hcx-technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity#message-encryption) of the HCX specifications.","example":"eyJlbmMiOiJBMjU2R0NNIiwKImFsZyI6IlJTQS1PQUVQIiwKIngtaGN4LXNlbmRlcl9jb2RlIjoiMS00ZGMzZTA4OC1hMzEzLTQ0YWItYWZhMS0wMjIyOTU5Y2I3NWIiLAoieC1oY3gtcmVjaXBpZW50X2NvZGUiOiIxLTkzZjkwOGJhLWI1NzktNDUzZS04YjJhLTU2MDIyYWZhZDI3NSIsCiJ4LWhjeC1yZXF1ZXN0X2lkIjoiMjZiMTA2MGMtMWU4My00NjAwLTk2MTItZWEzMWUwY2E1MDkxIiwKIngtaGN4LWNvcnJlbGF0aW9uX2lkIjoiNWU5MzRmOTAtMTExZC00ZjBiLWIwMTYtYzIyZDgyMDY3NGUxIiwKIngtaGN4LXRpbWVzdGFtcCI6IjIwMjEtMTAtMjdUMjA6MzU6NTIuNjM2KzA1MzAiLAoieC1oY3gtc3RhdHVzIjoicmVxdWVzdC5pbml0aWF0ZSIsCiJ4LWhjeC13b3JrZmxvd19pZCI6IjVlOTM0ZjkwLTExMWQtNGYwYi1iMDE2LWMyMmQ4MjA2NzRlMiIsCiJ4LWhjeC1kZWJ1Z19mbGFnIjoiSW5mbyIsCiJ4LWhjeC1lcnJvcl9kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCAidHJhY2UiOiAiIn0sCiJ4LWhjeC1kZWJ1Z19kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCJ0cmFjZSI6IiJ9LAoiandzX2hlYWRlciI6eyJ0eXAiOiJKV1QiLCAiYWxnIjoiUlMyNTYifSwKImp3ZV9oZWFkZXIiOnsiYWxnIjoiUlNBLU9BRVAiLCJlbmMiOiJBMjU2R0NNIn0KfQ==.6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.AxY8DCtDaGlsbGljb3RoZQ.KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.Mz-VPPyU4RlcuYv1IwIvzw"}},"required":["payload"]},"Error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}},"StatusResponseObject":{"type":"object","properties":{"sender_code":{"type":"string"},"recipient_code":{"type":"string"},"entity_type":{"type":"string","enum":["coverageeligibility","predetermination","preauthorization","claim","task","payment","insuranceplan"]},"protocol_status":{"type":"string","enum":["request.queued","request.error","request.dispatched"]}}},"StatusSuccessResponse":{"type":"object","properties":{"timestamp":{"type":"string"},"api_call_id":{"type":"string","format":"uuid"},"correlation_id":{"type":"string","format":"uuid"},"result":{"$ref":"#/components/schemas/StatusResponseObject"},"error":{"$ref":"#/components/schemas/Error"}}},"DomainHeaders":{"type":"object","description":"JSON object containing a map of domain-specific header values as proposed in domain data specifications. E.g. For claims use cases, domain specs may decide to populate the total claimed amount, list of diagnostics/procedures.","properties":{"use_case_name":{"type":"string"},"amt_processed":{"type":"string"}}},"JWEPayloadResponse":{"allOf":[{"$ref":"#/components/schemas/PreauthOnSubmitBody"},{"type":"object","properties":{"payload":{"type":"string","description":"The paylod should be a JWE token containing the following elements. 1. Protected headers (**protected**) - A set of attributes that provide transport, security, message integrity and summary information about the message being exchanged. Refer to the ProtectedHeader schema definition below for details. 2. JWE element (**encrypted_key**) - Content Encryption Key. Refer to the EncryptedKey schema definition below for details. 3. JWE element (**iv**) - Initialisation Vector for the algorithm. Refer to the InitializationVector schema definition below for details. 4. JWE element (**aad**) - Additional authentication data. Refer to AAD schema definition below for details. 5. Encrypted Payload (**ciphertext**) - Payload containing the relevant domain entity (eObject) as prescribed for the use case by the domain specifications. This needs to be encrypted so that HCX cannot read this. Refer to CipherText schema definition below for more details. 6. Authentication tag (**tag**) - Digital signature on the protected header and the payload of the message to ensure its integrity. Refer to AuthenticationTag schema definition below for more details. Detailed steps on how to construct the JWE token are provided in this [section](https://docs.pmjay.gov.in/hcx-specifications/hcx-technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity#message-encryption) of the HCX specifications.","example":"eyJlbmMiOiJBMjU2R0NNIiwKImFsZyI6IlJTQS1PQUVQIiwKIngtaGN4LXNlbmRlcl9jb2RlIjoiMS00ZGMzZTA4OC1hMzEzLTQ0YWItYWZhMS0wMjIyOTU5Y2I3NWIiLAoieC1oY3gtcmVjaXBpZW50X2NvZGUiOiIxLTkzZjkwOGJhLWI1NzktNDUzZS04YjJhLTU2MDIyYWZhZDI3NSIsCiJ4LWhjeC1yZXF1ZXN0X2lkIjoiMjZiMTA2MGMtMWU4My00NjAwLTk2MTItZWEzMWUwY2E1MDkxIiwKIngtaGN4LWNvcnJlbGF0aW9uX2lkIjoiNWU5MzRmOTAtMTExZC00ZjBiLWIwMTYtYzIyZDgyMDY3NGUxIiwKIngtaGN4LXRpbWVzdGFtcCI6IjIwMjEtMTAtMjdUMjA6MzU6NTIuNjM2KzA1MzAiLAoieC1oY3gtc3RhdHVzIjoicmVxdWVzdC5pbml0aWF0ZSIsCiJ4LWhjeC13b3JrZmxvd19pZCI6IjVlOTM0ZjkwLTExMWQtNGYwYi1iMDE2LWMyMmQ4MjA2NzRlMiIsCiJ4LWhjeC1kZWJ1Z19mbGFnIjoiSW5mbyIsCiJ4LWhjeC1lcnJvcl9kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCAidHJhY2UiOiAiIn0sCiJ4LWhjeC1kZWJ1Z19kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCJ0cmFjZSI6IiJ9LAoiandzX2hlYWRlciI6eyJ0eXAiOiJKV1QiLCAiYWxnIjoiUlMyNTYifSwKImp3ZV9oZWFkZXIiOnsiYWxnIjoiUlNBLU9BRVAiLCJlbmMiOiJBMjU2R0NNIn0KfQ==.6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.AxY8DCtDaGlsbGljb3RoZQ.KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.Mz-VPPyU4RlcuYv1IwIvzw"}}}],"description":"All the HCX protocol APIs require the request body to sent in JWE format (as defined in [RFC-7516](https://datatracker.ietf.org/doc/html/rfc7516)).","required":["payload"]},"PreauthOnSubmitBody":{"discriminator":{"propertyName":"type"},"properties":{"type":{"type":"string"}},"required":["type"]},"ProtocolHeaderXhcxdebugDetails":{"type":"object","description":"Expected to be used for providing details of the status. Will be specially useful in debugging scenarios.","properties":{"code":{"type":"string"},"message":{"type":"string"},"trace":{"type":"string"}}},"ProtocolHeaderXhcxerrorDetails":{"type":"object","description":"Expected to be used for providing details of the status. Will be specially useful in scenarios where operational status indicates irrecoverable error.","properties":{"code":{"type":"string"},"message":{"type":"string"},"trace":{"type":"string"}}},"ProtocolResponse":{"allOf":[{"$ref":"#/components/schemas/PreauthOnSubmitBody"},{"type":"object","properties":{"x-hcx-sender_code":{"type":"string","description":"Registry code of the sender (e.g. provider or payer)","example":"PROVIDER01@HCX01"},"x-hcx-recipient_code":{"type":"string","description":"Registry code of the recipient (e.g. provider or payer)","example":"PAYOR01@HCX01"},"x-hcx-api_call_id":{"type":"string","format":"uuid","description":"Sender generated unique id for each originating request. All senders (providers & payors) must generate and set a unique value to the x-hcx-api_call_id protocol header in all the API calls to the HCX gateway."},"x-hcx-correlation_id":{"type":"string","format":"uuid","description":"Unique id for all messages (requests & responses) that are involved in processing of one cycle (like coverage eligibility, pre-auth, claim, or payment notice cycle). The participant system sending the originating request of the cycle must set the x-hcx-correlation_id in the initial API call and the HCX gateway shall forward the same correlation id to the recipient of the request. The recipient must set the same correlation id in the response API call and in other API calls related to the original request (e.g. communication request, forward/redirect requests). And the same correlation id must be sent in all subsequent API calls (related to the same cycle). In case of status API call, this header should have the correlation id of the request for which the status is being requested for."},"x-hcx-workflow_id":{"type":"string","description":"Unique id for one complete workflow that spans over a series of cycles and message exchanges within the context of an admission/case. This is an optional header that can be set by providers to the same value for all requests (coverage eligibility check, preauth, claim, etc) related to a single admission/case. And when the workflow_id is sent by the originating provider, all other participant systems (payors) must set the same workflow id in all API calls (responses, forwards/redirects, payment notices, etc) related to the workflow."},"x-hcx-timestamp":{"type":"string","description":"Unix timestamp when the request is sent.","example":1629057611000},"x-hcx-debug_flag":{"type":"string","description":"Request to the server to include debug information. Useful in the time of integration testing and prod debugging. However server(s) may choose to ignore this flag based on their policy.","enum":["Error","Info","Debug"]},"x-hcx-status":{"type":"string","description":"Operational status of the message. Depending on the leg of the message, it would be one of the defined values in the enum.","enum":["request.initiated","request.processed","request.queued","request.error","request.stopped","request.dispatched","response.complete","response.error","response.partial","response.redirect"]},"x-hcx-redirect_to":{"type":"string"},"x-hcx-error_details":{"$ref":"#/components/schemas/ProtocolHeaderXhcxerrorDetails"},"x-hcx-debug_details":{"$ref":"#/components/schemas/ProtocolHeaderXhcxdebugDetails"},"x-hcx-domain-header":{"$ref":"#/components/schemas/DomainHeaders"},"x-hcx-entity-type":{"type":"string","enum":["coverageeligibility","predetermination","preauthorization","claim","task","payment","insuranceplan"]},"x-hcx-ben-abha-id":{"type":"string"}}}],"description":"Object to be returned as payload of the callback API (on_* APIs) in case there are any protocol related errors while processing the request or send a redirection instruction to the original sender of the request.","required":["x-hcx-api_call_id","x-hcx-correlation_id","x-hcx-recipient_code","x-hcx-sender_code","x-hcx-timestamp"]}}}} \ No newline at end of file diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/searchhcxservice.json b/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/searchhcxservice.json new file mode 100644 index 000000000..f8a91e7ec --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/searchhcxservice.json @@ -0,0 +1 @@ +{"openapi":"3.1.0","info":{"title":"NHCX - Search APIs","description":"The National Health Claims Exchange (NHCX)","termsOfService":"http://swagger.io/terms/","license":{"name":"Apache 2.0","url":"http://springdoc.org"},"version":"1.0.0"},"servers":[{"url":"/searchhcxservice","description":"Default Server URL"}],"paths":{"/v1/search/submit":{"post":{"tags":["V1.0 APIs-Payer Side"],"description":"This API is for any authorised entity to search the claim related information. For example, NHA/IRDAI can search for the claim information for a given case number by sending Task [resource](https://nrces.in/ndhm/fhir/r4/StructureDefinition/Task) and payers will provide the claim documents as requested. Payload for this API has to be created as per the TaskBundle.

The request body for this API should be sent in the form of a JWE token ([RFC-7516](https://datatracker.ietf.org/doc/html/rfc7516)) using the steps defined in [HCX specs](https://hcxsbx.abdm.gov.in/#/technical-specifications). As defined in the specs, JWE should contain the protected headers and the encrypted FHIR resource as the domain payload. 1. Protected headers should have the protocol headers as defined in the ProtocolHeader schema definition below. Specifically for this API, the header x-hcx-correlation_id should carry the correlation id of the request for which the status is being requested for. 2. The domain payload should be an encrypted Task FHIR resource. The Task resource should have the reference to the entity for which the search is being quered for in the \"**about**\" element. This reference object should contain the sender's reference id of the entity.","operationId":"hcxSearchPost","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JWEPayload"}}},"required":true},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"400":{"description":"Request Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"404":{"description":"Requested resource was not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/v1/search/on_submit":{"post":{"tags":["V1.0 APIs-Provider side"],"description":"This is the callback API to return the response for search requests based on the task type (code=poll). Payload for this API has to be created as per the TaskBundle.

Domain Payload for this API will be based on the task type. If it is for claim document, domain payload will be claim response resource for given reference number. The encrypted claim FHIR resource containing the following information: - **basedOn** - reference to the entity sent by the sender in the original request and should contain sender's reference id of the entity. - **about** - reference to the response entity and should contain the recipient's reference id and the current status of the response entity.","operationId":"hcxOnSearchPost","requestBody":{"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/JWEPayloadResponse"},{"$ref":"#/components/schemas/ProtocolResponse"}]}}},"required":true},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"400":{"description":"Request Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"404":{"description":"Requested resource was not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}}},"security":[{"bearer_auth":[]}]}}},"components":{"schemas":{"JWEPayload":{"type":"object","description":"All the HCX protocol APIs require the request body to sent in JWE format (as defined in [RFC-7516](https://datatracker.ietf.org/doc/html/rfc7516)).","properties":{"payload":{"type":"string","description":"The paylod should be a JWE token containing the following elements. 1. Protected headers (**protected**) - A set of attributes that provide transport, security, message integrity and summary information about the message being exchanged. Refer to the ProtectedHeader schema definition below for details. 2. JWE element (**encrypted_key**) - Content Encryption Key. Refer to the EncryptedKey schema definition below for details. 3. JWE element (**iv**) - Initialisation Vector for the algorithm. Refer to the InitializationVector schema definition below for details. 4. JWE element (**aad**) - Additional authentication data. Refer to AAD schema definition below for details. 5. Encrypted Payload (**ciphertext**) - Payload containing the relevant domain entity (eObject) as prescribed for the use case by the domain specifications. This needs to be encrypted so that HCX cannot read this. Refer to CipherText schema definition below for more details. 6. Authentication tag (**tag**) - Digital signature on the protected header and the payload of the message to ensure its integrity. Refer to AuthenticationTag schema definition below for more details. Detailed steps on how to construct the JWE token are provided in this [section](https://docs.pmjay.gov.in/hcx-specifications/hcx-technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity#message-encryption) of the HCX specifications.","example":"eyJlbmMiOiJBMjU2R0NNIiwKImFsZyI6IlJTQS1PQUVQIiwKIngtaGN4LXNlbmRlcl9jb2RlIjoiMS00ZGMzZTA4OC1hMzEzLTQ0YWItYWZhMS0wMjIyOTU5Y2I3NWIiLAoieC1oY3gtcmVjaXBpZW50X2NvZGUiOiIxLTkzZjkwOGJhLWI1NzktNDUzZS04YjJhLTU2MDIyYWZhZDI3NSIsCiJ4LWhjeC1yZXF1ZXN0X2lkIjoiMjZiMTA2MGMtMWU4My00NjAwLTk2MTItZWEzMWUwY2E1MDkxIiwKIngtaGN4LWNvcnJlbGF0aW9uX2lkIjoiNWU5MzRmOTAtMTExZC00ZjBiLWIwMTYtYzIyZDgyMDY3NGUxIiwKIngtaGN4LXRpbWVzdGFtcCI6IjIwMjEtMTAtMjdUMjA6MzU6NTIuNjM2KzA1MzAiLAoieC1oY3gtc3RhdHVzIjoicmVxdWVzdC5pbml0aWF0ZSIsCiJ4LWhjeC13b3JrZmxvd19pZCI6IjVlOTM0ZjkwLTExMWQtNGYwYi1iMDE2LWMyMmQ4MjA2NzRlMiIsCiJ4LWhjeC1kZWJ1Z19mbGFnIjoiSW5mbyIsCiJ4LWhjeC1lcnJvcl9kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCAidHJhY2UiOiAiIn0sCiJ4LWhjeC1kZWJ1Z19kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCJ0cmFjZSI6IiJ9LAoiandzX2hlYWRlciI6eyJ0eXAiOiJKV1QiLCAiYWxnIjoiUlMyNTYifSwKImp3ZV9oZWFkZXIiOnsiYWxnIjoiUlNBLU9BRVAiLCJlbmMiOiJBMjU2R0NNIn0KfQ==.6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.AxY8DCtDaGlsbGljb3RoZQ.KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.Mz-VPPyU4RlcuYv1IwIvzw"}},"required":["payload"]},"Error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}},"StatusResponseObject":{"type":"object","properties":{"sender_code":{"type":"string"},"recipient_code":{"type":"string"},"entity_type":{"type":"string","enum":["coverageeligibility","predetermination","preauth","claim","task","payment","insuranceplan","search"]},"protocol_status":{"type":"string","enum":["request.queued","request.error","request.dispatched"]}}},"StatusSuccessResponse":{"type":"object","properties":{"timestamp":{"type":"string"},"api_call_id":{"type":"string","format":"uuid"},"correlation_id":{"type":"string","format":"uuid"},"result":{"$ref":"#/components/schemas/StatusResponseObject"},"error":{"$ref":"#/components/schemas/Error"}}},"DomainHeaders":{"type":"object","description":"JSON object containing a map of domain-specific header values as proposed in domain data specifications. E.g. For claims use cases, domain specs may decide to populate the total claimed amount, list of diagnostics/procedures.","properties":{"use_case_name":{"type":"string"},"amt_processed":{"type":"string"}}},"HcxOnSearchBody":{"discriminator":{"propertyName":"type"},"properties":{"type":{"type":"string"}},"required":["type"]},"JWEPayloadResponse":{"allOf":[{"$ref":"#/components/schemas/HcxOnSearchBody"},{"type":"object","properties":{"payload":{"type":"string","description":"The paylod should be a JWE token containing the following elements. 1. Protected headers (**protected**) - A set of attributes that provide transport, security, message integrity and summary information about the message being exchanged. Refer to the ProtectedHeader schema definition below for details. 2. JWE element (**encrypted_key**) - Content Encryption Key. Refer to the EncryptedKey schema definition below for details. 3. JWE element (**iv**) - Initialisation Vector for the algorithm. Refer to the InitializationVector schema definition below for details. 4. JWE element (**aad**) - Additional authentication data. Refer to AAD schema definition below for details. 5. Encrypted Payload (**ciphertext**) - Payload containing the relevant domain entity (eObject) as prescribed for the use case by the domain specifications. This needs to be encrypted so that HCX cannot read this. Refer to CipherText schema definition below for more details. 6. Authentication tag (**tag**) - Digital signature on the protected header and the payload of the message to ensure its integrity. Refer to AuthenticationTag schema definition below for more details. Detailed steps on how to construct the JWE token are provided in this [section](https://docs.pmjay.gov.in/hcx-specifications/hcx-technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity#message-encryption) of the HCX specifications.","example":"eyJlbmMiOiJBMjU2R0NNIiwKImFsZyI6IlJTQS1PQUVQIiwKIngtaGN4LXNlbmRlcl9jb2RlIjoiMS00ZGMzZTA4OC1hMzEzLTQ0YWItYWZhMS0wMjIyOTU5Y2I3NWIiLAoieC1oY3gtcmVjaXBpZW50X2NvZGUiOiIxLTkzZjkwOGJhLWI1NzktNDUzZS04YjJhLTU2MDIyYWZhZDI3NSIsCiJ4LWhjeC1yZXF1ZXN0X2lkIjoiMjZiMTA2MGMtMWU4My00NjAwLTk2MTItZWEzMWUwY2E1MDkxIiwKIngtaGN4LWNvcnJlbGF0aW9uX2lkIjoiNWU5MzRmOTAtMTExZC00ZjBiLWIwMTYtYzIyZDgyMDY3NGUxIiwKIngtaGN4LXRpbWVzdGFtcCI6IjIwMjEtMTAtMjdUMjA6MzU6NTIuNjM2KzA1MzAiLAoieC1oY3gtc3RhdHVzIjoicmVxdWVzdC5pbml0aWF0ZSIsCiJ4LWhjeC13b3JrZmxvd19pZCI6IjVlOTM0ZjkwLTExMWQtNGYwYi1iMDE2LWMyMmQ4MjA2NzRlMiIsCiJ4LWhjeC1kZWJ1Z19mbGFnIjoiSW5mbyIsCiJ4LWhjeC1lcnJvcl9kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCAidHJhY2UiOiAiIn0sCiJ4LWhjeC1kZWJ1Z19kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCJ0cmFjZSI6IiJ9LAoiandzX2hlYWRlciI6eyJ0eXAiOiJKV1QiLCAiYWxnIjoiUlMyNTYifSwKImp3ZV9oZWFkZXIiOnsiYWxnIjoiUlNBLU9BRVAiLCJlbmMiOiJBMjU2R0NNIn0KfQ==.6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.AxY8DCtDaGlsbGljb3RoZQ.KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.Mz-VPPyU4RlcuYv1IwIvzw"}}}],"description":"All the HCX protocol APIs require the request body to sent in JWE format (as defined in [RFC-7516](https://datatracker.ietf.org/doc/html/rfc7516)).","required":["payload"]},"ProtocolHeaderXhcxdebugDetails":{"type":"object","description":"Expected to be used for providing details of the status. Will be specially useful in debugging scenarios.","properties":{"code":{"type":"string"},"message":{"type":"string"},"trace":{"type":"string"}}},"ProtocolHeaderXhcxerrorDetails":{"type":"object","description":"Expected to be used for providing details of the status. Will be specially useful in scenarios where operational status indicates irrecoverable error.","properties":{"code":{"type":"string"},"message":{"type":"string"},"trace":{"type":"string"}}},"ProtocolResponse":{"allOf":[{"$ref":"#/components/schemas/HcxOnSearchBody"},{"type":"object","properties":{"x-hcx-sender_code":{"type":"string","description":"Registry code of the sender (e.g. provider or payer)","example":"PROVIDER01@HCX01"},"x-hcx-recipient_code":{"type":"string","description":"Registry code of the recipient (e.g. provider or payer)","example":"PAYOR01@HCX01"},"x-hcx-api_call_id":{"type":"string","format":"uuid","description":"Sender generated unique id for each originating request. All senders (providers & payors) must generate and set a unique value to the x-hcx-api_call_id protocol header in all the API calls to the HCX gateway."},"x-hcx-correlation_id":{"type":"string","format":"uuid","description":"Unique id for all messages (requests & responses) that are involved in processing of one cycle (like coverage eligibility, pre-auth, claim, or payment notice cycle). The participant system sending the originating request of the cycle must set the x-hcx-correlation_id in the initial API call and the HCX gateway shall forward the same correlation id to the recipient of the request. The recipient must set the same correlation id in the response API call and in other API calls related to the original request (e.g. communication request, forward/redirect requests). And the same correlation id must be sent in all subsequent API calls (related to the same cycle). In case of status API call, this header should have the correlation id of the request for which the status is being requested for."},"x-hcx-workflow_id":{"type":"string","description":"Unique id for one complete workflow that spans over a series of cycles and message exchanges within the context of an admission/case. This is an optional header that can be set by providers to the same value for all requests (coverage eligibility check, preauth, claim, etc) related to a single admission/case. And when the workflow_id is sent by the originating provider, all other participant systems (payors) must set the same workflow id in all API calls (responses, forwards/redirects, payment notices, etc) related to the workflow."},"x-hcx-timestamp":{"type":"string","description":"Unix timestamp when the request is sent.","example":1629057611000},"x-hcx-debug_flag":{"type":"string","description":"Request to the server to include debug information. Useful in the time of integration testing and prod debugging. However server(s) may choose to ignore this flag based on their policy.","enum":["Error","Info","Debug"]},"x-hcx-status":{"type":"string","description":"Operational status of the message. Depending on the leg of the message, it would be one of the defined values in the enum.","enum":["request.initiated","request.processed","request.queued","request.error","request.stopped","request.dispatched","response.complete","response.error","response.partial","response.redirect"]},"x-hcx-redirect_to":{"type":"string"},"x-hcx-error_details":{"$ref":"#/components/schemas/ProtocolHeaderXhcxerrorDetails"},"x-hcx-debug_details":{"$ref":"#/components/schemas/ProtocolHeaderXhcxdebugDetails"},"x-hcx-domain-header":{"$ref":"#/components/schemas/DomainHeaders"},"x-hcx-entity-type":{"type":"string","enum":["coverageeligibility","predetermination","preauth","claim","task","payment","insuranceplan","search"]},"x-hcx-ben-abha-id":{"type":"string"}}}],"description":"Object to be returned as payload of the callback API (on_* APIs) in case there are any protocol related errors while processing the request or send a redirection instruction to the original sender of the request.","required":["x-hcx-api_call_id","x-hcx-correlation_id","x-hcx-recipient_code","x-hcx-sender_code","x-hcx-timestamp"]}}}} \ No newline at end of file diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/servicehcxpayment.json b/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/servicehcxpayment.json new file mode 100644 index 000000000..006b2c1a0 --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/servicehcxpayment.json @@ -0,0 +1 @@ +{"openapi":"3.1.0","info":{"title":"NHCX - Payment APIs","description":"The National Health Claims Exchange (NHCX) is a digital","termsOfService":"http://swagger.io/terms/","license":{"name":"Apache 2.0","url":"http://springdoc.org"},"version":"1.0.0"},"servers":[{"url":"/servicehcxpayment","description":"Default Server URL"}],"paths":{"/v1/paymentnotice/request":{"post":{"tags":["V1.0 APIs-Provider side"],"description":"This API is for Payors to send Payment notification/reconciliation objects to Providers via the HCX gateway. This API is available on HCX gateways and Provider systems.

Payload for this API has to be created as per the [TaskBundle PaymentNotice](https://nrces.in/ndhm/fhir/r4/StructureDefinition/PaymentNotice) defined in HCX Specifications and serialized as JWE json as per the [guidelines](https://hcxsbx.abdm.gov.in/#/technical-specifications) in HCX Specifications.","operationId":"paymentnoticeRequestPost","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JWEPayload"}}},"required":true},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"400":{"description":"Request Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"404":{"description":"Requested resource was not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/v1/paymentnotice/on_request":{"post":{"tags":["V1.0 APIs-Payer side"],"description":"This is callback API for payment acknowledgement by the Providers. This API is available on HCX gateways and Payor systems.

Payload for this API has to be created as per the TaskBundle defined in HCX Specifications and serialized as JWE json as per the [guidelines](https://hcxsbx.abdm.gov.in/#/technical-specifications) in HCX Specifications.","operationId":"paymentnoticeOnRequestPost","requestBody":{"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/JWEPayloadResponse"},{"$ref":"#/components/schemas/ProtocolResponse"}]}}},"required":true},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"400":{"description":"Request Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"404":{"description":"Requested resource was not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}}},"security":[{"bearer_auth":[]}]}}},"components":{"schemas":{"JWEPayload":{"type":"object","description":"All the HCX protocol APIs require the request body to sent in JWE format (as defined in [RFC-7516](https://datatracker.ietf.org/doc/html/rfc7516)).","properties":{"payload":{"type":"string","description":"The paylod should be a JWE token containing the following elements. 1. Protected headers (**protected**) - A set of attributes that provide transport, security, message integrity and summary information about the message being exchanged. Refer to the ProtectedHeader schema definition below for details. 2. JWE element (**encrypted_key**) - Content Encryption Key. Refer to the EncryptedKey schema definition below for details. 3. JWE element (**iv**) - Initialisation Vector for the algorithm. Refer to the InitializationVector schema definition below for details. 4. JWE element (**aad**) - Additional authentication data. Refer to AAD schema definition below for details. 5. Encrypted Payload (**ciphertext**) - Payload containing the relevant domain entity (eObject) as prescribed for the use case by the domain specifications. This needs to be encrypted so that HCX cannot read this. Refer to CipherText schema definition below for more details. 6. Authentication tag (**tag**) - Digital signature on the protected header and the payload of the message to ensure its integrity. Refer to AuthenticationTag schema definition below for more details. Detailed steps on how to construct the JWE token are provided in this [section](https://docs.pmjay.gov.in/hcx-specifications/hcx-technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity#message-encryption) of the HCX specifications.","example":"eyJlbmMiOiJBMjU2R0NNIiwKImFsZyI6IlJTQS1PQUVQIiwKIngtaGN4LXNlbmRlcl9jb2RlIjoiMS00ZGMzZTA4OC1hMzEzLTQ0YWItYWZhMS0wMjIyOTU5Y2I3NWIiLAoieC1oY3gtcmVjaXBpZW50X2NvZGUiOiIxLTkzZjkwOGJhLWI1NzktNDUzZS04YjJhLTU2MDIyYWZhZDI3NSIsCiJ4LWhjeC1yZXF1ZXN0X2lkIjoiMjZiMTA2MGMtMWU4My00NjAwLTk2MTItZWEzMWUwY2E1MDkxIiwKIngtaGN4LWNvcnJlbGF0aW9uX2lkIjoiNWU5MzRmOTAtMTExZC00ZjBiLWIwMTYtYzIyZDgyMDY3NGUxIiwKIngtaGN4LXRpbWVzdGFtcCI6IjIwMjEtMTAtMjdUMjA6MzU6NTIuNjM2KzA1MzAiLAoieC1oY3gtc3RhdHVzIjoicmVxdWVzdC5pbml0aWF0ZSIsCiJ4LWhjeC13b3JrZmxvd19pZCI6IjVlOTM0ZjkwLTExMWQtNGYwYi1iMDE2LWMyMmQ4MjA2NzRlMiIsCiJ4LWhjeC1kZWJ1Z19mbGFnIjoiSW5mbyIsCiJ4LWhjeC1lcnJvcl9kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCAidHJhY2UiOiAiIn0sCiJ4LWhjeC1kZWJ1Z19kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCJ0cmFjZSI6IiJ9LAoiandzX2hlYWRlciI6eyJ0eXAiOiJKV1QiLCAiYWxnIjoiUlMyNTYifSwKImp3ZV9oZWFkZXIiOnsiYWxnIjoiUlNBLU9BRVAiLCJlbmMiOiJBMjU2R0NNIn0KfQ==.6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.AxY8DCtDaGlsbGljb3RoZQ.KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.Mz-VPPyU4RlcuYv1IwIvzw"}},"required":["payload"]},"Error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}},"StatusResponseObject":{"type":"object","properties":{"sender_code":{"type":"string"},"recipient_code":{"type":"string"},"entity_type":{"type":"string","enum":["coverageeligibility","predetermination","preauth","claim","task","payment","insuranceplan"]},"protocol_status":{"type":"string","enum":["request.queued","request.error","request.dispatched"]}}},"StatusSuccessResponse":{"type":"object","properties":{"timestamp":{"type":"string"},"api_call_id":{"type":"string","format":"uuid"},"correlation_id":{"type":"string","format":"uuid"},"result":{"$ref":"#/components/schemas/StatusResponseObject"},"error":{"$ref":"#/components/schemas/Error"}}},"DomainHeaders":{"type":"object","description":"JSON object containing a map of domain-specific header values as proposed in domain data specifications. E.g. For claims use cases, domain specs may decide to populate the total claimed amount, list of diagnostics/procedures.","properties":{"use_case_name":{"type":"string"},"amt_processed":{"type":"string"}}},"JWEPayloadResponse":{"allOf":[{"$ref":"#/components/schemas/PaymentnoticeOnRequestBody"},{"type":"object","properties":{"payload":{"type":"string","description":"The paylod should be a JWE token containing the following elements. 1. Protected headers (**protected**) - A set of attributes that provide transport, security, message integrity and summary information about the message being exchanged. Refer to the ProtectedHeader schema definition below for details. 2. JWE element (**encrypted_key**) - Content Encryption Key. Refer to the EncryptedKey schema definition below for details. 3. JWE element (**iv**) - Initialisation Vector for the algorithm. Refer to the InitializationVector schema definition below for details. 4. JWE element (**aad**) - Additional authentication data. Refer to AAD schema definition below for details. 5. Encrypted Payload (**ciphertext**) - Payload containing the relevant domain entity (eObject) as prescribed for the use case by the domain specifications. This needs to be encrypted so that HCX cannot read this. Refer to CipherText schema definition below for more details. 6. Authentication tag (**tag**) - Digital signature on the protected header and the payload of the message to ensure its integrity. Refer to AuthenticationTag schema definition below for more details. Detailed steps on how to construct the JWE token are provided in this [section](https://docs.pmjay.gov.in/hcx-specifications/hcx-technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity#message-encryption) of the HCX specifications.","example":"eyJlbmMiOiJBMjU2R0NNIiwKImFsZyI6IlJTQS1PQUVQIiwKIngtaGN4LXNlbmRlcl9jb2RlIjoiMS00ZGMzZTA4OC1hMzEzLTQ0YWItYWZhMS0wMjIyOTU5Y2I3NWIiLAoieC1oY3gtcmVjaXBpZW50X2NvZGUiOiIxLTkzZjkwOGJhLWI1NzktNDUzZS04YjJhLTU2MDIyYWZhZDI3NSIsCiJ4LWhjeC1yZXF1ZXN0X2lkIjoiMjZiMTA2MGMtMWU4My00NjAwLTk2MTItZWEzMWUwY2E1MDkxIiwKIngtaGN4LWNvcnJlbGF0aW9uX2lkIjoiNWU5MzRmOTAtMTExZC00ZjBiLWIwMTYtYzIyZDgyMDY3NGUxIiwKIngtaGN4LXRpbWVzdGFtcCI6IjIwMjEtMTAtMjdUMjA6MzU6NTIuNjM2KzA1MzAiLAoieC1oY3gtc3RhdHVzIjoicmVxdWVzdC5pbml0aWF0ZSIsCiJ4LWhjeC13b3JrZmxvd19pZCI6IjVlOTM0ZjkwLTExMWQtNGYwYi1iMDE2LWMyMmQ4MjA2NzRlMiIsCiJ4LWhjeC1kZWJ1Z19mbGFnIjoiSW5mbyIsCiJ4LWhjeC1lcnJvcl9kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCAidHJhY2UiOiAiIn0sCiJ4LWhjeC1kZWJ1Z19kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCJ0cmFjZSI6IiJ9LAoiandzX2hlYWRlciI6eyJ0eXAiOiJKV1QiLCAiYWxnIjoiUlMyNTYifSwKImp3ZV9oZWFkZXIiOnsiYWxnIjoiUlNBLU9BRVAiLCJlbmMiOiJBMjU2R0NNIn0KfQ==.6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.AxY8DCtDaGlsbGljb3RoZQ.KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.Mz-VPPyU4RlcuYv1IwIvzw"}}}],"description":"All the HCX protocol APIs require the request body to sent in JWE format (as defined in [RFC-7516](https://datatracker.ietf.org/doc/html/rfc7516)).","required":["payload"]},"PaymentnoticeOnRequestBody":{"discriminator":{"propertyName":"type"},"properties":{"type":{"type":"string"}},"required":["type"]},"ProtocolHeaderXhcxdebugDetails":{"type":"object","description":"Expected to be used for providing details of the status. Will be specially useful in debugging scenarios.","properties":{"code":{"type":"string"},"message":{"type":"string"},"trace":{"type":"string"}}},"ProtocolHeaderXhcxerrorDetails":{"type":"object","description":"Expected to be used for providing details of the status. Will be specially useful in scenarios where operational status indicates irrecoverable error.","properties":{"code":{"type":"string"},"message":{"type":"string"},"trace":{"type":"string"}}},"ProtocolResponse":{"allOf":[{"$ref":"#/components/schemas/PaymentnoticeOnRequestBody"},{"type":"object","properties":{"x-hcx-sender_code":{"type":"string","description":"Registry code of the sender (e.g. provider or payer)","example":"PROVIDER01@HCX01"},"x-hcx-recipient_code":{"type":"string","description":"Registry code of the recipient (e.g. provider or payer)","example":"PAYOR01@HCX01"},"x-hcx-api_call_id":{"type":"string","format":"uuid","description":"Sender generated unique id for each originating request. All senders (providers & payors) must generate and set a unique value to the x-hcx-api_call_id protocol header in all the API calls to the HCX gateway."},"x-hcx-correlation_id":{"type":"string","format":"uuid","description":"Unique id for all messages (requests & responses) that are involved in processing of one cycle (like coverage eligibility, pre-auth, claim, or payment notice cycle). The participant system sending the originating request of the cycle must set the x-hcx-correlation_id in the initial API call and the HCX gateway shall forward the same correlation id to the recipient of the request. The recipient must set the same correlation id in the response API call and in other API calls related to the original request (e.g. communication request, forward/redirect requests). And the same correlation id must be sent in all subsequent API calls (related to the same cycle). In case of status API call, this header should have the correlation id of the request for which the status is being requested for."},"x-hcx-workflow_id":{"type":"string","description":"Unique id for one complete workflow that spans over a series of cycles and message exchanges within the context of an admission/case. This is an optional header that can be set by providers to the same value for all requests (coverage eligibility check, preauth, claim, etc) related to a single admission/case. And when the workflow_id is sent by the originating provider, all other participant systems (payors) must set the same workflow id in all API calls (responses, forwards/redirects, payment notices, etc) related to the workflow."},"x-hcx-timestamp":{"type":"string","description":"Unix timestamp when the request is sent.","example":1629057611000},"x-hcx-debug_flag":{"type":"string","description":"Request to the server to include debug information. Useful in the time of integration testing and prod debugging. However server(s) may choose to ignore this flag based on their policy.","enum":["Error","Info","Debug"]},"x-hcx-status":{"type":"string","description":"Operational status of the message. Depending on the leg of the message, it would be one of the defined values in the enum.","enum":["request.initiated","request.processed","request.queued","request.error","request.stopped","request.dispatched","response.complete","response.error","response.partial","response.redirect"]},"x-hcx-redirect_to":{"type":"string"},"x-hcx-error_details":{"$ref":"#/components/schemas/ProtocolHeaderXhcxerrorDetails"},"x-hcx-debug_details":{"$ref":"#/components/schemas/ProtocolHeaderXhcxdebugDetails"},"x-hcx-domain-header":{"$ref":"#/components/schemas/DomainHeaders"},"x-hcx-ben-abha-id":{"type":"string"}}}],"description":"Object to be returned as payload of the callback API (on_* APIs) in case there are any protocol related errors while processing the request or send a redirection instruction to the original sender of the request.","required":["x-hcx-api_call_id","x-hcx-correlation_id","x-hcx-recipient_code","x-hcx-sender_code","x-hcx-timestamp"]}}}} \ No newline at end of file diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/statushcxservice.json b/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/statushcxservice.json new file mode 100644 index 000000000..7933d6d08 --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/statushcxservice.json @@ -0,0 +1 @@ +{"openapi":"3.0.1","info":{"title":"NHCX - Status APIs","description":"The National Health Claims Exchange (NHCX) is a digital infrastructure designed to enable automated, data-driven management of health insurance claims in an open ecosystem. These API specifications enable all actors to interact with the NHCX.","termsOfService":"http://swagger.io/terms/","license":{"name":"Apache 2.0","url":"http://springdoc.org"},"version":"1.0.0"},"servers":[{"url":"/statushcxservice","description":"Default Server URL","variables":{}}],"paths":{"/v1/status":{"post":{"tags":["V1.0 APIs-Payer side"],"description":"This API is for senders to query the status of a request made by them. For example, a provider can query the status of a pre-auth request using the status API. Payload for this API has to be created as per the TaskBundle.

The request body for this API should be sent in the form of a JWE token ([RFC-7516](https://datatracker.ietf.org/doc/html/rfc7516)) using the steps defined in [HCX specs](https://hcxsbx.abdm.gov.in/#/technical-specifications). As defined in the specs, JWE should contain the protected headers and the encrypted FHIR resource as the domain payload. 1. Protected headers should have the protocol headers as defined in the ProtocolHeader schema definition below. Specifically for this API, the header x-hcx-correlation_id should carry the correlation id of the request for which the status is being requested for. 2. The domain payload should be an encrypted CommunicationRequest FHIR resource. The CommunicationRequest resource should have the reference to the entity for which the status is being quered for in the \"**about**\" element. This reference object should contain the sender's reference id of the entity. HCX gateway shall validate the incoming request and send the protocol status in the http response. The protocol status value could be one of the following: - **request.queued** - This status means that HCX gateway has not yet forwarded the original request (for which the status is being requeested for) to the intended recipient. The request is still under processing by the HCX gateway. In this scenario, there shall not be a status response via the call back API /hcx/on_status to the caller. - **request.dispatched** - This means that HCX gateway has dispatched the original request to the intended recipient and thus, HCX gateway will forward the status request to the same recipient. And the recipient shall respond with status details via the call back API /v1/on_status to the caller.","operationId":"hcxStatusPost","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JWEPayload"}}},"required":true},"responses":{"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"404":{"description":"Requested resource was not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"400":{"description":"Request Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/v3/api-docs":{"get":{"tags":["open-api-controller-web-mvc"],"operationId":"getDocumentation","parameters":[{"name":"group","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"string"}},"application/hal+json":{"schema":{"type":"string"}}}}}}},"/v2/api-docs":{"get":{"tags":["swagger-2-controller-web-mvc"],"operationId":"getDocumentation_1","parameters":[{"name":"group","in":"query","required":false,"schema":{"type":"string"}}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"string"}},"application/hal+json":{"schema":{"type":"string"}}}}}}},"/swagger-resources":{"get":{"tags":["api-resource-controller"],"operationId":"swaggerResources","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/SwaggerResource"}}}}}}}},"/swagger-resources/configuration/ui":{"get":{"tags":["api-resource-controller"],"operationId":"uiConfiguration","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/UiConfiguration"}}}}}}},"/swagger-resources/configuration/security":{"get":{"tags":["api-resource-controller"],"operationId":"securityConfiguration","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SecurityConfiguration"}}}}}}}},"components":{"schemas":{"JWEPayload":{"required":["payload"],"type":"object","properties":{"payload":{"type":"string","description":"The paylod should be a JWE token containing the following elements. 1. Protected headers (**protected**) - A set of attributes that provide transport, security, message integrity and summary information about the message being exchanged. Refer to the ProtectedHeader schema definition below for details. 2. JWE element (**encrypted_key**) - Content Encryption Key. Refer to the EncryptedKey schema definition below for details. 3. JWE element (**iv**) - Initialisation Vector for the algorithm. Refer to the InitializationVector schema definition below for details. 4. JWE element (**aad**) - Additional authentication data. Refer to AAD schema definition below for details. 5. Encrypted Payload (**ciphertext**) - Payload containing the relevant domain entity (eObject) as prescribed for the use case by the domain specifications. This needs to be encrypted so that HCX cannot read this. Refer to CipherText schema definition below for more details. 6. Authentication tag (**tag**) - Digital signature on the protected header and the payload of the message to ensure its integrity. Refer to AuthenticationTag schema definition below for more details. Detailed steps on how to construct the JWE token are provided in this [section](https://docs.pmjay.gov.in/hcx-specifications/hcx-technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity#message-encryption) of the HCX specifications.","example":"eyJlbmMiOiJBMjU2R0NNIiwKImFsZyI6IlJTQS1PQUVQIiwKIngtaGN4LXNlbmRlcl9jb2RlIjoiMS00ZGMzZTA4OC1hMzEzLTQ0YWItYWZhMS0wMjIyOTU5Y2I3NWIiLAoieC1oY3gtcmVjaXBpZW50X2NvZGUiOiIxLTkzZjkwOGJhLWI1NzktNDUzZS04YjJhLTU2MDIyYWZhZDI3NSIsCiJ4LWhjeC1yZXF1ZXN0X2lkIjoiMjZiMTA2MGMtMWU4My00NjAwLTk2MTItZWEzMWUwY2E1MDkxIiwKIngtaGN4LWNvcnJlbGF0aW9uX2lkIjoiNWU5MzRmOTAtMTExZC00ZjBiLWIwMTYtYzIyZDgyMDY3NGUxIiwKIngtaGN4LXRpbWVzdGFtcCI6IjIwMjEtMTAtMjdUMjA6MzU6NTIuNjM2KzA1MzAiLAoieC1oY3gtc3RhdHVzIjoicmVxdWVzdC5pbml0aWF0ZSIsCiJ4LWhjeC13b3JrZmxvd19pZCI6IjVlOTM0ZjkwLTExMWQtNGYwYi1iMDE2LWMyMmQ4MjA2NzRlMiIsCiJ4LWhjeC1kZWJ1Z19mbGFnIjoiSW5mbyIsCiJ4LWhjeC1lcnJvcl9kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCAidHJhY2UiOiAiIn0sCiJ4LWhjeC1kZWJ1Z19kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCJ0cmFjZSI6IiJ9LAoiandzX2hlYWRlciI6eyJ0eXAiOiJKV1QiLCAiYWxnIjoiUlMyNTYifSwKImp3ZV9oZWFkZXIiOnsiYWxnIjoiUlNBLU9BRVAiLCJlbmMiOiJBMjU2R0NNIn0KfQ==.6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.AxY8DCtDaGlsbGljb3RoZQ.KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.Mz-VPPyU4RlcuYv1IwIvzw"}},"description":"All the HCX protocol APIs require the request body to sent in JWE format (as defined in [RFC-7516](https://datatracker.ietf.org/doc/html/rfc7516))."},"Error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}},"StatusResponseObject":{"type":"object","properties":{"sender_code":{"type":"string"},"recipient_code":{"type":"string"},"entity_type":{"type":"string","enum":["coverageeligibility","predetermination","preauth","claim","task","status","payment","insuranceplan"]},"protocol_status":{"type":"string","enum":["request.queued","request.error","request.dispatched"]}}},"StatusSuccessResponse":{"type":"object","properties":{"timestamp":{"type":"string"},"api_call_id":{"type":"string","format":"uuid"},"correlation_id":{"type":"string","format":"uuid"},"result":{"$ref":"#/components/schemas/StatusResponseObject"},"error":{"$ref":"#/components/schemas/Error"}}},"SwaggerResource":{"type":"object","properties":{"name":{"type":"string"},"url":{"type":"string"},"swaggerVersion":{"type":"string"},"location":{"type":"string","deprecated":true}}},"UiConfiguration":{"type":"object","properties":{"deepLinking":{"type":"boolean"},"displayOperationId":{"type":"boolean"},"defaultModelsExpandDepth":{"type":"integer","format":"int32"},"defaultModelExpandDepth":{"type":"integer","format":"int32"},"defaultModelRendering":{"type":"string","enum":["example","model"]},"displayRequestDuration":{"type":"boolean"},"docExpansion":{"type":"string","enum":["none","list","full"]},"filter":{"type":"object"},"maxDisplayedTags":{"type":"integer","format":"int32"},"operationsSorter":{"type":"string","enum":["alpha","method"]},"showExtensions":{"type":"boolean"},"showCommonExtensions":{"type":"boolean"},"tagsSorter":{"type":"string","enum":["alpha"]},"validatorUrl":{"type":"string"},"supportedSubmitMethods":{"type":"array","items":{"type":"string"}},"swaggerBaseUiUrl":{"type":"string"}}},"SecurityConfiguration":{"type":"object","properties":{"apiKey":{"type":"string","deprecated":true},"apiKeyVehicle":{"type":"string","deprecated":true},"apiKeyName":{"type":"string","deprecated":true},"clientId":{"type":"string"},"clientSecret":{"type":"string"},"realm":{"type":"string"},"appName":{"type":"string"},"scopeSeparator":{"type":"string"},"additionalQueryStringParams":{"type":"object","additionalProperties":{"type":"object"}},"useBasicAuthenticationWithAccessCodeGrant":{"type":"boolean"},"enableCsrfSupport":{"type":"boolean"}}}}}} \ No newline at end of file diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/subscriptionhcxservice.json b/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/subscriptionhcxservice.json new file mode 100644 index 000000000..d9f898c21 --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/subscriptionhcxservice.json @@ -0,0 +1 @@ +{"openapi":"3.1.0","info":{"title":"NHCX - Notification APIs","description":"NHCX Subscription Service - Beneficiary Service Provider (BSP) integration","termsOfService":"http://swagger.io/terms/","license":{"name":"Apache 2.0","url":"http://springdoc.org"},"version":"1.0.0"},"servers":[{"url":"/subscriptionhcxservice","description":"Default Server URL"}],"paths":{"/v1/notification/subscribe":{"post":{"tags":["V1.0 APIs - Subscription"],"summary":"Subscribe a beneficiary to NHCX notifications (synchronous)","description":"Receives an encrypted (JWE / RSA-OAEP / A256GCM) subscribe request from a registered BSP. The request body is `{ \"payload\": \"\" }` where the compact JWE carries the NHCX protected headers and the subscribe JSON payload. NHCX decrypts the request with its private key, validates headers and payload, persists the subscription (Last-Linked-Wins per ABHA ID) and returns the subscription state synchronously.","operationId":"subscribe","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JWEPayload"}}},"required":true},"responses":{"200":{"description":"Subscription accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeResponse"}}}},"400":{"description":"Validation failed (invalid headers, malformed JWE, bad ABHA, unknown topic, etc.)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeResponse"}}}},"401":{"description":"Sender not authorized (missing / invalid bearer token, or sender code not in registry)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeResponse"}}}},"403":{"description":"Forbidden - sender code not permitted to subscribe","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeResponse"}}}},"409":{"description":"Duplicate request (same x-hcx-correlation_id already processed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeResponse"}}}},"500":{"description":"Decryption / persistence failure","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/v1/notification/on_subscribe":{"post":{"tags":["notification-api-controller"],"operationId":"onSubscribe","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/NotificationOnSubscribePayload"}}},"required":true},"responses":{"200":{"description":"Subscription accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/SubscribeResponse"}}}},"400":{"description":"Validation failed (invalid headers, malformed JWE, bad ABHA, unknown topic, etc.)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"401":{"description":"Sender not authorized (missing / invalid bearer token, or sender code not in registry)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"403":{"description":"Forbidden - sender code not permitted to subscribe","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"409":{"description":"Duplicate request (same x-hcx-correlation_id already processed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"500":{"description":"Decryption / persistence failure","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}}}}}},"components":{"schemas":{"JWEPayload":{"type":"object","description":"Generic JWE-wrapped payload (compact serialization) per RFC-7516","properties":{"payload":{"type":"string","description":"JWE compact serialization (5 dot-separated base64url segments)"}},"required":["payload"]},"SubscribeResponse":{"type":"object","description":"Response from NHCX subscribe API (or BSP-side persistence acknowledgement)","properties":{"timestamp":{"type":"string"},"api_call_id":{"type":"string","format":"uuid"},"correlation_id":{"type":"string","format":"uuid"},"subscription_id":{"type":"string"},"subscription_status":{"type":"string","description":"active | replaced | expired","example":"active"},"expiry":{"type":"string"},"message":{"type":"string"}}},"HeaderValues":{"type":"object","properties":{"senderid":{"type":"string","description":"This field contains the payer/insurance company id. This id is generated when the hospital/provider register in hcx system through participant creation system.","example":"10000007@hcx"},"receiverid":{"type":"string","description":"This field contains the provider/hospital id. This id is generated when the hospital/provider register in hcx system through participant creation system.","example":"10000007@hcx"},"correlationid":{"type":"string","description":"This field contains the corelation id. This id is used to track the request generated by provider.","example":"ab309340-731c-4d8b-863f-94bb6ba6de58"},"workflowid":{"type":"string"},"source":{"type":"string"},"status":{"type":"string"},"api_caller_id":{"type":"string"},"call_type":{"type":"string"},"usertoken":{"type":"string"}},"required":["correlationid","receiverid","senderid","status"]},"NotificationOnSubscribePayload":{"type":"object","properties":{"request":{"$ref":"#/components/schemas/NotificationOnSubscribeRequest"},"hvalues":{"$ref":"#/components/schemas/HeaderValues"}}},"NotificationOnSubscribeRequest":{"type":"object","properties":{"abhaid":{"type":"string"},"domain_values":{"type":"object","additionalProperties":{"type":"string"}}},"required":["abhaid"]},"Error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}},"StatusResponseObject":{"type":"object","properties":{"sender_code":{"type":"string"},"recipient_code":{"type":"string"},"entity_type":{"type":"string","enum":["coverageeligibility","predetermination","preauthorization","claim","task","payment","communication","subscription","insuranceplan"]},"protocol_status":{"type":"string","enum":["request.queued","request.error","request.dispatched"]}}},"StatusSuccessResponse":{"type":"object","properties":{"timestamp":{"type":"string"},"api_call_id":{"type":"string","format":"uuid"},"correlation_id":{"type":"string","format":"uuid"},"result":{"$ref":"#/components/schemas/StatusResponseObject"},"error":{"$ref":"#/components/schemas/Error"}}}}}} \ No newline at end of file diff --git a/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/taskhcxservice.json b/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/taskhcxservice.json new file mode 100644 index 000000000..53ae831a9 --- /dev/null +++ b/catalogue/openapi/.raw/nhcx-site-2026-09-14/swagger/taskhcxservice.json @@ -0,0 +1 @@ +{"openapi":"3.1.0","info":{"title":"NHCX - Task (Reprocess/cancel) APIs","description":"The National Health Claims Exchange (NHCX) is a digital","termsOfService":"http://swagger.io/terms/","license":{"name":"Apache 2.0","url":"http://springdoc.org"},"version":"1.0.0"},"servers":[{"url":"/taskhcxservice","description":"Default Server URL"}],"paths":{"/v1/task/submit":{"post":{"tags":["V1.0 APIs-Payer side"],"description":"This API is for providers to reporcess/cancel the claims or preauthorisations. For example, a provider can request for reprocessing of the claim incase of rejection or partial approval. Payload for this API has to be created as per the TaskBundle.

The request body for this API should be sent in the form of a JWE token ([RFC-7516](https://datatracker.ietf.org/doc/html/rfc7516)) using the steps defined in [HCX specs](https://hcxsbx.abdm.gov.in/#/technical-specifications). As defined in the specs, JWE should contain the protected headers and the encrypted Task FHIR resource as the domain payload. 1. Protected headers should have the protocol headers as defined in the ProtocolHeader schema definition below. Specifically for this API, the header x-hcx-correlation_id should carry the correlation id of the request for which the status is being requested for. 2. The domain payload should be an encrypted Task FHIR resource. The Task resource should have the reference to the entity for which the task is being requested for in the \"**basedOn**\" element. This reference object should contain the sender's reference id of the entity. ","operationId":"hcxTaskPost","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JWEPayload"}}},"required":true},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"400":{"description":"Request Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"404":{"description":"Requested resource was not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/v1/task/on_submit":{"post":{"tags":["V1.0 APIs-Provider side"],"description":"This is the callback API to return the response for task requests such as reprocess/cancel. Payload for this API has to be created as per the TaskBundle ClaimResponseBundle.

Domain Payload for this API has to an encrypted Task resource containing the Task.output.type as ClaimResponse resource reference to the entity sent by the sender in the original request.","operationId":"hcxOnTaskPost","requestBody":{"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/JWEPayloadResponse"},{"$ref":"#/components/schemas/ProtocolResponse"}]}}},"required":true},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"400":{"description":"Request Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"404":{"description":"Requested resource was not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/internal/v1/task/submit":{"post":{"tags":["V1.0 APIs-Payer side"],"description":"This API is for providers to reporcess/cancel the claims or preauthorisations. For example, a provider can request for reprocessing of the claim incase of rejection or partial approval. Payload for this API has to be created as per the TaskBundle.

The request body for this API should be sent in the form of a JWE token ([RFC-7516](https://datatracker.ietf.org/doc/html/rfc7516)) using the steps defined in [HCX specs](https://hcxsbx.abdm.gov.in/#/technical-specifications). As defined in the specs, JWE should contain the protected headers and the encrypted Task FHIR resource as the domain payload. 1. Protected headers should have the protocol headers as defined in the ProtocolHeader schema definition below. Specifically for this API, the header x-hcx-correlation_id should carry the correlation id of the request for which the status is being requested for. 2. The domain payload should be an encrypted Task FHIR resource. The Task resource should have the reference to the entity for which the task is being requested for in the \"**basedOn**\" element. This reference object should contain the sender's reference id of the entity. ","operationId":"hcxTaskPostInternal","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/JWEPayload"}}},"required":true},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"400":{"description":"Request Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"404":{"description":"Requested resource was not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}}},"security":[{"bearer_auth":[]}]}},"/internal/v1/task/on_submit":{"post":{"tags":["V1.0 APIs-Provider side"],"description":"This is the callback API to return the response for task requests such as reprocess/cancel. Payload for this API has to be created as per the TaskBundle ClaimResponseBundle.

Domain Payload for this API has to an encrypted Task resource containing the Task.output.type as ClaimResponse resource reference to the entity sent by the sender in the original request.","operationId":"hcxOnTaskPostInternal","requestBody":{"content":{"application/json":{"schema":{"oneOf":[{"$ref":"#/components/schemas/JWEPayloadResponse"},{"$ref":"#/components/schemas/ProtocolResponse"}]}}},"required":true},"responses":{"202":{"description":"Accepted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"400":{"description":"Request Validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"404":{"description":"Requested resource was not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}},"500":{"description":"Downstream systems down/unhandled exceptions.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/StatusSuccessResponse"}}}}},"security":[{"bearer_auth":[]}]}}},"components":{"schemas":{"JWEPayload":{"type":"object","description":"All the HCX protocol APIs require the request body to sent in JWE format (as defined in [RFC-7516](https://datatracker.ietf.org/doc/html/rfc7516)).","properties":{"payload":{"type":"string","description":"The paylod should be a JWE token containing the following elements. 1. Protected headers (**protected**) - A set of attributes that provide transport, security, message integrity and summary information about the message being exchanged. Refer to the ProtectedHeader schema definition below for details. 2. JWE element (**encrypted_key**) - Content Encryption Key. Refer to the EncryptedKey schema definition below for details. 3. JWE element (**iv**) - Initialisation Vector for the algorithm. Refer to the InitializationVector schema definition below for details. 4. JWE element (**aad**) - Additional authentication data. Refer to AAD schema definition below for details. 5. Encrypted Payload (**ciphertext**) - Payload containing the relevant domain entity (eObject) as prescribed for the use case by the domain specifications. This needs to be encrypted so that HCX cannot read this. Refer to CipherText schema definition below for more details. 6. Authentication tag (**tag**) - Digital signature on the protected header and the payload of the message to ensure its integrity. Refer to AuthenticationTag schema definition below for more details. Detailed steps on how to construct the JWE token are provided in this [section](https://docs.pmjay.gov.in/hcx-specifications/hcx-technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity#message-encryption) of the HCX specifications.","example":"eyJlbmMiOiJBMjU2R0NNIiwKImFsZyI6IlJTQS1PQUVQIiwKIngtaGN4LXNlbmRlcl9jb2RlIjoiMS00ZGMzZTA4OC1hMzEzLTQ0YWItYWZhMS0wMjIyOTU5Y2I3NWIiLAoieC1oY3gtcmVjaXBpZW50X2NvZGUiOiIxLTkzZjkwOGJhLWI1NzktNDUzZS04YjJhLTU2MDIyYWZhZDI3NSIsCiJ4LWhjeC1yZXF1ZXN0X2lkIjoiMjZiMTA2MGMtMWU4My00NjAwLTk2MTItZWEzMWUwY2E1MDkxIiwKIngtaGN4LWNvcnJlbGF0aW9uX2lkIjoiNWU5MzRmOTAtMTExZC00ZjBiLWIwMTYtYzIyZDgyMDY3NGUxIiwKIngtaGN4LXRpbWVzdGFtcCI6IjIwMjEtMTAtMjdUMjA6MzU6NTIuNjM2KzA1MzAiLAoieC1oY3gtc3RhdHVzIjoicmVxdWVzdC5pbml0aWF0ZSIsCiJ4LWhjeC13b3JrZmxvd19pZCI6IjVlOTM0ZjkwLTExMWQtNGYwYi1iMDE2LWMyMmQ4MjA2NzRlMiIsCiJ4LWhjeC1kZWJ1Z19mbGFnIjoiSW5mbyIsCiJ4LWhjeC1lcnJvcl9kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCAidHJhY2UiOiAiIn0sCiJ4LWhjeC1kZWJ1Z19kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCJ0cmFjZSI6IiJ9LAoiandzX2hlYWRlciI6eyJ0eXAiOiJKV1QiLCAiYWxnIjoiUlMyNTYifSwKImp3ZV9oZWFkZXIiOnsiYWxnIjoiUlNBLU9BRVAiLCJlbmMiOiJBMjU2R0NNIn0KfQ==.6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.AxY8DCtDaGlsbGljb3RoZQ.KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.Mz-VPPyU4RlcuYv1IwIvzw"}},"required":["payload"]},"Error":{"type":"object","properties":{"code":{"type":"string"},"message":{"type":"string"}}},"StatusResponseObject":{"type":"object","properties":{"sender_code":{"type":"string"},"recipient_code":{"type":"string"},"entity_type":{"type":"string","enum":["coverageeligibility","predetermination","preauth","claim","task","payment","insuranceplan"]},"protocol_status":{"type":"string","enum":["request.queued","request.error","request.dispatched"]}}},"StatusSuccessResponse":{"type":"object","properties":{"timestamp":{"type":"string"},"api_call_id":{"type":"string","format":"uuid"},"correlation_id":{"type":"string","format":"uuid"},"result":{"$ref":"#/components/schemas/StatusResponseObject"},"error":{"$ref":"#/components/schemas/Error"}}},"DomainHeaders":{"type":"object","description":"JSON object containing a map of domain-specific header values as proposed in domain data specifications. E.g. For claims use cases, domain specs may decide to populate the total claimed amount, list of diagnostics/procedures.","properties":{"use_case_name":{"type":"string"},"amt_processed":{"type":"string"}}},"HcxOnTaskBody":{"discriminator":{"propertyName":"type"},"properties":{"type":{"type":"string"}},"required":["type"]},"JWEPayloadResponse":{"allOf":[{"$ref":"#/components/schemas/HcxOnTaskBody"},{"type":"object","properties":{"payload":{"type":"string","description":"The paylod should be a JWE token containing the following elements. 1. Protected headers (**protected**) - A set of attributes that provide transport, security, message integrity and summary information about the message being exchanged. Refer to the ProtectedHeader schema definition below for details. 2. JWE element (**encrypted_key**) - Content Encryption Key. Refer to the EncryptedKey schema definition below for details. 3. JWE element (**iv**) - Initialisation Vector for the algorithm. Refer to the InitializationVector schema definition below for details. 4. JWE element (**aad**) - Additional authentication data. Refer to AAD schema definition below for details. 5. Encrypted Payload (**ciphertext**) - Payload containing the relevant domain entity (eObject) as prescribed for the use case by the domain specifications. This needs to be encrypted so that HCX cannot read this. Refer to CipherText schema definition below for more details. 6. Authentication tag (**tag**) - Digital signature on the protected header and the payload of the message to ensure its integrity. Refer to AuthenticationTag schema definition below for more details. Detailed steps on how to construct the JWE token are provided in this [section](https://docs.pmjay.gov.in/hcx-specifications/hcx-technical-specifications/open-protocol/data-security-and-privacy/message-security-and-integrity#message-encryption) of the HCX specifications.","example":"eyJlbmMiOiJBMjU2R0NNIiwKImFsZyI6IlJTQS1PQUVQIiwKIngtaGN4LXNlbmRlcl9jb2RlIjoiMS00ZGMzZTA4OC1hMzEzLTQ0YWItYWZhMS0wMjIyOTU5Y2I3NWIiLAoieC1oY3gtcmVjaXBpZW50X2NvZGUiOiIxLTkzZjkwOGJhLWI1NzktNDUzZS04YjJhLTU2MDIyYWZhZDI3NSIsCiJ4LWhjeC1yZXF1ZXN0X2lkIjoiMjZiMTA2MGMtMWU4My00NjAwLTk2MTItZWEzMWUwY2E1MDkxIiwKIngtaGN4LWNvcnJlbGF0aW9uX2lkIjoiNWU5MzRmOTAtMTExZC00ZjBiLWIwMTYtYzIyZDgyMDY3NGUxIiwKIngtaGN4LXRpbWVzdGFtcCI6IjIwMjEtMTAtMjdUMjA6MzU6NTIuNjM2KzA1MzAiLAoieC1oY3gtc3RhdHVzIjoicmVxdWVzdC5pbml0aWF0ZSIsCiJ4LWhjeC13b3JrZmxvd19pZCI6IjVlOTM0ZjkwLTExMWQtNGYwYi1iMDE2LWMyMmQ4MjA2NzRlMiIsCiJ4LWhjeC1kZWJ1Z19mbGFnIjoiSW5mbyIsCiJ4LWhjeC1lcnJvcl9kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCAidHJhY2UiOiAiIn0sCiJ4LWhjeC1kZWJ1Z19kZXRhaWxzIjp7ImVycm9yLmNvZGUiOiAiYmFkLmlucHV0IiwgImVycm9yLm1lc3NhZ2UiOiAiUHJvdmlkZXIgY29kZSBub3QgZm91bmQiLCJ0cmFjZSI6IiJ9LAoiandzX2hlYWRlciI6eyJ0eXAiOiJKV1QiLCAiYWxnIjoiUlMyNTYifSwKImp3ZV9oZWFkZXIiOnsiYWxnIjoiUlNBLU9BRVAiLCJlbmMiOiJBMjU2R0NNIn0KfQ==.6KB707dM9YTIgHtLvtgWQ8mKwboJW3of9locizkDTHzBC2IlrT1oOQ.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.AxY8DCtDaGlsbGljb3RoZQ.KDlTtXchhZTGufMYmOYGS4HffxPSUrfmqCHXaI9wOGY.Mz-VPPyU4RlcuYv1IwIvzw"}}}],"description":"All the HCX protocol APIs require the request body to sent in JWE format (as defined in [RFC-7516](https://datatracker.ietf.org/doc/html/rfc7516)).","required":["payload"]},"ProtocolHeaderXhcxdebugDetails":{"type":"object","description":"Expected to be used for providing details of the status. Will be specially useful in debugging scenarios.","properties":{"code":{"type":"string"},"message":{"type":"string"},"trace":{"type":"string"}}},"ProtocolHeaderXhcxerrorDetails":{"type":"object","description":"Expected to be used for providing details of the status. Will be specially useful in scenarios where operational status indicates irrecoverable error.","properties":{"code":{"type":"string"},"message":{"type":"string"},"trace":{"type":"string"}}},"ProtocolResponse":{"allOf":[{"$ref":"#/components/schemas/HcxOnTaskBody"},{"type":"object","properties":{"x-hcx-sender_code":{"type":"string","description":"Registry code of the sender (e.g. provider or payer)","example":"PROVIDER01@HCX01"},"x-hcx-recipient_code":{"type":"string","description":"Registry code of the recipient (e.g. provider or payer)","example":"PAYOR01@HCX01"},"x-hcx-api_call_id":{"type":"string","format":"uuid","description":"Sender generated unique id for each originating request. All senders (providers & payors) must generate and set a unique value to the x-hcx-api_call_id protocol header in all the API calls to the HCX gateway."},"x-hcx-correlation_id":{"type":"string","format":"uuid","description":"Unique id for all messages (requests & responses) that are involved in processing of one cycle (like coverage eligibility, pre-auth, claim, or payment notice cycle). The participant system sending the originating request of the cycle must set the x-hcx-correlation_id in the initial API call and the HCX gateway shall forward the same correlation id to the recipient of the request. The recipient must set the same correlation id in the response API call and in other API calls related to the original request (e.g. communication request, forward/redirect requests). And the same correlation id must be sent in all subsequent API calls (related to the same cycle). In case of status API call, this header should have the correlation id of the request for which the status is being requested for."},"x-hcx-workflow_id":{"type":"string","description":"Unique id for one complete workflow that spans over a series of cycles and message exchanges within the context of an admission/case. This is an optional header that can be set by providers to the same value for all requests (coverage eligibility check, preauth, claim, etc) related to a single admission/case. And when the workflow_id is sent by the originating provider, all other participant systems (payors) must set the same workflow id in all API calls (responses, forwards/redirects, payment notices, etc) related to the workflow."},"x-hcx-timestamp":{"type":"string","description":"Unix timestamp when the request is sent.","example":1629057611000},"x-hcx-debug_flag":{"type":"string","description":"Request to the server to include debug information. Useful in the time of integration testing and prod debugging. However server(s) may choose to ignore this flag based on their policy.","enum":["Error","Info","Debug"]},"x-hcx-status":{"type":"string","description":"Operational status of the message. Depending on the leg of the message, it would be one of the defined values in the enum.","enum":["request.initiated","request.processed","request.queued","request.error","request.stopped","request.dispatched","response.complete","response.error","response.partial","response.redirect"]},"x-hcx-redirect_to":{"type":"string"},"x-hcx-error_details":{"$ref":"#/components/schemas/ProtocolHeaderXhcxerrorDetails"},"x-hcx-debug_details":{"$ref":"#/components/schemas/ProtocolHeaderXhcxdebugDetails"},"x-hcx-domain-header":{"$ref":"#/components/schemas/DomainHeaders"},"x-hcx-entity-type":{"type":"string","enum":["coverageeligibility","predetermination","preauth","claim","task","payment","insuranceplan"]},"x-hcx-ben-abha-id":{"type":"string"}}}],"description":"Object to be returned as payload of the callback API (on_* APIs) in case there are any protocol related errors while processing the request or send a redirection instruction to the original sender of the request.","required":["x-hcx-api_call_id","x-hcx-correlation_id","x-hcx-recipient_code","x-hcx-sender_code","x-hcx-timestamp"]}}}} \ No newline at end of file diff --git a/catalogue/openapi/CONVENTIONS.md b/catalogue/openapi/CONVENTIONS.md index 8c10b6f26..09dd17215 100644 --- a/catalogue/openapi/CONVENTIONS.md +++ b/catalogue/openapi/CONVENTIONS.md @@ -13,6 +13,32 @@ without three different shapes of truth. | `hiecm-m2.yaml` | Care context linking and HIP data sharing | `dev.abdm.gov.in` | | `hiecm-m3.yaml` | Consent and HIU data fetch | `dev.abdm.gov.in` | | `hiecm-m4.yaml` | HPR and HFR registration. Phase 2, nothing written | `apihspsbx.abdm.gov.in` | +| `hiecm-p1.yaml`, `hiecm-p2.yaml`, `hiecm-p3.yaml` | The PHR modules P1 to P3 | `phrsbx.abdm.gov.in` | +| `hiecm-phr-services.yaml` | PHR application services | `phrsbx.abdm.gov.in` | + +The NHCX files under `nhcx/v1/` are one per module of the exchange, and are +not written in this repository. The NHCX package writes them with +`make ekadocs` (`system/build-ekadocs.mjs`) from its Bruno collection, and +replaces them on every port, so a change goes into the package and is ported +again. The port sets `x-abdm-atom` on every operation and webhook whose method +and path an NHCX endpoint or callback atom names in its title. + +| File | Module | Gateway host | +|---|---|---| +| `nhcx-session.yaml` | Session token, the ABDM gateway's | `dev.abdm.gov.in` | +| `nhcx-registry.yaml` | Participant registry: search, details, certificates, policies | `apisbx.abdm.gov.in` | +| `nhcx-onboarding.yaml` | Creating and validating a participant | `apisbx.abdm.gov.in` | +| `nhcx-eligibility.yaml` | Coverage eligibility | `apisbx.abdm.gov.in` | +| `nhcx-insurance-plan.yaml` | Insurance plan | `apisbx.abdm.gov.in` | +| `nhcx-preauth.yaml` | Pre-authorisation | `apisbx.abdm.gov.in` | +| `nhcx-predetermination.yaml` | Predetermination | `apisbx.abdm.gov.in` | +| `nhcx-claim.yaml` | Claim | `apisbx.abdm.gov.in` | +| `nhcx-payment-notice.yaml` | Payment notice | `apisbx.abdm.gov.in` | +| `nhcx-communication.yaml` | Communication | `apisbx.abdm.gov.in` | +| `nhcx-status.yaml` | Status and search | `apisbx.abdm.gov.in` | +| `nhcx-other.yaml` | Task, notification subscription, the error callback | `apisbx.abdm.gov.in` | +| `nhcx-biometric.yaml` | ABHA biometric authentication | `apisbx.abdm.gov.in` | +| `nhcx-adjudicator.yaml` | The PMJAY payer service and the sandbox dummy payer | `apisbx.abdm.gov.in` | Every file is self-contained. No `$ref` reaches across files, because the site serves each spec as a static file and an unresolvable reference renders @@ -98,7 +124,7 @@ specification must carry. | Extension | Where | What it carries | |---|---|---| | `x-abdm-gateway` | `info` | `hiecm`, `uhi`, `nhcx` or `shared`. All four are accepted. | -| `x-abdm-module` | `info` | `gateway`, `M1`, `M2`, `M3`, `M4` | +| `x-abdm-module` | `info` | HIE-CM: `gateway`, `M1`, `M2`, `M3`, `M4`. NHCX: the module id, as `claim` or `registry` | | `x-abdm-phase` | `info` | `1` for what ships now, `2` for declared but unwritten | | `x-abdm-roles` | `info` | Which integrator roles call this module | | `x-abdm-sources` | root | Where the content came from, with fetch status | diff --git a/catalogue/openapi/corrections/2026-09-15-nhcx-ingest.md b/catalogue/openapi/corrections/2026-09-15-nhcx-ingest.md new file mode 100644 index 000000000..abea38267 --- /dev/null +++ b/catalogue/openapi/corrections/2026-09-15-nhcx-ingest.md @@ -0,0 +1,93 @@ +# NHCX ingest, 14 and 15 September 2026 + +The sources behind the NHCX atoms and specifications, where each is stored, +and every change made to what the Catalogue recorded about them. Nothing was +fixed silently. + +## The sandbox site snapshot + +`catalogue/openapi/.raw/nhcx-site-2026-09-14/` holds what the NHCX sandbox +site, `https://hcxsbx.abdm.gov.in`, listed on 14 September 2026, stored +untouched. + +The site is a JavaScript application, so its listing is not a file. What was +read is the site's own document sheet, `NHCX-Website_DocumentDetails.xlsx - +Sheet2.csv`. The bundle the site served that day, `main.js`, is recorded with +its sha256 (`f2ff7f475af0...`), so a later fetch can tell whether the listing +itself changed. + +`manifest.json` has one entry per stored item: the file, its title and sheet +row, the page that lists it, the download URL, the byte count, the fetch date +and the sha256. Its 103 entries describe 81 files. The other 22 entries are +members of `hmisdocuments/Sample FHIR bundles.zip`, each recorded against the +archive. + +| Folder | Files | What it holds | +| --- | --- | --- | +| `documents/` | 27 | The general documents: use cases, standards, authentication, the request and response workbooks, the error code sheets, the FAQs and the Postman collections | +| `hmisdocuments/` | 12 | The PMJAY HMIS documents: the integration guide, biometric authentication, the test cases and the sample FHIR bundles | +| `swagger/` | 11 | The live specification of each exchange service, as its `/api-docs` served it | +| `pages/` | 28 | The site's own pages, as text | +| `media/` | 2 | The provider guide and the brochure | +| `not-on-site/` | 1 | The payer service workflow guide, which the site does not list | + +The snapshot was scanned for credentials before it was stored. The six +Postman collections carry no client secret or password value. `client_secret` +appears in two pages, as the name of a field. + +542 of the 543 NHCX atoms cite at least one file here, with its hash. The +remaining one is `nhcx.error.err-pyr-clm-007`, below. + +## C1: citations of the ported specifications removed + +137 source entries, in 129 atoms, cited a file under +`catalogue/openapi/nhcx/v1/` with a hash. Those files are not a source. The +NHCX package writes them with `make ekadocs` and replaces them on every port, +so each hash matched the committed port and would stop matching at the next +one without anything upstream having changed. + +Every one of the 129 atoms also cites, from the snapshot above, the file its +facts come from. The 137 entries were removed. Nothing else in any atom +changed. + +## C2: the ERR-PYR-CLM-007 source stored + +`nhcx.error.err-pyr-clm-007` records a code that the package's `nhcx-error.yaml` +files under `space: observed`, and that appears on none of the error sheets in +the snapshot. No response carrying the code is stored in this repository. The +atom's only source was `package/nhcx-error.yaml`, a path outside this +repository, so nothing could check it. + +The file is now stored at +`catalogue/openapi/.raw/nhcx-package-2026-09-15/nhcx-error.yaml`, byte for +byte, with the sha256 the atom already recorded (`d24ac927ed4d...`). The atom +cites that path. + +## The ported specifications + +`catalogue/openapi/nhcx/v1/` is not ingested here. The NHCX package writes one +file per module from its Bruno collection, `baseurl.yaml` and +`nhcx-error.yaml` with `make ekadocs` (`system/build-ekadocs.mjs`), and +replaces the folder on every port. Change the package and port again rather +than editing a file. + +Each file's `x-abdm-sources` names those package files with their hashes. They +are not stored under `.raw/`, so `npm run lint:sources` lists them as MISSING. +That is a warning, and expected. + +From this port on, every operation and webhook whose method and path an NHCX +endpoint or callback atom names in its title carries `x-abdm-atom`, so its +generated page joins its atom. The port joined 71: all 50 endpoint atoms, and +21 of the 22 callback atoms. `nhcx.callback.notification-delivery` names no +path, so it joins nothing. + +32 of the 103 operations and webhooks carry no `x-abdm-atom`, because no atom +documents them: + +- 14 internal twins under `/internal/v1/`, which the NHCX adapter deployment uses. +- 5 of the services' own documentation routes (`/v2/api-docs`, `/v3/api-docs`, `/swagger-resources`). +- 13 calls with no atom yet: `/v2/participant/hementity/create`, + `/v1/notification/on_subscribe`, `/v1/delete`, the `/v1/error` call itself, + `/fetch/certs/path`, `/get/linked/registry/mst`, the v2 ABHA policy link + `init` and `validate`, `/update/abhanumber`, the three `/product/` calls and + `/participant/getProductIdName`. diff --git a/catalogue/openapi/nhcx/v1/README.md b/catalogue/openapi/nhcx/v1/README.md index 0b8ad963d..eeddde355 100644 --- a/catalogue/openapi/nhcx/v1/README.md +++ b/catalogue/openapi/nhcx/v1/README.md @@ -1,24 +1,6 @@ # NHCX V1 specifications -One OpenAPI 3.1 YAML per module. Dropping a file here generates its endpoint -pages under `site/docs/nhcx/v1/api/` and publishes an interactive reference -at `/reference/`. - -Name the module in the info block: - -```yaml -info: - x-portal: - module: m1 # folder name under api/ - label: M1 ABHA identity - position: 2 # order among this gateway's modules -``` - -See `../../CONVENTIONS.md` for how the specs are written. - -Two rules the build enforces: - -- The file name must be unique across the whole `openapi/` tree, because it is - the served path and the Scalar route. Prefix it with the gateway. -- Generated pages carry `generated: true`. Never hand-write a page at a - generated name; the build stops rather than overwrite one. +One OpenAPI 3.1 file per folder of the NHCX package's Bruno collection, written by the +package's `make ekadocs`. Callbacks are `webhooks`, error codes are `x-abdm-errors` blocks. +Change the package and port again rather than editing these files; see `../../CONVENTIONS.md` +for the rules they follow. diff --git a/catalogue/openapi/nhcx/v1/nhcx-adjudicator.yaml b/catalogue/openapi/nhcx/v1/nhcx-adjudicator.yaml new file mode 100644 index 000000000..74044831c --- /dev/null +++ b/catalogue/openapi/nhcx/v1/nhcx-adjudicator.yaml @@ -0,0 +1,402 @@ +# NHCX PMJAY adjudicator, from the NHCX package's Bruno folder apis/12-adjudicator. +# +# Written by the package's system/build-ekadocs.mjs (make ekadocs); change the .bru +# requests there and port again rather than editing this file. +# +# Rules this file follows: catalogue/openapi/CONVENTIONS.md +openapi: 3.1.1 +info: + x-portal: + module: adjudicator + label: PMJAY adjudicator + position: 12 + title: NHCX PMJAY adjudicator + summary: A PMJAY case is not decided over NHCX. + description: |- + The PMJAY adjudicator calls on the National Health Claims Exchange (NHCX): 4 operations. + + A PMJAY case is not decided over NHCX. + + Guides that use these calls: [Receiving a callback](/docs/nhcx/v1/getting-started/receiving-a-callback), [Get your sandbox credentials](/docs/nhcx/v1/getting-started/get-your-sandbox-credentials), [PMJAY sandbox run](/docs/nhcx/v1/roles/provider/pmjay-sandbox-run), [PMJAY adjudication APIs](/docs/nhcx/v1/roles/provider/pmjay-adjudication-apis). + + Production address for the PMJAY payer service, role lookup: not published. Confirm at onboarding. + + Production address for the PMJAY payer service, act on a case: not published. Confirm at onboarding. + + Production address for the Dummy payer: A sandbox test hook only. + version: nhcx-v1 + license: + name: MIT + identifier: MIT + contact: + name: NHCX sandbox + url: https://hcxsbx.abdm.gov.in + x-abdm-gateway: nhcx + x-abdm-module: adjudicator + x-abdm-phase: 1 + x-abdm-roles: + - provider +x-abdm-sources: + - file: nhcx-package/apis/12-adjudicator + role: upstream + hash: sha256:cf374ac235b2e017924e723b2904d8305c73a0d0c30d252edce5b09f713e80c0 + note: The package's Bruno collection, one request per operation. + - file: nhcx-package/baseurl.yaml + role: upstream + hash: sha256:88515b7b29c6b349a131e016c80774436ea16a29738db743b4cc3a24cbd42453 + note: The sandbox and production hosts. +servers: + - url: https://apisbx.abdm.gov.in/pmjay/sbxhcx/dummyhcxpayer + description: Sandbox, Dummy payer. +tags: + - name: PMJAY adjudicator + description: A PMJAY case is not decided over NHCX. +security: + - bearerAuth: [] +paths: + /pmjay/sbxhcx/nhcxpayerservice/v1/get/user-role: + post: + operationId: adjudicator_adjudicator_role + x-abdm-atom: nhcx.endpoint.payer-service-get-user-role + x-abdm-use-case: PMJAY adjudicator + tags: + - PMJAY adjudicator + summary: "Adjudicator: role for a case" + description: |- + Asks the NHCX Payer Service which role in the State Health Agency's Transaction Management System holds a PMJAY case, and so which actions may be taken on it next. + + ### Business purpose + + A PMJAY case is not decided over NHCX. The exchange carries the submission to the scheme and the verdict back, but the decision is taken in the SHA's own system, by a named role, on that system's schedule. This call is how an integrator reads that queue. It is also the only way to see where a PMJAY case stands, because a status `Task` sent to the scheme over NHCX is refused, first with `PAYR-1018` and then with `PAYR-1008`. + + ### When to use + + Before every call to `Adjudicator: act on a case`, because the role that answers is the only one whose action names are legal, and whenever a PMJAY case has gone quiet. The service moves cases on its own schedule, so read the role again rather than assuming the next step. + + ### Preconditions + + - `caseid` is the scheme's case ID, the digits at the end of the case reference the payer issues, not the hospital's claim number. The sandbox hands it out inside the `PAYR-1238` refusal of a later request for the same beneficiary, and in the payer's acknowledgement and status answers once a request is accepted. + - `payerid` is the scheme payer's code. + - An ordinary ABDM session token on `bearer_auth`, with `Content-Type` and `Accept` set to `application/json`. + + ### Postconditions + + The service answers with the role that holds the case in `currentuserrole`, and `errormessage` empty. Once a case is decided, the lookup answers with no role at all. Asked about the hospital's own number, it answers `No Data found with the caseid . Please use the current active case id.` + + ### Common mistakes + + - Sending the hospital's claim number as `caseid`. + - Acting on the case without reading the role first, and being refused because it has moved. + - Reading a pre-authorisation role on a claim as an error. `PPD-Trust` while you are asking about a claim means the case has not yet left the pre-authorisation queue. + - Expecting a status API over NHCX for a PMJAY case. + + ### Best practices + + - Store the scheme's case ID beside your own claim number the moment it appears. + - Read the role before every action, and again after it. + - Expect this lookup and the action call to sit on different hosts. That is how the service is deployed, not a documentation error. + + ### Related scenario + + A hospital has raised a pre-authorisation that sits at `request.initiated`. It takes the case ID from the payer's acknowledgement and posts it here with the payer code. The answer is `PPD-Trust`, so it approves the case as that role with `Adjudicator: act on a case`. After the claim is raised it reads the role again at every step, through `CEX-Trust`, `CPD-Trust`, `ACO-Trust` and `SHA-Trust`, until the lookup answers with no role and the verdict arrives on the claim's own callback. + + ### Specification + + Chapter [PMJAY adjudication APIs](/docs/nhcx/v1/roles/provider/pmjay-adjudication-apis) of the NHCX integration specification. + servers: + - url: https://apisbx.abdm.gov.in + description: Sandbox, PMJAY payer service, role lookup. + parameters: + - $ref: "#/components/parameters/BearerAuth" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + caseid: + type: string + payerid: + type: string + example: + caseid: + payerid: + responses: + "200": + description: The service answers with the role that holds the case in `currentuserrole`, and `errormessage` empty. + content: + application/json: + schema: + type: object + properties: + currentuserrole: + type: string + errormessage: {} + example: + currentuserrole: PPD-Trust + errormessage: null + /pmjay/hcx/nhcxpayerservice/wrapper/process/case: + post: + operationId: adjudicator_adjudicator_process + x-abdm-atom: nhcx.endpoint.payer-service-process-case + x-abdm-use-case: PMJAY adjudicator + tags: + - PMJAY adjudicator + summary: "Adjudicator: act on a case" + description: |- + Approves, rejects, queries or forwards a PMJAY case in the State Health Agency's Transaction Management System, as the role that currently holds it. + + ### Business purpose + + This is the action half of the NHCX Payer Service. A PMJAY case sits at `request.initiated` until a role acts on it here, so in the sandbox this call is what makes a case move. A scheme payer building its own side can copy the shape: the exchange carries messages, the queue decides cases, and a case ID the payer issues joins the two. + + ### When to use + + After `Adjudicator: role for a case` has named the role that holds the case, with the action spelled exactly as that role takes it: + + - `PPD-Trust`, pre-authorisation: `Approve`, `Reject`, `Query`, with `usecase` `PREAUTH`. + - `CEX-Trust`, first claim desk: `Forward`, with `usecase` `CLAIM`. + - `CPD-Trust`, second claim desk: `cpdApprove`, `cpdReject`, `Pending`, with `usecase` `CLAIM`. + - Medical Audit Committee: `Approve`, `Reject`, `iQuery`, with `usecase` `Medical Audit Committee`. + - `ACO-Trust` and `SHA-Trust`: `Approve`, `Reject`, `Pending`, with `usecase` `CLAIM`. + - Claim Review Committee: `Approve`, `Reject`, `Pending`, with `usecase` `Claim Review Committee`. + + ### Preconditions + + - `casenumber` is the scheme's case ID, not the hospital's claim number. + - `action` is spelled exactly as the holding role takes it. It is case-sensitive. + - `receivercode` is the payer's registry ID and `sendercode` the provider's participant code, both without the `@hcx` suffix. + - `memberid` names the beneficiary, and `remarks` is free text the desk records. + - `correlationid` is a fresh UUID for every call. + - An ordinary ABDM session token on `bearer_auth`. + + ### Postconditions + + Acting on the case makes the scheme issue its verdict, which reaches the provider over NHCX as an ordinary `ClaimResponse` on the original request's correlation ID. The desk call and that callback are two halves of one step, correlated by the case rather than by this call's own correlation ID. An action refused for the current role means the role has moved, or was never what you assumed. + + ### Common mistakes + + - Sending `Approve` to `CPD-Trust`, which takes `cpdApprove` and `cpdReject`. + - Sending `CLAIM` as the `usecase` at either committee, which takes its full name with spaces. + - Assuming a case walks all six claim roles. On the recorded sandbox run neither committee held the case. + - Reusing a correlation ID across desk calls. + - Raising a second request on a case while the first is still queued, which the sandbox refused with `PAYR-1322`. + + ### Best practices + + - Read the role immediately before every action. + - Retry shortly on `Event Meta Log not found for correlationId`, which means the exchange has not finished delivering the request, and on `Case not found for caseId`, which means the case is mid-filing. + - Hold both threads in a test harness: this call, and the callback it causes. + - Report the scheme's pace rather than asserting it. An enhancement may be answered `queued` again and decided minutes later. + + ### Related scenario + + On the recorded sandbox run the pre-authorisation was approved as `PPD-Trust` with `Approve` and `usecase` `PREAUTH`. After the claim was raised it was forwarded by `CEX-Trust`, approved by `CPD-Trust` as `cpdApprove`, then by `ACO-Trust` and `SHA-Trust`, each time after reading the role again and with a new correlation ID. The role lookup then answered with no role, and the approval arrived on the claim's own callback. + + ### Specification + + Chapter [PMJAY adjudication APIs](/docs/nhcx/v1/roles/provider/pmjay-adjudication-apis) of the NHCX integration specification. + servers: + - url: https://apisbeta.nha.gov.in + description: Sandbox, PMJAY payer service, act on a case. + parameters: + - $ref: "#/components/parameters/BearerAuth" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + casenumber: + type: string + action: + type: string + receivercode: + type: string + usecase: + type: string + correlationid: + type: string + sendercode: + type: string + memberid: + type: string + remarks: + type: string + example: + casenumber: + action: Approve + receivercode: + usecase: PREAUTH + correlationid: + sendercode: + memberid: + remarks: ok + responses: + "200": + description: Acting on the case makes the scheme issue its verdict, which reaches the provider over NHCX as an ordinary `ClaimResponse` on the original request's correlation ID. + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + example: + status: success + message: Case processed + /process/request: + post: + operationId: adjudicator_dummy_payer_process_request + x-abdm-atom: nhcx.endpoint.dummy-payer-process-request + x-abdm-use-case: PMJAY adjudicator + tags: + - PMJAY adjudicator + summary: Dummy payer, act on a request + description: |- + Makes the sandbox dummy payer, participant `1000003538@hcx`, approve, reject or query a pre-authorisation or claim you have submitted, by correlation ID. + + ### Business purpose + + The sandbox hosts a payer that answers back, and this hook decides what it answers. It closes the loop on the first message a new integration sends. Whichever answer comes back proves the token works, the participant record is live, the exchange can reach the provider's address, the dummy payer could open the message, and the provider could read its reply. + + ### When to use + + Sandbox testing only, after submitting a pre-authorisation or claim addressed to the dummy payer. `action` is `Approve`, `Reject` or `Query`. `method` is `Preauth` or `Claim`. `correlationId` is the correlation ID of the request you sent. + + ### Preconditions + + - A pre-authorisation or claim has been sent to the dummy payer, `1000003538@hcx`, and you hold its correlation ID. + - Your callback address is registered, reachable by the exchange, and answers 202 within 30 seconds. + - An ordinary ABDM session token on `bearer_auth`. + + ### Postconditions + + The answer arrives on your callback for the request's family, `/v1/preauth/on_submit` for a pre-authorisation, as a sealed `ClaimResponse` or as a `ProtocolResponse` carrying a refusal, on the correlation ID you sent. A `Query` makes the dummy payer raise a communication request instead, which you answer on `/v1/communication/on_request` before the decision comes back on `on_submit`. + + ### Common mistakes + + - Passing the correlation ID of a request that was not addressed to the dummy payer. + - Waiting for the decision after a `Query` without answering the communication request first. + - Treating a refusal of the empty smoke-test bundle as a failure. The dummy payer rejects it because there is no `Claim` inside, and that rejection is the expected answer. + + ### Best practices + + - Test all three outcomes of each flow, not only approval. + - Make the callback handler idempotent, since the exchange retries a missed receipt. + - Keep this hook out of production code paths. It exists only in the sandbox. + + ### Related scenario + + A new provider integration sends the empty bundle from its smoke test to the dummy payer on `/v1/preauth/submit` and gets 202. It posts this hook with `action` `Approve`, `method` `Preauth` and that request's correlation ID. A `ProtocolResponse` refusing the empty bundle lands on its `/v1/preauth/on_submit`, the handler answers 202, and the base framework is proven end to end. + + ### Specification + + Chapter [Building and sending a JWE](/docs/nhcx/v1/getting-started/building-and-sending-a-jwe) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + action: + type: string + method: + type: string + correlationId: + type: string + example: + action: Approve + method: Preauth + correlationId: + responses: + "200": + description: The answer arrives on your callback for the request's family, `/v1/preauth/on_submit` for a pre-authorisation, as a sealed `ClaimResponse` or as a `ProtocolResponse` carrying a refusal, on the correlation ID you sent. + /paymentNotice/init: + post: + operationId: adjudicator_dummy_payer_paymentnotice_init + x-abdm-atom: nhcx.endpoint.dummy-payer-paymentnotice-init + x-abdm-use-case: PMJAY adjudicator + tags: + - PMJAY adjudicator + summary: Dummy payer, send a payment notice + description: |- + Makes the sandbox dummy payer send a payment notice to the provider named, on `/v1/paymentnotice/request`. + + ### Business purpose + + A payment notice only follows a settled claim, which is slow to reach in a test. This hook makes the sandbox's dummy payer, `1000003538@hcx`, send one on demand, so a provider can build and test its payment notice handling and acknowledgement without waiting for a settlement. + + ### When to use + + Sandbox testing of the payment notice flow, once your `/v1/paymentnotice/request` callback is in place. The body names your participant code in `providerId`. It also carries a `claimNumber` field, left empty in this collection, whose effect the documentation does not describe. + + ### Preconditions + + - Your participant is registered on the sandbox with a reachable callback address. + - You host `/v1/paymentnotice/request` and answer it 202 within 30 seconds. + - An ordinary ABDM session token. + + ### Postconditions + + The dummy payer sends a payment notice to the provider named, arriving on `/v1/paymentnotice/request`. The provider acknowledges it on `/v1/paymentnotice/on_request`. + + ### Common mistakes + + - Triggering the notice before the `/v1/paymentnotice/request` handler is in place. + - Sending another participant's code in `providerId`. + - Receiving the notice and never sending the acknowledgement on `/v1/paymentnotice/on_request`. + + ### Best practices + + - Test both the receipt and the acknowledgement. + - Keep this hook out of production code paths. It exists only in the sandbox. + + ### Related scenario + + A provider has built its payment notice handler. It posts this hook with its own participant code in `providerId`. A payment notice from the dummy payer arrives on its `/v1/paymentnotice/request`. The handler answers 202, opens and records the notice, and sends the acknowledgement on `/v1/paymentnotice/on_request`. + + ### Specification + + Chapter [NHCX Use Cases](/docs/nhcx/v1/concepts/nhcx-use-cases) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + providerId: + type: string + claimNumber: + type: string + example: + providerId: + claimNumber: "" + responses: + "200": + description: The dummy payer sends a payment notice to the provider named, arriving on `/v1/paymentnotice/request`. +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + description: "On every NHCX call, the token goes in a header called `bearer_auth`, with the word `Bearer` and a space in front. The sources are not unanimous: the authentication page and the FAQ both write the example as `Authorization`, and the notification endpoint uses `Authorization`. The safe course, and what the adapter does, is to send both headers with the same value." + parameters: + BearerAuth: + name: bearer_auth + in: header + required: true + description: It is `bearer_auth`, not `Authorization`, on NHCX's own endpoints. + schema: + type: string + example: Bearer diff --git a/catalogue/openapi/nhcx/v1/nhcx-biometric.yaml b/catalogue/openapi/nhcx/v1/nhcx-biometric.yaml new file mode 100644 index 000000000..f1607e87f --- /dev/null +++ b/catalogue/openapi/nhcx/v1/nhcx-biometric.yaml @@ -0,0 +1,632 @@ +# NHCX ABHA biometric authentication, from the NHCX package's Bruno folder apis/14-biometric. +# +# Written by the package's system/build-ekadocs.mjs (make ekadocs); change the .bru +# requests there and port again rather than editing this file. +# +# Rules this file follows: catalogue/openapi/CONVENTIONS.md +openapi: 3.1.1 +info: + x-portal: + module: biometric + label: ABHA biometric authentication + position: 14 + title: NHCX ABHA biometric authentication + summary: PMJAY requires proof that the beneficiary was physically present. + description: |- + The ABHA biometric authentication calls on the National Health Claims Exchange (NHCX): 6 operations. + + PMJAY requires proof that the beneficiary was physically present. + + Guides that use these calls: [Biometric authentication](/docs/nhcx/v1/roles/provider/biometric-authentication). + + Production address for the ABDM proxy: not published. Confirm at onboarding. + version: nhcx-v1 + license: + name: MIT + identifier: MIT + contact: + name: NHCX sandbox + url: https://hcxsbx.abdm.gov.in + x-abdm-gateway: nhcx + x-abdm-module: biometric + x-abdm-phase: 1 + x-abdm-roles: + - provider +x-abdm-sources: + - file: nhcx-package/apis/14-biometric + role: upstream + hash: sha256:67a84b282e192889df0e71793d38df1c4e3615dce1337beb40f13737036b8100 + note: The package's Bruno collection, one request per operation. + - file: nhcx-package/baseurl.yaml + role: upstream + hash: sha256:88515b7b29c6b349a131e016c80774436ea16a29738db743b4cc3a24cbd42453 + note: The sandbox and production hosts. +servers: + - url: https://apisbx.abdm.gov.in + description: Sandbox. +tags: + - name: ABHA biometric authentication + description: PMJAY requires proof that the beneficiary was physically present. +security: + - bearerAuth: [] +paths: + /hcx/abha/biometric/auth/init: + post: + operationId: biometric_auth_init + x-abdm-atom: nhcx.endpoint.abha-biometric-auth-init + x-abdm-use-case: ABHA biometric authentication + tags: + - ABHA biometric authentication + summary: Biometric auth init + description: |- + Starts a fingerprint or iris authentication of a PMJAY beneficiary against the ABHA registry and returns the `txnId` the verify call needs. + + ### Business purpose + + PMJAY requires proof that the beneficiary was physically present. A hospital proves it by authenticating them against their ABHA, biometrically, and the user token that results rides on the eligibility check, the pre-authorisation and the claim. A request without it, and without the consent form that stands in for it, is refused by name. These are ABDM calls built for the PMJAY payer, not NHCX calls: no JWE and no callbacks. + + ### When to use + + At the desk with the beneficiary present: at admission with `process` `Preauth`, and at discharge, and at every visit of a cyclic case, with `process` `Discharge`. `scope` selects the modality, `aadhaar-bio-verify` for fingerprint and `aadhaar-iris-verify` for iris. `authMode` is `FINGERPRINT` or `IRIS`. The NHCX-PMJAY-HMIS Integration Guide and the Biometric Authentication APIs Postman collection also list face on this call, `aadhaar-face-verify` with `FACE_AUTH`, but show no face request made this way; the face path documented end to end is `Face auth init` on the ABDM proxy host. `payerid` names the scheme payer the authentication is performed for. + + ### Preconditions + + - The beneficiary's ABHA is linked to their PMJAY card. Where it is not, biometric authentication does not apply and the scheme's existing KYC protocols are followed. + - The ABDM session token on `Authorization: Bearer`, not on `bearer_auth`. + - `loginId` is the ABHA number with hyphens, the opposite of the envelope convention. + - A capture device, whose capture needs the wrapped Aadhaar data hash built with `lr` set to `Y`. + + ### Postconditions + + Returns the `txnId` that `Biometric auth verify` quotes, with a message saying the authentication request was sent. + + ### Common mistakes + + - Sending the token on `bearer_auth` only, which gets a `401` that looks like an expired token. + - Calling it on the face-authentication host. Fingerprint and iris sit under `/hcx/abha/biometric/`, face under `/pmjay/sbxhcx/abdmproxy/abha/biometric/`. + - Stripping the hyphens from `loginId`. + - Building the wrapped Aadhaar data hash with `lr` as `N`, which the biometric APIs answer with `K-547`. + + ### Best practices + + - Implement fingerprint, iris and face. Each is mandatory, because any one of them may be the only one that works for a given patient. + - Set `process` from the stage of the case, not from a constant. + - Record the transaction ID, the method and the moment it succeeded against the case. + + ### Related scenario + + A PMJAY beneficiary arrives for admission. The desk posts this request with `scope` `["abha-login", "aadhaar-bio-verify"]`, `authMode` `FINGERPRINT`, the ABHA number with hyphens, `process` `Preauth` and the scheme payer's code, and gets a `txnId` back. The fingerprint is captured on the device and sent with that `txnId` to `Biometric auth verify`. + + ### Specification + + Chapter [Biometric authentication](/docs/nhcx/v1/roles/provider/biometric-authentication) of the NHCX integration specification. + security: [] + parameters: + - $ref: "#/components/parameters/Process" + - $ref: "#/components/parameters/Payerid" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + scope: + type: array + items: + type: string + loginHint: + type: string + loginId: + type: string + otpSystem: + type: string + authMode: + type: string + example: + scope: + - abha-login + - aadhaar-bio-verify + loginHint: abha-number + loginId: 91-XXXX-XXXX-1234 + otpSystem: aadhaar + authMode: FINGERPRINT + responses: + "200": + description: Returns the `txnId` that `Biometric auth verify` quotes, with a message saying the authentication request was sent. + content: + application/json: + schema: + type: object + properties: + txnId: + type: string + authMode: {} + message: + type: string + status: {} + example: + txnId: 8c8a12e3-xxxx-4278-xxxx-10acffa44f07 + authMode: null + message: FingerPrint authentication request successfully sent. + status: null + /hcx/abha/biometric/auth/verify: + post: + operationId: biometric_auth_verify + x-abdm-atom: nhcx.endpoint.abha-biometric-auth-verify + x-abdm-use-case: ABHA biometric authentication + tags: + - ABHA biometric authentication + summary: Biometric auth verify + description: |- + Completes the authentication started by `Biometric auth init` with the captured PID block, and returns the beneficiary's user token, valid thirty minutes. + + ### Business purpose + + The user token this call returns is the proof of presence PMJAY asks for. It rides on the eligibility check, the pre-authorisation and the claim. Without it a request must carry the plan's consent questionnaire instead, or it is refused: `PAYR-1256` at the pre-authorisation, `PAYR-1363` at the claim. + + ### When to use + + Immediately after the capture. `authMethods` is `bio` for fingerprint and `iris` for iris, and the matching object carries the `txnId` from init and the device's PID block, in `fingerPrintAuthPid` or `irisAuthPid` accordingly. The same two sources that list a face mode on `Biometric auth init` give it here as `authMethods` `face`, with the capture in `authData.face.faceAuthPid`. + + ### Preconditions + + - A `txnId` from `Biometric auth init` for the same modality. + - The PID block from the capture device. + - The same headers as init: `Authorization: Bearer `, `process` and `payerid`. + + ### Postconditions + + On success it returns `authResult` `success`, a user `token` with `expiresIn` 1800 seconds, a `refreshToken` with `refreshExpiresIn` 1296000 seconds, fifteen days, and the ABHA `accounts` matched. + + ### Common mistakes + + - Putting the PID block under the wrong key for the modality. + - Holding the token against the session rather than the case. If it lapses mid-case and cannot be refreshed, a fresh authentication is needed. + - Standing a refreshed token in for a capture at a cyclic visit. Every visit needs a real capture. + + ### Best practices + + - Store the user token and its expiry against the case. + - Store the refresh token, and refresh automatically for the duration of the transaction cycle. + - Keep nothing from the ABHA profile beyond what the encounter needs. + + ### Related scenario + + Right after the fingerprint capture, the desk posts the `txnId` from init and the device's PID block in `fingerPrintAuthPid`, with `authMethods` `["bio"]`. The answer carries a thirty-minute token and a fifteen-day refresh token. The token goes on the header of the eligibility check and the pre-authorisation, and both tokens are stored against the case. + + ### Specification + + Chapter [Biometric authentication](/docs/nhcx/v1/roles/provider/biometric-authentication) of the NHCX integration specification. + security: [] + parameters: + - $ref: "#/components/parameters/Process" + - $ref: "#/components/parameters/Payerid" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + scope: + type: array + items: + type: string + authData: + type: object + properties: + authMethods: + type: array + items: + type: string + bio: + type: object + properties: + txnId: + type: string + fingerPrintAuthPid: + type: string + authMode: + type: string + example: + scope: + - abha-login + - aadhaar-bio-verify + authData: + authMethods: + - bio + bio: + txnId: + fingerPrintAuthPid: + authMode: FINGERPRINT + responses: + "200": + description: On success it returns `authResult` `success`, a user `token` with `expiresIn` 1800 seconds, a `refreshToken` with `refreshExpiresIn` 1296000 seconds, fifteen days, and the ABHA `accounts` matched. + content: + application/json: + schema: + type: object + properties: + txnId: + type: string + authResult: + type: string + message: + type: string + token: + type: string + refreshToken: + type: string + expiresIn: + type: integer + refreshExpiresIn: + type: integer + accounts: + type: array + items: + type: object + properties: + ABHANumber: + type: string + name: + type: string + status: + type: string + example: + txnId: d21b3db9-478a-xxxx-xxxx-8f75e7f86b9f + authResult: success + message: … verified successfully + token: eyZhx…. + refreshToken: eyZhx…. + expiresIn: 1800 + refreshExpiresIn: 1296000 + accounts: + - ABHANumber: 91-XXXX-XXXX-1234 + name: … + status: ACTIVE + /hcx/abha/biometric/auth/refresh/token: + get: + operationId: biometric_auth_refresh_token + x-abdm-atom: nhcx.endpoint.abha-biometric-auth-refresh-token + x-abdm-use-case: ABHA biometric authentication + tags: + - ABHA biometric authentication + summary: Biometric auth refresh token + description: |- + Exchanges the refresh token from `Biometric auth verify` for a new thirty-minute user token without a fresh capture. + + ### Business purpose + + A beneficiary's user token lasts thirty minutes, and a case lasts much longer. The refresh keeps a case authenticated through its transaction cycle without bringing the patient back to the device each time the token lapses. + + ### When to use + + When the user token has lapsed during a transaction cycle. Refresh automatically for the duration of the cycle. Each refresh returns a new refresh token whose fifteen days run from that moment, and the portal's advice is to refresh once within every ten days and store the new token, which keeps a chain alive indefinitely. + + ### Preconditions + + - A refresh token from `Biometric auth verify` or an earlier refresh, less than fifteen days old, sent on `R-token` as `Bearer `. + - The ABDM session token on `Authorization`, with `payerid` and `process`. + + ### Postconditions + + Returns a new user token and a new refresh token. The new refresh token replaces the old one. + + ### Common mistakes + + - Sending the refresh token on `Authorization` instead of `R-token`. + - Keeping the old refresh token after a refresh. + - Using a refresh where a capture is required. On a cyclic procedure the payer pays only for cycles with a live biometric, and a refresh token is accepted only at the final claim. Every visit needs a real capture with `process` `Discharge`. + + ### Best practices + + - Refresh within every ten days and store the new token. + - Refresh automatically while a case is open. If the token has lapsed and cannot be refreshed, start a fresh authentication. + + ### Related scenario + + A beneficiary's eligibility was checked with a fresh token at admission, but the pre-authorisation is ready only after the thirty minutes have passed. The integration sends the stored refresh token on `R-token` to this endpoint, receives a new user token and a new refresh token, sends the user token on the pre-authorisation, and stores the new refresh token against the case. + + ### Specification + + Chapter [Biometric authentication](/docs/nhcx/v1/roles/provider/biometric-authentication) of the NHCX integration specification. + security: [] + parameters: + - $ref: "#/components/parameters/RToken" + - $ref: "#/components/parameters/Payerid" + - $ref: "#/components/parameters/Process" + responses: + "200": + description: Returns a new user token and a new refresh token. + /pmjay/sbxhcx/abdmproxy/abha/biometric/faceauth/init: + post: + operationId: biometric_faceauth_init + x-abdm-atom: nhcx.endpoint.abha-biometric-faceauth-init + x-abdm-use-case: ABHA biometric authentication + tags: + - ABHA biometric authentication + summary: Face auth init + description: |- + Starts a face authentication on the ABDM proxy host and returns the `txnId` the rest of the face flow quotes. + + ### Business purpose + + Face authentication is the method that works when fingerprint and iris do not. The capture happens on the patient's own phone, in the ABHA app, rather than on a hospital device. A case authenticated by fingerprint at admission can be authenticated by face at discharge, because the methods do not have to match across a case. + + ### When to use + + When fingerprint and iris are not possible for the patient. Face authentication runs on a different host from the other two modalities and takes three calls and a QR code: this call, a QR code the patient scans, polling `Face auth capture PID`, then `Face auth verify`. + + ### Preconditions + + - The ABDM session token on `Authorization`, with a fresh `REQUEST-ID` and the current `TIMESTAMP`. + - The request sent to the ABDM proxy host, under `/pmjay/sbxhcx/abdmproxy/abha/biometric/`. + - `scope` is `["abha-enrol", "face-auth"]`. + - The patient has the ABHA app on a phone. + + ### Postconditions + + Returns a `txnId`. Render `https://phrsbx.abdm.gov.in/face-auth?txnId=` as a QR code. The patient scans it with the ABHA app and completes the face scan there. + + ### Common mistakes + + - Sending it to the fingerprint host, which fails in a way that looks like a routing problem rather than a configuration one. + - Waiting for a callback. There is none, and the capture is polled. + - Treating face as optional. All three methods are mandatory to implement. + + ### Best practices + + - Keep both biometric base paths in configuration. + - Record the `txnId` against the case as soon as it arrives. + + ### Related scenario + + A patient authenticated by fingerprint at admission cannot be captured on the device at discharge. The desk calls this endpoint, shows the QR code built from the `txnId`, and the patient scans it with the ABHA app. The desk polls `Face auth capture PID` until the capture is complete, then calls `Face auth verify`. + + ### Specification + + Chapter [Biometric authentication](/docs/nhcx/v1/roles/provider/biometric-authentication) of the NHCX integration specification. + security: [] + parameters: + - $ref: "#/components/parameters/RequestId" + - $ref: "#/components/parameters/Timestamp" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + scope: + type: array + items: + type: string + example: + scope: + - abha-enrol + - face-auth + responses: + "200": + description: Returns a `txnId`. + /pmjay/sbxhcx/abdmproxy/abha/biometric/capture/pid: + post: + operationId: biometric_faceauth_capture_pid + x-abdm-atom: nhcx.endpoint.abha-biometric-capture-pid + x-abdm-use-case: ABHA biometric authentication + tags: + - ABHA biometric authentication + summary: Face auth capture PID + description: |- + Polls for the face capture the patient completes in the ABHA app after scanning the QR code for the `txnId` from `Face auth init`. + + ### Business purpose + + The face capture happens on the patient's phone, out of the hospital system's sight. This call is how the hospital learns that it has finished. It is the step between showing the QR code and verifying. + + ### When to use + + After showing the QR code and before `Face auth verify`, repeatedly until the capture is complete. There is no callback. + + ### Preconditions + + - A `txnId` from `Face auth init`. + - The patient has scanned the QR code built from it. + - The ABDM session token on `Authorization`, with a fresh `REQUEST-ID` and the current `TIMESTAMP`. No source sends `process` or `payerid` on this call. + - The request sent to the ABDM proxy host. + + ### Postconditions + + Answers `PENDING` with `Awaiting PID capture` until the patient finishes, then `COMPLETE` with `PID capture successful`. On `COMPLETE`, move on to `Face auth verify`. + + ### Common mistakes + + - Waiting for a callback instead of polling. + - Calling `Face auth verify` before this answers `COMPLETE`. + - Sending it to the fingerprint host. + + ### Best practices + + - Poll while the QR code is on screen, and stop when the answer is `COMPLETE`. + - Show the desk that the capture is pending, so the patient is not asked to scan twice. + + ### Related scenario + + The desk has shown the QR code for a discharge face authentication. It polls this endpoint with the `txnId` and gets `PENDING` while the patient completes the scan in the ABHA app. The next poll answers `COMPLETE`, and the desk calls `Face auth verify`. + + ### Specification + + Chapter [Biometric authentication](/docs/nhcx/v1/roles/provider/biometric-authentication) of the NHCX integration specification. + security: [] + parameters: + - $ref: "#/components/parameters/RequestId" + - $ref: "#/components/parameters/Timestamp" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + txnId: + type: string + example: + txnId: + responses: + "200": + description: Answers `PENDING` with `Awaiting PID capture` until the patient finishes, then `COMPLETE` with `PID capture successful`. + content: + application/json: + schema: + type: object + properties: + status: + type: string + message: + type: string + example: + status: COMPLETE + message: PID capture successful + /pmjay/sbxhcx/abdmproxy/abha/biometric/v2/auth/verify: + post: + operationId: biometric_faceauth_v2_auth_verify + x-abdm-atom: nhcx.endpoint.abha-biometric-v2-auth-verify + x-abdm-use-case: ABHA biometric authentication + tags: + - ABHA biometric authentication + summary: Face auth verify + description: |- + Completes a face authentication with the encrypted Aadhaar number, the Aadhaar-linked mobile and the `txnId`, and returns the beneficiary's user token. + + ### Business purpose + + It completes the face method with the same outcome as fingerprint and iris: the user token that proves presence to the scheme and rides on the eligibility check, the pre-authorisation and the claim. + + ### When to use + + After `Face auth capture PID` answers `COMPLETE`. + + ### Preconditions + + - The `txnId` from `Face auth init`, with the capture reported `COMPLETE`. + - `aadhaar` is the Aadhaar number encrypted with the X.509 public key the portal publishes, using the transformation `RSA/ECB/OAEPWithSHA-1AndMGF1Padding`. The ciphertext is roughly 680 base64 characters for a 4096-bit key. + - `mobile` is the Aadhaar-linked mobile number. + - `authMethods` is `["face_auth"]` and `authMode` is `FACE_AUTH`. + - The ABDM session token on `Authorization`, with a fresh `REQUEST-ID`, the current `TIMESTAMP`, `payerid` and `process`, sent to the ABDM proxy host. + + ### Postconditions + + Returns the same token pair as `Biometric auth verify`, a thirty-minute user token and a fifteen-day refresh token, plus a full ABHA profile: name, date of birth, gender, photo, address, state and district. + + ### Common mistakes + + - Sending the Aadhaar number in the clear. + - Validating the ciphertext as a twelve-digit number. + - Logging or storing the encrypted Aadhaar value. + - Sending it to the fingerprint host. + + ### Best practices + + - Never log or store the encrypted Aadhaar value. + - Take from the ABHA profile only what the record needs. + - Store the user token and its expiry against the case. + + ### Related scenario + + The capture for a discharge face authentication has answered `COMPLETE`. The desk encrypts the patient's Aadhaar number with the portal's public key, posts it here with the `txnId` and the Aadhaar-linked mobile, and receives the token pair and the ABHA profile. It stores the token against the case, keeps only the profile fields the record needs, and discards the encrypted value. + + ### Specification + + Chapter [Biometric authentication](/docs/nhcx/v1/roles/provider/biometric-authentication) of the NHCX integration specification. + security: [] + parameters: + - $ref: "#/components/parameters/RequestId" + - $ref: "#/components/parameters/Timestamp" + - $ref: "#/components/parameters/Payerid" + - $ref: "#/components/parameters/Process" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + authData: + type: object + properties: + authMethods: + type: array + items: + type: string + face: + type: object + properties: + txnId: + type: string + aadhaar: + type: string + mobile: + type: string + authMode: + type: string + example: + authData: + authMethods: + - face_auth + face: + txnId: + aadhaar: + mobile: + authMode: FACE_AUTH + responses: + "200": + description: "Returns the same token pair as `Biometric auth verify`, a thirty-minute user token and a fifteen-day refresh token, plus a full ABHA profile: name, date of birth, gender, photo, address, state and district." +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + description: "On every NHCX call, the token goes in a header called `bearer_auth`, with the word `Bearer` and a space in front. The sources are not unanimous: the authentication page and the FAQ both write the example as `Authorization`, and the notification endpoint uses `Authorization`. The safe course, and what the adapter does, is to send both headers with the same value." + parameters: + Process: + name: process + in: header + required: true + description: No source puts `process` or `payerid` on `faceauth/init` or `capture/pid`. + schema: + type: string + example: Preauth + Payerid: + name: payerid + in: header + required: true + description: "`payerid` is the insurer's own participant code. Every insurer has one, even when it works through a TPA." + schema: + type: string + example: + RToken: + name: R-token + in: header + required: true + description: Sent on this call, as the package's request carries it. + schema: + type: string + example: Bearer + RequestId: + name: REQUEST-ID + in: header + required: true + description: "`REQUEST-ID` is a fresh UUID that you generate for every call. Sending the same one twice is the mistake to avoid; generate it, do not copy it from an example." + schema: + type: string + example: + Timestamp: + name: TIMESTAMP + in: header + required: true + description: "`TIMESTAMP` is the current time in UTC, ISO 8601 with milliseconds and a trailing `Z`, as in `2026-09-04T06:15:51.975Z`. A clock that has drifted will be refused, so take the time from the system rather than constructing it by hand. How to produce it in each language is at the end of this chapter." + schema: + type: string + example: +x-abdm-errors: + notes: "Codes any exchange call can meet are recorded once, in the [Other](/docs/nhcx/v1/api/other) specification: the gateway's NHCX- codes, the standard payer codes, and the reference payer's structure and transport codes. The reference payer's other codes sit with the exchange they reject: coverage eligibility, preauthorisation, claim and insurance plan. [Reading error codes](/docs/nhcx/v1/reference/error-code-guide) explains the code spaces." diff --git a/catalogue/openapi/nhcx/v1/nhcx-claim.yaml b/catalogue/openapi/nhcx/v1/nhcx-claim.yaml new file mode 100644 index 000000000..6abe28acb --- /dev/null +++ b/catalogue/openapi/nhcx/v1/nhcx-claim.yaml @@ -0,0 +1,1079 @@ +# NHCX claim, from the NHCX package's Bruno folder apis/05-claim. +# +# Written by the package's system/build-ekadocs.mjs (make ekadocs); change the .bru +# requests there and port again rather than editing this file. +# +# Rules this file follows: catalogue/openapi/CONVENTIONS.md +openapi: 3.1.1 +info: + x-portal: + module: claim + label: Claim + position: 5 + title: NHCX claim + summary: The claim is where money actually moves. + description: |- + The Claim calls on the National Health Claims Exchange (NHCX): 4 operations, and 2 callbacks you host. + + The claim is where money actually moves. + + Guides that use these calls: [Claim request](/docs/nhcx/v1/reference/fhir/claim-request), [Claim response](/docs/nhcx/v1/reference/fhir/claim-response), [Claim query and answer](/docs/nhcx/v1/reference/fhir/claim-query-and-answer). + version: nhcx-v1 + license: + name: MIT + identifier: MIT + contact: + name: NHCX sandbox + url: https://hcxsbx.abdm.gov.in + x-abdm-gateway: nhcx + x-abdm-module: claim + x-abdm-phase: 1 + x-abdm-roles: + - provider + - payer +x-abdm-sources: + - file: nhcx-package/apis/05-claim + role: upstream + hash: sha256:d216977cce22632f8ab901882dfe7b64d92ba5f0dcdd08f477d105b15d14cfbc + note: The package's Bruno collection, one request per operation. + - file: nhcx-package/baseurl.yaml + role: upstream + hash: sha256:88515b7b29c6b349a131e016c80774436ea16a29738db743b4cc3a24cbd42453 + note: The sandbox and production hosts. + - file: nhcx-package/nhcx-error.yaml + role: upstream + hash: sha256:d24ac927ed4dd722e60d7bd1d6fed15de370cc29f750d68999ee56fac93c941b + note: The error codes. +servers: + - url: https://apisbx.abdm.gov.in/hcx + description: Sandbox, NHCX exchange. + - url: https://apisprod.nha.gov.in/hcx + description: Production. +tags: + - name: Claim + description: The claim is where money actually moves. + - name: Adapter + description: Internal twins of the exchange calls, for the NHCX adapter deployment. +security: + - bearerAuth: [] +paths: + /v1/claim/submit: + post: + operationId: claim_v1_claim_submit + x-abdm-atom: nhcx.endpoint.claim-submit + x-abdm-use-case: Claim + tags: + - Claim + summary: Claim submit + description: |- + Provider submits the final itemised Claim bundle (Claim.use claim), or a claim query response or resubmission; NHCX routes it to the payer. + + ### Business purpose + + The claim is where money actually moves. After treatment the provider assembles finalised bills, the complete document set and the preAuthRef, and asks the payer to adjudicate and settle. A well-prepared claim closes within days; a poorly prepared one cycles through queries and resubmissions for weeks. The endpoint gives hospitals a single structured channel for settlement requests and gives payers a complete evidentiary package against which to calculate the approved amount, apply deductions and trigger payment. + + ### When to use + + Called after discharge, once an approved preauth exists (PAYR-1302 otherwise). x-hcx-workflow_id distinguishes the step: 15 CLAIM_REQUEST_INITIATED for the final claim (in PMJAY the discharge and claim steps are merged into this one submission); 151 CLAIM_QUERY_RESPONSE_SUBMITTED to answer a payer query received under 27; the optional x-hcx-use_case header takes New or Resubmit. The NHA sheet also lists R15 and R151 for the reimbursement mirror and 36 CLAIM_ARBITRATION_REQUEST_SUBMITTED for reprocess or erroneous-claim requests, which the FAQ routes through /v1/task/submit rather than this endpoint. Send x-hcx-status request.initiated. PMJAY LAMA or DAMA discharges before or during surgery must carry only procedure LM100 (PAYR-1362). + + ### Preconditions + + - An approved preauth exists for the case and no claim has already been raised for it (PAYR-1301, PAYR-1302). + - Claim.use is claim; the bundle reuses the preauth's identifier or references preAuthRef, with estimated amounts replaced by final bill amounts. + - Patient carries PMJAY Member ID and ABHA number; diagnosis, procedure, care team, supportingInfo and an active Coverage are present; discharge summary, operative notes, diagnostics and itemised billing are attached. + - Discharge information is in supportingInfo (category DIS, code DTH, DTM, LAMA or DAMA, value Before Surgery or After Surgery); for PMJAY either discharge biometric authentication or the Authentication Consent questionnaire response is included (PAYR-1363, PAYR-1364). + - Admission, registration and discharge dates are valid and ordered (PAYR-1357, PAYR-1358, PAYR-1325 to PAYR-1330). + - Valid Bearer token, payer certificate, JWE encryption, fresh correlation ID for a new cycle, processingID as recipient code. + + ### Postconditions + + NHCX returns HTTP 202 Accepted with a StatusSuccessResponse acknowledgement (entity_type claim) and forwards the request asynchronously. The payer may respond several times on /v1/claim/on_submit: 25 received, 28 in process and 29 forwarded as response.partial, 27 queried, then 26 approved or a rejection as response.complete. A response.complete closes the claim identifier permanently; no further submissions or responses are permitted against it. An approved final claim triggers the payment sequence 30, 31 and 33 on /v1/paymentnotice/request. Protocol failures arrive as a ProtocolResponse with x-hcx-error_details. + + ### Common mistakes + + - Submitting a claim without an approved preauth (PAYR-1302), or a second claim for the same case (PAYR-1301, PAYR-1016 duplicate by service codes and dates). + - Claiming more than the preauth approved amount (PAYR-1012) or items that were not in the preauth or were rejected there (PAYR-1306, PAYR-1315). + - Answering a claim query (27) with a fresh 15 instead of 151, or sending an invalid workflow ID (PAYR-1321). + - Wrong or missing discharge stage (PAYR-1324) and, for PMJAY LAMA or DAMA cases, omitting LM100 or including other approved items alongside it (PAYR-1362). + - Missing the mandatory documents named by the InsurancePlan or eligibility response, which produces a query rather than a rejection and delays settlement. + - Reusing a correlation ID from the preauth cycle for a new claim cycle (NHCX-1006), or retrying a failed cycle with the same ID. + + ### Best practices + + - Start from the approved preauth payload: keep diagnosis and procedure entries, change Claim.use to claim, replace estimates with final amounts and add the full document set. + - Reference preAuthRef and reuse the case number; key every submission on the correlation ID and persist workflow ID and use_case with it. + - Check response.outcome on every callback; partial means the claim is still live, so keep monitoring the same correlation ID. + - Validate supportingInfo value types and discharge codes before encrypting; the PAYR-1098, 1099 and 1501 to 1505 family rejects malformed supporting info. + - For LAMA discharges send stratification with duration; for cyclic procedures send cycle information for every cycle with one biometric record per date (PAYR-1368, PAYR-1369). + - Implement v1/error and use /v1/status with the claim's correlation ID when no callback arrives. + + ### Related scenario + + A patient is discharged home after the corneal grafting approved under preAuthRef PREAUTH-HP-2026-78901. The billing desk takes the preauth bundle, sets Claim.use to claim, records discharge code DTH After Surgery, attaches the discharge summary, operative notes and final itemised bill of 13700 INR, and posts it to /v1/claim/submit under workflow 15 with use_case New and a new correlation ID. NHCX returns 202. The payer sends 25 and 28 as response.partial, then queries under 27 for a missing investigation report; the hospital answers under 151. Approval arrives under 26 as response.complete, and a payment notice follows on /v1/paymentnotice/request. + + ### Specification + + Chapter [Claim request](/docs/nhcx/v1/reference/fhir/claim-request) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - $ref: "#/components/parameters/XHcxSenderCode" + - $ref: "#/components/parameters/XHcxRecipientCode" + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxWorkflowId" + - $ref: "#/components/parameters/XHcxTimestamp" + - $ref: "#/components/parameters/XHcxStatus" + - $ref: "#/components/parameters/XHcxBenAbhaId" + - $ref: "#/components/parameters/XHcxUseCase" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOi4uLn0.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: NHCX returns HTTP 202 Accepted with a StatusSuccessResponse acknowledgement (entity_type claim) and forwards the request asynchronously. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 19/03/2026 11:46:35:120 + api_call_id: 5d4c3b2a-1f0e-4d9c-8b7a-6f5e4d3c2b1a + correlation_id: 5d4c3b2a-1f0e-4d9c-8b7a-6f5e4d3c2b1a + result: + sender_code: 1000004446@hcx + recipient_code: 1518@hcx + entity_type: claim + protocol_status: request.queued + error: + code: "" + message: "" + /v1/claim/on_submit: + post: + operationId: claim_v1_claim_on_submit + x-abdm-atom: nhcx.endpoint.claim-on-submit + x-abdm-use-case: Claim + tags: + - Claim + summary: Claim callback + description: |- + Payer returns interim (response.partial) and final (response.complete) ClaimResponseBundles for a claim to the provider via NHCX. + + ### Business purpose + + This callback carries the payer's adjudication of the final claim, possibly in several stages. Interim partial responses let the payer signal receipt, processing and queries while the claim stays open; the complete response fixes the financial decision (approved, partially approved or rejected) and triggers payment advice and settlement. For the hospital it is the source of truth for what will be paid and why; for the payer it is the auditable record of the decision. + + ### When to use + + Called by the payer or TPA after each adjudication step on a /v1/claim/submit message, with the same correlation ID. Workflow IDs: 25 CLAIM_REQUEST_RECEIVED, 28 CLAIM_REQUEST_IN_PROCESS and 29 CLAIM_FORWARDED with x-hcx-status response.partial; 27 CLAIM_REQUEST_QUERIED (framed as request.initiated in the NHA sheet, answered by the provider under 151); 26 CLAIM_REQUEST_APPROVED with response.complete; rejection with outcome complete and adjudication reason cancelled. ClaimResponse.outcome complete plus reason approved is approval, complete plus cancelled is rejection, partial plus approved is partial approval, partial plus queried is a query with totals at zero. + + ### Preconditions + + - A claim request with this correlation ID exists in NHCX (NHCX-1010 otherwise) and has not been closed by an earlier response.complete. + - The payer has a valid Bearer token and the provider's certificate, and encrypts the ClaimResponseBundle for the provider. + - x-hcx-correlation_id echoes the request; x-hcx-api_call_id is new; sender and recipient codes are swapped; x-hcx-status is response.partial, response.complete or response.error. + - Adjudication categories (submitted, eligible, copay, benefit) and total[].category codes are populated; processNote explains reductions; query text is carried in the adjudication reason display. + - Protocol errors are a ProtocolResponse with x-hcx-error_details; business errors are inside the encrypted resource. + + ### Postconditions + + HTTP 202 Accepted with the StatusSuccessResponse acknowledgement (entity_type claim) from NHCX, then asynchronous delivery to the provider's callback, which must acknowledge with 202 within 30 seconds or NHCX retries up to five times before deleting the request. After a response.partial the claim remains open and further callbacks on the same correlation ID are expected. After a response.complete no further provider submissions or payer responses are permitted against that claim identifier; an approval starts the payment notices 30, 31 and 33, and a rejection leaves the provider the option of a reprocess request (workflow 36) via /v1/task/submit. + + ### Common mistakes + + - Provider side: treating outcome complete as approval without checking adjudication[0].reason.coding.code; a rejection is also complete. + - Provider side: stopping monitoring after the first callback; multiple partial responses may precede the complete one. + - Provider side: reading a carried-over benefit total on a rejected response as payable, or keying totals by array index instead of category code. + - Provider side: returning anything other than 202 with the acceptance body, which triggers retries and eventual deletion. + - Payer side: sending a further response after response.complete on the same claim identifier, or minting a new correlation ID. + - Payer side: using JWEPayloadResponse instead of ProtocolResponse for protocol rejections (PAYR-1517). + + ### Best practices + + - Provider: acknowledge first, then decrypt, then update case state; be idempotent on correlation ID and api_call_id. + - Provider: parse the PMJAY query audit trail (USER~datetime~type~comment~trust, entries separated by |) as a plain string. + - Provider: on complete plus approved, trigger settlement tracking and await 30, 31 and 33; the claim is only closed when 33 arrives and the UTR is persisted. + - Payer: emit 25 on receipt and 28 during processing so the desk sees progress, and put reduction reasons in processNote linked by noteNumber. + - Both: keep x-hcx-status and x-hcx-workflow_id consistent with the NHA status sheet, since the pair identifies the message. + + ### Related scenario + + A state health agency receives a final claim for 13700 INR against an approved preauth. Its bridge first posts 25 (received) and 28 (in process) as response.partial to /v1/claim/on_submit. The medical auditor finds the investigation report missing and the bridge posts 27 with the query text in the adjudication reason display; the hospital answers under 151 on /v1/claim/submit. Satisfied, the payer posts 26 with outcome complete, reason approved and benefit 13700 as response.complete. The hospital's callback acknowledges each message within 30 seconds, marks the claim adjudicated and waits for the payment notice under workflow 30. + + ### Specification + + Chapter [Claim response](/docs/nhcx/v1/reference/fhir/claim-response) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + - name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - name: x-hcx-workflow_id + in: header + required: false + description: Which step, or which case. See the two readings below. Optional on the envelope. + schema: + type: string + example: "26" + - $ref: "#/components/parameters/XHcxTimestamp" + - name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: response.complete + - $ref: "#/components/parameters/XHcxBenAbhaId" + - $ref: "#/components/parameters/XHcxDebugFlag" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOi4uLn0.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: HTTP 202 Accepted with the StatusSuccessResponse acknowledgement (entity_type claim) from NHCX, then asynchronous delivery to the provider's callback, which must acknowledge with 202 within 30 seconds or NHCX retries up to five times before deleting the request. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 19/03/2026 11:46:35:120 + api_call_id: 9a8b7c6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d + correlation_id: 5d4c3b2a-1f0e-4d9c-8b7a-6f5e4d3c2b1a + result: + sender_code: 1518@hcx + recipient_code: 1000004446@hcx + entity_type: claim + protocol_status: request.dispatched + error: + code: "" + message: "" + /internal/v1/claim/submit: + post: + operationId: claim_internal_v1_claim_submit + x-abdm-use-case: Adapter + tags: + - Adapter + summary: Claim submit (internal) (adapter) + description: |- + Internal twin of /v1/claim/submit (operationId claimSubmitPostInternal) with the same JWEPayload body and response set. + + ### Business purpose + + The claim service publishes its submit operation twice, at /v1 and at /internal/v1. Both let a provider submit or resubmit the final claim bundle for adjudication and settlement. The internal path is documented only as a distinct operationId on the same contract; no separate business purpose is described for it. + + ### When to use + + Documented as the internal variant of claim submit, consumed by providers with a JWEPayload body. The same workflow discriminators apply: 15 for the final claim, 151 for a claim query response, with x-hcx-use_case New or Resubmit and x-hcx-status request.initiated. The OpenAPI specs expose this operation twice, at /v1/... and at /internal/v1/..., with identical descriptions, request bodies and response sets; only the operationId differs (an Internal suffix). The specs do not document what makes the internal variant different beyond that suffix, so treat it as a mirror of the public path and integrate against the public /v1 path unless NHCX onboarding tells you otherwise. + + ### Preconditions + + Identical to /v1/claim/submit: an approved preauth for the case, Claim.use set to claim with preAuthRef and final amounts, the complete document set and discharge information, PMJAY authentication or consent questionnaire, a valid Bearer token, the payer certificate, JWE encryption and a fresh correlation ID. Nothing additional is documented for the internal route. + + ### Postconditions + + Same as the public path: HTTP 202 Accepted with a StatusSuccessResponse acknowledgement, asynchronous forwarding to the payer, and one or more ClaimResponseBundles on the claim callback (the internal twin /internal/v1/claim/on_submit exists with the same body). 400, 404 and 500 carry the same schema. + + ### Common mistakes + + - Assuming a different body or semantics for the internal route; the spec gives it the same JWEPayload body and responses. + - Using it without confirmation from NHCX onboarding and then chasing a 404; try the alternate host and prefix shape before escalating. + - Every public claim-submit pitfall applies unchanged: no approved preauth (PAYR-1302), duplicate claim (PAYR-1301), amount above the approved preauth (PAYR-1012), wrong workflow ID (PAYR-1321), reused correlation ID (NHCX-1006). + + ### Best practices + + - Default to /v1/claim/submit and keep the internal path as a configuration option only. + - Share one client implementation across both paths so header hygiene, encryption and correlation handling cannot diverge. + - Record which variant carried each correlation ID for support conversations. + + ### Related scenario + + A hospital's HMIS vendor reading the claimhcxservice OpenAPI notices claimSubmitPost and claimSubmitPostInternal side by side. They implement a single claim client against /v1/claim/submit, parameterise the base path, and ask NHCX support whether the internal twin is relevant to their deployment. The end-to-end flow is unchanged: the claim goes out under workflow 15 after discharge, returns a 202, and the payer's adjudication arrives on the claim callback. + + ### Specification + + Chapter [Claim request](/docs/nhcx/v1/reference/fhir/claim-request) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - $ref: "#/components/parameters/XHcxSenderCode" + - $ref: "#/components/parameters/XHcxRecipientCode" + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxWorkflowId" + - $ref: "#/components/parameters/XHcxTimestamp" + - $ref: "#/components/parameters/XHcxStatus" + - $ref: "#/components/parameters/XHcxBenAbhaId" + - $ref: "#/components/parameters/XHcxUseCase" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOi4uLn0.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: "Same as the public path: HTTP 202 Accepted with a StatusSuccessResponse acknowledgement, asynchronous forwarding to the payer, and one or more ClaimResponseBundles on the claim callback (the internal twin /internal/v1/claim/on_submit exists with the same body)." + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 19/03/2026 11:46:35:120 + api_call_id: 5d4c3b2a-1f0e-4d9c-8b7a-6f5e4d3c2b1a + correlation_id: 5d4c3b2a-1f0e-4d9c-8b7a-6f5e4d3c2b1a + result: + sender_code: 1000004446@hcx + recipient_code: 1518@hcx + entity_type: claim + protocol_status: request.queued + error: + code: "" + message: "" + /internal/v1/claim/on_submit: + post: + operationId: claim_internal_v1_claim_on_submit + x-abdm-use-case: Adapter + tags: + - Adapter + summary: Claim callback (internal) (adapter) + description: |- + Internal twin of /v1/claim/on_submit (operationId claimOnSubmitPostInternal) taking the same bare object body. + + ### Business purpose + + Mirror of the public claim callback: the payer or TPA returns interim and final ClaimResponseBundles, or a protocol error, to the provider through NHCX. It serves the same settlement purpose of communicating the adjudication decision that triggers payment. No separate business role is documented for the internal route. + + ### When to use + + Documented as the internal variant of the claim callback, consumed by payers. Called after each adjudication step with the request's correlation ID and x-hcx-status response.partial (25, 28, 29), response.complete (26 approved or a rejection) or response.error; queries arrive under 27. The OpenAPI specs expose this operation twice, at /v1/... and at /internal/v1/..., with identical descriptions, request bodies and response sets; only the operationId differs (an Internal suffix). The specs do not document what makes the internal variant different beyond that suffix, so treat it as a mirror of the public path and integrate against the public /v1 path unless NHCX onboarding tells you otherwise. + + ### Preconditions + + Identical to the public callback: an in-flight claim request with this correlation ID that has not been closed by a response.complete, the provider's certificate for encryption, a new api_call_id, swapped sender and recipient codes, a valid responder status, and business errors inside the encrypted ClaimResponse rather than the header. + + ### Postconditions + + Same as /v1/claim/on_submit: HTTP 202 Accepted with the StatusSuccessResponse acknowledgement, asynchronous delivery to the provider's callback with the 30-second acknowledgement rule and five retries before deletion, the claim remaining open after a partial and closing permanently after a complete, and an approval starting the payment notices 30, 31 and 33. + + ### Common mistakes + + - Treating the internal callback as a different contract; the spec gives it the same object body and response set. + - All public claim-callback pitfalls apply: outcome complete misread as approval without checking the reason code, monitoring stopped after the first partial, 200 returned instead of the 202 acceptance body, new correlation ID minted, JWEPayloadResponse sent instead of ProtocolResponse (PAYR-1517). + + ### Best practices + + - Route both callback variants into one handler keyed on x-hcx-correlation_id. + - Acknowledge with 202 inside 30 seconds and process asynchronously; be idempotent under redelivery. + - Use the public /v1 path unless NHCX onboarding specifies the internal one. + + ### Related scenario + + A TPA that adjudicates claims for several insurers builds one response pipeline that emits 25, 28, 27 and 26 with the correct outcome and reason codes and echoes the claim's correlation ID. It posts to /v1/claim/on_submit by default and keeps /internal/v1/claim/on_submit as a configurable alternative in case NHCX requires it. The hospital callback acknowledges each message and, on 26, awaits the payment notice. + + ### Specification + + Chapter [Claim response](/docs/nhcx/v1/reference/fhir/claim-response) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + - name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - name: x-hcx-workflow_id + in: header + required: false + description: Which step, or which case. See the two readings below. Optional on the envelope. + schema: + type: string + example: "26" + - $ref: "#/components/parameters/XHcxTimestamp" + - name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: response.complete + - $ref: "#/components/parameters/XHcxBenAbhaId" + - $ref: "#/components/parameters/XHcxDebugFlag" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOi4uLn0.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: "Same as /v1/claim/on_submit: HTTP 202 Accepted with the StatusSuccessResponse acknowledgement, asynchronous delivery to the provider's callback with the 30-second acknowledgement rule and five retries before deletion, the claim remaining open after a partial and closing permanently after a complete, and an approval starting the payment notices 30, 31 and 33." + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 19/03/2026 11:46:35:120 + api_call_id: 9a8b7c6d-5e4f-4a3b-2c1d-0e9f8a7b6c5d + correlation_id: 5d4c3b2a-1f0e-4d9c-8b7a-6f5e4d3c2b1a + result: + sender_code: 1518@hcx + recipient_code: 1000004446@hcx + entity_type: claim + protocol_status: request.dispatched + error: + code: "" + message: "" +webhooks: + v1_claim_submit: + post: + operationId: claim_webhook_v1_claim_submit + x-abdm-atom: nhcx.callback.claim-submit + x-abdm-triggered-by: claim_v1_claim_submit + x-abdm-use-case: Webhooks + tags: + - Claim + summary: Receive claim submit + description: |- + Hosted by the payer. The exchange posts this message to the `endpoint_url` you registered, at `/v1/claim/submit`, with the headers and the sealed payload the sender posted. Answer HTTP 202 with the receipt first and process afterwards; [Receiving a callback](/docs/nhcx/v1/getting-started/receiving-a-callback) has the rules. + + Provider submits the final itemised Claim bundle (Claim.use claim), or a claim query response or resubmission; NHCX routes it to the payer. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - $ref: "#/components/parameters/XHcxSenderCode" + - $ref: "#/components/parameters/XHcxRecipientCode" + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxWorkflowId" + - $ref: "#/components/parameters/XHcxTimestamp" + - $ref: "#/components/parameters/XHcxStatus" + - $ref: "#/components/parameters/XHcxBenAbhaId" + - $ref: "#/components/parameters/XHcxUseCase" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOi4uLn0.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: Received. The receipt names the message it answers; the answer itself follows as a call of your own. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 04/09/2026 11:46:41:305 + api_call_id: + correlation_id: + result: + sender_code: 1000003538@hcx + recipient_code: 1000004446@hcx + entity_type: preauth + protocol_status: request.queued + error: + code: "" + message: "" + v1_claim_on_submit: + post: + operationId: claim_webhook_v1_claim_on_submit + x-abdm-atom: nhcx.callback.claim-on-submit + x-abdm-triggered-by: claim_v1_claim_on_submit + x-abdm-use-case: Webhooks + tags: + - Claim + summary: Receive claim callback + description: |- + Hosted by the provider. The exchange posts this message to the `endpoint_url` you registered, at `/v1/claim/on_submit`, with the headers and the sealed payload the sender posted. Answer HTTP 202 with the receipt first and process afterwards; [Receiving a callback](/docs/nhcx/v1/getting-started/receiving-a-callback) has the rules. + + Payer returns interim (response.partial) and final (response.complete) ClaimResponseBundles for a claim to the provider via NHCX. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + - name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - name: x-hcx-workflow_id + in: header + required: false + description: Which step, or which case. See the two readings below. Optional on the envelope. + schema: + type: string + example: "26" + - $ref: "#/components/parameters/XHcxTimestamp" + - name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: response.complete + - $ref: "#/components/parameters/XHcxBenAbhaId" + - $ref: "#/components/parameters/XHcxDebugFlag" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOi4uLn0.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: Received. The receipt names the message it answers; the answer itself follows as a call of your own. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 04/09/2026 11:46:41:305 + api_call_id: + correlation_id: + result: + sender_code: 1000003538@hcx + recipient_code: 1000004446@hcx + entity_type: preauth + protocol_status: request.queued + error: + code: "" + message: "" +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + description: "On every NHCX call, the token goes in a header called `bearer_auth`, with the word `Bearer` and a space in front. The sources are not unanimous: the authentication page and the FAQ both write the example as `Authorization`, and the notification endpoint uses `Authorization`. The safe course, and what the adapter does, is to send both headers with the same value." + parameters: + BearerAuth: + name: bearer_auth + in: header + required: true + description: It is `bearer_auth`, not `Authorization`, on NHCX's own endpoints. + schema: + type: string + example: Bearer + XHcxSenderCode: + name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + XHcxRecipientCode: + name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + XHcxApiCallId: + name: x-hcx-api_call_id + in: header + required: true + description: Fresh on every message, including responses. Mandatory on the envelope. + schema: + type: string + example: + XHcxRequestId: + name: x-hcx-request_id + in: header + required: false + description: One per originating request. The Open Protocol page marks it Mandatory; the Technical Specifications page marks it Optional. Optional on the envelope. + schema: + type: string + example: + XHcxCorrelationId: + name: x-hcx-correlation_id + in: header + required: true + description: The thread. See the rule below. Mandatory on the envelope. + schema: + type: string + example: + XHcxWorkflowId: + name: x-hcx-workflow_id + in: header + required: false + description: Which step, or which case. See the two readings below. Optional on the envelope. + schema: + type: string + example: "15" + XHcxTimestamp: + name: x-hcx-timestamp + in: header + required: true + description: See the format note below. Mandatory on the envelope. + schema: + type: string + example: + XHcxStatus: + name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: request.initiated + XHcxBenAbhaId: + name: x-hcx-ben-abha-id + in: header + required: true + description: The beneficiary's ABHA number. Mandatory on every exchange, including those with no beneficiary in the payload. Mandatory on the envelope. + schema: + type: string + example: "91711234567890" + XHcxUseCase: + name: x-hcx-use_case + in: header + required: false + description: Values differ by exchange, see below. Optional on the envelope. + schema: + type: string + example: New + XHcxDebugFlag: + name: x-hcx-debug_flag + in: header + required: false + description: "`Error`, `Info` or `Debug`. A server may ignore it. Optional on the envelope." + schema: + type: string + example: INFO +x-abdm-errors: + notes: "Codes any exchange call can meet are recorded once, in the [Other](/docs/nhcx/v1/api/other) specification: the gateway's NHCX- codes, the standard payer codes, and the reference payer's structure and transport codes. The reference payer's other codes sit with the exchange they reject: coverage eligibility, preauthorisation, claim and insurance plan. [Reading error codes](/docs/nhcx/v1/reference/error-code-guide) explains the code spaces." +x-abdm-errors-reference-payer: + source: Reference payer codes, PAYR-1001 to PAYR-1520. Sent by the PMJAY reference implementation; they arrive inside the sealed response. + codes: + - code: PAYR-1301 + message: Claim has already been raised for case number %s. Hence new claim request will not be accepted. + action: "" + - code: PAYR-1302 + message: No preauthorization approved record found for case number %s. Hence new claim request will not be accepted. + action: "" + - code: PAYR-1303 + message: No active claim record found for case number %s. Hence query updation request will not be accepted. + action: "" + - code: PAYR-1304 + message: No claim queried record found for case number %s. Hence query updation request will not be accepted. + action: "" + - code: PAYR-1305 + message: Invalid usecase requested for case number %s. Please try again with valid usecase. + action: "" + - code: PAYR-1306 + message: No item found in preauthorization request for procedure %s with item sequence %s for case number %s. Please try again with valid items. + action: "" + - code: PAYR-1307 + message: Invalid quantity requested for procedure %s with item sequence %s for case number %s. Please try again with valid quantity. + action: "" + - code: PAYR-1308 + message: No item found in active claim request for procedure %s with item sequence %s for case number %s. Please try again with valid items. + action: "" + - code: PAYR-1309 + message: No item found in preauthorization request for implant %s with item sequence %s for case number %s. Please try again with valid items. + action: "" + - code: PAYR-1310 + message: Invalid quantity requested for implant %s with item sequence %s for case number %s. Please try again with valid quantity. + action: "" + - code: PAYR-1311 + message: No item found in active claim request for implant %s with item sequence %s for case number %s. Please try again with valid items. + action: "" + - code: PAYR-1312 + message: No item found in preauthorization request for investigation %s with item sequence %s for case number %s. Please try again with valid items. + action: "" + - code: PAYR-1313 + message: Invalid quantity requested for investigation %s with item sequence %s for case number %s. Please try again with valid quantity. + action: "" + - code: PAYR-1314 + message: No item found in active claim request for investigation %s with item sequence %s for case number %s. Please try again with valid items. + action: "" + - code: PAYR-1315 + message: Rejected item found for preauthorization for procedure %s with item sequence %s for case number %s. Please try again with valid items. + action: "" + - code: PAYR-1316 + message: Rejected item found for preauthorization for investigation %s with item sequence %s for case number %s. Please try again with valid items. + action: "" + - code: PAYR-1317 + message: Rejected item found for preauthorization for implant %s with item sequence %s for case number %s. Please try again with valid items. + action: "" + - code: PAYR-1318 + message: No requested treatment plan found for case number %s. Please try again with valid items. + action: "" + - code: PAYR-1319 + message: No requested investigation plan found for case number %s. Please try again with valid items. + action: "" + - code: PAYR-1320 + message: No details found for the requested investigations in the system. Hence request will not be processed. + action: "" + - code: PAYR-1321 + message: Error occurred while processing the request due to invalid workflow id as (%s) + action: "" + - code: PAYR-1322 + message: No active case found for the given case number. + action: The SHA HP sandbox sent this code as "Active instance found for case number", for a second request on a case while the first was still queued. The sheet's message reads the opposite way. + - code: PAYR-1323 + message: Insufficient wallet balance. Hence the request will not be processed. + action: "" + - code: PAYR-1324 + message: Invalid discharge stage received for case number %s. Hence the request will not be processed. + action: "" + - code: PAYR-1325 + message: Invalid admission date received for case number %s. Hence the request will not be processed. + action: "" + - code: PAYR-1326 + message: Invalid discharge date received for case number %s. Hence the request will not be processed. + action: "" + - code: PAYR-1327 + message: Invalid admission date format received for case number %s. Hence the request will not be processed. + action: "" + - code: PAYR-1328 + message: Invalid discharge date format received for case number %s. Hence the request will not be processed. + action: "" + - code: PAYR-1329 + message: Invalid registration date received for case number %s. Hence the request will not be processed. + action: "" + - code: PAYR-1330 + message: Invalid registration date format received for case number %s. Hence the request will not be processed. + action: "" + - code: PAYR-1331 + message: Receiver not registered in NHCX. Please try again with valid receiver details. + action: "" + - code: PAYR-1332 + message: Invalid CRC request. + action: "" + - code: PAYR-1333 + message: Invalid claim type (in-patient/out-patient) received. Hence the request will not be processed. + action: "" + - code: PAYR-1334 + message: Hospital configuration not found. Please contact support team. + action: "" + - code: PAYR-1335 + message: Invalid implant quantity received as %s for implant %s for case number %s. Please try again with valid data. + action: "" + - code: PAYR-1336 + message: Invalid implant unit price received as INR %s for implant %s for case number %s. Please try again with valid data. + action: "" + - code: PAYR-1337 + message: Invalid implant net amount received as INR %s for implant %s for case number %s. Please try again with valid data. + action: "" + - code: PAYR-1338 + message: Invalid implant attachment received for investigation %s for case number %s. Please try again with valid data. + action: "" + - code: PAYR-1339 + message: Invalid implant status received as %s for investigation %s for case number %s. Please try again with valid data. + action: "" + - code: PAYR-1340 + message: Invalid investigation status received as %s for investigation %s for case number %s. Please try again with valid data. + action: "" + - code: PAYR-1341 + message: Invalid investigation attachment received for investigation %s for case number %s. Please try again with valid data. + action: "" + - code: PAYR-1342 + message: Existing case in progress found for case number %s. Hence new reimbursement request will not be accepted. + action: "" + - code: PAYR-1343 + message: Previous reimbursement approved record found for the new reimbursement request for case number %s. Hence request will not be processed further. + action: "" + - code: PAYR-1344 + message: No details found for the requested procedures in the system. + action: "" + - code: PAYR-1345 + message: Invalid procedure status received as %s for procedure %s for case number %s. Please try again with valid data. + action: "" + - code: PAYR-1346 + message: Invalid procedure description received as %s for procedure %s for case number %s. Please try again with valid data. + action: "" + - code: PAYR-1347 + message: Invalid procedure type received as %s for procedure %s for case number %s. Please try again with valid data. + action: "" + - code: PAYR-1348 + message: Invalid procedure factor received as %s for procedure %s for case number %s. Please try again with valid data. + action: "" + - code: PAYR-1349 + message: Invalid procedure quantity received as %s for procedure %s for case number %s. Please try again with valid data. + action: "" + - code: PAYR-1350 + message: Invalid procedure net amount received as INR %s for procedure %s for case number %s. Please try again with valid data. + action: "" + - code: PAYR-1351 + message: Invalid speciality code received as %s for procedure %s for case number %s. Please try again with valid data. + action: "" + - code: PAYR-1352 + message: Requested beneficary details and careplan details does not match any criteria for processing the case at this hospital. Please try again with valid data. + action: "" + - code: PAYR-1353 + message: Invalid careplan id received. Please try again with valid careplan id. + action: "" + - code: PAYR-1354 + message: Rule failure. + action: "" + - code: PAYR-1355 + message: No details found for the requested implants in the system. Hence request will not be processed. + action: "" + - code: PAYR-1356 + message: Patient liability is not aplicable for the hospital and beneficiary do not have enough wallet balance with deficit amount INR %s for the requested preauthorization for case number %s. + action: "" + - code: PAYR-1357 + message: Admission date cannot be after the discharge date. Hence request will not be processed. Please correct the data and try again. + action: "" + - code: PAYR-1358 + message: Registration of the patient is allowed maximum upto %s days after admission. Hence request will not be processed. Please correct the data and try again. + action: "" + - code: PAYR-1359 + message: No billable treatment plan received for case number %s. Please try again with valid treatment plan data. + action: "" + - code: PAYR-1360 + message: Invalid item code received as %s for item sequence %s case number %s. Please try again with valid data. + action: "" + - code: PAYR-1361 + message: Invalid item sequence received as %s for case number %s. Please try again with valid data. + action: "" + - code: PAYR-1362 + message: No procedure with code LM100 received with 'Requested' status for case number %s. Please try again with valid data. For PMJAY claims, if case comes under LAMA/DAMA scenario with beneficiary being discharged before surgery or during surgery, procedure with code LM100 is mandatory. Only this procedure code will be accepted for LAMA/DAMA case, and all other previous preauthorization approved items will get disqualified for the claim submission + action: "" + - code: PAYR-1363 + message: Response for Authentication Consent Questionnaire is missing for case number %s. This must be sent if the biometric authentication for patient is not available during discharge. For new claim request, either biometric authentication for patient during discharge, or response for Authentication Consent questionnaire must be sent. Please check/update the insurance plan for the policy for the details of the questionnaire. + action: "" + - code: PAYR-1364 + message: No value received for link id %s for Authentication Consent Questionnaire for claim request. This must be sent if the biometric authentication for patient is not available during discharge. For new claim request, either biometric authentication for patient during discharge, or response for Authentication Consent questionnaire must be sent. Please check/update the insurance plan for the policy for the details of the questionnaire. + action: "" + - code: PAYR-1365 + message: Response for STG Questionnaire id %s is mandatory for procedure code %s. Hence the preauthorization request will not be processed as the questionnaire response is not received for procedure code. + action: "" + - code: PAYR-1366 + message: Invalid biometric user token received. Please try again with valid biometric details of the beneficiary. For any issues with biometric, please try with Authentication Consent Questionnaire for discharge, details for which has been received in insurance plan. + action: "" + - code: PAYR-1367 + message: No biometric records found for the beneficiary for %s. Please ensure correctness of biometric authentication date for the day for cyclic procedure %s. + action: "" + - code: PAYR-1368 + message: "%s units of cycle information received for procedure code %s with item sequence %s. Cycle information should be sent for all the requested/processed cycles." + action: "" + - code: PAYR-1369 + message: Biometric authentication cannot be performed more than once on the same date. Multiple biometric authentication information has been provided for same date for cyclic procedure %s. Hence case will not be processed. Please check and update biometric authentication execution dates and try again. + action: "" + - code: PAYR-1370 + message: Received invalid start date as %s for supporting details with item sequence %s. Please try again with valid start date. + action: "" diff --git a/catalogue/openapi/nhcx/v1/nhcx-communication.yaml b/catalogue/openapi/nhcx/v1/nhcx-communication.yaml new file mode 100644 index 000000000..837f32f63 --- /dev/null +++ b/catalogue/openapi/nhcx/v1/nhcx-communication.yaml @@ -0,0 +1,836 @@ +# NHCX communication, from the NHCX package's Bruno folder apis/07-communication. +# +# Written by the package's system/build-ekadocs.mjs (make ekadocs); change the .bru +# requests there and port again rather than editing this file. +# +# Rules this file follows: catalogue/openapi/CONVENTIONS.md +openapi: 3.1.1 +info: + x-portal: + module: communication + label: Communication + position: 7 + title: NHCX communication + summary: Every other NHCX exchange is provider-initiated and expects a matching response. + description: |- + The Communication calls on the National Health Claims Exchange (NHCX): 4 operations, and 2 callbacks you host. + + Every other NHCX exchange is provider-initiated and expects a matching response. + + Guides that use these calls: [Communication](/docs/nhcx/v1/reference/fhir/communication). + version: nhcx-v1 + license: + name: MIT + identifier: MIT + contact: + name: NHCX sandbox + url: https://hcxsbx.abdm.gov.in + x-abdm-gateway: nhcx + x-abdm-module: communication + x-abdm-phase: 1 + x-abdm-roles: + - provider + - payer +x-abdm-sources: + - file: nhcx-package/apis/07-communication + role: upstream + hash: sha256:9b96a557306151b1501f1b58eaf412af456d28bc8a061a12b2994ba81625dadc + note: The package's Bruno collection, one request per operation. + - file: nhcx-package/baseurl.yaml + role: upstream + hash: sha256:88515b7b29c6b349a131e016c80774436ea16a29738db743b4cc3a24cbd42453 + note: The sandbox and production hosts. +servers: + - url: https://apisbx.abdm.gov.in/hcx + description: Sandbox, NHCX exchange. + - url: https://apisprod.nha.gov.in/hcx + description: Production. +tags: + - name: Communication + description: Every other NHCX exchange is provider-initiated and expects a matching response. + - name: Adapter + description: Internal twins of the exchange calls, for the NHCX adapter deployment. +security: + - bearerAuth: [] +paths: + /v1/communication/request: + post: + operationId: communication_v1_communication_request + x-abdm-atom: nhcx.endpoint.communication-request + x-abdm-use-case: Communication + tags: + - Communication + summary: Communication request + description: |- + Payer pushes a Task plus Communication bundle to a provider mid-claim: TAT alerts, wallet or policy changes, grievances or extra-information requests. + + ### Business purpose + + Every other NHCX exchange is provider-initiated and expects a matching response. Communication inverts that: it is the payer's asynchronous, event-driven channel into the hospital system, used when something must be said about an in-flight case without the provider having asked. It carries TAT breach alerts, grievance notices, wallet or benefit updates, policy or package-rate changes, requests for additional evidence and claim-arbitration intimations. Hospitals benefit because these signals arrive in a structured, routable bundle rather than by phone or email, and payers benefit because adjudication can proceed without waiting for an out-of-band exchange. + + ### When to use + + Call it whenever the payer needs to communicate outside the direct request-response lifecycle of a preauth or claim. It does not replace the in-band query path (ClaimResponse outcome=partial with a DOC_MISSING processNote); both can be in flight for the same case. The scenario is identified by Task.reasonCode: tatquery, grievance, walletupdate, policychange, additionalinfo and the arbitration code (spelt claimArbitration in one handbook table and claimArbitartion in another). Send x-hcx-status request.initiated; the x-hcx-workflow_id must be the workflow of the associated claim or preauth and is validated at the gateway. + + ### Preconditions + + - Payer and provider both registered on NHCX; a valid Bearer token from the client-credentials session call (1200 s expiry). + - The provider's public certificate fetched via /fetch/certs (cache up to 24 h) and used to JWE-encrypt with RSA-OAEP-256 and A256GCM. + - A collection Bundle containing a Task (status completed, intent proposal, code poll, input type include) that references a Communication or CommunicationRequest carrying category, priority and topic; the identifiers key off the claim or preauth reference. + - Protected header with x-hcx-sender_code, x-hcx-recipient_code, x-hcx-api_call_id, x-hcx-correlation_id, x-hcx-workflow_id, x-hcx-timestamp (IST +05:30) and x-hcx-status request.initiated. A fresh UUID correlation id opens the conversation. + - HTTP headers Accept, Content-Type and bearer_auth. + + ### Postconditions + + The gateway validates the JWE headers, workflow id and NIIP and returns HTTP 202 with a StatusSuccessResponse (timestamp, api_call_id, correlation_id, result with sender_code, recipient_code, entity_type and protocol_status, and an error object). Nothing is decided synchronously; the gateway forwards the bundle to the provider's registered callback. The provider must acknowledge with 202 within 30 seconds, then close the loop by posting an acknowledgement Task bundle to /v1/communication/on_request under the same x-hcx-correlation_id. Errors are 400 (validation failed), 404 and 500, all in the same envelope. Communication.status completed describes the event, not the resolution of the underlying issue. + + ### Common mistakes + + - Treating the 202 as delivery or as the provider's answer; the acknowledgement comes later on on_request. + - Sending a workflow id that does not match the associated claim or preauth, which fails gateway validation (PAYR-1003 Invalid workflow requested). + - Wrong x-hcx-status spelling (request.initiate instead of request.initiated) producing NHCX-1011. + - Reusing a correlation id from an earlier cycle (NHCX-1006 Duplicate request) or from a failed cycle, which NHCX has made inactive. + - Copying the sandbox sample's swapped Organization identifier types (NIIP versus NPI), a known data-quality defect. + - Using Communication as a substitute for the in-band ClaimResponse query mechanism. + + ### Best practices + + - Mint a new UUID for x-hcx-api_call_id on every call and for x-hcx-correlation_id on every new communication cycle, including retries after failure. + - Put the routing intent in Task.reasonCode and the message classification in Communication.category, topic and priority; pair additionalinfo with category instruction or questionnaire. + - Use IST timestamps; UTC causes validation failures. + - Persist the correlation id before posting so the on_request acknowledgement can be matched. + - Expect up to five redeliveries if the provider mis-acknowledges; keep your own handling idempotent. + - Implement v1/error so a message that never reaches the provider is reported back to you. + + ### Related scenario + + A state health agency's TPA notices that a cashless claim from a district hospital has sat in adjudication past the scheme's turnaround threshold. It builds a Task bundle with reasonCode tatquery, category reminder, topic progress-update and priority asap, encrypts it for the hospital and posts /v1/communication/request with the workflow id of the claim submitted earlier on /v1/claim/submit. The gateway returns 202 and forwards the bundle. The hospital's claims desk is alerted, and its system posts the acknowledgement Task on /v1/communication/on_request with the same correlation id. Adjudication then continues and the outcome arrives on /v1/claim/on_submit as usual. + + ### Specification + + Chapter [Communication](/docs/nhcx/v1/reference/fhir/communication) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - $ref: "#/components/parameters/XHcxSenderCode" + - $ref: "#/components/parameters/XHcxRecipientCode" + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxWorkflowId" + - $ref: "#/components/parameters/XHcxTimestamp" + - $ref: "#/components/parameters/XHcxStatus" + - $ref: "#/components/parameters/XHcxBenAbhaId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOiIxNTE4QGhjeCJ9.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: The gateway validates the JWE headers, workflow id and NIIP and returns HTTP 202 with a StatusSuccessResponse (timestamp, api_call_id, correlation_id, result with sender_code, recipient_code, entity_type and protocol_status, and an error object). + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 25/08/2026 11:46:35:120 + api_call_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890 + correlation_id: 11223344-5566-7788-99aa-bbccddeeff00 + result: + sender_code: 1518@hcx + recipient_code: 1000004446@hcx + entity_type: task + protocol_status: request.queued + error: + code: "" + message: "" + /v1/communication/on_request: + post: + operationId: communication_v1_communication_on_request + x-abdm-atom: nhcx.endpoint.communication-on-request + x-abdm-use-case: Communication + tags: + - Communication + summary: Communication acknowledgement callback + description: |- + Provider returns the acknowledgement Task bundle for a payer communication, echoing the reason code and correlation id so the payer can close the loop. + + ### Business purpose + + A payer that has pushed a TAT alert, grievance, wallet update, policy change or document request needs proof that the hospital received it, because the next adjudication step or SLA clock often depends on it. This callback is that proof. The provider posts a bundle of identical structure to the request, with Task.status completed confirming receipt, and the payer's system can then continue, escalate or wait for the documents. It keeps the entire exchange inside NHCX, auditable by correlation id, rather than in phone calls and email. + + ### When to use + + Call it after receiving and persisting a /v1/communication/request bundle. The gateway has already been given a 202 within 30 seconds; this call is the separate business acknowledgement. Echo the same Task.reasonCode (tatquery, grievance, walletupdate, policychange, additionalinfo or the arbitration code) and Task.code poll, keep Task.intent proposal, and use the same x-hcx-correlation_id as the incoming request. x-hcx-workflow_id is validated at the gateway for the acknowledgement as well as the request. Responder status values are response.complete, response.partial or response.error. + + ### Preconditions + + - The inbound JWE was extracted from the payload field, validated as a five-part string, decrypted with your PKCS8 private key and its protected header parsed for correlation id, status and workflow id. + - The provider is a registered NHCX participant and holds a valid Bearer token. + - The payer's certificate is available to encrypt the acknowledgement bundle. + - The acknowledgement bundle mirrors the request (Task completed, intent proposal, code poll, reasonCode echoed) with the provider Organization listed before the payer Organization and Bundle.timestamp updated to the acknowledgement time. + - Protected header reuses the request's x-hcx-correlation_id, carries a fresh x-hcx-api_call_id and a responder x-hcx-status. + + ### Postconditions + + The gateway returns HTTP 202 with the StatusSuccessResponse envelope (timestamp, api_call_id, correlation_id, result, error) and forwards the bundle to the payer. The payer's system can link the acknowledgement to the original notification by correlation id and by the shared claim or preauth reference in Task.identifier and Communication.id. The underlying issue is not resolved by this call: a TAT breach or grievance may still be open, and any documents requested via additionalinfo are supplied through the relevant preauth or claim resubmission path. Validation failures come back as 400, unknown resources as 404, downstream faults as 500. + + ### Common mistakes + + - Minting a new correlation id on the acknowledgement instead of echoing the request's; the payer can no longer link it (NHCX-1010 No Data with given Correlation id for call back request). + - Sending the acknowledgement before, or instead of, the synchronous 202; the gateway treats a missing or malformed 202 as an error and retries up to five times. + - Holding the socket open while a human reviews the message, breaching the 30-second window. + - Closing the hospital case on acknowledgement because Communication.status reads completed. + - Deriving sender and receiver roles from Organization identifier types, which are swapped in the sandbox sample. + - Building the reason-code switch on a single spelling of the arbitration code. + + ### Best practices + + - Acknowledge first, process later: return 202 with the acceptance body, queue the bundle, then build and post the on_request acknowledgement asynchronously. + - Switch on Task.reasonCode.code to route: tatquery to the claims desk, walletupdate to the benefit cache, policychange to package rate tables. + - Be idempotent on x-hcx-correlation_id; the same communication may be redelivered. + - Validate x-hcx-workflow_id against the workflow of the associated claim or preauth before acting. + - Use IST timestamps and a fresh x-hcx-api_call_id on the acknowledgement call. + - Log the reason code, category, priority and correlation id for the audit trail. + + ### Related scenario + + A district hospital receives a communication from the scheme payer on its registered callback: reasonCode additionalinfo, category instruction, asking for an updated discharge summary on a claim submitted last week. The endpoint returns 202 immediately and queues the bundle. The claims desk is notified, and the integration posts the acknowledgement Task on /v1/communication/on_request with the same correlation id and reasonCode. The desk then attaches the discharge summary through the claim's resubmission path, and the final adjudication arrives later on /v1/claim/on_submit, possibly followed by a payment notice on /v1/paymentnotice/request. + + ### Specification + + Chapter [Communication](/docs/nhcx/v1/reference/fhir/communication) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + - name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxWorkflowId" + - $ref: "#/components/parameters/XHcxTimestamp" + - name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: response.complete + - $ref: "#/components/parameters/XHcxBenAbhaId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOiIxMDAwMDA0NDQ2QGhjeCJ9.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: The gateway returns HTTP 202 with the StatusSuccessResponse envelope (timestamp, api_call_id, correlation_id, result, error) and forwards the bundle to the payer. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 25/08/2026 11:56:35:004 + api_call_id: b2c3d4e5-f6a7-8901-bcde-f12345678901 + correlation_id: 11223344-5566-7788-99aa-bbccddeeff00 + result: + sender_code: 1000004446@hcx + recipient_code: 1518@hcx + entity_type: task + protocol_status: request.queued + error: + code: "" + message: "" + /internal/v1/communication/request: + post: + operationId: communication_internal_v1_communication_request + x-abdm-use-case: Adapter + tags: + - Adapter + summary: Communication request (internal variant) (adapter) + description: |- + Internal twin of /v1/communication/request: same JWEPayload body, description and 202 envelope, operationId communicationRequestPostInternal. + + ### Business purpose + + Six NHCX services expose each operation twice, once at /v1/... and once at /internal/v1/..., with identical descriptions and request bodies and only the operationId suffix differing. This entry is the internal twin of the payer-initiated communication request: the channel through which a payer pushes TAT alerts, grievances, wallet or policy updates and additional-information requests to a provider. It exists so the exchange can route the same operation over an internal path; the specifications do not document any further difference from the public endpoint. + + ### When to use + + The published OpenAPI documents give this path the same semantics as /v1/communication/request: a payer submits a Task plus Communication bundle for a provider during the claim lifecycle, identified by Task.reasonCode (tatquery, grievance, walletupdate, policychange, additionalinfo, claim arbitration). The specs do not state when an integrator should prefer the internal path over the public one, so integrators should code against /v1/communication/request unless onboarding instructions direct otherwise. Header rules are unchanged: request.initiated status and a workflow id validated against the associated case. + + ### Preconditions + + - Identical to the public endpoint: registered sender and recipient, valid Bearer token, recipient certificate for JWE encryption (RSA-OAEP-256, A256GCM). + - Request body is a JWEPayload, { "payload": "" }, whose plaintext is the Task plus Communication collection Bundle. + - Protected header carries sender_code, recipient_code, api_call_id, correlation_id, workflow_id, timestamp in IST and status request.initiated. + - Whether the internal prefix is reachable from a participant's network is not documented; confirm with the environment index and your onboarding contact. + + ### Postconditions + + Returns the same response set as the public endpoint: 202 Accepted with a StatusSuccessResponse (timestamp, api_call_id, correlation_id, result, error), or 400 Request Validation failed, 404 Requested resource was not found and 500 Downstream systems down/unhandled exceptions in the same envelope. The bundle is forwarded to the provider's registered callback, which must acknowledge with 202 within 30 seconds and then answer on the communication on_request path under the same correlation id. No additional state change is documented for the internal variant. + + ### Common mistakes + + - Assuming the internal path behaves differently or bypasses header validation; the specs describe it as identical apart from the operationId. + - Hard-coding the internal prefix in a participant integration without confirmation that it is the route you were onboarded to. + - The same envelope errors as the public path: wrong status spelling (NHCX-1011), invalid header (NHCX-1005), duplicate correlation id (NHCX-1006), invalid workflow (PAYR-1003). + - Mixing the hcxsbx.abdm.gov.in/ spec host and the apisbx.abdm.gov.in/pmjay/sbxhcx gateway base; a 404 is the first sign. + + ### Best practices + + - Treat this path exactly as /v1/communication/request in your client: same bundle builder, same header hygiene, same correlation-id persistence. + - Keep the path prefix configurable so you can switch between public and internal forms without a code change. + - Use fresh UUIDs for api_call_id per call and correlation_id per cycle; use IST timestamps. + - Implement v1/error and idempotent callback handling regardless of which path you post to. + + ### Related scenario + + An insurer's integration team exploring the communicationhcxservice Swagger on the sandbox host sees both communicationRequestPost and communicationRequestPostInternal listed with the same description. They wire their TAT-alert sender to the public /v1/communication/request path as documented in the handbook, keep the internal variant as a configurable alternative, and confirm with NHCX onboarding which form their gateway route expects. The rest of the flow is unchanged: 202 acknowledgement, provider callback within 30 seconds, and the acknowledgement Task on the on_request path. + + ### Specification + + Chapter [Communication](/docs/nhcx/v1/reference/fhir/communication) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - $ref: "#/components/parameters/XHcxSenderCode" + - $ref: "#/components/parameters/XHcxRecipientCode" + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxWorkflowId" + - $ref: "#/components/parameters/XHcxTimestamp" + - $ref: "#/components/parameters/XHcxStatus" + - $ref: "#/components/parameters/XHcxBenAbhaId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOiIxNTE4QGhjeCJ9.encrypted_key.iv.ciphertext.tag + responses: + "200": + description: "Returns the same response set as the public endpoint: 202 Accepted with a StatusSuccessResponse (timestamp, api_call_id, correlation_id, result, error), or 400 Request Validation failed, 404 Requested resource was not found and 500 Downstream systems down/unhandled exceptions in the same envelope." + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 25/08/2026 12:05:00:412 + api_call_id: c3d4e5f6-a7b8-9012-cdef-123456789012 + correlation_id: 22334455-6677-8899-aabb-ccddeeff0011 + result: + sender_code: 1518@hcx + recipient_code: 1000004446@hcx + entity_type: task + protocol_status: request.queued + error: + code: "" + message: "" + /internal/v1/communication/on_request: + post: + operationId: communication_internal_v1_communication_on_request + x-abdm-use-case: Adapter + tags: + - Adapter + summary: Communication acknowledgement callback (internal variant) (adapter) + description: |- + Internal twin of /v1/communication/on_request: the provider acknowledgement Task bundle, operationId communicationOnRequestPostInternal. + + ### Business purpose + + This is the internal-path form of the provider acknowledgement that closes a payer communication. The OpenAPI document lists it with the same description and bare object request body as the public callback and distinguishes it only by the operationId suffix. Its business role is unchanged: give the payer auditable confirmation that a TAT alert, grievance, wallet or policy update or additional-information request reached the hospital, so adjudication and SLA tracking can proceed inside NHCX rather than over phone or email. + + ### When to use + + Use it in the same circumstances as the public on_request callback: after receiving, acknowledging with a synchronous 202, and persisting a communication request, the provider posts a mirror-image Task bundle with the same reasonCode, Task.code poll, Task.intent proposal, Task.status completed and the same x-hcx-correlation_id. The responder status is response.complete, response.partial or response.error. The specs do not say when the internal path is used instead of the public one; follow your onboarding instructions. + + ### Preconditions + + - The inbound communication was decrypted and its correlation id, status and workflow id captured. + - A valid Bearer token and the payer's certificate for encrypting the acknowledgement. + - The acknowledgement bundle mirrors the request, provider Organization first, timestamps updated. + - Protected header echoes the request's x-hcx-correlation_id, carries a fresh x-hcx-api_call_id, an IST timestamp and a responder status; x-hcx-workflow_id is validated at the gateway. + - Confirm the internal prefix is the route you were onboarded to before using it. + + ### Postconditions + + Same as the public callback: HTTP 202 with the StatusSuccessResponse envelope, or 400, 404 or 500 in the same shape; the bundle is forwarded to the payer, who links it to the original notification by correlation id and by the shared claim or preauth reference. The underlying issue remains open until resolved through the preauth or claim path. No additional behaviour is documented for the internal variant. + + ### Common mistakes + + - Expecting the internal path to relax any rule; it carries the same validation and the same errors (NHCX-1010 for an unknown correlation id, NHCX-1011 for a bad status value). + - Minting a new correlation id on the acknowledgement. + - Sending this call in place of the synchronous 202, which triggers the five-attempt retry loop and deletion of the request. + - Closing the case because Communication.status is completed. + - Using an unconfigurable path prefix that cannot switch between public and internal forms. + + ### Best practices + + - Share one acknowledgement builder with the public callback; only the path differs. + - Return 202 within 30 seconds first, then post the acknowledgement asynchronously. + - Be idempotent on correlation id; expect redeliveries. + - Route on Task.reasonCode and log reason, category, priority and correlation id. + - Keep IST timestamps and a fresh api_call_id on every call. + + ### Related scenario + + A hospital integrator generating client code from the communicationhcxservice Swagger finds two acknowledgement operations, communicationOnRequestPost and communicationOnRequestPostInternal, with identical descriptions. The team implements one handler for inbound communications, answers 202 immediately, and posts the acknowledgement Task to the public /v1/communication/on_request path as the handbook documents, leaving the internal form selectable by configuration. When a walletupdate arrives for a patient mid-admission, the same handler refreshes the benefit cache before the enhancement request goes out on /v1/preauth/submit. + + ### Specification + + Chapter [Communication](/docs/nhcx/v1/reference/fhir/communication) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + - name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxWorkflowId" + - $ref: "#/components/parameters/XHcxTimestamp" + - name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: response.complete + - $ref: "#/components/parameters/XHcxBenAbhaId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOiIxMDAwMDA0NDQ2QGhjeCJ9.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: "Same as the public callback: HTTP 202 with the StatusSuccessResponse envelope, or 400, 404 or 500 in the same shape; the bundle is forwarded to the payer, who links it to the original notification by correlation id and by the shared claim or preauth reference." + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 25/08/2026 12:15:00:377 + api_call_id: d4e5f6a7-b8c9-0123-def0-234567890123 + correlation_id: 22334455-6677-8899-aabb-ccddeeff0011 + result: + sender_code: 1000004446@hcx + recipient_code: 1518@hcx + entity_type: task + protocol_status: request.queued + error: + code: "" + message: "" +webhooks: + v1_communication_request: + post: + operationId: communication_webhook_v1_communication_request + x-abdm-atom: nhcx.callback.communication-request + x-abdm-triggered-by: communication_v1_communication_request + x-abdm-use-case: Webhooks + tags: + - Communication + summary: Receive communication request + description: |- + Hosted by the provider. The exchange posts this message to the `endpoint_url` you registered, at `/v1/communication/request`, with the headers and the sealed payload the sender posted. Answer HTTP 202 with the receipt first and process afterwards; [Receiving a callback](/docs/nhcx/v1/getting-started/receiving-a-callback) has the rules. + + Payer pushes a Task plus Communication bundle to a provider mid-claim: TAT alerts, wallet or policy changes, grievances or extra-information requests. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - $ref: "#/components/parameters/XHcxSenderCode" + - $ref: "#/components/parameters/XHcxRecipientCode" + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxWorkflowId" + - $ref: "#/components/parameters/XHcxTimestamp" + - $ref: "#/components/parameters/XHcxStatus" + - $ref: "#/components/parameters/XHcxBenAbhaId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOiIxNTE4QGhjeCJ9.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: Received. The receipt names the message it answers; the answer itself follows as a call of your own. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 04/09/2026 11:46:41:305 + api_call_id: + correlation_id: + result: + sender_code: 1000003538@hcx + recipient_code: 1000004446@hcx + entity_type: preauth + protocol_status: request.queued + error: + code: "" + message: "" + v1_communication_on_request: + post: + operationId: communication_webhook_v1_communication_on_request + x-abdm-atom: nhcx.callback.communication-on-request + x-abdm-triggered-by: communication_v1_communication_on_request + x-abdm-use-case: Webhooks + tags: + - Communication + summary: Receive communication acknowledgement callback + description: |- + Hosted by the payer. The exchange posts this message to the `endpoint_url` you registered, at `/v1/communication/on_request`, with the headers and the sealed payload the sender posted. Answer HTTP 202 with the receipt first and process afterwards; [Receiving a callback](/docs/nhcx/v1/getting-started/receiving-a-callback) has the rules. + + Provider returns the acknowledgement Task bundle for a payer communication, echoing the reason code and correlation id so the payer can close the loop. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + - name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxWorkflowId" + - $ref: "#/components/parameters/XHcxTimestamp" + - name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: response.complete + - $ref: "#/components/parameters/XHcxBenAbhaId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOiIxMDAwMDA0NDQ2QGhjeCJ9.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: Received. The receipt names the message it answers; the answer itself follows as a call of your own. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 04/09/2026 11:46:41:305 + api_call_id: + correlation_id: + result: + sender_code: 1000003538@hcx + recipient_code: 1000004446@hcx + entity_type: preauth + protocol_status: request.queued + error: + code: "" + message: "" +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + description: "On every NHCX call, the token goes in a header called `bearer_auth`, with the word `Bearer` and a space in front. The sources are not unanimous: the authentication page and the FAQ both write the example as `Authorization`, and the notification endpoint uses `Authorization`. The safe course, and what the adapter does, is to send both headers with the same value." + parameters: + BearerAuth: + name: bearer_auth + in: header + required: true + description: It is `bearer_auth`, not `Authorization`, on NHCX's own endpoints. + schema: + type: string + example: Bearer + XHcxSenderCode: + name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + XHcxRecipientCode: + name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + XHcxApiCallId: + name: x-hcx-api_call_id + in: header + required: true + description: Fresh on every message, including responses. Mandatory on the envelope. + schema: + type: string + example: + XHcxRequestId: + name: x-hcx-request_id + in: header + required: false + description: One per originating request. The Open Protocol page marks it Mandatory; the Technical Specifications page marks it Optional. Optional on the envelope. + schema: + type: string + example: + XHcxCorrelationId: + name: x-hcx-correlation_id + in: header + required: true + description: The thread. See the rule below. Mandatory on the envelope. + schema: + type: string + example: + XHcxWorkflowId: + name: x-hcx-workflow_id + in: header + required: false + description: Which step, or which case. See the two readings below. Optional on the envelope. + schema: + type: string + example: "15" + XHcxTimestamp: + name: x-hcx-timestamp + in: header + required: true + description: See the format note below. Mandatory on the envelope. + schema: + type: string + example: + XHcxStatus: + name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: request.initiated + XHcxBenAbhaId: + name: x-hcx-ben-abha-id + in: header + required: true + description: The beneficiary's ABHA number. Mandatory on every exchange, including those with no beneficiary in the payload. Mandatory on the envelope. + schema: + type: string + example: "91711234567890" +x-abdm-errors: + notes: "Codes any exchange call can meet are recorded once, in the [Other](/docs/nhcx/v1/api/other) specification: the gateway's NHCX- codes, the standard payer codes, and the reference payer's structure and transport codes. The reference payer's other codes sit with the exchange they reject: coverage eligibility, preauthorisation, claim and insurance plan. [Reading error codes](/docs/nhcx/v1/reference/error-code-guide) explains the code spaces." diff --git a/catalogue/openapi/nhcx/v1/nhcx-eligibility.yaml b/catalogue/openapi/nhcx/v1/nhcx-eligibility.yaml new file mode 100644 index 000000000..0628bb239 --- /dev/null +++ b/catalogue/openapi/nhcx/v1/nhcx-eligibility.yaml @@ -0,0 +1,908 @@ +# NHCX coverage eligibility, from the NHCX package's Bruno folder apis/02-eligibility. +# +# Written by the package's system/build-ekadocs.mjs (make ekadocs); change the .bru +# requests there and port again rather than editing this file. +# +# Rules this file follows: catalogue/openapi/CONVENTIONS.md +openapi: 3.1.1 +info: + x-portal: + module: eligibility + label: Coverage eligibility + position: 2 + title: NHCX coverage eligibility + summary: Coverage eligibility is the pre-check a hospital desk runs before committing a patient to a cashless pathway. + description: |- + The Coverage eligibility calls on the National Health Claims Exchange (NHCX): 4 operations, and 2 callbacks you host. + + Coverage eligibility is the pre-check a hospital desk runs before committing a patient to a cashless pathway. + + Guides that use these calls: [Coverage eligibility request](/docs/nhcx/v1/reference/fhir/coverage-eligibility-request), [Coverage eligibility response](/docs/nhcx/v1/reference/fhir/coverage-eligibility-response). + version: nhcx-v1 + license: + name: MIT + identifier: MIT + contact: + name: NHCX sandbox + url: https://hcxsbx.abdm.gov.in + x-abdm-gateway: nhcx + x-abdm-module: eligibility + x-abdm-phase: 1 + x-abdm-roles: + - provider + - payer +x-abdm-sources: + - file: nhcx-package/apis/02-eligibility + role: upstream + hash: sha256:e42e738c449e98effd44ddef6394558cb87c97fc073c3ddb7d9662895f6afe51 + note: The package's Bruno collection, one request per operation. + - file: nhcx-package/baseurl.yaml + role: upstream + hash: sha256:88515b7b29c6b349a131e016c80774436ea16a29738db743b4cc3a24cbd42453 + note: The sandbox and production hosts. + - file: nhcx-package/nhcx-error.yaml + role: upstream + hash: sha256:d24ac927ed4dd722e60d7bd1d6fed15de370cc29f750d68999ee56fac93c941b + note: The error codes. +servers: + - url: https://apisbx.abdm.gov.in/hcx + description: Sandbox, NHCX exchange. + - url: https://apisprod.nha.gov.in/hcx + description: Production. +tags: + - name: Coverage eligibility + description: Coverage eligibility is the pre-check a hospital desk runs before committing a patient to a cashless pathway. + - name: Adapter + description: Internal twins of the exchange calls, for the NHCX adapter deployment. +security: + - bearerAuth: [] +paths: + /v1/coverageeligibility/check: + post: + operationId: eligibility_v1_coverageeligibility_check + x-abdm-atom: nhcx.endpoint.coverageeligibility-check + x-abdm-use-case: Coverage eligibility + tags: + - Coverage eligibility + summary: Coverage eligibility check + description: |- + Provider asks the payer, via NHCX, whether a beneficiary's policy is in force, what it covers and which documents a preauth will need. + + ### Business purpose + + Coverage eligibility is the pre-check a hospital desk runs before committing a patient to a cashless pathway. It confirms three things the desk needs: that the policy is active, what benefits and wallet balance are available, and whether a specific procedure needs authorisation at all. A rejection that would otherwise surface days later at preauth or claim adjudication surfaces in seconds while the patient is still at the counter, which benefits the hospital (less rework), the payer (fewer malformed preauths) and the patient (earlier certainty). + + ### When to use + + Call it at registration or admission, before /v1/preauth/submit. The CoverageEligibilityRequest.purpose field (1..*) decides what the payer computes: discovery is the fallback when /participant/get/policies does not yield a policy code; validation retrieves used amount, available balance and wallet liability; auth-requirements checks whether a chosen procedure is covered at this hospital and returns the STG questionnaires and MAND document codes the preauth must carry; benefits is also listed. Send x-hcx-status request.initiated. No eligibility-specific workflow code is published in the workflow tables; the workbook sample shows x-hcx-workflow_id 11 (PATIENT_ADMITTED). For PMJAY an unspecified procedure still requires an auth-requirements check. + + ### Preconditions + + - The provider is an onboarded NHCX participant (otherwise NHCX-1002) holding a valid Bearer token from the client-credentials session call; tokens expire after 1200 seconds. + - The payer's public certificate has been fetched via /fetch/certs (cache 24 hours) and the bundle is JWE-encrypted with RSA-OAEP-256 and A256GCM. + - x-hcx-recipient_code is the processingID from the get/policies response, not the PayerID. + - x-hcx-correlation_id is a fresh UUID for this request cycle; x-hcx-api_call_id is unique per call. + - The bundle contains the Patient (PMJAY Member ID and/or ABHA number), the Coverage record, both Organisations (provider and insurer) and a PractitionerRole for the enterer; items are included when purpose is auth-requirements. + - HTTP headers Accept: application/json, Content-Type: application/json and bearer_auth are all present. + + ### Postconditions + + NHCX replies synchronously with HTTP 202 Accepted and a StatusSuccessResponse acknowledgement (timestamp, api_call_id, correlation_id, result with sender_code, recipient_code, entity_type coverageeligibility and protocol_status such as request.queued or request.dispatched, plus an empty error object). The 202 means only that the JWE structure and open protocol headers validated; the gateway then forwards the request to the payer asynchronously. The eligibility answer arrives later on the provider's /v1/coverageeligibility/on_check endpoint as a CoverageEligibilityResponseBundle, or as a ProtocolResponse carrying x-hcx-error_details, or as a redirect or forward instruction to try another payer. Other documented statuses are 400 request validation failed, 404 resource not found and 500 downstream systems down. + + ### Common mistakes + + - Treating the 202 as the eligibility answer instead of waiting for the on_check callback; NHCX never returns a synchronous FHIR decision. + - Using the PayerID from get/policies as x-hcx-recipient_code instead of the processingID (NHCX-1003 receiver not registered). + - Reusing a correlation ID from an earlier cycle (NHCX-1006 duplicate request) or retrying a failed cycle under the same ID, which NHCX has already marked inactive. + - Sending the wrong status string; only request.initiated is accepted on an initiating request (NHCX-1011). + - Payer-side business rejections such as PAYR-1113 invalid item code, PAYR-1115 quantity not greater than 1, PAYR-1116 hospital not authorised for the policy, PAYR-1117 or PAYR-1122 no policy details, PAYR-1123 beneficiary not a covered member, and PAYR-1014 date of birth after date of service. + - Omitting the Accept header on the HTTP call. + + ### Best practices + + - Persist the correlation ID against the patient episode before posting; it is the only key for matching the callback. + - Refresh the token automatically before the 1200-second expiry and treat a 401 as refresh-and-retry-once. + - Run discovery first only when get/policies gives no policy code, then validation, then auth-requirements for the chosen package; store the returned MAND codes and STG questionnaire references and attach them to the preauth. + - Do not assume the response echoes your request codes: items come back in the payer's numeric master codes (for example 100478 against your MG003B). + - Use IST timestamps with the +05:30 offset in the protected header. + - Log the 202 body (protocol_status, api_call_id) so a missing callback can be traced with /v1/status. + + ### Related scenario + + A patient arrives at a district hospital with a PMJAY card. The desk calls /participant/get/policies and receives a processingID for the state health agency. Because the treating doctor wants a corneal grafting package, the desk builds a CoverageEligibilityRequest with purpose validation and auth-requirements, encrypts it for the payer and posts it to /v1/coverageeligibility/check, receiving a 202 with protocol_status request.queued. Minutes later the payer's answer lands on /v1/coverageeligibility/on_check with inforce true, authorizationRequired true and MAND0409 and MAND0104 listed as supporting documents. The desk collects those documents and proceeds to /v1/preauth/submit under workflow 12. + + ### Specification + + Chapter [Coverage eligibility request](/docs/nhcx/v1/reference/fhir/coverage-eligibility-request) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - $ref: "#/components/parameters/XHcxSenderCode" + - $ref: "#/components/parameters/XHcxRecipientCode" + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxWorkflowId" + - $ref: "#/components/parameters/XHcxTimestamp" + - $ref: "#/components/parameters/XHcxStatus" + - $ref: "#/components/parameters/XHcxBenAbhaId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOi4uLn0.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: NHCX replies synchronously with HTTP 202 Accepted and a StatusSuccessResponse acknowledgement (timestamp, api_call_id, correlation_id, result with sender_code, recipient_code, entity_type coverageeligibility and protocol_status such as request.queued or request.dispatched, plus an empty error object). + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 19/03/2026 11:46:35:120 + api_call_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890 + correlation_id: 11223344-5566-7788-99aa-bbccddeeff00 + result: + sender_code: 1000004446@hcx + recipient_code: 1518@hcx + entity_type: coverageeligibility + protocol_status: request.queued + error: + code: "" + message: "" + /v1/coverageeligibility/on_check: + post: + operationId: eligibility_v1_coverageeligibility_on_check + x-abdm-atom: nhcx.endpoint.coverageeligibility-on-check + x-abdm-use-case: Coverage eligibility + tags: + - Coverage eligibility + summary: Coverage eligibility callback + description: |- + Payer returns the CoverageEligibilityResponse (policy in force, benefits, auth requirements) or an error to the provider through NHCX. + + ### Business purpose + + This is the answer leg of the eligibility check. The payer (or a TPA acting for it) tells the provider whether the policy is live, which items are covered or excluded, the allowed amounts, whether preauthorisation is required and which supporting documents the preauth must carry. Delivering this before treatment lets the hospital counsel the patient and assemble the right evidence, and lets the payer avoid adjudicating preauths that were never going to be covered. + + ### When to use + + The payer calls it after it has processed a /v1/coverageeligibility/check request, using the same x-hcx-correlation_id. The protected header carries x-hcx-status response.complete for a final answer (the coverage-eligibility workbook sheets spell this response.completed; the preauth and claim sheets use response.complete), response.partial for a partial answer, or response.error for a protocol-level rejection with x-hcx-error_details populated. The plaintext is a CoverageEligibilityResponseBundle with outcome complete, insurance[*].inforce, item[*].excluded, item[*].authorizationRequired and item[*].authorizationSupporting. A redirect or forward instruction to another payer is an alternate documented outcome. + + ### Preconditions + + - A /v1/coverageeligibility/check request with this correlation ID must exist in NHCX; a callback against an unknown or already deleted correlation ID fails with NHCX-1010. + - The payer has a valid Bearer token and has fetched the provider's certificate to encrypt the response bundle for the provider's private key. + - x-hcx-correlation_id echoes the request's value; x-hcx-api_call_id is a new UUID; sender and recipient codes are swapped relative to the request. + - x-hcx-status is one of response.complete, response.partial or response.error (NHCX-1011 otherwise). + - Business or clinical errors are embedded inside the encrypted CoverageEligibilityResponse, never in the clear header; only protocol errors go in x-hcx-error_details. + + ### Postconditions + + The gateway (and, when the callback reaches it, the provider system) returns HTTP 202 Accepted with the StatusSuccessResponse acknowledgement echoing correlation_id and api_call_id, entity_type coverageeligibility and a protocol_status. NHCX forwards the encrypted response to the provider's registered callback URL; the provider must acknowledge with 202 within 30 seconds or NHCX retries, and after five failed attempts the request under that correlation ID is deleted and the sender is notified via v1/error. On success the eligibility conversation is closed and the provider can decide whether to proceed to preauth. + + ### Common mistakes + + - Returning HTTP 200 or an ad-hoc body instead of the 202 acceptance shape on the receiving side, which NHCX treats as an error and retries up to five times. + - Minting a new correlation ID on the callback instead of echoing the request's (NHCX-1010 no data with given correlation id). + - Sending a JWEPayloadResponse where a ProtocolResponse is expected on error (PAYR-1517), or using the superseded status spelling response.fail versus response.error; the sources disagree, so check which your gateway build accepts. + - Placing patient or clinical error detail in x-hcx-error_details, which the gateway stores for audit. + - Provider side: expecting the response codes to match the request codes verbatim; the payer answers in its own master codes. + + ### Best practices + + - Acknowledge first, process later: return 202 within 30 seconds and queue decryption and business handling. + - Be idempotent on x-hcx-correlation_id; the same callback may be redelivered up to five times. + - Set inforce, disposition, excluded, authorizationRequired and authorizationSupporting explicitly so the desk can act without free-text interpretation. + - Use ProtocolResponse with x-hcx-status response.error and a catalogued error code for protocol rejections; put business errors inside the encrypted resource. + - Providers: whitelist the NHCX NAT IPs, expose the callback on a domain name (not IP or port) on an India-based server, and implement v1/error alongside on_check. + + ### Related scenario + + A state health agency's bridge receives an eligibility check for a beneficiary requesting validation and auth-requirements for package SE012A. Its rules engine confirms the policy is active with sufficient wallet balance and that SE012A needs preauthorisation with documents MAND0409, MAND0104 and MAND0062. The bridge builds a CoverageEligibilityResponseBundle, encrypts it for the hospital, sets x-hcx-status response.complete with the original correlation ID and posts it to /v1/coverageeligibility/on_check. NHCX acknowledges with 202 and delivers it to the hospital's callback, which acknowledges within 30 seconds; the hospital then prepares its /v1/preauth/submit. + + ### Specification + + Chapter [Coverage eligibility response](/docs/nhcx/v1/reference/fhir/coverage-eligibility-response) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + - name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxWorkflowId" + - $ref: "#/components/parameters/XHcxTimestamp" + - name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: response.complete + - $ref: "#/components/parameters/XHcxBenAbhaId" + - $ref: "#/components/parameters/XHcxDebugFlag" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOi4uLn0.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: The gateway (and, when the callback reaches it, the provider system) returns HTTP 202 Accepted with the StatusSuccessResponse acknowledgement echoing correlation_id and api_call_id, entity_type coverageeligibility and a protocol_status. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 19/03/2026 11:46:35:120 + api_call_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890 + correlation_id: 11223344-5566-7788-99aa-bbccddeeff00 + result: + sender_code: 1518@hcx + recipient_code: 1000004446@hcx + entity_type: coverageeligibility + protocol_status: request.dispatched + error: + code: "" + message: "" + /internal/v1/coverageeligibility/check: + post: + operationId: eligibility_internal_v1_coverageeligibility_check + x-abdm-use-case: Adapter + tags: + - Adapter + summary: Coverage eligibility check (internal) (adapter) + description: |- + Internal twin of /v1/coverageeligibility/check with the same JWEPayload body and response set; only the operationId differs. + + ### Business purpose + + The coverage eligibility service publishes its check operation twice, once at /v1 and once at /internal/v1. Both let a provider validate a beneficiary's coverage with a payer before preauthorisation. The internal path exists in the OpenAPI document as an operationally distinct route for the same business function; the published material does not describe a separate business purpose for it. + + ### When to use + + Documented as the internal variant of the eligibility check (operationId coverageeligibilityCheckPostInternal), served by coverageeligibilityhcxservice and tagged V1.0 APIs-Payer side like its public twin. The same purposes (discovery, validation, auth-requirements, benefits) and the same x-hcx-status request.initiated apply. The OpenAPI specs expose this operation twice, at /v1/... and at /internal/v1/..., with identical descriptions, request bodies and response sets; only the operationId differs (an Internal suffix). The specs do not document what makes the internal variant different beyond that suffix, so treat it as a mirror of the public path and integrate against the public /v1 path unless NHCX onboarding tells you otherwise. + + ### Preconditions + + Identical to the public path: an onboarded provider with a valid Bearer token, the payer certificate fetched and cached, a CoverageEligibilityRequest bundle encrypted with RSA-OAEP-256 and A256GCM, a fresh correlation UUID, the processingID as recipient code, and the full x-hcx-* protected header set. Nothing additional is documented for the internal route. + + ### Postconditions + + Same as /v1/coverageeligibility/check: HTTP 202 Accepted with a StatusSuccessResponse acknowledgement, then asynchronous forwarding to the payer and an answer on the on_check callback (the internal twin /internal/v1/coverageeligibility/on_check exists with the same body). 400, 404 and 500 carry the same schema. + + ### Common mistakes + + - Assuming the internal path has different semantics or a different body; the specs give it the same JWEPayload body and the same responses. + - Integrating against the internal path without confirmation from NHCX onboarding, then hitting a 404 on the gateway host; when a path 404s, the endpoint index recommends trying the alternate host and prefix shape. + - All the mistakes listed for the public check (202 treated as an answer, wrong recipient code, reused correlation ID, wrong status string) apply unchanged. + + ### Best practices + + - Default to /v1/coverageeligibility/check; use the internal path only where NHCX instructs you to. + - Keep one client implementation for both paths, parameterised only on the URL, so header hygiene and correlation handling stay identical. + - Log which variant was used with each correlation ID for troubleshooting. + + ### Related scenario + + A hospital integration team exploring the coverageeligibilityhcxservice Swagger sees two check operations. They build one client against /v1/coverageeligibility/check and confirm with NHCX support whether the internal twin is meant for their deployment. In production traffic the eligibility request still starts from get/policies, goes out as a JWE to the check path, receives a 202, and the payer's answer arrives on the on_check callback before the preauth is raised. + + ### Specification + + Chapter [Coverage eligibility request](/docs/nhcx/v1/reference/fhir/coverage-eligibility-request) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - $ref: "#/components/parameters/XHcxSenderCode" + - $ref: "#/components/parameters/XHcxRecipientCode" + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxWorkflowId" + - $ref: "#/components/parameters/XHcxTimestamp" + - $ref: "#/components/parameters/XHcxStatus" + - $ref: "#/components/parameters/XHcxBenAbhaId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOi4uLn0.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: "Same as /v1/coverageeligibility/check: HTTP 202 Accepted with a StatusSuccessResponse acknowledgement, then asynchronous forwarding to the payer and an answer on the on_check callback (the internal twin /internal/v1/coverageeligibility/on_check exists with the same body)." + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 19/03/2026 11:46:35:120 + api_call_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890 + correlation_id: 11223344-5566-7788-99aa-bbccddeeff00 + result: + sender_code: 1000004446@hcx + recipient_code: 1518@hcx + entity_type: coverageeligibility + protocol_status: request.queued + error: + code: "" + message: "" + /internal/v1/coverageeligibility/on_check: + post: + operationId: eligibility_internal_v1_coverageeligibility_on_check + x-abdm-use-case: Adapter + tags: + - Adapter + summary: Coverage eligibility callback (internal) (adapter) + description: |- + Internal twin of /v1/coverageeligibility/on_check taking the same bare object body; only the operationId differs. + + ### Business purpose + + Mirror of the public eligibility callback: the payer or TPA returns the CoverageEligibilityResponseBundle, or a protocol error, to the provider through NHCX. It serves the same settlement purpose, letting the hospital know before treatment whether the policy is in force and which documents the preauth will need. No separate business role is documented for the internal route. + + ### When to use + + Documented as the internal variant of the eligibility callback (operationId coverageeligibilityOnCheckPostInternal), tagged V1.0 APIs-Provider side. Called after processing a check request, with the request's correlation ID and x-hcx-status response.complete, response.partial or response.error. The OpenAPI specs expose this operation twice, at /v1/... and at /internal/v1/..., with identical descriptions, request bodies and response sets; only the operationId differs (an Internal suffix). The specs do not document what makes the internal variant different beyond that suffix, so treat it as a mirror of the public path and integrate against the public /v1 path unless NHCX onboarding tells you otherwise. + + ### Preconditions + + Identical to the public callback: an in-flight check request with this correlation ID, the provider's certificate for encryption, a new api_call_id, swapped sender and recipient codes, a valid responder status, and business errors embedded inside the encrypted resource rather than the header. + + ### Postconditions + + Same as /v1/coverageeligibility/on_check: HTTP 202 Accepted with the StatusSuccessResponse acknowledgement, asynchronous delivery to the provider's callback URL with the 30-second acknowledgement rule, five retries then deletion on failure, and closure of the eligibility conversation on success. + + ### Common mistakes + + - Treating the internal callback as a different contract; the spec gives it the same object body and response set as the public path. + - Every public on_check pitfall applies: returning 200 instead of the 202 acceptance body, minting a new correlation ID, sending a JWEPayloadResponse instead of a ProtocolResponse on error (PAYR-1517), and leaking business errors into x-hcx-error_details. + + ### Best practices + + - Route both callback variants to the same handler keyed on x-hcx-correlation_id so behaviour cannot diverge. + - Acknowledge with 202 inside 30 seconds and process asynchronously; be idempotent under redelivery. + - Use the public /v1 path unless NHCX onboarding specifies the internal one. + + ### Related scenario + + A TPA bridge that processes eligibility checks on behalf of an insurer sees both on_check operations in the service spec. It implements a single response builder that populates inforce, excluded and authorizationRequired, echoes the correlation ID and posts to /v1/coverageeligibility/on_check by default, with the internal path configurable if NHCX requires it. The hospital's callback acknowledges with 202 and the desk moves on to the preauth. + + ### Specification + + Chapter [Coverage eligibility response](/docs/nhcx/v1/reference/fhir/coverage-eligibility-response) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + - name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxWorkflowId" + - $ref: "#/components/parameters/XHcxTimestamp" + - name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: response.complete + - $ref: "#/components/parameters/XHcxBenAbhaId" + - $ref: "#/components/parameters/XHcxDebugFlag" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOi4uLn0.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: "Same as /v1/coverageeligibility/on_check: HTTP 202 Accepted with the StatusSuccessResponse acknowledgement, asynchronous delivery to the provider's callback URL with the 30-second acknowledgement rule, five retries then deletion on failure, and closure of the eligibility conversation on success." + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 19/03/2026 11:46:35:120 + api_call_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890 + correlation_id: 11223344-5566-7788-99aa-bbccddeeff00 + result: + sender_code: 1518@hcx + recipient_code: 1000004446@hcx + entity_type: coverageeligibility + protocol_status: request.dispatched + error: + code: "" + message: "" +webhooks: + v1_coverageeligibility_check: + post: + operationId: eligibility_webhook_v1_coverageeligibility_check + x-abdm-atom: nhcx.callback.coverageeligibility-check + x-abdm-triggered-by: eligibility_v1_coverageeligibility_check + x-abdm-use-case: Webhooks + tags: + - Coverage eligibility + summary: Receive coverage eligibility check + description: |- + Hosted by the payer. The exchange posts this message to the `endpoint_url` you registered, at `/v1/coverageeligibility/check`, with the headers and the sealed payload the sender posted. Answer HTTP 202 with the receipt first and process afterwards; [Receiving a callback](/docs/nhcx/v1/getting-started/receiving-a-callback) has the rules. + + Provider asks the payer, via NHCX, whether a beneficiary's policy is in force, what it covers and which documents a preauth will need. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - $ref: "#/components/parameters/XHcxSenderCode" + - $ref: "#/components/parameters/XHcxRecipientCode" + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxWorkflowId" + - $ref: "#/components/parameters/XHcxTimestamp" + - $ref: "#/components/parameters/XHcxStatus" + - $ref: "#/components/parameters/XHcxBenAbhaId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOi4uLn0.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: Received. The receipt names the message it answers; the answer itself follows as a call of your own. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 04/09/2026 11:46:41:305 + api_call_id: + correlation_id: + result: + sender_code: 1000003538@hcx + recipient_code: 1000004446@hcx + entity_type: preauth + protocol_status: request.queued + error: + code: "" + message: "" + v1_coverageeligibility_on_check: + post: + operationId: eligibility_webhook_v1_coverageeligibility_on_check + x-abdm-atom: nhcx.callback.coverageeligibility-on-check + x-abdm-triggered-by: eligibility_v1_coverageeligibility_on_check + x-abdm-use-case: Webhooks + tags: + - Coverage eligibility + summary: Receive coverage eligibility callback + description: |- + Hosted by the provider. The exchange posts this message to the `endpoint_url` you registered, at `/v1/coverageeligibility/on_check`, with the headers and the sealed payload the sender posted. Answer HTTP 202 with the receipt first and process afterwards; [Receiving a callback](/docs/nhcx/v1/getting-started/receiving-a-callback) has the rules. + + Payer returns the CoverageEligibilityResponse (policy in force, benefits, auth requirements) or an error to the provider through NHCX. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + - name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxWorkflowId" + - $ref: "#/components/parameters/XHcxTimestamp" + - name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: response.complete + - $ref: "#/components/parameters/XHcxBenAbhaId" + - $ref: "#/components/parameters/XHcxDebugFlag" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOi4uLn0.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: Received. The receipt names the message it answers; the answer itself follows as a call of your own. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 04/09/2026 11:46:41:305 + api_call_id: + correlation_id: + result: + sender_code: 1000003538@hcx + recipient_code: 1000004446@hcx + entity_type: preauth + protocol_status: request.queued + error: + code: "" + message: "" +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + description: "On every NHCX call, the token goes in a header called `bearer_auth`, with the word `Bearer` and a space in front. The sources are not unanimous: the authentication page and the FAQ both write the example as `Authorization`, and the notification endpoint uses `Authorization`. The safe course, and what the adapter does, is to send both headers with the same value." + parameters: + BearerAuth: + name: bearer_auth + in: header + required: true + description: It is `bearer_auth`, not `Authorization`, on NHCX's own endpoints. + schema: + type: string + example: Bearer + XHcxSenderCode: + name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + XHcxRecipientCode: + name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + XHcxApiCallId: + name: x-hcx-api_call_id + in: header + required: true + description: Fresh on every message, including responses. Mandatory on the envelope. + schema: + type: string + example: + XHcxRequestId: + name: x-hcx-request_id + in: header + required: false + description: One per originating request. The Open Protocol page marks it Mandatory; the Technical Specifications page marks it Optional. Optional on the envelope. + schema: + type: string + example: + XHcxCorrelationId: + name: x-hcx-correlation_id + in: header + required: true + description: The thread. See the rule below. Mandatory on the envelope. + schema: + type: string + example: + XHcxWorkflowId: + name: x-hcx-workflow_id + in: header + required: false + description: Which step, or which case. See the two readings below. Optional on the envelope. + schema: + type: string + example: "11" + XHcxTimestamp: + name: x-hcx-timestamp + in: header + required: true + description: See the format note below. Mandatory on the envelope. + schema: + type: string + example: + XHcxStatus: + name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: request.initiated + XHcxBenAbhaId: + name: x-hcx-ben-abha-id + in: header + required: true + description: The beneficiary's ABHA number. Mandatory on every exchange, including those with no beneficiary in the payload. Mandatory on the envelope. + schema: + type: string + example: "91711234567890" + XHcxDebugFlag: + name: x-hcx-debug_flag + in: header + required: false + description: "`Error`, `Info` or `Debug`. A server may ignore it. Optional on the envelope." + schema: + type: string + example: INFO +x-abdm-errors: + notes: "Codes any exchange call can meet are recorded once, in the [Other](/docs/nhcx/v1/api/other) specification: the gateway's NHCX- codes, the standard payer codes, and the reference payer's structure and transport codes. The reference payer's other codes sit with the exchange they reject: coverage eligibility, preauthorisation, claim and insurance plan. [Reading error codes](/docs/nhcx/v1/reference/error-code-guide) explains the code spaces." +x-abdm-errors-reference-payer: + source: Reference payer codes, PAYR-1001 to PAYR-1520. Sent by the PMJAY reference implementation; they arrive inside the sealed response. + codes: + - code: PAYR-1101 + message: Invalid purpose received as (%s) for beneficiary id (%s) from hospital id (%s). Hence no result will be returned. Please try again with a valid purpose. + action: "" + - code: PAYR-1102 + message: Invalid search parameter requested. Please try again with a valid id. + action: "" + - code: PAYR-1103 + message: Invalid careplan id received. Please try again with valid careplan id. + action: "" + - code: PAYR-1104 + message: Multiple records found for the beneficiary. Hence request will not be processed further. + action: "" + - code: PAYR-1105 + message: Hospital configuration not found. Please contact support team. + action: "" + - code: PAYR-1106 + message: No details found for the requested procedures in the system. + action: "" + - code: PAYR-1107 + message: No billable item received. Please try again with valid item data. + action: "" + - code: PAYR-1108 + message: No details found for the requested stratification in the system. + action: "" + - code: PAYR-1109 + message: No details found for the requested investigations in the system. + action: "" + - code: PAYR-1110 + message: No details found for the requested implants in the system. + action: "" + - code: PAYR-1111 + message: Rule failure. + action: "" + - code: PAYR-1112 + message: Invalid payer id received. Please try again ith valid payer details + action: "" + - code: PAYR-1113 + message: Invalid item code received as %s. Please try again with valid data + action: "" + - code: PAYR-1114 + message: Invalid speciality code received as %s for item %s. Please try again with valid data. Speciality code is available as the code of the category for specific cost of plan in isurance plan + action: "" + - code: PAYR-1115 + message: Invalid procedure quantity received as %s for item %s. Please try again with valid data. Item quantity should be greater than 1 + action: "" + - code: PAYR-1116 + message: Hospital is not authorized to raise any case under policy %s. Hence request will not be processed further. Please connect with the support team to get the required authorization + action: "" + - code: PAYR-1117 + message: No policy details found for %s. Hence request will not be processed further + action: "" + - code: PAYR-1118 + message: No details found for requested items. Hence request will not be processed further + action: "" + - code: PAYR-1119 + message: No payer details received for payer id %s from HCX. Please try again with valid payer details. + action: "" + - code: PAYR-1120 + message: Duplicate reference id found as %s. Please try again with valid reference details. + action: "" + - code: PAYR-1121 + message: No policy details found for %s for beneficiary %s. Hence request will not be processed further. + action: "" + - code: PAYR-1122 + message: No policy details found for beneficiary %s. Hence request will not be processed further. + action: "" + - code: PAYR-1123 + message: Beneficiary is not a covered member for requested payer. Please enroll beneficiary for applicable policy of requested payer and try again. + action: "" diff --git a/catalogue/openapi/nhcx/v1/nhcx-insurance-plan.yaml b/catalogue/openapi/nhcx/v1/nhcx-insurance-plan.yaml new file mode 100644 index 000000000..8c12d3e77 --- /dev/null +++ b/catalogue/openapi/nhcx/v1/nhcx-insurance-plan.yaml @@ -0,0 +1,920 @@ +# NHCX insurance plan, from the NHCX package's Bruno folder apis/09-insurance-plan. +# +# Written by the package's system/build-ekadocs.mjs (make ekadocs); change the .bru +# requests there and port again rather than editing this file. +# +# Rules this file follows: catalogue/openapi/CONVENTIONS.md +openapi: 3.1.1 +info: + x-portal: + module: insurance-plan + label: Insurance plan + position: 9 + title: NHCX insurance plan + summary: Policies have traditionally been PDFs that hospital desks interpret by hand, producing ambiguity about benefits, claim conditions and documents, and rework and rejections downstream. + description: |- + The Insurance plan calls on the National Health Claims Exchange (NHCX): 4 operations, and 2 callbacks you host. + + Policies have traditionally been PDFs that hospital desks interpret by hand, producing ambiguity about benefits, claim conditions and documents, and rework and rejections downstream. + + Guides that use these calls: [Insurance plan request](/docs/nhcx/v1/reference/fhir/insurance-plan-request), [Insurance plan response](/docs/nhcx/v1/reference/fhir/insurance-plan-response-overview). + version: nhcx-v1 + license: + name: MIT + identifier: MIT + contact: + name: NHCX sandbox + url: https://hcxsbx.abdm.gov.in + x-abdm-gateway: nhcx + x-abdm-module: insurance-plan + x-abdm-phase: 1 + x-abdm-roles: + - provider + - payer +x-abdm-sources: + - file: nhcx-package/apis/09-insurance-plan + role: upstream + hash: sha256:a4d48ce98594530d1f58959c966bfc5b0cc4f94910a37853a45f1f63ecf0456b + note: The package's Bruno collection, one request per operation. + - file: nhcx-package/baseurl.yaml + role: upstream + hash: sha256:88515b7b29c6b349a131e016c80774436ea16a29738db743b4cc3a24cbd42453 + note: The sandbox and production hosts. + - file: nhcx-package/nhcx-error.yaml + role: upstream + hash: sha256:d24ac927ed4dd722e60d7bd1d6fed15de370cc29f750d68999ee56fac93c941b + note: The error codes. +servers: + - url: https://apisbx.abdm.gov.in/hcx + description: Sandbox, NHCX exchange. + - url: https://apisprod.nha.gov.in/hcx + description: Production. +tags: + - name: Insurance plan + description: Policies have traditionally been PDFs that hospital desks interpret by hand, producing ambiguity about benefits, claim conditions and documents, and rework and rejections downstream. + - name: Adapter + description: Internal twins of the exchange calls, for the NHCX adapter deployment. +security: + - bearerAuth: [] +paths: + /v1/insuranceplan/request: + post: + operationId: insurance_plan_v1_insuranceplan_request + x-abdm-atom: nhcx.endpoint.insuranceplan-request + x-abdm-use-case: Insurance plan + tags: + - Insurance plan + summary: Insurance plan request + description: |- + Provider sends a Task with code poll naming a policy number and/or its HFR id to fetch the payer's machine-readable InsurancePlan for that pairing. + + ### Business purpose + + Policies have traditionally been PDFs that hospital desks interpret by hand, producing ambiguity about benefits, claim conditions and documents, and rework and rejections downstream. The InsurancePlan API replaces that with a structured, provider-specific, policy-specific contract view: empanelled specialities, package codes and rates, implant and stratification qualifiers, claim conditions such as EnhancementAllowed or Standalone, mandatory documents and questionnaires. Hospitals gain an authoritative view before treatment; payers gain fewer malformed preauths and claims. It is one of the most critical APIs for implementors. + + ### When to use + + Call it before any preauth or claim for a given payer and policy, ideally at patient registration or admission and before treatment planning and cost estimation, alongside coverage eligibility. The request carries no clinical content: a Task with status requested, intent order, code poll (system https://nhcx.abdm.gov.in/api) and at least one input, policyNumber or providerId (the HFR id). Send x-hcx-status request.initiated. No dedicated workflow code for InsurancePlan appears in the workflow tables; the Services reference marks x-hcx-workflow_id optional. The plan arrives asynchronously on /v1/insuranceplan/on_request. + + ### Preconditions + + - Both provider and payer registered on NHCX; valid Bearer token from the client-credentials session call. + - Payer certificate fetched via /fetch/certs and verified before encryption; JWE with RSA-OAEP-256 and A256GCM. + - Task bundle with at least one of policyNumber or providerId in Task.input; both may be supplied for precision. + - Protected header with sender_code, recipient_code, fresh api_call_id, a fresh UUID correlation_id for this discovery cycle, IST timestamp and status request.initiated. + - Recipient code taken from processingID in the get/Policies response, not PayerID. + - HTTP headers Accept, Content-Type and bearer_auth. + + ### Postconditions + + The gateway returns HTTP 202 with a StatusSuccessResponse whose result carries sender_code, recipient_code, entity_type insuranceplan and protocol_status; 400, 404 and 500 use the same envelope. The 202 is a receipt, never the plan. The payer later posts an InsurancePlan collection Bundle (InsurancePlan, Organization, optional Questionnaire) to /v1/insuranceplan/on_request under the same correlation id, and the provider must acknowledge that with 202 within 30 seconds. The payer may return an empty plan or an error if no coverage matches the policy-provider combination; an empty plan is a business outcome, not a transport failure. Plans may be cached but should be refreshed periodically or when treatment changes. + + ### Common mistakes + + - Sending a Task with no input at all; at least one of policyNumber or providerId is mandatory. + - Expecting the plan in the synchronous response. + - Resubmitting while a previous request is still with the payer: PAYR-1406 rejects a new request until the earlier correlation id completes (wait 15 to 60 minutes). + - Requesting a policy the hospital is not allowed to use (PAYR-1401), a policy with no payer (PAYR-1402), a renewal not linked to the policy (PAYR-1403), or from an HFR id or sender id with no enrolled hospital (PAYR-1405). + - Using the wrong registry id in production; providers must use the HFR id. + - Treating an empty plan (PAYR-1404, no treatment under any speciality) as a gateway fault. + + ### Best practices + + - Integrate deeply: call at registration or admission, before cost estimation, and together with coverage eligibility. + - Cache the returned plan and refresh on a schedule or when the treatment plan changes; it is provider-, policy- and MoU-specific. + - Enforce the returned claim conditions (GovtReserved, EnhancementAllowed, QuantityAllowed, ImplantApplicable, Standalone, ParentProcedure, Unspecified) locally before building preauths. + - Persist the correlation id so the on_request callback can be matched; mint a new one for each discovery cycle. + - Use IST timestamps and a fresh api_call_id per call. + - Stand up the on_request receiver and v1/error before the first request. + + ### Related scenario + + A PMJAY beneficiary arrives at an empanelled hospital's admission desk. After the desk fetches the patient's policies through the participant registry and resolves the processingID, the integration posts /v1/insuranceplan/request with a Task carrying policyNumber and the hospital's HFR id. The gateway returns 202. Minutes later the payer's package master arrives on /v1/insuranceplan/on_request: the hospital's empanelled specialities, package codes, rates, implant qualifiers and the mandatory-document questionnaire. The desk selects the relevant package, checks the claim conditions, and proceeds to /v1/coverageeligibility/check and then /v1/preauth/submit. + + ### Specification + + Chapter [Insurance plan request](/docs/nhcx/v1/reference/fhir/insurance-plan-request) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - $ref: "#/components/parameters/XHcxSenderCode" + - $ref: "#/components/parameters/XHcxRecipientCode" + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxWorkflowId" + - $ref: "#/components/parameters/XHcxTimestamp" + - $ref: "#/components/parameters/XHcxStatus" + - $ref: "#/components/parameters/XHcxBenAbhaId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOiIxMDAwMDA0NDQ2QGhjeCJ9.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: The gateway returns HTTP 202 with a StatusSuccessResponse whose result carries sender_code, recipient_code, entity_type insuranceplan and protocol_status; 400, 404 and 500 use the same envelope. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 25/08/2026 09:05:00:188 + api_call_id: b8c9d0e1-f2a3-4567-1234-678901234567 + correlation_id: 44556677-8899-aabb-ccdd-eeff00112233 + result: + sender_code: 1000004446@hcx + recipient_code: 1518@hcx + entity_type: insuranceplan + protocol_status: request.queued + error: + code: "" + message: "" + /v1/insuranceplan/on_request: + post: + operationId: insurance_plan_v1_insuranceplan_on_request + x-abdm-atom: nhcx.endpoint.insuranceplan-on-request + x-abdm-use-case: Insurance plan + tags: + - Insurance plan + summary: Insurance plan callback + description: |- + Payer returns the InsurancePlan collection Bundle (InsurancePlan, Organization, optional Questionnaire) under the request correlation id. + + ### Business purpose + + This callback delivers the digital policy that every later preauth and claim is judged against. The payer publishes, for one policy and one hospital, the empanelled specialities, packages and rates, cost qualifiers for implants and stratification, exclusions, claim conditions and mandatory documents, and the questionnaires for standard treatment guidelines or history. Hospitals use it to select packages and validate submissions before they go out; payers use it to cut malformed requests and to make the MoU an enforceable, machine-readable contract view rather than a PDF. + + ### When to use + + The payer calls it after receiving a /v1/insuranceplan/request Task (code poll), acknowledging it with 202 and assembling the plan for the policyNumber and/or providerId supplied. The bundle is of type collection and follows one of two structures: plan, specificCost, category, benefit, cost, qualifiers (the PMJAY package-master shape) or coverage, benefit, limit. Carry the same x-hcx-correlation_id as the request and a responder x-hcx-status (response.complete, or response.error with x-hcx-error_details when no plan can be produced). The plan may legitimately be empty when no coverage matches. + + ### Preconditions + + - The inbound Task was decrypted, its correlation id captured and the 202 acceptance body already returned. + - Payer registered on NHCX with a valid Bearer token and the provider's certificate for JWE encryption. + - A collection Bundle containing InsurancePlan (with plan.generalCost for the overall sum insured, specificCost per speciality, benefit per package with cost and qualifiers, and the claim-exclusion, claimCondition and claimSupportingInfoRequirement extensions), Organization entries and any Questionnaire resources. + - Protected header echoing the request's correlation id with a fresh api_call_id, IST timestamp and responder status; request body declared as a bare object in the OpenAPI but still a JWE per RFC-7516. + + ### Postconditions + + The gateway returns HTTP 202 with the StatusSuccessResponse envelope (400, 404 and 500 in the same shape) and forwards the bundle to the provider's registered endpoint, which must acknowledge with 202 within 30 seconds. After decryption the provider holds the plan, may cache it, and must enforce its claim conditions and document requirements before preauth. Codes carried in the plan, such as specificCost.category as the speciality code and benefit.type as the procedure code, are what later PAYR-1114, PAYR-1202 and PAYR-1204 validations are checked against. Errors returned instead of a plan use PAYR-1401 to PAYR-1406. + + ### Common mistakes + + - Returning the plan in the synchronous 202 to the request, or before acknowledging the inbound Task within 30 seconds. + - Minting a new correlation id rather than echoing the request's (NHCX-1010). + - Encoding cost.value as the package rate; the IG defines it as the extra amount paid over and above the procedure cost. + - Synthesising codes for claim conditions listed as NA (rules_yn, los, ip_op_flag, incentive_applicable, gst_applicable, gst_percentage). + - Shipping the full package master unfiltered; the response must be provider-specific and contextually filtered per the MoU. + - Provider side: treating an empty plan as a transport failure, or failing to parse both structuring approaches. + + ### Best practices + + - Acknowledge the inbound request first, build the bundle asynchronously, then post this callback. + - Filter to the requesting provider's empanelled specialities and the named policy; include Questionnaire resources for mandatory documents and STGs. + - Use the documented claim-condition codes (GovtReserved, ApprovalNotRequired, EnhancementAllowed, QuantityAllowed, IsDayCare, ImplantApplicable, StratificationAllowed, Standalone, ParentProcedure, Unspecified) so provider systems can enforce them. + - Provider side: cache with periodic refresh, refresh when treatment changes, and validate preauth items against the plan's speciality and package codes. + - Use a fresh api_call_id, IST timestamp and response.complete or response.error. + + ### Related scenario + + A state health agency's payer platform receives a plan discovery Task from an empanelled hospital for policy PMJAY with the hospital's HFR id. It returns 202, then generates the InsurancePlan bundle: General Medicine and Ophthalmology as specificCost categories, each package as a benefit with its rate, implant qualifiers on the packages that allow them, EnhancementAllowed and Standalone conditions, and the proof-of-identity questionnaire. It posts /v1/insuranceplan/on_request under the same correlation id. The hospital acknowledges within 30 seconds, caches the plan, selects a package, and moves to /v1/coverageeligibility/check before submitting the preauth. + + ### Specification + + Chapter [Insurance plan response](/docs/nhcx/v1/reference/fhir/insurance-plan-response-overview) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + - name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxWorkflowId" + - $ref: "#/components/parameters/XHcxTimestamp" + - name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: response.complete + - $ref: "#/components/parameters/XHcxBenAbhaId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOiIxNTE4QGhjeCJ9.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: The gateway returns HTTP 202 with the StatusSuccessResponse envelope (400, 404 and 500 in the same shape) and forwards the bundle to the provider's registered endpoint, which must acknowledge with 202 within 30 seconds. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 25/08/2026 09:12:00:502 + api_call_id: c9d0e1f2-a3b4-5678-2345-789012345678 + correlation_id: 44556677-8899-aabb-ccdd-eeff00112233 + result: + sender_code: 1518@hcx + recipient_code: 1000004446@hcx + entity_type: insuranceplan + protocol_status: request.queued + error: + code: "" + message: "" + /internal/v1/insuranceplan/request: + post: + operationId: insurance_plan_internal_v1_insuranceplan_request + x-abdm-use-case: Adapter + tags: + - Adapter + summary: Insurance plan request (internal variant) (adapter) + description: |- + Internal twin of /v1/insuranceplan/request on the insuranceplanhcxservice: same TaskBundle payload, same 202 envelope, distinct operationId. + + ### Business purpose + + The insuranceplanhcxservice is one of six NHCX services that expose every operation at both /v1/... and /internal/v1/... with identical descriptions and bodies, differing only in the operationId suffix. This entry is the internal form of the provider's plan discovery request, whose purpose is to retrieve the payer's structured, provider-specific digital policy before treatment. The documentation states the internal variant has the same semantics as /v1/insuranceplan/request and does not describe any behavioural difference. + + ### When to use + + Same circumstances as the public request: before any preauth or claim for a payer and policy, at registration or admission, and before cost estimation. The payload is the Task poll bundle with at least one of policyNumber or providerId; the header carries request.initiated. The specifications do not say when the internal path applies instead of the public one, so integrators should default to /v1/insuranceplan/request unless onboarding guidance names the internal route. + + ### Preconditions + + - As for the public endpoint: registered provider and payer, Bearer token, payer certificate verified and used for JWE encryption. + - Body is a JWEPayload, { "payload": "" }, whose plaintext is the TaskBundle. + - Protected header with sender_code, recipient_code, fresh api_call_id and correlation_id, IST timestamp, status request.initiated. + - Confirmation that the internal prefix is reachable and intended for your integration; the specs are silent on this. + + ### Postconditions + + Returns 202 Accepted with StatusSuccessResponse (timestamp, api_call_id, correlation_id, result with sender_code, recipient_code, entity_type and protocol_status, error), or 400, 404 or 500 in the same envelope. The payer's plan arrives later on the insurance plan on_request callback under the same correlation id; the provider must acknowledge that within 30 seconds. An empty plan or a PAYR-1401 to PAYR-1406 error is a documented business outcome. No additional behaviour is documented for the internal variant. + + ### Common mistakes + + - Assuming the internal route bypasses validation or returns the plan synchronously; it is documented as identical to the public request. + - Omitting both Task inputs; at least one of policyNumber or providerId is required. + - Resubmitting while a previous request is in progress (PAYR-1406). + - Hard-coding the internal prefix without confirming it is your onboarded route; a 404 may simply mean the wrong host or prefix shape. + + ### Best practices + + - Reuse the public request's bundle builder and header hygiene; make only the path prefix configurable. + - Mint a fresh UUID correlation id per discovery cycle and a fresh api_call_id per call; use IST timestamps. + - Cache and periodically refresh the returned plan; enforce its claim conditions before preauth. + - Have the on_request receiver and v1/error in place before sending. + + ### Related scenario + + A hospital information system vendor generating clients from the insuranceplanhcxservice Swagger finds both insuranceplanRequestPost-style operations and their Internal twins. The vendor implements one plan-discovery module that posts to /v1/insuranceplan/request by default, with the internal path selectable per deployment after confirmation from NHCX onboarding. Either way the flow is the same: 202 receipt, the package master arriving on the on_request callback, then coverage eligibility and preauth built against the cached plan. + + ### Specification + + Chapter [Insurance plan request](/docs/nhcx/v1/reference/fhir/insurance-plan-request) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - $ref: "#/components/parameters/XHcxSenderCode" + - $ref: "#/components/parameters/XHcxRecipientCode" + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxWorkflowId" + - $ref: "#/components/parameters/XHcxTimestamp" + - $ref: "#/components/parameters/XHcxStatus" + - $ref: "#/components/parameters/XHcxBenAbhaId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOiIxMDAwMDA0NDQ2QGhjeCJ9.encrypted_key.iv.ciphertext.tag + responses: + "200": + description: Returns 202 Accepted with StatusSuccessResponse (timestamp, api_call_id, correlation_id, result with sender_code, recipient_code, entity_type and protocol_status, error), or 400, 404 or 500 in the same envelope. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 25/08/2026 09:30:00:077 + api_call_id: d0e1f2a3-b4c5-6789-3456-890123456789 + correlation_id: 55667788-99aa-bbcc-ddee-ff0011223344 + result: + sender_code: 1000004446@hcx + recipient_code: 1518@hcx + entity_type: insuranceplan + protocol_status: request.queued + error: + code: "" + message: "" + /internal/v1/insuranceplan/on_request: + post: + operationId: insurance_plan_internal_v1_insuranceplan_on_request + x-abdm-use-case: Adapter + tags: + - Adapter + summary: Insurance plan callback (internal variant) (adapter) + description: |- + Internal twin of /v1/insuranceplan/on_request: the payer InsuranceplanBundle callback with identical semantics, distinct operationId. + + ### Business purpose + + This is the internal-path form of the callback through which a payer delivers the digital policy: the InsurancePlan collection Bundle with packages, rates, qualifiers, claim conditions, mandatory documents and questionnaires for one policy and one hospital. The documentation lists it as an internal variant of the callback API with the same semantics as /v1/insuranceplan/on_request and does not describe any difference beyond the operationId. Its business value is unchanged: a machine-readable contract view that reduces rework and rejections. + + ### When to use + + Same as the public callback: after receiving and acknowledging an insurance plan request Task, the payer posts the plan bundle under the request's correlation id with a responder status (response.complete, or response.error with x-hcx-error_details). The bundle may follow either documented structure and may be empty when no coverage matches. The specifications do not indicate when the internal path is used in preference to the public one. + + ### Preconditions + + - Inbound request decrypted, correlation id captured, 202 acceptance already returned. + - Registered payer with a valid Bearer token and the provider's certificate for encryption. + - Collection Bundle containing InsurancePlan, Organization and any Questionnaire resources, filtered to the requesting provider per the MoU. + - Protected header echoing the request's correlation id with a fresh api_call_id, IST timestamp and responder status. + - Confirmation that the internal route is the one intended for your gateway integration. + + ### Postconditions + + Returns 202 Accepted with the StatusSuccessResponse envelope, or 400, 404 or 500 in the same shape; the bundle is forwarded to the provider, which must acknowledge within 30 seconds and may then cache the plan and enforce its conditions before preauth. Insurance plan business errors are PAYR-1401 to PAYR-1406. No additional behaviour is documented for the internal variant. + + ### Common mistakes + + - Expecting different validation or routing from the public callback; none is documented. + - Minting a new correlation id instead of echoing the request's (NHCX-1010). + - Populating cost.value with the package rate rather than the extra amount over the procedure cost. + - Returning an unfiltered package master rather than the provider-specific view. + - Provider side: failing to handle both structuring approaches or treating an empty plan as a fault. + + ### Best practices + + - Share one bundle builder with the public callback; only the path differs. + - Acknowledge the inbound Task first, assemble the plan asynchronously, then post. + - Use the documented claim-condition codes and include Questionnaire resources for mandatory documents. + - Fresh api_call_id, IST timestamp, response.complete or response.error with error details. + - Provider side: cache, refresh periodically or on treatment change, validate preauth items against the plan. + + ### Related scenario + + A payer platform team reviewing the insuranceplanhcxservice specification notices the callback appears twice, publicly and under /internal/v1. They implement a single plan-publication service that emits the InsurancePlan bundle under the request's correlation id, configured to the public /v1/insuranceplan/on_request path unless NHCX onboarding specifies the internal one. When a hospital's discovery Task arrives, the service returns 202, builds the filtered package master and posts it; the hospital acknowledges within 30 seconds and proceeds to eligibility and preauth. + + ### Specification + + Chapter [Insurance plan response](/docs/nhcx/v1/reference/fhir/insurance-plan-response-overview) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + - name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxWorkflowId" + - $ref: "#/components/parameters/XHcxTimestamp" + - name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: response.complete + - $ref: "#/components/parameters/XHcxBenAbhaId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOiIxNTE4QGhjeCJ9.encrypted_key.iv.ciphertext.tag + responses: + "200": + description: Returns 202 Accepted with the StatusSuccessResponse envelope, or 400, 404 or 500 in the same shape; the bundle is forwarded to the provider, which must acknowledge within 30 seconds and may then cache the plan and enforce its conditions before preauth. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 25/08/2026 09:37:00:263 + api_call_id: e1f2a3b4-c5d6-7890-4567-901234567890 + correlation_id: 55667788-99aa-bbcc-ddee-ff0011223344 + result: + sender_code: 1518@hcx + recipient_code: 1000004446@hcx + entity_type: insuranceplan + protocol_status: request.queued + error: + code: "" + message: "" +webhooks: + v1_insuranceplan_request: + post: + operationId: insurance_plan_webhook_v1_insuranceplan_request + x-abdm-atom: nhcx.callback.insuranceplan-request + x-abdm-triggered-by: insurance_plan_v1_insuranceplan_request + x-abdm-use-case: Webhooks + tags: + - Insurance plan + summary: Receive insurance plan request + description: |- + Hosted by the payer. The exchange posts this message to the `endpoint_url` you registered, at `/v1/insuranceplan/request`, with the headers and the sealed payload the sender posted. Answer HTTP 202 with the receipt first and process afterwards; [Receiving a callback](/docs/nhcx/v1/getting-started/receiving-a-callback) has the rules. + + Provider sends a Task with code poll naming a policy number and/or its HFR id to fetch the payer's machine-readable InsurancePlan for that pairing. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - $ref: "#/components/parameters/XHcxSenderCode" + - $ref: "#/components/parameters/XHcxRecipientCode" + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxWorkflowId" + - $ref: "#/components/parameters/XHcxTimestamp" + - $ref: "#/components/parameters/XHcxStatus" + - $ref: "#/components/parameters/XHcxBenAbhaId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOiIxMDAwMDA0NDQ2QGhjeCJ9.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: Received. The receipt names the message it answers; the answer itself follows as a call of your own. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 04/09/2026 11:46:41:305 + api_call_id: + correlation_id: + result: + sender_code: 1000003538@hcx + recipient_code: 1000004446@hcx + entity_type: preauth + protocol_status: request.queued + error: + code: "" + message: "" + v1_insuranceplan_on_request: + post: + operationId: insurance_plan_webhook_v1_insuranceplan_on_request + x-abdm-atom: nhcx.callback.insuranceplan-on-request + x-abdm-triggered-by: insurance_plan_v1_insuranceplan_on_request + x-abdm-use-case: Webhooks + tags: + - Insurance plan + summary: Receive insurance plan callback + description: |- + Hosted by the provider. The exchange posts this message to the `endpoint_url` you registered, at `/v1/insuranceplan/on_request`, with the headers and the sealed payload the sender posted. Answer HTTP 202 with the receipt first and process afterwards; [Receiving a callback](/docs/nhcx/v1/getting-started/receiving-a-callback) has the rules. + + Payer returns the InsurancePlan collection Bundle (InsurancePlan, Organization, optional Questionnaire) under the request correlation id. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + - name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxWorkflowId" + - $ref: "#/components/parameters/XHcxTimestamp" + - name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: response.complete + - $ref: "#/components/parameters/XHcxBenAbhaId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOiIxNTE4QGhjeCJ9.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: Received. The receipt names the message it answers; the answer itself follows as a call of your own. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 04/09/2026 11:46:41:305 + api_call_id: + correlation_id: + result: + sender_code: 1000003538@hcx + recipient_code: 1000004446@hcx + entity_type: preauth + protocol_status: request.queued + error: + code: "" + message: "" +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + description: "On every NHCX call, the token goes in a header called `bearer_auth`, with the word `Bearer` and a space in front. The sources are not unanimous: the authentication page and the FAQ both write the example as `Authorization`, and the notification endpoint uses `Authorization`. The safe course, and what the adapter does, is to send both headers with the same value." + parameters: + BearerAuth: + name: bearer_auth + in: header + required: true + description: It is `bearer_auth`, not `Authorization`, on NHCX's own endpoints. + schema: + type: string + example: Bearer + XHcxSenderCode: + name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + XHcxRecipientCode: + name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + XHcxApiCallId: + name: x-hcx-api_call_id + in: header + required: true + description: Fresh on every message, including responses. Mandatory on the envelope. + schema: + type: string + example: + XHcxRequestId: + name: x-hcx-request_id + in: header + required: false + description: One per originating request. The Open Protocol page marks it Mandatory; the Technical Specifications page marks it Optional. Optional on the envelope. + schema: + type: string + example: + XHcxCorrelationId: + name: x-hcx-correlation_id + in: header + required: true + description: The thread. See the rule below. Mandatory on the envelope. + schema: + type: string + example: + XHcxWorkflowId: + name: x-hcx-workflow_id + in: header + required: false + description: Which step, or which case. See the two readings below. Optional on the envelope. + schema: + type: string + example: "" + XHcxTimestamp: + name: x-hcx-timestamp + in: header + required: true + description: See the format note below. Mandatory on the envelope. + schema: + type: string + example: + XHcxStatus: + name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: request.initiated + XHcxBenAbhaId: + name: x-hcx-ben-abha-id + in: header + required: true + description: The beneficiary's ABHA number. Mandatory on every exchange, including those with no beneficiary in the payload. Mandatory on the envelope. + schema: + type: string + example: "" +x-abdm-errors: + notes: "Codes any exchange call can meet are recorded once, in the [Other](/docs/nhcx/v1/api/other) specification: the gateway's NHCX- codes, the standard payer codes, and the reference payer's structure and transport codes. The reference payer's other codes sit with the exchange they reject: coverage eligibility, preauthorisation, claim and insurance plan. [Reading error codes](/docs/nhcx/v1/reference/error-code-guide) explains the code spaces." +x-abdm-errors-reference-payer: + source: Reference payer codes, PAYR-1001 to PAYR-1520. Sent by the PMJAY reference implementation; they arrive inside the sealed response. + codes: + - code: PAYR-1401 + message: policy not allowed for the hospital. Please reach out to technical support team. + action: "" + - code: PAYR-1402 + message: Requested policy found not be associated with any payer for insurance plan request. Hence request will not be processed. + action: "" + - code: PAYR-1403 + message: Requested renewal found not be associated with requested policy for insurance plan request. Hence request will not be processed. + action: "" + - code: PAYR-1404 + message: No treatment provided for policy under any speciality. Please reach out to technical support team. + action: "" + - code: PAYR-1405 + message: No enrolled hospital found for HFR id or sender id . Please reach out to technical support team. + action: "" + - code: PAYR-1406 + message: Existing request with correlation id %s is in progress with the payer. Hence this request will not be accepted until the execution for previous request is complete. Please wait for 15 - 60 minutes to allow the execution of previous requests. For further assistance, please reach out to technical support team. + action: "" + - code: PAYR-1501 + message: Value type received as %s for category - ONS and code - PSP for item with sequence %s in supporting info in claim resource. In supporting info list, item with category - ONS and code - PSP combination is used to get the surgery date. So the surgery date should be sent as timing (date or period) or as a string value, adhering to the NRCES standards, with the category - ONS and code - PSP. + action: "" + - code: PAYR-1502 + message: Value type received as %s for category - ONS and code - ADDD for item with sequence %s in supporting info in claim resource. In supporting info list, item with category - ONS and code - ADDD combination is used to get the admission date. So the admission date should be sent as timing (date or period) or as a string value, adhering to the NRCES standards, with the category - ONS and code - ADDD. + action: "" + - code: PAYR-1503 + message: Value type received as %s for category - ONS and code - DTM for item with sequence %s in supporting info in claim resource. In supporting info list, item with category - ONS and code - DTM combination is used to get the death date. So the death date should be sent as timing (date or period) or as a string value, adhering to the NRCES standards, with the category - ONS and code - DTM. + action: "" + - code: PAYR-1504 + message: Value type received as %s for category - NMI and code - CQD for item with sequence %s in supporting info in claim resource. In supporting info list, item with category - NMI and code - CQD combination is used to get the overall case remarks for query response. So the case remarks for query response should be sent as a string value, adhering to the NRCES standards, with the category - NMI and code - CQD. + action: "" + - code: PAYR-1505 + message: Category received as %s and code received as %s for item with sequence %s in supporting info in claim resource, where the reference value redirects to Questionnaire Response resource in the FHIR bundle. To include a policy/case level Questionnaire Response, in supporting info list there should be an entry with category - INF and code - ODN , and the value as reference. This reference value should refer to a resource of Questionnaire Response in the FHIR bundle. To include response for any STG questionnaire, in supporting info list there should be an entry with category - STG, and the value as reference + action: "" + - code: PAYR-1506 + message: Invalid gender received for new born patient. Please try agian with valid gender data as it is mandatory for PMJAY in new born case. Please refer to the valid gender values at https://hl7.org/fhir/R4/valueset-administrative-gender.html + action: "" + - code: PAYR-1507 + message: Invalid date of birth received for new born patient. Please try agian with valid date of birth as it is mandatory for PMJAY in new born case. + action: "" + - code: PAYR-1508 + message: Invalid resource received for new born patient for url %s. Please try agian with valid Patient resource for the link reference as linked Patient resource is mandatory for PMJAY in new born case + action: "" + - code: PAYR-1509 + message: Invalid attachment received for new born patient. Please try agian with valid attachment as attachment is mandatory for PMJAY in new born case + action: "" + - code: PAYR-1510 + message: Invalid parameter code received. Please check and try again with a valid parameter code + action: "" + - code: PAYR-1511 + message: Invalid parameter value received. Please check and try again with a valid parameter value + action: "" + - code: PAYR-1512 + message: Invalid resource received for patient for url %s. Please try agian with valid Patient resource for the reference + action: "" + - code: PAYR-1513 + message: Invalid diagnosis received in DiagnosisComponent. In DiagnosisComponent, diagnosis should be sent as CodeableConcept. Please try agian with valid data + action: "" + - code: PAYR-1514 + message: Value type received as %s for category - DIS for item with sequence %s in supporting info in claim resource. In supporting info list, item with category - DIS is used to get the discharge related information. So the discharge information should be sent as string value, with value representing discharge stage (After Surgery / Before Surgery / During Surgery), with the category - DIS and code - DTH/LAMA/DAMA/DTM + action: "" + - code: PAYR-1515 + message: Invalid name received for organization resource with url %s. Name is mandatory for organization resource. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html + action: "" + - code: PAYR-1516 + message: No event found for api-caller-id %s and correlation id %s for sender code %s. Hence error response willnot be accepted. + action: "" + - code: PAYR-1517 + message: Invalid error structure received for NHCX error. Protocol response structure is expected, but received JWEPayloadResponse. + action: "" + - code: PAYR-1518 + message: No input parameters received for task resource. Input parameters are expected for task resource, but not received. Please try again with valid data. + action: "" + - code: PAYR-1519 + message: No type found for task input parameters. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html + action: "" + - code: PAYR-1520 + message: Invalid resource received for communication for url %s. Please try agian with valid Communication resource for the reference. + action: "" diff --git a/catalogue/openapi/nhcx/v1/nhcx-onboarding.yaml b/catalogue/openapi/nhcx/v1/nhcx-onboarding.yaml new file mode 100644 index 000000000..eab737045 --- /dev/null +++ b/catalogue/openapi/nhcx/v1/nhcx-onboarding.yaml @@ -0,0 +1,663 @@ +# NHCX onboarding, from the NHCX package's Bruno folder apis/11-onboarding. +# +# Written by the package's system/build-ekadocs.mjs (make ekadocs); change the .bru +# requests there and port again rather than editing this file. +# +# Rules this file follows: catalogue/openapi/CONVENTIONS.md +openapi: 3.1.1 +info: + x-portal: + module: onboarding + label: Onboarding + position: 11 + title: NHCX onboarding + summary: Nothing moves through NHCX until both the sender and the recipient exist in the participant registry, which the platform treats as the source of truth for who may exchange claims data. + description: |- + The Onboarding calls on the National Health Claims Exchange (NHCX): 5 operations. + + Nothing moves through NHCX until both the sender and the recipient exist in the participant registry, which the platform treats as the source of truth for who may exchange claims data. + + Guides that use these calls: [Creating and updating a participant](/docs/nhcx/v1/getting-started/creating-and-updating-a-participant), [Your callback URL is rejected or never called](/docs/nhcx/v1/troubleshooting/your-callback-url-is-rejected). + version: nhcx-v1 + license: + name: MIT + identifier: MIT + contact: + name: NHCX sandbox + url: https://hcxsbx.abdm.gov.in + x-abdm-gateway: nhcx + x-abdm-module: onboarding + x-abdm-phase: 1 + x-abdm-roles: + - provider + - payer +x-abdm-sources: + - file: nhcx-package/apis/11-onboarding + role: upstream + hash: sha256:41195ab9975347123e36e509ad940f4fe77c467855d32dad802e46eb78e9c10e + note: The package's Bruno collection, one request per operation. + - file: nhcx-package/baseurl.yaml + role: upstream + hash: sha256:88515b7b29c6b349a131e016c80774436ea16a29738db743b4cc3a24cbd42453 + note: The sandbox and production hosts. +servers: + - url: https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice + description: Sandbox, Participant service. + - url: https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice + description: Production. +tags: + - name: Onboarding + description: Nothing moves through NHCX until both the sender and the recipient exist in the participant registry, which the platform treats as the source of truth for who may exchange claims data. +security: + - bearerAuth: [] +paths: + /participant/create: + post: + operationId: onboarding_participant_create + x-abdm-atom: nhcx.endpoint.participant-create + x-abdm-use-case: Onboarding + tags: + - Onboarding + summary: Participant create (v1) + description: |- + Creates a participant record in the NHCX registry from a full v1 profile and returns the generated participant_code. + + ### Business purpose + + Nothing moves through NHCX until both the sender and the recipient exist in the participant registry, which the platform treats as the source of truth for who may exchange claims data. This call is the original, full-profile way to register a hospital, insurer or TPA: it captures the organisation's name, roles, contact points, linked registry identifiers, callback endpoint and public encryption certificate in one record. The registry then issues the participant_code that every later transaction is addressed with. + + ### When to use + + Call it once, at onboarding time, before any transaction API is attempted. The FAQ base-URL table lists this path (not the v2 form) as the sandbox Create Participant API at https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/participant/create, whereas production onboarding is documented against /v2/participant/create followed by GET /validate. It is a plain synchronous registry call; no NHCX workflow or x-hcx-status codes are involved. If the organisation later rotates its certificate or moves its callback URL, use /participant/update or /v2/update/cert rather than creating again. + + ### Preconditions + + - Sandbox or production access has been granted through the semi-manual registration review, so you hold a client_id and client_secret. + - A valid Bearer token from POST /get/session, sent with the Bearer prefix in the bearer_auth (Authorization) header, plus Accept: application/json and Content-Type: application/json. + - Required body fields of ParticipantCreateBody: linked_registry_codes, participant_name, registryid, roles, primaryEmail, primaryMobile, encryption_cert and endpoint_url. The certificate is mandatory at creation, so generate the 2048-bit RSA key pair and self-signed X.509 certificate first and Base64-encode it. + - Correct registry ID for your type: HFR ID for providers, IRDAI-issued ID for payers and TPAs. + + ### Postconditions + + On success the registry returns HTTP 200 with ParticipantCreateResponse containing only participant_code, described as the machine-generated unique identifier of the participant on the HCX instance; sandbox codes look like 100001@sbx and production codes like XXXXX7583@hcx. There is no asynchronous callback. The new record carries a status (Created, Active, Inactive or Blocked in the architecture description) that the gateway checks on every routing leg, so the code is not usable for transactions until the instance activates it. Failures return 400 Client Error, 404 Resource not found or 500 with the ErrorResponse envelope (timestamp plus error code, message and trace). + + ### Common mistakes + + - Passing the wrong registry ID: providers must send the HFR ID, payers the IRDAI ID with leading zeros stripped (0123 becomes 123). + - Mixing field casing across generations: this v1 body is snake_case (participant_code, encryption_cert, endpoint_url); copying v2 names such as endpointurl yields a 400. + - Omitting the Accept header or the Bearer prefix on the token, which surfaces as a rejection before business logic or a flat 401. + - Registering an endpoint_url that is an IP address or carries a port; the callback URL must be a domain name on an India-based server with the NHCX NAT IPs whitelisted. + - Submitting the raw PEM instead of the Base64-encoded certificate. + + ### Best practices + + - Keep the private key generated alongside the certificate in PKCS8 form locally; only the certificate (public half) is registered. + - Store the returned participant_code as configuration; it becomes x-hcx-sender_code on every outbound message and the value payers use in /fetch/certs. + - Do not re-run create to fix a field; the registry is updated with /participant/update, and an entity can legitimately hold several participant codes only when each is linked to a separate HFR ID. + - Log the request minus the certificate body and never log the bearer token or client_secret. + - Treat host and prefix as one environment variable; sandbox codes and credentials do not carry into production. + + ### Related scenario + + A 200-bed hospital has been approved for the NHCX sandbox and received its client credentials. The integration team first calls POST /get/session to obtain a Bearer token, then generates an RSA key pair and self-signed certificate. They call /participant/create with the hospital's HFR ID as registryid, role PROVIDER, the Base64 certificate and their callback base URL. The registry returns participant_code 100001@sbx. With that code in hand the team calls /fetch/participants/list to find the dummy payer 1000003538@hcx and /fetch/certs to obtain its certificate, and only then sends the first /v1/coverageeligibility/check. + + ### Specification + + Chapter [Your certificate](/docs/nhcx/v1/getting-started/your-certificate) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - $ref: "#/components/parameters/Source" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + linked_registry_codes: + type: array + items: + type: string + registryid: + type: string + participant_name: + type: string + scheme_code: + type: string + state: + type: string + district: + type: string + roles: + type: array + items: + type: string + primaryEmail: + type: string + phone: + type: array + items: + type: string + primaryMobile: + type: string + signing_cert_path: + type: string + encryption_cert: + type: string + endpoint_url: + type: string + example: + linked_registry_codes: + - "10001" + registryid: + participant_name: Test Hospital + scheme_code: PMJAY + state: Haryana + district: Panchkula + roles: + - "10001" + primaryEmail: integration@hospital.example + phone: + - "01123456789" + primaryMobile: "9876543210" + signing_cert_path: "" + encryption_cert: + endpoint_url: https://nhcx.hospital.example + responses: + "200": + description: On success the registry returns HTTP 200 with ParticipantCreateResponse containing only participant_code, described as the machine-generated unique identifier of the participant on the HCX instance; sandbox codes look like 100001@sbx and production codes like XXXXX7583@hcx. + content: + application/json: + schema: + type: object + properties: + participant_code: + type: string + example: + participant_code: 100001@sbx + /v2/participant/create: + post: + operationId: onboarding_v2_participant_create + x-abdm-atom: nhcx.endpoint.v2-participant-create + x-abdm-use-case: Onboarding + tags: + - Onboarding + summary: Participant create (v2) + description: |- + Registry-linked creation: registry type and ID, role codes, endpoint URL and contacts; returns participantid and a transactionid for /validate. + + ### Business purpose + + Production onboarding needs to prove that the organisation registering on NHCX is the same one already known to an external authority (the ABDM Health Facility Registry for hospitals, the IRDAI registry for insurers and TPAs). The v2 create therefore takes a thin, registry-linked payload rather than a full profile, validates the mobile number against the number held in HFR or the NHCX payer details, and sends a one-time passcode to that number. This is step 1 of the four-step production sequence and is what turns a verified facility into an addressable NHCX participant. + + ### When to use + + Use at production onboarding after sandbox certification has been reviewed and credentials issued; the documented URL is https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice/v2/participant/create. It is always followed by GET /validate with the returned transactionid and the SMS passcode, which must happen within 24 hours. In the sandbox the FAQ lists the unversioned /participant/create instead. No NHCX workflow codes or x-hcx-status values apply; this is a synchronous JSON call outside the JWE protocol. + + ### Preconditions + + - Production (or sandbox) credentials and a fresh Bearer token in bearer_auth with the Bearer prefix; Accept and Content-Type set to application/json. + - registrytype from the Valid Registry Enums: HFR 10001, NIN 10002, ROHINI 10003, PAYER 10004 (HFR/EUA use 10001, PAYER/TPA use 10004). + - role as an array from the Valid Role Enums: PROVIDER 10001, PAYER 10002, AGENCY_TPA 10003, EUA 10009, among others. + - registryid formatted correctly: HFR ID for providers; IRDAI ID with leading zeros stripped for payers. + - mobilenumber already registered with HFR (providers) or NHCX payer details (payers); both must match for the call to succeed. + - Required fields: registrytype, registryid, role, endpointurl, mobilenumber, email; scheme_code is optional. + + ### Postconditions + + HTTP 200 with ParticipantCreateV2Resp: participantid, facilityname, facilitycontact and facilityemail echoed from the linked registry, a transactionid such as 1vouv8tlz2tnl-1fpspjhwj07c6, and an error object (code, message, trace). A passcode is sent by SMS to the registered mobile number. The participant is not confirmed until GET /validate?transactionId=&passcode= succeeds; the transaction id and passcode are valid for 24 hours and each re-trigger generates a new pair. Only after creation confirmation can /v2/participant/update be used to upload the certificate and endpoint. Failures use the standard 400/404/500 ErrorResponse envelope. + + ### Common mistakes + + - Confusing the two 10001 enums: 10001 is PROVIDER as a role and HFR/EUA as a registry type; they are different fields. + - Sending the IRDAI registry ID with leading zeros (0123 instead of 123), which the NHA lists as a frequent production failure. + - Using a mobile number that does not match the one on record in HFR or the NHCX payer details; the validation requires an exact match. + - Losing the transactionid: if it is forgotten, the only recovery is to create the request again, which issues a new passcode. + - Letting the 24-hour validity lapse before calling /validate. + - Sending the v1 snake_case body or expecting a participant_code key; this response uses participantid. + + ### Best practices + + - Persist transactionid immediately, together with the timestamp, so the /validate step can be completed by whoever holds the registered phone. + - Verify the mobile number and registry ID against HFR or IRDAI records before calling; the check is strict and every failed attempt is a manual round trip. + - Treat the error object in a 200 response as meaningful and surface it to the operator rather than assuming success from the HTTP status alone. + - Do not retry blindly: each call generates a new transaction id and passcode and invalidates the plan to confirm the previous one. + - Keep sandbox and production credentials, hosts and participant codes strictly separate. + + ### Related scenario + + An insurer's TPA has cleared sandbox certification and received production credentials. Its integrator obtains a Bearer token, then calls /v2/participant/create with registrytype 10004, the IRDAI-issued registry ID (leading zeros stripped), role ["10003"], the production callback base URL and the mobile number the NHA has on file. The response returns participantid, the facility details and transactionid 1vouv8tlz2tnl-1fpspjhwj07c6, and an SMS passcode reaches the compliance officer's phone. Within the hour the team calls GET /validate with both values to confirm creation, then proceeds to /v2/participant/update to publish its encryption certificate. + + ### Specification + + Chapter [Your certificate](/docs/nhcx/v1/getting-started/your-certificate) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + registrytype: + type: string + registryid: + type: string + role: + type: array + items: + type: string + endpointurl: + type: string + mobilenumber: + type: string + email: + type: string + example: + registrytype: "10001" + registryid: XXXXX74586 + role: + - "10001" + endpointurl: https://nhcx.demohospital.example.in + mobilenumber: XXXX748348 + email: sample@gmail.com + responses: + "200": + description: "HTTP 200 with ParticipantCreateV2Resp: participantid, facilityname, facilitycontact and facilityemail echoed from the linked registry, a transactionid such as 1vouv8tlz2tnl-1fpspjhwj07c6, and an error object (code, message, trace)." + content: + application/json: + schema: + type: object + properties: + participantid: + type: string + facilityname: + type: string + facilitycontact: + type: string + facilityemail: + type: string + transactionid: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + trace: + type: string + example: + participantid: XXXXX7583@hcx + facilityname: Demo Multispeciality Hospital + facilitycontact: XXXX748348 + facilityemail: sample@gmail.com + transactionid: 1vouv8tlz2tnl-1fpspjhwj07c6 + error: + code: "" + message: "" + trace: "" + /v2/participant/hementity/create: + post: + operationId: onboarding_v2_participant_hementity_create + x-abdm-use-case: Onboarding + tags: + - Onboarding + summary: HEM-entity participant create + description: |- + Creates a hospital (HEM-entity) participant from the full empanelment payload (bank, tax, beds, specialities, doctors); returns status and hospitalid. + + ### Business purpose + + Government scheme empanelment needs far more than a name and a certificate: a hospital must be identified by scheme, state and district, carry bank details for settlement, tax identifiers for deduction handling, and descriptive data such as hospital type, bed strength, accreditation, specialities and doctors. This endpoint captures that full hospital-empanelment profile in one registry call so the payer side can settle and audit against it. It exists alongside the thinner v2 create because scheme onboarding (for example PMJAY) involves configuration that regular private-insurance onboarding does not. + + ### When to use + + Use during scheme-specific hospital onboarding when the operator directs you to the HEM-entity form rather than the registry-linked /v2/participant/create. It shares the create description with the other two create endpoints, but the OpenAPI schemas differ materially, so it is not a drop-in alternative. It is a synchronous registry call with no workflow or x-hcx-status codes. The docs do not state whether a passcode confirmation via /validate follows; the response carries no transactionid, so plan the approval step with your onboarding contact. + + ### Preconditions + + - Bearer token with the Bearer prefix in bearer_auth, plus Accept and Content-Type: application/json. + - Required ParticipantCreateBodyV2 fields: participant_name, scheme_code, state, district, entityid, bankdetails, participantcode, hospitaltype, incentiveCode, hospitalbedstrength, lab_yn, roles, specialityList, primaryEmail, primaryMobile, encryption_cert, endpoint_url. + - BankDetails requires facilitybankaccountname, authorizedsignatoryname, bankaccountnumber, ifsccode, bankname, bankbranchname, bankaddress, micrcode and accounttype; upiid, paymenttype and mailid are optional. + - If taxdetails is supplied, pannumber, tannumber and gstnumber are all required within it. + - A Base64-encoded self-signed X.509 encryption certificate and a domain-name callback URL. + + ### Postconditions + + HTTP 200 with ParticipantCreateResponseV2 containing status and hospitalid. Unlike the other two create calls, the response does not return a participant code, despite the shared description; the participantcode you supplied in the body is the identifier the record is keyed on. There is no asynchronous callback. Errors follow the registry envelope of 400 Client Error, 404 Resource not found and 500 Downstream systems down, each with ErrorResponse (timestamp, error code, message, trace). + + ### Common mistakes + + - Expecting a participant_code in the response and failing to persist the hospitalid that is actually returned. + - Leaving out nested required fields, especially inside bankdetails, or supplying taxdetails with only some of pannumber, tannumber and gstnumber. + - Mixing field naming: this schema uses snake_case for participant_name, scheme_code and encryption_cert but flattened lowercase for participantcode and hospitalbedstrength; copy names exactly from the schema. + - Sending the PEM certificate without Base64 encoding. + - Registering an endpoint_url with an IP address or port, which fails the go-live reachability checks. + + ### Best practices + + - Build the payload from the schema field by field and validate nested objects (BankDetails, HospitalDoctorDetails, IncentiveRequest) before sending; a 400 does not point at the offending nested field. + - Collect bank, tax, MICR and IFSC values from the finance team in advance; they are mandatory and settlement depends on them. + - Keep the private key that pairs with encryption_cert in PKCS8 form on the callback host only. + - Never log the full request; it contains bank account and tax identifiers. + - Confirm with the onboarding operator whether a passcode approval step applies, since the response has no transactionid to pair with /validate. + + ### Related scenario + + A district hospital being empanelled under a state scheme is asked to register as an HEM entity. The hospital's IT partner obtains a Bearer token and assembles the full payload: scheme_code, state and district, bed strength, hospital type, speciality list, doctor roster, bank details for settlement and PAN, TAN and GST numbers, plus the Base64 certificate and callback URL. They call /v2/participant/hementity/create and receive status and hospitalid. The record is then available to the scheme payer via /participant/search, and the hospital moves on to fetching the payer's certificate with /fetch/certs before sending its first pre-authorisation. + + ### Specification + + Chapter [Your certificate](/docs/nhcx/v1/getting-started/your-certificate) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + participant_name: + type: string + participantcode: + type: string + scheme_code: + type: string + state: + type: string + district: + type: string + entityid: + type: string + hospitaltype: + type: string + incentiveCode: + type: string + hospitalbedstrength: + type: string + lab_yn: + type: string + roles: + type: array + items: + type: string + specialityList: + type: array + items: + type: string + primaryEmail: + type: string + primaryMobile: + type: string + encryption_cert: + type: string + endpoint_url: + type: string + bankdetails: + type: object + properties: + facilitybankaccountname: + type: string + authorizedsignatoryname: + type: string + bankaccountnumber: + type: string + ifsccode: + type: string + bankname: + type: string + bankbranchname: + type: string + bankaddress: + type: string + micrcode: + type: string + accounttype: + type: string + taxdetails: + type: object + properties: + pannumber: + type: string + tannumber: + type: string + gstnumber: + type: string + example: + participant_name: District Hospital Demo + participantcode: XXXXX7583@hcx + scheme_code: PMJAY + state: Karnataka + district: Mysuru + entityid: IN2910001234 + hospitaltype: Public + incentiveCode: NABH + hospitalbedstrength: "200" + lab_yn: Y + roles: + - provider + specialityList: + - General Medicine + - General Surgery + primaryEmail: claims@districthospital.example.in + primaryMobile: "9800000000" + encryption_cert: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t... + endpoint_url: https://nhcx.districthospital.example.in + bankdetails: + facilitybankaccountname: District Hospital Demo + authorizedsignatoryname: Medical Superintendent + bankaccountnumber: "000000000000" + ifsccode: SBIN0000000 + bankname: State Bank of India + bankbranchname: Mysuru Main + bankaddress: Mysuru, Karnataka + micrcode: "570002000" + accounttype: Current + taxdetails: + pannumber: AAAAA0000A + tannumber: BLRA00000A + gstnumber: 29AAAAA0000A1Z5 + responses: + "200": + description: HTTP 200 with ParticipantCreateResponseV2 containing status and hospitalid. + content: + application/json: + schema: + type: object + properties: + status: + type: string + hospitalid: + type: string + example: + status: Created + hospitalid: H00012345 + /validate: + get: + operationId: onboarding_validate + x-abdm-atom: nhcx.endpoint.validate + x-abdm-use-case: Onboarding + tags: + - Onboarding + summary: Validate participant creation + description: |- + Confirms a participant creation by presenting the SMS passcode and the transactionId returned by /v2/participant/create. + + ### Business purpose + + Registering an organisation on a national claims exchange must be authorised by someone who actually controls that organisation's registered contact channel. The create call therefore only stages the record and sends a passcode to the mobile number held in HFR or the NHCX payer details; this validation call closes the loop by proving possession of that passcode. It is step 2 of the four-step production onboarding sequence and is what turns a staged participant into a confirmed one. + + ### When to use + + Call it after /v2/participant/create has returned a transactionid and the passcode has arrived by SMS, and before attempting /v2/participant/update, whose validations require that creation confirmation is already completed. The production URL is https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice/validate?transactionId=""&passcode="". The pair is valid for 24 hours. It is one of only three GET operations in the participant service and carries no workflow or x-hcx-status codes. + + ### Preconditions + + - A completed /v2/participant/create whose response supplied the transactionid. + - The passcode delivered to the registered mobile number for that specific transaction; passcodes are bound to a transaction id and cannot be reused across attempts. + - Both values presented as query parameters passcode and transactionId within 24 hours of the create call. + - A Bearer token in bearer_auth with the Bearer prefix and Accept: application/json, as for every registry call. + + ### Postconditions + + HTTP 200 with a bare string body; the OpenAPI declares the 200 response type as string and the operation (particiapntValidate) as validating approval from the participant for participant creation. The participant is now confirmed in the registry and satisfies the precondition for /v2/participant/update, which uploads the encryption certificate and callback endpoint. There is no asynchronous callback. A wrong or expired passcode, or an unknown transaction id, returns the registry ErrorResponse envelope on 400 or 404. + + ### Common mistakes + + - Waiting more than 24 hours; both the transaction id and the passcode expire and the create call must be repeated. + - Re-triggering /v2/participant/create while a passcode is pending, which issues a new transaction id and passcode and orphans the earlier pair. + - Using a passcode from a different transaction id; passcodes are specific to the transaction that generated them. + - Calling /update/validate by mistake; that endpoint confirms updates, not creation. + - Losing the transaction id: the documented recovery is to create the request again. + + ### Best practices + + - Treat the passcode like a one-time credential: never log it, and hand it from the phone holder to the integrator through a controlled channel. + - Store transactionid with a 24-hour expiry so the operator dashboard can show whether confirmation is still possible. + - Send parameters as query string values on a GET; there is no JSON body. + - After success, proceed straight to /v2/participant/update so the certificate and endpoint are in place before any counterparty tries to fetch them. + + ### Related scenario + + A hospital's production onboarding started with /v2/participant/create, which returned transactionid 1vouv8tlz2tnl-1fpspjhwj07c6 and triggered a passcode to the medical superintendent's registered phone. The superintendent reads the passcode to the integration engineer, who calls GET /validate?transactionId=1vouv8tlz2tnl-1fpspjhwj07c6&passcode=482913 with the Bearer token. The registry returns 200 and the participant is confirmed. The engineer then calls /v2/participant/update with the Base64 certificate and callback URL, and completes that change with /update/validate. + + ### Specification + + Chapter [Your certificate](/docs/nhcx/v1/getting-started/your-certificate) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - name: transactionId + in: query + required: true + schema: + type: string + example: + - name: passcode + in: query + required: true + schema: + type: string + example: + responses: + "200": + description: HTTP 200 with a bare string body; the OpenAPI declares the 200 response type as string and the operation (particiapntValidate) as validating approval from the participant for participant creation. + content: + application/json: + schema: + type: object + properties: + _contentType: + type: string + _body: + type: string + example: + _contentType: string + _body: + /update/validate: + get: + operationId: onboarding_update_validate + x-abdm-atom: nhcx.endpoint.update-validate + x-abdm-use-case: Onboarding + tags: + - Onboarding + summary: Validate participant update + description: |- + Confirms a participant update by presenting the SMS passcode and the transactionId returned by /v2/participant/update. + + ### Business purpose + + Changing a participant's encryption certificate or callback endpoint changes where encrypted claims data is delivered and who can decrypt it, so the registry does not apply such updates on an API call alone. /v2/participant/update stages the change and sends a passcode to the registered mobile number; this call confirms it. It is step 4 of the production onboarding sequence and the same approval mechanism protects every later certificate or bridge rotation done through the v2 update. + + ### When to use + + Call it after /v2/participant/update returns a transactionid and the passcode arrives by SMS, within the 24-hour validity window. The production URL is https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice/update/validate?transactionId=""&passcode="". It is also the closing step of the annual key-rotation checklist when rotation is done via /v2/participant/update. The passcode-free alternative for certificate-only changes is /v2/update/cert. No workflow or x-hcx-status codes apply. + + ### Preconditions + + - The participant is already registered and its creation was confirmed via /validate. + - A completed /v2/participant/update that returned a transactionid, with the matching passcode received on the registered mobile number. + - The call is made within 24 hours; each new update trigger generates a new transaction id and passcode. + - Bearer token with the Bearer prefix in bearer_auth and Accept: application/json; parameters go in the query string. + + ### Postconditions + + HTTP 200 with a bare string body (operation particiapntUpdateValidate, response type string). The staged certificate and endpoint URL become the participant's live registry values, which is what counterparties will receive from /fetch/certs and what the gateway will use for callback delivery. There is no asynchronous callback. Errors return the registry ErrorResponse envelope with 400, 404 or 500. + + ### Common mistakes + + - Assuming the update is live as soon as /v2/participant/update returns; until this call succeeds counterparties may still fetch the old certificate. + - Presenting a passcode from a previous update attempt after a new one was triggered. + - Letting the 24-hour window lapse and then retrying validation instead of re-issuing the update. + - Calling /validate (creation) instead of /update/validate. + - Losing the transaction id, which requires repeating the update request. + + ### Best practices + + - Rotate keys in two phases: keep the old private key available for decrypting inbound callbacks until the update is validated and cached certificates (24-hour TTL on the payer side) have refreshed. + - Persist transactionid with its 24-hour expiry and record who completed validation, for audit. + - Never log the passcode; treat it as a one-time credential. + - After success, call /participant/search on your own code to confirm encryption_cert and endpoint_url reflect the change. + + ### Related scenario + + A year after go-live a payer's security team rotates the encryption key pair. The integrator generates a new self-signed X.509 certificate, Base64-encodes it and calls /v2/participant/update with participantcode and encryptioncert. The registry returns status and a new transactionid and sends a passcode to the registered mobile. Within the hour the team calls GET /update/validate with both values; on 200 the new certificate is live. Providers that cached the old certificate pick up the new one at their next 24-hour refresh, and the payer keeps the old private key for one more day to decrypt in-flight callbacks. + + ### Specification + + Chapter [Your certificate](/docs/nhcx/v1/getting-started/your-certificate) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - name: transactionId + in: query + required: true + schema: + type: string + example: + - name: passcode + in: query + required: true + schema: + type: string + example: + responses: + "200": + description: HTTP 200 with a bare string body (operation particiapntUpdateValidate, response type string). + content: + application/json: + schema: + type: object + properties: + _contentType: + type: string + _body: + type: string + example: + _contentType: string + _body: +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + description: "On every NHCX call, the token goes in a header called `bearer_auth`, with the word `Bearer` and a space in front. The sources are not unanimous: the authentication page and the FAQ both write the example as `Authorization`, and the notification endpoint uses `Authorization`. The safe course, and what the adapter does, is to send both headers with the same value." + parameters: + BearerAuth: + name: bearer_auth + in: header + required: true + description: It is `bearer_auth`, not `Authorization`, on NHCX's own endpoints. + schema: + type: string + example: Bearer + Source: + name: source + in: header + required: true + description: Sent on this call, as the package's request carries it. + schema: + type: string + example: internal diff --git a/catalogue/openapi/nhcx/v1/nhcx-other.yaml b/catalogue/openapi/nhcx/v1/nhcx-other.yaml new file mode 100644 index 000000000..38b3a5e8c --- /dev/null +++ b/catalogue/openapi/nhcx/v1/nhcx-other.yaml @@ -0,0 +1,2639 @@ +# NHCX other, from the NHCX package's Bruno folder apis/13-other. +# +# Written by the package's system/build-ekadocs.mjs (make ekadocs); change the .bru +# requests there and port again rather than editing this file. +# +# Rules this file follows: catalogue/openapi/CONVENTIONS.md +openapi: 3.1.1 +info: + x-portal: + module: other + label: Other + position: 13 + title: NHCX other + summary: "Claims are often not fully approved first time, for mundane reasons: missing documents, policy interpretation differences, package or pricing discrepancies." + description: |- + The Other calls on the National Health Claims Exchange (NHCX): 14 operations, and 4 callbacks you host. + + Claims are often not fully approved first time, for mundane reasons: missing documents, policy interpretation differences, package or pricing discrepancies. + + Guides that use these calls: [Cancel, reprocess and shortfall](/docs/nhcx/v1/reference/fhir/cancel-reprocess-and-shortfall), [Predetermination, status and search](/docs/nhcx/v1/reference/fhir/predetermination-status-and-search), [Notifications and patient apps](/docs/nhcx/v1/reference/notifications-and-patient-apps), [Accepted with 202, and no callback arrives](/docs/nhcx/v1/troubleshooting/accepted-then-no-callback). + + Production address for the NHCX portal: not published. + version: nhcx-v1 + license: + name: MIT + identifier: MIT + contact: + name: NHCX sandbox + url: https://hcxsbx.abdm.gov.in + x-abdm-gateway: nhcx + x-abdm-module: other + x-abdm-phase: 1 + x-abdm-roles: + - provider + - payer +x-abdm-sources: + - file: nhcx-package/apis/13-other + role: upstream + hash: sha256:d65315e2042e17c77dd9400fc36380a58195496d693f53bb5102e805d7231de2 + note: The package's Bruno collection, one request per operation. + - file: nhcx-package/baseurl.yaml + role: upstream + hash: sha256:88515b7b29c6b349a131e016c80774436ea16a29738db743b4cc3a24cbd42453 + note: The sandbox and production hosts. + - file: nhcx-package/nhcx-error.yaml + role: upstream + hash: sha256:d24ac927ed4dd722e60d7bd1d6fed15de370cc29f750d68999ee56fac93c941b + note: The error codes. +servers: + - url: https://apisbx.abdm.gov.in/hcx + description: Sandbox, NHCX exchange. + - url: https://apisprod.nha.gov.in/hcx + description: Production. +tags: + - name: Other + description: "Claims are often not fully approved first time, for mundane reasons: missing documents, policy interpretation differences, package or pricing discrepancies." + - name: Adapter + description: Internal twins of the exchange calls, for the NHCX adapter deployment. +security: + - bearerAuth: [] +paths: + /v1/task/submit: + post: + operationId: other_v1_task_submit + x-abdm-atom: nhcx.endpoint.task-submit + x-abdm-use-case: Other + tags: + - Other + summary: Task submit (reprocess or cancel) + description: |- + Provider sends a FHIR Task asking the payer to reprocess a rejected or short-paid claim or to cancel a preauth; Task.code and reasonCode set the intent. + + ### Business purpose + + Claims are often not fully approved first time, for mundane reasons: missing documents, policy interpretation differences, package or pricing discrepancies. Without a formal appeal path, disputes leave the system and become phone calls and email. The Task flow gives providers a structured, auditable way to contest a decision with new evidence, and to withdraw a pre-authorisation that will never be used. Payers get a controlled re-adjudication workflow with SLA adherence, aligned with NHA and IRDAI expectations of transparent dispute resolution. + + ### When to use + + After adjudication, when a claim was rejected or partially paid and you have valid justification and additional evidence: Task.code reprocess with reasonCode claimrejected (or partialpayment for a short payment; the handbook sample uses rejectiondisputed), workflow 18 REPROCESS_REQUEST_SUBMITTED, with 36 listed for the arbitration or erroneous case. For cancelling a submitted or approved preauth: Task.code cancel with a cancellation reasonCode (treatmentplanchanged, patientrequest, financialconstraints, alternativetreatment, duplicateclaim, administrativeerror, other), workflow 122 PREAUTH_CANCEL_INITIATED (PC01 in the scenario sheet). x-hcx-correlation_id carries the correlation id of the original claim or preauth. Reprocess outcomes are final within the workflow. + + ### Preconditions + + - Provider is an active NHCX participant with a valid NPI facility code and Bearer token; payer certificate available for JWE encryption. + - The original claim or preauth exists; Task.basedOn references it with the sender's reference id, and Task.input carries claimNumber and the intimation number. + - Patient resource carries PMJAY Member ID and ABHA number; supporting evidence attached (the FAQ says a document as valueAttachment is mandatory for reprocess). + - Task.status requested, Task.intent order, Task.code from http://terminology.hl7.org/CodeSystem/financialtaskcode, reasonCode from ndhm-reason-code; Task.description explains when reasonCode is other. + - Protected header with the original correlation id, fresh api_call_id, IST timestamp, workflow id and status request.initiated. + + ### Postconditions + + The gateway returns HTTP 202 with a StatusSuccessResponse whose result carries entity_type task and a protocol_status; 400, 404 and 500 use the same envelope. The payer validates completeness and eligibility (workflow 251 acknowledges receipt), re-adjudicates and answers on /v1/task/on_submit with a Task bundle whose Task.output references a ClaimResponse: 252 approved, 253 rejected (outcome complete with adjudication reason cancelled), 254 queried (answer with workflow 19). Approval may be followed by payment workflows 30, 31 and 33. For cancellation, only preauths in submitted or approved state can be cancelled; PAYR-1252, PAYR-1253, PAYR-1257 and PAYR-1258 explain refusals. + + ### Common mistakes + + - Omitting Task.basedOn, so the payer has nothing to act on; or sending the sender's reference only in input and not in basedOn. + - Minting a fresh correlation id instead of carrying the original claim or preauth's. + - Submitting a reprocess without new evidence; the handbook restricts appeals to cases with valid justification and supporting documents. + - Cancelling a preauth that is already cancelled, paid or not in an active state (PAYR-1252, PAYR-1253, PAYR-1257, PAYR-1258). + - Spelling the intimation input anything other than intimationNumber; a reprocess under another spelling is refused with PAYR-1008. + - Offering a second reprocess by default; the response is final unless scheme rules allow otherwise. + - Using unverified codes such as a numeric PC01 reason or workflow 36 for a plain reprocess without checking the workflow reference. + + ### Best practices + + - Link the Task to the original entity twice: basedOn with the sender's reference id and Task.input with claimNumber and intimation number. + - Use reasonCode other only with a clear Task.description. + - Persist the correlation id and workflow id so the on_submit Task bundle can be matched and the ClaimResponse extracted from Task.output. + - Design the case state machine so 252 or 253 terminates the appeal branch. + - Fresh api_call_id per call, IST timestamps, request.initiated on the outbound header. + - Implement v1/error; a Task that never reaches the payer is otherwise silent. + + ### Related scenario + + A hospital's claim for a cardiac package, submitted on /v1/claim/submit, comes back on /v1/claim/on_submit rejected for a missing implant invoice. The billing team obtains the invoice and the integration builds a Task: code reprocess, reasonCode claimrejected, basedOn the original claim, input claimNumber and intimation number, the invoice attached, workflow 18, and the claim's correlation id. It posts /v1/task/submit and receives 202. The payer acknowledges (251), re-adjudicates and returns a Task bundle on /v1/task/on_submit whose Task.output wraps a ClaimResponse with outcome complete and workflow 252; a payment notice follows on /v1/paymentnotice/request. + + ### Specification + + Chapter [Cancel, reprocess and shortfall](/docs/nhcx/v1/reference/fhir/cancel-reprocess-and-shortfall) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - $ref: "#/components/parameters/XHcxSenderCode" + - $ref: "#/components/parameters/XHcxRecipientCode" + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxWorkflowId" + - $ref: "#/components/parameters/XHcxTimestamp" + - $ref: "#/components/parameters/XHcxStatus" + - $ref: "#/components/parameters/XHcxBenAbhaId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOiIxMDAwMDA0NDQ2QGhjeCJ9.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: The gateway returns HTTP 202 with a StatusSuccessResponse whose result carries entity_type task and a protocol_status; 400, 404 and 500 use the same envelope. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 25/08/2026 10:00:00:154 + api_call_id: f2a3b4c5-d6e7-8901-5678-012345678901 + correlation_id: 66778899-aabb-ccdd-eeff-001122334455 + result: + sender_code: 1000004446@hcx + recipient_code: 1518@hcx + entity_type: task + protocol_status: request.queued + error: + code: "" + message: "" + /v1/task/on_submit: + post: + operationId: other_v1_task_on_submit + x-abdm-atom: nhcx.endpoint.task-on-submit + x-abdm-use-case: Other + tags: + - Other + summary: Task callback (reprocess or cancel outcome) + description: |- + Payer returns a Task bundle with Task.status completed whose Task.output references a ClaimResponse carrying the reprocess or cancellation outcome. + + ### Business purpose + + This callback closes the appeal or cancellation the provider opened on /v1/task/submit. It carries the payer's final decision on a reprocess (approved, partially approved, queried or rejected) or confirms a pre-authorisation cancellation, in the same ClaimResponse shape used for ordinary adjudication so hospitals can reuse their parsers. Because the reprocess response is final within the workflow, it delivers closure, a clean audit trail and reduced ambiguity for both sides, which is the point of moving disputes inside NHCX. + + ### When to use + + The payer calls it after acknowledging a Task (workflow 251 REPROCESS_REQUEST_RECEIVED), validating it and re-adjudicating. The outer wrapper is a collection Bundle with a Task whose status is completed and whose Task.output.type references a ClaimResponse for the entity the sender named; workflow 252 approved (outcome complete), 253 rejected (outcome complete with adjudication reason cancelled, display Rejected), 254 queried (outcome partial, often zero totals; provider answers with workflow 19). Cancellation accomplished is PC02. Carry the same x-hcx-correlation_id and a responder status (response.complete, or request.initiated for a query per the workflow sheet). + + ### Preconditions + + - The inbound Task was decrypted, its correlation id and workflow captured, and the 202 acceptance body returned within 30 seconds. + - Payer registered with a valid Bearer token and the provider's certificate for encryption. + - A Task bundle: Task.status completed, Task.output[0].valueReference pointing to a ClaimResponse entry that is structurally identical to a normal adjudication response (total, item adjudication, processNote, adjudication reason). + - Protected header echoing the request's correlation id with a fresh api_call_id, IST timestamp, the outcome workflow id and a responder status. + + ### Postconditions + + The gateway returns HTTP 202 with the StatusSuccessResponse envelope (400, 404, 500 in the same shape) and forwards the bundle to the provider, which must acknowledge within 30 seconds. The provider resolves Task.output[0].valueReference.reference within the bundle and passes the ClaimResponse through its standard adjudication parser. The reprocess decision is final within the workflow context; no further standard reprocessing cycles are expected unless scheme rules allow. After approval, payment proceeds through workflows 30 PAYMENT_INITIATED, 31 PAYMENT_PROCESSED and 33 PAYMENT_SETTLED. A cancelled preauth requires a new preauth with a new case number if treatment resumes (PAYR-1255). + + ### Common mistakes + + - Provider side: looking for the ClaimResponse as a direct Bundle.entry instead of following Task.output[].valueReference. + - Reading outcome complete as approval; a rejected reprocess is outcome complete with adjudication reason cancelled. + - Treating a queried response with outcome partial and zero totals as a zero-value approval. + - Payer side: minting a new correlation id on the callback (NHCX-1010) or sending a standalone ClaimResponse bundle instead of a Task wrapper. + - Missing the 30-second 202 on the inbound Task, triggering five redeliveries and deletion of the request. + - Splitting the PMJAY pipe-delimited adjudication reason (USER~datetime~type~comment~trust) as if it were structured. + + ### Best practices + + - Payer: acknowledge first, re-adjudicate asynchronously, then post the Task bundle with the outcome workflow id and ClaimResponse nested in Task.output. + - Provider: share the ClaimResponse parser between /v1/claim/on_submit and this callback; only the extraction path differs. + - Branch on adjudication reason as well as outcome; check processNote for reductions or query text. + - Terminate the appeal branch of the case state machine on 252 or 253; on 254 respond with workflow 19. + - Be idempotent on correlation id; expect redeliveries. + - Fresh api_call_id, IST timestamp, responder status on the callback header. + + ### Related scenario + + A scheme payer's TPA receives a reprocess Task on a rejected claim with the missing implant invoice attached. Its endpoint returns 202 and the case reopens for re-adjudication with the original claim, the new document and the justification. The reviewer approves at the package rate, and the TPA posts /v1/task/on_submit: a Task bundle, status completed, Task.output referencing a ClaimResponse with outcome complete, workflow 252, under the claim's correlation id. The hospital acknowledges within 30 seconds, extracts the ClaimResponse from Task.output, marks the appeal closed and awaits the payment notice on /v1/paymentnotice/request. + + ### Specification + + Chapter [Cancel, reprocess and shortfall](/docs/nhcx/v1/reference/fhir/cancel-reprocess-and-shortfall) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + - name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - name: x-hcx-workflow_id + in: header + required: false + description: Which step, or which case. See the two readings below. Optional on the envelope. + schema: + type: string + example: "252" + - $ref: "#/components/parameters/XHcxTimestamp" + - name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: response.complete + - $ref: "#/components/parameters/XHcxBenAbhaId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOiIxNTE4QGhjeCJ9.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: The gateway returns HTTP 202 with the StatusSuccessResponse envelope (400, 404, 500 in the same shape) and forwards the bundle to the provider, which must acknowledge within 30 seconds. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 26/08/2026 16:30:00:611 + api_call_id: a3b4c5d6-e7f8-9012-6789-123456789012 + correlation_id: 66778899-aabb-ccdd-eeff-001122334455 + result: + sender_code: 1518@hcx + recipient_code: 1000004446@hcx + entity_type: task + protocol_status: request.queued + error: + code: "" + message: "" + /internal/v1/task/submit: + post: + operationId: other_internal_v1_task_submit + x-abdm-use-case: Adapter + tags: + - Adapter + summary: Task submit (internal variant) (adapter) + description: |- + Internal twin of /v1/task/submit on the taskhcxservice, operationId hcxTaskPostInternal, with the same JWEPayload Task body and 202 envelope. + + ### Business purpose + + The taskhcxservice is one of six NHCX services that publish each operation at both /v1/... and /internal/v1/... with identical descriptions and request bodies, differing only in the operationId suffix. This is the internal form of the provider's reprocess or cancel request: the structured appeal path for rejected or short-paid claims and the withdrawal path for unused pre-authorisations. The specifications document no behavioural difference from the public endpoint. + + ### When to use + + Same circumstances as /v1/task/submit: a reprocess (Task.code reprocess, reasonCode claimrejected or partialpayment, workflow 18) after an adverse adjudication with new evidence, or a preauth cancellation (Task.code cancel with a cancellation reasonCode, workflow 122 or PC01). x-hcx-correlation_id carries the original claim or preauth correlation id. The specs do not say when the internal path applies; default to the public path unless onboarding guidance names this one. + + ### Preconditions + + - As for the public endpoint: active provider with NPI facility code, Bearer token, payer certificate for JWE encryption. + - Body is a JWEPayload whose plaintext is the Task resource with basedOn referencing the original entity by the sender's reference id, Task.input with claimNumber and intimation number, and supporting evidence. + - Protected header with the original correlation id, fresh api_call_id, IST timestamp, workflow id and status request.initiated. + - Confirmation that the internal route is intended for your integration. + + ### Postconditions + + Returns 202 Accepted with StatusSuccessResponse (entity_type task), or 400, 404 or 500 in the same envelope. The payer answers later on the task on_submit callback with a Task bundle wrapping a ClaimResponse: workflows 251 received, 252 approved, 253 rejected, 254 queried, PC02 cancellation accomplished. The decision is final within the workflow context. No additional behaviour is documented for the internal variant. + + ### Common mistakes + + - Expecting the internal path to skip validation of basedOn, correlation id or status; it is documented as identical. + - Omitting Task.basedOn or minting a fresh correlation id. + - Cancelling a preauth not in submitted or approved state (PAYR-1252, PAYR-1253, PAYR-1257, PAYR-1258). + - Hard-coding the internal prefix without confirming the route; a 404 may be a host or prefix mismatch. + + ### Best practices + + - Reuse the public endpoint's Task builder; make only the path prefix configurable. + - Link to the original entity in both basedOn and Task.input; use Task.description with reasonCode other. + - Fresh api_call_id per call, IST timestamps, request.initiated on the outbound header. + - Persist correlation id and workflow id for matching the callback; implement v1/error. + + ### Related scenario + + A hospital integrator generating a client from the taskhcxservice Swagger sees hcxTaskPost and hcxTaskPostInternal with the same description. The team builds one reprocess-and-cancel module that posts to /v1/task/submit by default and can be switched to the internal path if NHCX onboarding requires it. When a surgeon changes the treatment plan after a preauth was approved, the module sends Task.code cancel with reasonCode treatmentplanchanged under the preauth's correlation id, receives 202, and later gets the cancellation confirmation on the task on_submit callback before a new preauth is raised. + + ### Specification + + Chapter [Cancel, reprocess and shortfall](/docs/nhcx/v1/reference/fhir/cancel-reprocess-and-shortfall) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - $ref: "#/components/parameters/XHcxSenderCode" + - $ref: "#/components/parameters/XHcxRecipientCode" + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - name: x-hcx-workflow_id + in: header + required: false + description: Which step, or which case. See the two readings below. Optional on the envelope. + schema: + type: string + example: "122" + - $ref: "#/components/parameters/XHcxTimestamp" + - $ref: "#/components/parameters/XHcxStatus" + - $ref: "#/components/parameters/XHcxBenAbhaId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOiIxMDAwMDA0NDQ2QGhjeCJ9.encrypted_key.iv.ciphertext.tag + responses: + "200": + description: Returns 202 Accepted with StatusSuccessResponse (entity_type task), or 400, 404 or 500 in the same envelope. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 25/08/2026 10:20:00:093 + api_call_id: b4c5d6e7-f8a9-0123-7890-234567890123 + correlation_id: 778899aa-bbcc-ddee-ff00-112233445566 + result: + sender_code: 1000004446@hcx + recipient_code: 1518@hcx + entity_type: task + protocol_status: request.queued + error: + code: "" + message: "" + /internal/v1/task/on_submit: + post: + operationId: other_internal_v1_task_on_submit + x-abdm-use-case: Adapter + tags: + - Adapter + summary: Task callback (internal variant) (adapter) + description: |- + Internal twin of /v1/task/on_submit (hcxOnTaskPostInternal): the payer Task bundle wrapping the ClaimResponse outcome of a reprocess or cancel. + + ### Business purpose + + This is the internal-path form of the callback that closes a reprocess or cancellation. The OpenAPI lists it with the same description and bare object body as the public callback and distinguishes it only by the operationId suffix. Its role is unchanged: deliver the payer's final, auditable decision on an appeal, or confirmation of a preauth cancellation, in a Task bundle whose Task.output references a ClaimResponse that hospitals can parse with their normal adjudication logic. + + ### When to use + + Same as the public callback: after acknowledging and re-adjudicating a Task, the payer posts a Task bundle with status completed and Task.output referencing the ClaimResponse, under the original correlation id, with workflow 252, 253 or 254 (or PC02 for cancellation) and a responder status. The specifications do not say when the internal path is used in preference to the public one. + + ### Preconditions + + - Inbound Task decrypted, correlation id captured, 202 acceptance returned within 30 seconds. + - Registered payer with a valid Bearer token and the provider's certificate. + - Task bundle with Task.status completed and Task.output[0].valueReference resolving to a ClaimResponse entry in the bundle. + - Protected header echoing the request's correlation id with a fresh api_call_id, IST timestamp, outcome workflow id and responder status. + - Confirmation that the internal route is the intended one. + + ### Postconditions + + Returns 202 Accepted with the StatusSuccessResponse envelope, or 400, 404 or 500 in the same shape; the bundle is forwarded to the provider, which acknowledges within 30 seconds, extracts the ClaimResponse from Task.output and closes the appeal branch. The decision is final within the workflow context; approval leads to payment workflows 30, 31 and 33. No additional behaviour is documented for the internal variant. + + ### Common mistakes + + - Expecting a different envelope or relaxed validation; none is documented. + - Sending a standalone ClaimResponse bundle rather than a Task wrapper, or minting a new correlation id (NHCX-1010). + - Provider side: reading the ClaimResponse from Bundle.entry directly, or treating outcome complete as approval without checking the adjudication reason. + - Using an unconfigurable path that cannot switch between public and internal forms. + + ### Best practices + + - Share the public callback's bundle builder; only the path differs. + - Acknowledge the inbound Task first, re-adjudicate asynchronously, then post. + - Provider: reuse the claim ClaimResponse parser, reached via Task.output[0].valueReference.reference. + - Idempotent handling on correlation id; fresh api_call_id and IST timestamp on the callback. + + ### Related scenario + + A payer platform reviewing the taskhcxservice specification sees hcxOnTaskPost and hcxOnTaskPostInternal side by side. It implements a single outcome publisher that wraps the ClaimResponse in a Task bundle and posts to the public /v1/task/on_submit path unless configured for the internal one. When a hospital's cancellation Task for an unused preauth is processed, the publisher posts the Task bundle with PC02 semantics under the preauth's correlation id; the hospital acknowledges within 30 seconds and raises a fresh preauth with a new case number for the revised treatment. + + ### Specification + + Chapter [Cancel, reprocess and shortfall](/docs/nhcx/v1/reference/fhir/cancel-reprocess-and-shortfall) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + - name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - name: x-hcx-workflow_id + in: header + required: false + description: Which step, or which case. See the two readings below. Optional on the envelope. + schema: + type: string + example: PC02 + - $ref: "#/components/parameters/XHcxTimestamp" + - name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: response.complete + - $ref: "#/components/parameters/XHcxBenAbhaId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOiIxNTE4QGhjeCJ9.encrypted_key.iv.ciphertext.tag + responses: + "200": + description: Returns 202 Accepted with the StatusSuccessResponse envelope, or 400, 404 or 500 in the same shape; the bundle is forwarded to the provider, which acknowledges within 30 seconds, extracts the ClaimResponse from Task.output and closes the appeal branch. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 25/08/2026 11:05:00:448 + api_call_id: c5d6e7f8-a9b0-1234-8901-345678901234 + correlation_id: 778899aa-bbcc-ddee-ff00-112233445566 + result: + sender_code: 1518@hcx + recipient_code: 1000004446@hcx + entity_type: task + protocol_status: request.queued + error: + code: "" + message: "" + /v1/notification/subscribe: + post: + operationId: other_v1_notification_subscribe + x-abdm-atom: nhcx.endpoint.notification-subscribe + x-abdm-use-case: Other + tags: + - Other + summary: Notification subscribe + description: |- + A Beneficiary Service Provider (PHR app) subscribes an ABHA id to notification topics; NHCX persists it synchronously, Last-Linked-Wins per ABHA id. + + ### Business purpose + + Every other flow is a two-party exchange between hospital and payer. Notifications let a third party, the beneficiary through a PHR app, watch a claim move without being a sender or recipient on the underlying preauth or claim. The caller is a Beneficiary Service Provider (BSP), not a hospital or insurer; the persona label here is the nearest available. The subscription is what routes human-readable messages such as a preauth approval with amount and validity to the patient's app, giving beneficiaries transparency and reducing calls to the hospital desk. + + ### When to use + + Call it on every beneficiary login (Subscribe-on-Login): the user authenticates with the ABHA address, the app checks its NHCX token, refreshes via the sessions endpoint if expired, then subscribes the ABHA id and stores the returned subscription_id. Because Last-Linked-Wins replaces any earlier app's subscription, resubscribe on each login rather than trusting a stored id. Most PHR apps need only topic_code workflow_events; network_events and participant_events are also defined. The call is synchronous and sits outside the workflow-code sequence; a fresh x-hcx-correlation_id is required per attempt. + + ### Preconditions + + - ABDM M1 integration completed; BSP sandbox testing on hcxsbx.abdm.gov.in, certification and production registry onboarding. + - An HTTPS callback endpoint with TLS 1.2 or higher registered as on_notification_url, and JWT capability. + - Access token from the ABDM session token call (01-session/session-token.bru); sent as Authorization: Bearer with Content-Type application/json. + - Body is a JWEPayload whose compact JWE carries protected headers alg RSA-OAEP, enc A256GCM, x-hcx-sender_code (your BSP code), x-hcx-recipient_code (NHCX gateway code), x-hcx-timestamp (ISO 8601) and a unique x-hcx-correlation_id, plus the subscribe JSON: subscription_id, topic_code array, recipient_code, subscriber.id (ABHA id), on_notification_url and optional expiry. + - Explicit user consent obtained before subscribing. + + ### Postconditions + + NHCX decrypts the request with its private key, validates headers and payload, persists the subscription with Last-Linked-Wins per ABHA id and returns the subscription state synchronously: HTTP 200 with a SubscribeResponse carrying timestamp, api_call_id, correlation_id, subscription_id, subscription_status (active, replaced or expired), expiry and message. Thereafter, when a hospital submits a preauth or claim with that ABHA id and the payer responds, NHCX pushes a notification (notification_id, topic_code, timestamp, subscriber.id, a displayable message and optional domain_values) to the registered callback. Errors: 400 validation, 401 sender not authorised, 403 sender not permitted, 409 duplicate correlation id, 500 decryption or persistence failure. + + ### Common mistakes + + - Reusing x-hcx-correlation_id across attempts or retries, which returns 409 (the API reference defines 409 as replay detection, not an existing-subscription conflict). + - Subscribing once and trusting the stored subscription_id; another app's login silently replaces it (subscription_status replaced). + - Sending it to the exchange host, https://apisbx.abdm.gov.in/hcx, where the other /v1 calls go. The notification integration guide gives the portal host: https://hcxsbx.abdm.gov.in/v1/notification/subscribe. + - Sending the token on bearer_auth. This call reads it from Authorization: Bearer. + - Sending protocol headers in the clear rather than inside the JWE protected header. + - Using the NHCX client-credentials token endpoint instead of the ABDM gateway sessions endpoint. + - Subscribing silently without consent or without showing subscription status in settings. + + ### Best practices + + - Subscribe on every login and refresh the token before its 100-minute expiry; store access_token encrypted and never log the secret. + - Generate a fresh UUID correlation id per subscribe attempt, including retries; retry 500s with backoff, regenerate the token on 401, check the registry on 403. + - Subscribe only to the topics you need, typically workflow_events. + - Secure the callback: HTTPS with TLS 1.2 or higher, validate the JWT from NHCX, verify sender_code, rate-limit. + - Display the message field directly to users; treat domain_values as optional audit data and read status from x-hcx-status, not the workflow id description. + + ### Related scenario + + A beneficiary opens a PHR app and logs in with the ABHA address ravi@abdm. The app confirms its NHCX token is valid, then posts /v1/notification/subscribe with subscription_id sub_ravi_001, topic_code workflow_events, its BSP code and its on_notification_url, under a fresh correlation id. NHCX replies 200 with subscription_status active. Later that day a hospital submits a preauth for the same ABHA id on /v1/preauth/submit and the payer approves it on /v1/preauth/on_submit; NHCX pushes a notification to the app's callback reading that the preauthorisation was approved for Rs. 50,000 with its validity dates, which the app displays as-is. + + ### Specification + + Chapter [Notifications and patient apps](/docs/nhcx/v1/reference/notifications-and-patient-apps) of the NHCX integration specification. + security: [] + servers: + - url: https://hcxsbx.abdm.gov.in + description: Sandbox, NHCX portal. + parameters: + - name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: phr-app-xyz@bsp + - name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: nhcx-gateway@hcx + - $ref: "#/components/parameters/XHcxTimestamp" + - $ref: "#/components/parameters/XHcxCorrelationId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + _payload_plaintext: + type: object + properties: + subscription_id: + type: string + topic_code: + type: array + items: + type: string + recipient_code: + type: string + subscriber: + type: object + properties: + id: + type: string + on_notification_url: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00iLCJ4LWhjeC1zZW5kZXJfY29kZSI6InBoci1hcHAteHl6QGJzcCJ9.encrypted_key.iv.ciphertext.tag + _payload_plaintext: + subscription_id: sub_ravi_001 + topic_code: + - workflow_events + recipient_code: phr-app-xyz@bsp + subscriber: + id: ravi@abdm + on_notification_url: https://api.phrapp.com/v1/hcx/notification/on_subscribe + responses: + "200": + description: "NHCX decrypts the request with its private key, validates headers and payload, persists the subscription with Last-Linked-Wins per ABHA id and returns the subscription state synchronously: HTTP 200 with a SubscribeResponse carrying timestamp, api_call_id, correlation_id, subscription_id, subscription_status (active, replaced or expired), expiry and message." + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + subscription_id: + type: string + subscription_status: + type: string + expiry: + type: string + message: + type: string + example: + timestamp: 2026-08-25T08:30:00+05:30 + api_call_id: d6e7f8a9-b0c1-2345-9012-456789012345 + correlation_id: 8899aabb-ccdd-eeff-0011-223344556677 + subscription_id: sub_ravi_001 + subscription_status: active + expiry: "" + message: Subscription accepted + /v1/notification/on_subscribe: + post: + operationId: other_v1_notification_on_subscribe + x-abdm-use-case: Other + tags: + - Other + summary: Notification on_subscribe + description: |- + BSP-side subscription acknowledgement; the same name denotes the callback where NHCX pushes claim-event notifications for a subscribed ABHA id. + + ### Business purpose + + Two things share this name. The API reference defines an NHCX-side operation (operationId onSubscribe) that takes a NotificationOnSubscribePayload with the beneficiary's abhaid, optional domain_values and plain header values, and returns a SubscribeResponse; it is described as the BSP-side subscription persistence acknowledgement. The integration guide uses the same path on the BSP's own host as the callback where NHCX delivers notifications. Together they complete the beneficiary-facing loop: the patient's app learns, in plain language, that a preauth was approved, a claim adjudicated, a payment made or information requested. The caller is a Beneficiary Service Provider; the persona label is the nearest available. + + ### When to use + + As a BSP you implement this path on your host, registered through on_notification_url, and receive a push whenever a workflow event occurs for a subscribed ABHA id: preauth_request (queued, processing), preauth_response (approved, rejected), claim_request, claim_response, payment_notice (paid, pending) and communication (information_required). The NHCX-side operation is invoked with hvalues senderid, receiverid, correlationid and status required, and workflowid, source, api_caller_id, call_type and usertoken optional. It sits outside the workflow-code sequence; domain_values may carry x-hcx-workflow_id, x-hcx-correlation_id, x-hcx-status, x-hcx-action and amount fields. + + ### Preconditions + + - An active subscription created via /v1/notification/subscribe for the ABHA id; Last-Linked-Wins means only the most recently linked app receives events. + - The BSP callback exposed over HTTPS with TLS 1.2 or higher at the registered on_notification_url, validating the JWT from NHCX, verifying sender_code and rate-limiting. + - For the NHCX-side operation: a NotificationOnSubscribePayload with request.abhaid (required) and optional request.domain_values, plus hvalues with senderid, receiverid, correlationid and status. + - The ordinary preauth or claim exchange between hospital and payer has produced an event for that beneficiary. + + ### Postconditions + + The NHCX-side operation returns HTTP 200 with a SubscribeResponse (timestamp, api_call_id, correlation_id, subscription_id, subscription_status active, replaced or expired, expiry, message); 400, 401, 403, 409 and 500 return a StatusSuccessResponse with the same descriptions as the subscribe table. On the BSP callback the delivered payload carries notification_id, topic_code, timestamp, subscriber.id, a human-readable message that can be shown directly to the user, and optional domain_values with x-hcx-* headers for audit or custom formatting. Nothing changes in the hospital-payer exchange; the notification is a forked copy of the outcome. + + ### Common mistakes + + - Conflating the NHCX-side operation with your own callback and implementing only one of them. + - Parsing domain_values to build the user message instead of displaying the message field; domain_values is optional and may be absent. + - Reading status from the x-hcx-workflow_id description (approved, rejected, queued, processing), which is a documentation error; the example carries an identifier and status lives in x-hcx-status. + - Assuming the subscription is still yours; a subscription_status of replaced means another app took the routing slot on login. + - Accepting callbacks without validating the JWT or sender_code, or without TLS 1.2 or higher. + - Treating the senderid and receiverid descriptions (payer id, hospital id) literally in the notification context; they are inherited boilerplate. + + ### Best practices + + - Display message verbatim; keep domain_values for audit logging or advanced formatting only. + - Validate the JWT and sender_code on every inbound push, enforce TLS 1.2 or higher and rate limiting. + - Map event types (preauth_response, claim_response, payment_notice, communication) to in-app timelines using x-hcx-action and x-hcx-status. + - Show subscription status in settings so a replaced subscription is visible to the user; resubscribe on next login. + - Keep the endpoint fast and idempotent on notification_id. + + ### Related scenario + + A PHR app has subscribed ravi@abdm to workflow_events. A hospital submits a claim on /v1/claim/submit for that beneficiary and the payer adjudicates it on /v1/claim/on_submit. NHCX forks the outcome to the app's registered on_subscribe callback with topic_code workflow_events, a message stating the claim was approved with the amount, and domain_values including x-hcx-action claim_response and x-hcx-status response.complete. The app validates the JWT and sender_code, shows the message on the patient's timeline, and when the payer later sends a payment notice on /v1/paymentnotice/request the next push reads paid. + + ### Specification + + Chapter [Notifications and patient apps](/docs/nhcx/v1/reference/notifications-and-patient-apps) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + request: + type: object + properties: + abhaid: + type: string + domain_values: + type: object + properties: + x-hcx-workflow_id: + type: string + x-hcx-correlation_id: + type: string + x-hcx-timestamp: + type: string + x-hcx-sender_code: + type: string + x-hcx-recipient_code: + type: string + x-hcx-status: + type: string + x-hcx-action: + type: string + x-hcx-amount_submitted: + type: string + hvalues: + type: object + properties: + senderid: + type: string + receiverid: + type: string + correlationid: + type: string + status: + type: string + workflowid: + type: string + example: + request: + abhaid: ravi@abdm + domain_values: + x-hcx-workflow_id: wf_20260825_001 + x-hcx-correlation_id: corr_20260825_12345 + x-hcx-timestamp: 2026-08-25T14:30:00+05:30 + x-hcx-sender_code: payor.icici@nhcx + x-hcx-recipient_code: bsp.phrapp@nhcx + x-hcx-status: response.complete + x-hcx-action: preauth_response + x-hcx-amount_submitted: "75000.00" + hvalues: + senderid: payor.icici@nhcx + receiverid: bsp.phrapp@nhcx + correlationid: corr_20260825_12345 + status: response.complete + workflowid: wf_20260825_001 + responses: + "200": + description: The NHCX-side operation returns HTTP 200 with a SubscribeResponse (timestamp, api_call_id, correlation_id, subscription_id, subscription_status active, replaced or expired, expiry, message); 400, 401, 403, 409 and 500 return a StatusSuccessResponse with the same descriptions as the subscribe table. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + subscription_id: + type: string + subscription_status: + type: string + expiry: + type: string + message: + type: string + example: + timestamp: 2026-08-25T14:30:01+05:30 + api_call_id: e7f8a9b0-c1d2-3456-0123-567890123456 + correlation_id: corr_20260825_12345 + subscription_id: sub_ravi_001 + subscription_status: active + expiry: "" + message: "Preauthorization approved for Rs. 50,000. Valid from 2026-08-25 to 2026-09-01. Reference: PA-2026-004567" + /v1/delete: + post: + operationId: other_v1_delete + x-abdm-use-case: Other + tags: + - Other + summary: Delete records (troubleshooting) + description: |- + Internal troubleshooting operation on the claim service that deletes records by correlationid and action; not part of the business transaction flows. + + ### Business purpose + + The claim service OpenAPI lists /v1/delete as an internal troubleshooting operation for deleting records identified by a correlationid and an action. It exists to clear stuck or erroneous records during integration testing and support, not to move a claim through its lifecycle. The published documentation gives no further business context and does not state which participant roles may call it. + + ### When to use + + Only in troubleshooting, and only as directed by NHCX support. The endpoint index describes it as internal troubleshooting, deleting records by correlationid plus action. It does not appear in any transaction flow, sample bundle or workflow-code table, and it carries no x-hcx-workflow_id semantics. It is unrelated to the platform behaviour in which NHCX itself deletes a request after five failed delivery attempts; that deletion is automatic and needs no call. + + ### Preconditions + + - A valid Bearer token and the HTTP headers Accept: application/json, Content-Type: application/json and bearer_auth. + - The correlation ID of the record to be removed and the action it was recorded under; the docs name these two inputs (correlationid and action) but do not publish a schema, sample body or authorisation rule. + - Agreement from NHCX support that deletion is the right remedy; the documentation does not describe any business validation performed by the endpoint. + + ### Postconditions + + The endpoint sits in the claim service, whose domain operations all return 202 Accepted, 400 Request Validation failed, 404 Requested resource was not found and 500 Downstream systems down, each carrying StatusSuccessResponse. No worked response body, callback or state change is documented for /v1/delete beyond the removal of the record identified by correlationid and action. After deletion a fresh request cycle with a new correlation UUID is the documented way to proceed, since a deleted or inactive correlation ID cannot be resumed. + + ### Common mistakes + + - Treating /v1/delete as a way to cancel a preauth or claim; cancellation is a Task on /v1/task/submit (code cancel, workflow PC01 or 122) and reprocess is workflow 36 on the same endpoint. + - Calling it to recover from a failed delivery and then reusing the same correlation ID; NHCX marks failed correlation IDs inactive and a new cycle is required. + - Assuming the input names or authorisation are documented; only correlationid and action are named, and the specs do not say who may call it. + - Using it in production without NHCX support involvement; it is described as internal troubleshooting. + + ### Best practices + + - Reserve this call for sandbox troubleshooting and only on NHCX support's instruction. + - Record the correlation ID, action and reason for every deletion in your own audit log, since the docs describe no NHCX-side confirmation beyond the HTTP status. + - Prefer /v1/status to inspect a stuck correlation ID before deleting anything. + - Mint a new correlation UUID for any re-submission after a deletion. + + ### Related scenario + + During sandbox testing a hospital's integrator submits a claim whose callback keeps failing because their endpoint returned 200 instead of 202. NHCX support asks them to fix the acknowledgement and then clears the stuck record by correlation ID and action using /v1/delete so the test case can be rerun cleanly. The integrator resubmits the claim to /v1/claim/submit under a new correlation UUID, receives a 202, and this time the on_submit callback is acknowledged correctly. + + ### Specification + + No chapter of the current documentation covers this operation. It appears only in the claim service's OpenAPI. + parameters: + - $ref: "#/components/parameters/BearerAuth" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + correlationid: + type: string + action: + type: string + example: + correlationid: 5d4c3b2a-1f0e-4d9c-8b7a-6f5e4d3c2b1a + action: /v1/claim/submit + responses: + "200": + description: The endpoint sits in the claim service, whose domain operations all return 202 Accepted, 400 Request Validation failed, 404 Requested resource was not found and 500 Downstream systems down, each carrying StatusSuccessResponse. + content: + application/json: + schema: + type: object + properties: + httpStatus: + type: integer + schema: + type: string + note: + type: string + example: + httpStatus: 202 + schema: StatusSuccessResponse + note: The claim service spec lists 202, 400, 404 and 500, all carrying StatusSuccessResponse; no worked response body is published for /v1/delete. + /v3/api-docs: + get: + operationId: other_v3_api_docs + x-abdm-use-case: Other + tags: + - Other + summary: OpenAPI 3 document (status service) + description: |- + Serves the status service's OpenAPI 3 document, optionally filtered by a group query parameter; a discovery endpoint, not a protocol API. + + ### Business purpose + + Integrators need a machine-readable contract for the Status API in order to generate clients, validate their requests and confirm the server prefix. This endpoint serves that contract in OpenAPI 3 form for the status service (statushcxservice, OpenAPI 3.0.1, service version 1.0.0). It carries no claim-settlement data and involves no payer or provider business logic; its value is purely in making the /v1/status operation discoverable and verifiable during integration and troubleshooting. + + ### When to use + + Use it during integration setup, when generating or refreshing an API client, and when a status call is failing and you want to confirm the exact schema and server prefix the service advertises. The endpoint index lists it as endpoint 19 with an optional group query parameter. It is not part of any transaction workflow and is not referenced by the sandbox exit checklists. + + ### Preconditions + + - A GET request to the status service host; the OpenAPI documents in this corpus were captured from https://hcxsbx.abdm.gov.in//api-docs, and the status service declares the server prefix /statushcxservice. + - No JWE envelope, no x-hcx-* protocol headers and no correlation id; the docs do not state that a Bearer token is required for these discovery endpoints. + - No request body. + + ### Postconditions + + The service returns HTTP 200 with a JSON OpenAPI 3 document describing the status service: its info block, the /statushcxservice server entry and the /v1/status operation with its StatusSuccessResponse responses. Nothing changes on NHCX and no callback follows. The document is a description of the service as deployed and may differ from the handbook's gateway-side conventions, which the docs flag as an unresolved conflict. + + ### Common mistakes + + - Pointing at the gateway base https://apisbx.abdm.gov.in/pmjay/sbxhcx and expecting the per-service spec host; the docs advise swapping between the two URL shapes when a path 404s. + - Treating the served document as the integration contract for gateway traffic; the handbook's gateway base and header conventions take precedence where the two disagree. + - Sending a POST or a JSON body to a GET discovery endpoint. + - Wrapping the call in JWE or adding x-hcx-* headers, which only apply to protocol APIs such as /v1/status. + + ### Best practices + + - Use these endpoints for exploration and client generation in the sandbox, and cache the document rather than fetching it on every run. + - Diff the served document against the corpus (Status service: OpenAPI 3.0.1, version 1.0.0) when behaviour changes unexpectedly. + - Never let production traffic depend on the availability of the documentation endpoints. + - Keep the /v1/status protocol rules in mind when reading the spec: x-hcx-correlation_id must carry the original request's correlation id. + + ### Related scenario + + A hospital's integration team is building status polling for stalled preauthorisations. Before wiring /v1/status, an engineer fetches /v3/api-docs from the status service host, confirms the server prefix and the response schema, and generates a typed client. The team then implements the status request with the original correlation id in x-hcx-correlation_id, handles the synchronous request.queued and request.dispatched outcomes, and receives the payer's answer on the status callback. + + ### Specification + + Chapter [Environments and addresses](/docs/nhcx/v1/reference/environments-and-addresses) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + responses: + "200": + description: "The service returns HTTP 200 with a JSON OpenAPI 3 document describing the status service: its info block, the /statushcxservice server entry and the /v1/status operation with its StatusSuccessResponse responses." + content: + application/json: + schema: + type: object + properties: + openapi: + type: string + info: + type: object + properties: + title: + type: string + version: + type: string + servers: + type: array + items: + type: object + properties: + url: + type: string + paths: + type: object + properties: + /v1/status: + type: object + properties: + post: + type: object + properties: + operationId: + type: string + responses: + type: object + properties: + "202": + type: object + properties: + description: + type: string + example: + openapi: 3.0.1 + info: + title: Status service + version: 1.0.0 + servers: + - url: /statushcxservice + paths: + /v1/status: + post: + operationId: status + responses: + "202": + description: Accepted + /v2/api-docs: + get: + operationId: other_v2_api_docs + x-abdm-use-case: Other + tags: + - Other + summary: Swagger 2 document (status service) + description: |- + Serves the status service's Swagger 2 document, optionally filtered by a group query parameter; a discovery endpoint, not a protocol API. + + ### Business purpose + + Some tooling still consumes Swagger 2 rather than OpenAPI 3. This endpoint serves the status service's contract in that older format so that such tools can generate clients and validate requests against /v1/status. It exists alongside /v3/api-docs and describes the same service; it carries no claim-settlement data and involves no business logic. Its value is limited to integration setup and troubleshooting. + + ### When to use + + Use it when your client generator or API tooling requires Swagger 2 input, or when comparing the Swagger 2 and OpenAPI 3 renderings of the status service during a troubleshooting session. The endpoint index lists it as endpoint 20 with an optional group query parameter. It plays no part in any transaction workflow. + + ### Preconditions + + - A GET request to the status service host; the OpenAPI documents in this corpus were captured from https://hcxsbx.abdm.gov.in//api-docs, and the status service declares the server prefix /statushcxservice. + - No JWE envelope, no x-hcx-* protocol headers and no correlation id; the docs do not state that a Bearer token is required for these discovery endpoints. + - No request body. + + ### Postconditions + + The service returns HTTP 200 with a JSON Swagger 2 document (swagger: 2.0) describing the status service, its base path and the /v1/status operation. Nothing changes on NHCX and no callback follows. Where the served document and the handbook disagree on URL shape, the docs advise treating the per-service spec host as the exploration surface and the handbook's gateway base as the integration surface. + + ### Common mistakes + + - Pointing at the gateway base https://apisbx.abdm.gov.in/pmjay/sbxhcx and expecting the per-service spec host; the docs advise swapping between the two URL shapes when a path 404s. + - Treating the served document as the integration contract for gateway traffic; the handbook's gateway base and header conventions take precedence where the two disagree. + - Sending a POST or a JSON body to a GET discovery endpoint. + - Wrapping the call in JWE or adding x-hcx-* headers, which only apply to protocol APIs such as /v1/status. + + ### Best practices + + - Use these endpoints for exploration and client generation in the sandbox, and cache the document rather than fetching it on every run. + - Diff the served document against the corpus (Status service: OpenAPI 3.0.1, version 1.0.0) when behaviour changes unexpectedly. + - Never let production traffic depend on the availability of the documentation endpoints. + - Keep the /v1/status protocol rules in mind when reading the spec: x-hcx-correlation_id must carry the original request's correlation id. + + ### Related scenario + + A TPA's legacy integration platform only imports Swagger 2 definitions. During onboarding to the status flow the team fetches /v2/api-docs from the status service, imports it, and confirms that the /v1/status operation and its StatusSuccessResponse are represented. They then implement the JWE-wrapped status request for preauthorisations that have not received an on_submit callback, and respond to providers' status requests on the status callback. + + ### Specification + + Chapter [Environments and addresses](/docs/nhcx/v1/reference/environments-and-addresses) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + responses: + "200": + description: "The service returns HTTP 200 with a JSON Swagger 2 document (swagger: 2.0) describing the status service, its base path and the /v1/status operation." + content: + application/json: + schema: + type: object + properties: + swagger: + type: string + info: + type: object + properties: + title: + type: string + version: + type: string + basePath: + type: string + paths: + type: object + properties: + /v1/status: + type: object + properties: + post: + type: object + properties: + operationId: + type: string + responses: + type: object + properties: + "202": + type: object + properties: + description: + type: string + example: + swagger: "2.0" + info: + title: Status service + version: 1.0.0 + basePath: /statushcxservice + paths: + /v1/status: + post: + operationId: status + responses: + "202": + description: Accepted + /swagger-resources: + get: + operationId: other_swagger_resources + x-abdm-use-case: Other + tags: + - Other + summary: Swagger resources list + description: |- + Lists the Swagger resources (API document locations) exposed by the status service; used by Swagger UI, not by integrations. + + ### Business purpose + + Swagger UI discovers which API documents a service offers by reading this list. On the status service it points the UI at the /v2/api-docs and /v3/api-docs documents so that an engineer can browse the /v1/status operation interactively. It carries no claim-settlement data and involves no business logic; the endpoint index describes it simply as the list of Swagger resources. + + ### When to use + + Use it only when hosting or debugging a Swagger UI session against the status service, or when a tool needs to discover the available document URLs before fetching them. The endpoint index lists it as endpoint 21. It is not part of any transaction workflow and is not referenced by the sandbox exit checklists. + + ### Preconditions + + - A GET request to the status service host; the OpenAPI documents in this corpus were captured from https://hcxsbx.abdm.gov.in//api-docs, and the status service declares the server prefix /statushcxservice. + - No JWE envelope, no x-hcx-* protocol headers and no correlation id; the docs do not state that a Bearer token is required for these discovery endpoints. + - No request body. + + ### Postconditions + + The service returns HTTP 200 with a JSON list of resource descriptors that locate the service's API documents. Nothing changes on NHCX and no callback follows. The documentation does not detail the descriptor fields beyond the purpose line, so treat the shape shown here as illustrative and read the live response. + + ### Common mistakes + + - Pointing at the gateway base https://apisbx.abdm.gov.in/pmjay/sbxhcx and expecting the per-service spec host; the docs advise swapping between the two URL shapes when a path 404s. + - Treating the served document as the integration contract for gateway traffic; the handbook's gateway base and header conventions take precedence where the two disagree. + - Sending a POST or a JSON body to a GET discovery endpoint. + - Wrapping the call in JWE or adding x-hcx-* headers, which only apply to protocol APIs such as /v1/status. + + ### Best practices + + - Use these endpoints for exploration and client generation in the sandbox, and cache the document rather than fetching it on every run. + - Diff the served document against the corpus (Status service: OpenAPI 3.0.1, version 1.0.0) when behaviour changes unexpectedly. + - Never let production traffic depend on the availability of the documentation endpoints. + - Keep the /v1/status protocol rules in mind when reading the spec: x-hcx-correlation_id must carry the original request's correlation id. + + ### Related scenario + + An integration engineer opens Swagger UI against the status service in the sandbox to reproduce a colleague's failing status call. The UI first requests /swagger-resources to learn where the API documents live, then loads /v3/api-docs. The engineer inspects the /v1/status operation, notices the colleague had minted a fresh correlation id instead of reusing the original preauth correlation id, and fixes the client before retrying the status request. + + ### Specification + + Chapter [Environments and addresses](/docs/nhcx/v1/reference/environments-and-addresses) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + responses: + "200": + description: The service returns HTTP 200 with a JSON list of resource descriptors that locate the service's API documents. + content: + application/json: + schema: + type: object + properties: + _note: + type: string + resources: + type: array + items: + type: object + properties: + name: + type: string + url: + type: string + swaggerVersion: + type: string + example: + _note: The service returns a JSON array of resource descriptors; wrapped here for display. + resources: + - name: default + url: /v3/api-docs + swaggerVersion: "3.0" + /swagger-resources/configuration/ui: + get: + operationId: other_swagger_resources_configuration_ui + x-abdm-use-case: Other + tags: + - Other + summary: Swagger UI configuration + description: |- + Returns the Swagger UI display configuration for the status service; consumed by Swagger UI, not by integrations. + + ### Business purpose + + Swagger UI reads this endpoint to learn how the service wants its documentation rendered (for example, expansion and deep-linking settings). It supports the interactive exploration of the status service's /v1/status operation and has no role in claim settlement, routing or security. The endpoint index describes it as the Swagger UI configuration. + + ### When to use + + Use it only in the context of a Swagger UI session against the status service; ordinary integrations never call it. The endpoint index lists it as endpoint 22. It is not part of any transaction workflow and does not appear in the sandbox exit checklists. + + ### Preconditions + + - A GET request to the status service host; the OpenAPI documents in this corpus were captured from https://hcxsbx.abdm.gov.in//api-docs, and the status service declares the server prefix /statushcxservice. + - No JWE envelope, no x-hcx-* protocol headers and no correlation id; the docs do not state that a Bearer token is required for these discovery endpoints. + - No request body. + + ### Postconditions + + The service returns HTTP 200 with a small JSON object of UI settings. Nothing changes on NHCX and no callback follows. The documentation does not enumerate the settings, so the example below is illustrative; read the live response if you need specific values. + + ### Common mistakes + + - Pointing at the gateway base https://apisbx.abdm.gov.in/pmjay/sbxhcx and expecting the per-service spec host; the docs advise swapping between the two URL shapes when a path 404s. + - Treating the served document as the integration contract for gateway traffic; the handbook's gateway base and header conventions take precedence where the two disagree. + - Sending a POST or a JSON body to a GET discovery endpoint. + - Wrapping the call in JWE or adding x-hcx-* headers, which only apply to protocol APIs such as /v1/status. + + ### Best practices + + - Use these endpoints for exploration and client generation in the sandbox, and cache the document rather than fetching it on every run. + - Diff the served document against the corpus (Status service: OpenAPI 3.0.1, version 1.0.0) when behaviour changes unexpectedly. + - Never let production traffic depend on the availability of the documentation endpoints. + - Keep the /v1/status protocol rules in mind when reading the spec: x-hcx-correlation_id must carry the original request's correlation id. + + ### Related scenario + + While preparing sandbox exit evidence, a payer's engineer captures screenshots of the status service's Swagger UI. The browser loads /swagger-resources/configuration/ui to decide how to render the page, then the resources list and the OpenAPI document. The engineer uses the rendered /v1/status operation to explain to the certification reviewer how the payer responds on the status callback when a provider asks about a dispatched preauthorisation. + + ### Specification + + Chapter [Environments and addresses](/docs/nhcx/v1/reference/environments-and-addresses) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + responses: + "200": + description: The service returns HTTP 200 with a small JSON object of UI settings. + content: + application/json: + schema: + type: object + properties: + deepLinking: + type: boolean + docExpansion: + type: string + displayRequestDuration: + type: boolean + example: + deepLinking: true + docExpansion: none + displayRequestDuration: false + /swagger-resources/configuration/security: + get: + operationId: other_swagger_resources_configuration_security + x-abdm-use-case: Other + tags: + - Other + summary: Swagger security configuration + description: |- + Returns the Swagger UI security configuration for the status service; consumed by Swagger UI, not by integrations. + + ### Business purpose + + Swagger UI reads this endpoint to learn how to present authorisation inputs (such as a bearer token field) when a user tries operations from the browser. It describes UI behaviour only; it does not issue tokens, and it is unrelated to the client-credentials flow at /get/session or to the JWE encryption that protects protocol payloads. The endpoint index describes it as the Swagger security configuration. + + ### When to use + + Use it only in a Swagger UI session against the status service; integrations never need it. The endpoint index lists it as endpoint 23. It is not part of any transaction workflow, not a source of credentials, and not referenced by the sandbox exit checklists. + + ### Preconditions + + - A GET request to the status service host; the OpenAPI documents in this corpus were captured from https://hcxsbx.abdm.gov.in//api-docs, and the status service declares the server prefix /statushcxservice. + - No JWE envelope, no x-hcx-* protocol headers and no correlation id; the docs do not state that a Bearer token is required for these discovery endpoints. + - No request body. + + ### Postconditions + + The service returns HTTP 200 with a small JSON object describing how Swagger UI should handle security inputs. Nothing changes on NHCX, no token is issued and no callback follows. The documentation does not enumerate the fields, so the example below is illustrative. + + ### Common mistakes + + - Pointing at the gateway base https://apisbx.abdm.gov.in/pmjay/sbxhcx and expecting the per-service spec host; the docs advise swapping between the two URL shapes when a path 404s. + - Treating the served document as the integration contract for gateway traffic; the handbook's gateway base and header conventions take precedence where the two disagree. + - Sending a POST or a JSON body to a GET discovery endpoint. + - Wrapping the call in JWE or adding x-hcx-* headers, which only apply to protocol APIs such as /v1/status. + - Mistaking this endpoint for an authentication API; tokens come only from the client-credentials call documented in the authentication chapter. + + ### Best practices + + - Use these endpoints for exploration and client generation in the sandbox, and cache the document rather than fetching it on every run. + - Diff the served document against the corpus (Status service: OpenAPI 3.0.1, version 1.0.0) when behaviour changes unexpectedly. + - Never let production traffic depend on the availability of the documentation endpoints. + - Keep the /v1/status protocol rules in mind when reading the spec: x-hcx-correlation_id must carry the original request's correlation id. + + ### Related scenario + + A provider's engineer wants to try /v1/status from Swagger UI in the sandbox. The UI fetches /swagger-resources/configuration/security to decide how to show the authorisation dialog, and the engineer pastes a Bearer token obtained separately from the client-credentials call. Because the status request body must be a JWE built with the payer's certificate, the engineer ultimately uses the UI only to confirm the schema and runs the real status request from the integration code, which reuses the original preauth correlation id. + + ### Specification + + Chapter [Environments and addresses](/docs/nhcx/v1/reference/environments-and-addresses) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + responses: + "200": + description: The service returns HTTP 200 with a small JSON object describing how Swagger UI should handle security inputs. + content: + application/json: + schema: + type: object + properties: + apiKeyVehicle: + type: string + apiKeyName: + type: string + scopeSeparator: + type: string + example: + apiKeyVehicle: header + apiKeyName: bearer_auth + scopeSeparator: "," + /v1/on_status: + post: + operationId: other_v1_on_status + x-abdm-atom: nhcx.endpoint.on-status + x-abdm-use-case: Other + tags: + - Other + summary: Status callback + description: |- + The answer to a status request, delivered to the sender that asked. The `x-hcx-status` in the protected header says where the message you asked about got to. The payload is an empty string. + + ### Business purpose + + It separates "did my message arrive" from "what did the payer decide". A sender learns whether a quiet case is still held by the exchange, has reached the recipient, or is dead, without resubmitting it and creating a duplicate. + + ### When to use + + Hosted by every participant that sends `/v1/status`. It arrives in answer to a status request you sent. + + ### Preconditions + + - You sent `/v1/status` with `x-hcx-correlation_id` set to the `api_call_id` of the message you were asking about, and you kept that mapping. + - Your callback address is registered and answers 202 within 30 seconds. + + ### Postconditions + + Read `x-hcx-status` from the protected header. `request.dispatched` means the message reached the recipient, and `request.queued` that the exchange still holds it. `request.stopped` means redelivery was exhausted and the correlation ID retired, so the original request is dead and a retry needs a fresh correlation ID. `x-hcx-error_details`, with `code`, `message` and `trace`, is present where the original failed. Answer 202 with the receipt. + + ### Common mistakes + + - Expecting a bundle. The payload is an empty string and everything travels in the header. + - Matching the answer on the original request's correlation ID. It carries the correlation of your status request. + - Retrying a `request.stopped` message on its old correlation ID. + - Offering a refresh or chase control in the user interface with no status exchange behind it. + + ### Best practices + + - Keep every `api_call_id` you send. Without it you cannot ask the question at all. + - Act on `request.stopped` at once, and treat `request.dispatched` as a reason to wait for the payer. + - Ask from a support screen when a case has gone quiet for longer than the payer's expected turnaround, not on a timer. + + ### Related scenario + + A pre-authorisation has had no answer for longer than the payer's usual turnaround. The support screen sends `/v1/status` with that request's `api_call_id` as the correlation ID. The answer arrives here with an empty payload and `x-hcx-status` `request.stopped`, so the desk knows the request is dead rather than slow, and resubmits it with a fresh correlation ID. + + ### Specification + + Chapter [NHCX adapter (Optional)](/docs/nhcx/v1/getting-started/nhcx-adapter) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: + - name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: + - $ref: "#/components/parameters/XHcxApiCallId" + - name: x-hcx-correlation_id + in: header + required: true + description: The thread. See the rule below. Mandatory on the envelope. + schema: + type: string + example: + - $ref: "#/components/parameters/XHcxTimestamp" + - name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: response.complete + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: + responses: + "200": + description: Read `x-hcx-status` from the protected header. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 19/03/2026 11:46:35:120 + api_call_id: "{{$guid}}" + correlation_id: "{{correlationId}}" + error: + code: "" + message: "" + /v1/error: + post: + operationId: other_v1_error + x-abdm-use-case: Other + tags: + - Other + summary: Error report (callback) + description: |- + Where the exchange tells a sender that a request could not be delivered after five attempts. Received by every participant under its registered address. There is no outbound form. + + ### Business purpose + + When the exchange cannot deliver a request, it tries five times, retires the correlation ID and tells the original sender here. A system without this endpoint never learns that its request died, and a dead request looks exactly like a case still under review. Every participant must host it. + + ### When to use + + Hosted, never called. Implement it before anything else that is asynchronous. Providers and payers both host it. + + ### Preconditions + + - Your callback address is registered: a domain name over HTTPS with TLS 1.2 or newer, hosted in India, reachable from the exchange's outbound addresses and answering within 30 seconds. + - The handler accepts a body it does not recognise. What arrives is a plain JSON report of the request the exchange gave up on, with the rejection details, not a sealed `JWEPayload`. Its field names are not published, so the body in this request is an illustration rather than a schema. + + ### Postconditions + + Answer 202 with the receipt, like every other delivery, filling in whatever identifiers the report carries and leaving the rest empty. The original request is dead: its correlation ID has been retired, so a retry needs a fresh one. + + ### Common mistakes + + - Not hosting it, so failed deliveries are never seen. + - Parsing the report against a fixed schema and answering `4xx` when it does not match. + - Retrying the failed request on the retired correlation ID. + + ### Best practices + + - Store the report whole before doing anything with it. + - Mark the case it names as undelivered, so the desk does not wait for a decision that will not come. + - Check it first when a case goes quiet, before asking the exchange with `/v1/status`. + + ### Related scenario + + A hospital posts a pre-authorisation and gets its receipt, but the payer's endpoint is down. The exchange tries five times, retires the correlation ID and posts a report to the hospital's `/v1/error`. The handler stores the report whole, answers 202 with the receipt, and marks the pre-authorisation undelivered. The desk resubmits it with a fresh correlation ID once the payer is reachable. + + ### Specification + + Chapter [Building and sending a JWE](/docs/nhcx/v1/getting-started/building-and-sending-a-jwe) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: nhcx-gateway@hcx + - name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + - $ref: "#/components/parameters/XHcxApiCallId" + - name: x-hcx-correlation_id + in: header + required: true + description: The thread. See the rule below. Mandatory on the envelope. + schema: + type: string + example: + - $ref: "#/components/parameters/XHcxTimestamp" + - name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: response.error + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + type: + type: string + x-hcx-sender_code: + type: string + x-hcx-recipient_code: + type: string + x-hcx-api_call_id: + type: string + x-hcx-correlation_id: + type: string + x-hcx-workflow_id: + type: string + x-hcx-timestamp: + type: string + x-hcx-status: + type: string + x-hcx-error_details: + type: object + properties: + code: + type: string + message: + type: string + trace: + type: string + x-hcx-entity-type: + type: string + example: + type: ProtocolResponse + x-hcx-sender_code: nhcx-gateway@hcx + x-hcx-recipient_code: 1000004446@hcx + x-hcx-api_call_id: + x-hcx-correlation_id: + x-hcx-workflow_id: "12" + x-hcx-timestamp: + x-hcx-status: response.error + x-hcx-error_details: + code: ERR_DELIVERY_FAILED + message: Recipient endpoint unreachable after five attempts + trace: "" + x-hcx-entity-type: preauth + responses: + "200": + description: Answer 202 with the receipt, like every other delivery, filling in whatever identifiers the report carries and leaving the rest empty. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 04/09/2026 11:46:41:305 + api_call_id: + correlation_id: + result: + sender_code: 1000003538@hcx + recipient_code: 1000004446@hcx + entity_type: preauth + protocol_status: request.queued + error: + code: "" + message: "" +webhooks: + v1_task_submit: + post: + operationId: other_webhook_v1_task_submit + x-abdm-atom: nhcx.callback.task-submit + x-abdm-triggered-by: other_v1_task_submit + x-abdm-use-case: Webhooks + tags: + - Other + summary: Receive task submit (reprocess or cancel) + description: |- + Hosted by the payer. The exchange posts this message to the `endpoint_url` you registered, at `/v1/task/submit`, with the headers and the sealed payload the sender posted. Answer HTTP 202 with the receipt first and process afterwards; [Receiving a callback](/docs/nhcx/v1/getting-started/receiving-a-callback) has the rules. + + Provider sends a FHIR Task asking the payer to reprocess a rejected or short-paid claim or to cancel a preauth; Task.code and reasonCode set the intent. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - $ref: "#/components/parameters/XHcxSenderCode" + - $ref: "#/components/parameters/XHcxRecipientCode" + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxWorkflowId" + - $ref: "#/components/parameters/XHcxTimestamp" + - $ref: "#/components/parameters/XHcxStatus" + - $ref: "#/components/parameters/XHcxBenAbhaId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOiIxMDAwMDA0NDQ2QGhjeCJ9.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: Received. The receipt names the message it answers; the answer itself follows as a call of your own. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 04/09/2026 11:46:41:305 + api_call_id: + correlation_id: + result: + sender_code: 1000003538@hcx + recipient_code: 1000004446@hcx + entity_type: preauth + protocol_status: request.queued + error: + code: "" + message: "" + v1_task_on_submit: + post: + operationId: other_webhook_v1_task_on_submit + x-abdm-atom: nhcx.callback.task-on-submit + x-abdm-triggered-by: other_v1_task_on_submit + x-abdm-use-case: Webhooks + tags: + - Other + summary: Receive task callback (reprocess or cancel outcome) + description: |- + Hosted by the provider. The exchange posts this message to the `endpoint_url` you registered, at `/v1/task/on_submit`, with the headers and the sealed payload the sender posted. Answer HTTP 202 with the receipt first and process afterwards; [Receiving a callback](/docs/nhcx/v1/getting-started/receiving-a-callback) has the rules. + + Payer returns a Task bundle with Task.status completed whose Task.output references a ClaimResponse carrying the reprocess or cancellation outcome. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + - name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - name: x-hcx-workflow_id + in: header + required: false + description: Which step, or which case. See the two readings below. Optional on the envelope. + schema: + type: string + example: "252" + - $ref: "#/components/parameters/XHcxTimestamp" + - name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: response.complete + - $ref: "#/components/parameters/XHcxBenAbhaId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOiIxNTE4QGhjeCJ9.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: Received. The receipt names the message it answers; the answer itself follows as a call of your own. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 04/09/2026 11:46:41:305 + api_call_id: + correlation_id: + result: + sender_code: 1000003538@hcx + recipient_code: 1000004446@hcx + entity_type: preauth + protocol_status: request.queued + error: + code: "" + message: "" + v1_on_status: + post: + operationId: other_webhook_v1_on_status + x-abdm-atom: nhcx.callback.on-status + x-abdm-triggered-by: other_v1_on_status + x-abdm-use-case: Webhooks + tags: + - Other + summary: Receive status callback + description: |- + Hosted by the provider. The exchange posts this message to the `endpoint_url` you registered, at `/v1/on_status`, with the headers and the sealed payload the sender posted. Answer HTTP 202 with the receipt first and process afterwards; [Receiving a callback](/docs/nhcx/v1/getting-started/receiving-a-callback) has the rules. + + The answer to a status request, delivered to the sender that asked. The `x-hcx-status` in the protected header says where the message you asked about got to. The payload is an empty string. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: + - name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: + - $ref: "#/components/parameters/XHcxApiCallId" + - name: x-hcx-correlation_id + in: header + required: true + description: The thread. See the rule below. Mandatory on the envelope. + schema: + type: string + example: + - $ref: "#/components/parameters/XHcxTimestamp" + - name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: response.complete + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: + responses: + "202": + description: Received. The receipt names the message it answers; the answer itself follows as a call of your own. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 04/09/2026 11:46:41:305 + api_call_id: + correlation_id: + result: + sender_code: 1000003538@hcx + recipient_code: 1000004446@hcx + entity_type: preauth + protocol_status: request.queued + error: + code: "" + message: "" + v1_error: + post: + operationId: other_webhook_v1_error + x-abdm-atom: nhcx.callback.error + x-abdm-triggered-by: other_v1_error + x-abdm-use-case: Webhooks + tags: + - Other + summary: Receive error report (callback) + description: |- + Hosted by every participant. The exchange posts this message to the `endpoint_url` you registered, at `/v1/error`, with the headers and the sealed payload the sender posted. Answer HTTP 202 with the receipt first and process afterwards; [Receiving a callback](/docs/nhcx/v1/getting-started/receiving-a-callback) has the rules. + + Where the exchange tells a sender that a request could not be delivered after five attempts. Received by every participant under its registered address. There is no outbound form. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: nhcx-gateway@hcx + - name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + - $ref: "#/components/parameters/XHcxApiCallId" + - name: x-hcx-correlation_id + in: header + required: true + description: The thread. See the rule below. Mandatory on the envelope. + schema: + type: string + example: + - $ref: "#/components/parameters/XHcxTimestamp" + - name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: response.error + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + type: + type: string + x-hcx-sender_code: + type: string + x-hcx-recipient_code: + type: string + x-hcx-api_call_id: + type: string + x-hcx-correlation_id: + type: string + x-hcx-workflow_id: + type: string + x-hcx-timestamp: + type: string + x-hcx-status: + type: string + x-hcx-error_details: + type: object + properties: + code: + type: string + message: + type: string + trace: + type: string + x-hcx-entity-type: + type: string + example: + type: ProtocolResponse + x-hcx-sender_code: nhcx-gateway@hcx + x-hcx-recipient_code: 1000004446@hcx + x-hcx-api_call_id: + x-hcx-correlation_id: + x-hcx-workflow_id: "12" + x-hcx-timestamp: + x-hcx-status: response.error + x-hcx-error_details: + code: ERR_DELIVERY_FAILED + message: Recipient endpoint unreachable after five attempts + trace: "" + x-hcx-entity-type: preauth + responses: + "202": + description: Received. The receipt names the message it answers; the answer itself follows as a call of your own. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 04/09/2026 11:46:41:305 + api_call_id: + correlation_id: + result: + sender_code: 1000003538@hcx + recipient_code: 1000004446@hcx + entity_type: preauth + protocol_status: request.queued + error: + code: "" + message: "" +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + description: "On every NHCX call, the token goes in a header called `bearer_auth`, with the word `Bearer` and a space in front. The sources are not unanimous: the authentication page and the FAQ both write the example as `Authorization`, and the notification endpoint uses `Authorization`. The safe course, and what the adapter does, is to send both headers with the same value." + parameters: + BearerAuth: + name: bearer_auth + in: header + required: true + description: It is `bearer_auth`, not `Authorization`, on NHCX's own endpoints. + schema: + type: string + example: Bearer + XHcxSenderCode: + name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + XHcxRecipientCode: + name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + XHcxApiCallId: + name: x-hcx-api_call_id + in: header + required: true + description: Fresh on every message, including responses. Mandatory on the envelope. + schema: + type: string + example: + XHcxRequestId: + name: x-hcx-request_id + in: header + required: false + description: One per originating request. The Open Protocol page marks it Mandatory; the Technical Specifications page marks it Optional. Optional on the envelope. + schema: + type: string + example: + XHcxCorrelationId: + name: x-hcx-correlation_id + in: header + required: true + description: The thread. See the rule below. Mandatory on the envelope. + schema: + type: string + example: + XHcxWorkflowId: + name: x-hcx-workflow_id + in: header + required: false + description: Which step, or which case. See the two readings below. Optional on the envelope. + schema: + type: string + example: "18" + XHcxTimestamp: + name: x-hcx-timestamp + in: header + required: true + description: See the format note below. Mandatory on the envelope. + schema: + type: string + example: + XHcxStatus: + name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: request.initiated + XHcxBenAbhaId: + name: x-hcx-ben-abha-id + in: header + required: true + description: The beneficiary's ABHA number. Mandatory on every exchange, including those with no beneficiary in the payload. Mandatory on the envelope. + schema: + type: string + example: "91711234567890" +x-abdm-errors: + notes: |- + Codes any exchange call can meet are recorded once, in the [Other](/docs/nhcx/v1/api/other) specification: the gateway's NHCX- codes, the standard payer codes, and the reference payer's structure and transport codes. The reference payer's other codes sit with the exchange they reject: coverage eligibility, preauthorisation, claim and insurance plan. [Reading error codes](/docs/nhcx/v1/reference/error-code-guide) explains the code spaces. + + 18 codes from PAYR-1003 to PAYR-1020 mean one thing on the standard payer sheet and another on the reference payer's sheet. Read the code together with its message. + ranges: + - range: NHCX-1xxx + covers: The exchange, on the envelope. The message never reached the payer. + examples: "`NHCX-1001`, `NHCX-1002`" + - range: PAYR-10xx + covers: Transport and bundle structure. An element, id, sequence or type is missing. Not a value problem. + examples: "`PAYR-1001`, `PAYR-1002`" + - range: PAYR-11xx + covers: Coverage eligibility. The policy, the beneficiary or the hospital configuration. + examples: "`PAYR-1101`, `PAYR-1102`" + - range: PAYR-12xx + covers: Preauthorisation. Codes, amounts, dates, sequencing and scheme rules. + examples: "`PAYR-1201`, `PAYR-1202`" + - range: PAYR-13xx + covers: Claim. The same, against the approved preauthorisation. + examples: "`PAYR-1301`, `PAYR-1302`" + - range: PAYR-14xx + covers: Insurance plan, and the scheme's outer rules. Empanelment, policy association, plan configuration. + examples: "`PAYR-1401`, `PAYR-1402`" +x-abdm-errors-gateway: + source: Gateway codes, NHCX-. Sent by the exchange; they arrive synchronously on your own call, or on /v1/error. + codes: + - code: NHCX-401 + message: User Unauthorized + action: "" + - code: NHCX-1001 + message: Receiver system is not reachable. + action: "" + - code: NHCX-1002 + message: Sender not registered in NHCX. Please register in NHCX portal and try again. + action: "" + - code: NHCX-1003 + message: Receiver not registered in NHCX. Please try again with valid receiver details. + action: "" + - code: NHCX-1004 + message: No receiver registered in NHCX for the requested scheme. Please try again with valid receiver details for the scheme. + action: "" + - code: NHCX-1005 + message: Invalid request header. Please try again with valid headers. + action: "" + - code: NHCX-1006 + message: Duplicate request. Request with same correlation id already exist in the system. + action: "" + - code: NHCX-1007 + message: Something went wrong while processing the request. Please check the request structure and values and try again. + action: "" + - code: NHCX-1008 + message: Something went wrong while processing the request. Please try again after sometime. + action: "" + - code: NHCX-1009 + message: Something went wrong while processing the request. Please check log for more details. + action: "" + - code: NHCX-1010 + message: No Data with given Correlation id for call back request, please check status for more details + action: "" + - code: NHCX-1011 + message: Invalid Status, please check x-hcx-status value from the protected header + action: "" + - code: NHCX-1012 + message: No records found with the requested api caller id. Please try again with a valid api caller id. + action: "" + - code: NHCX-1013 + message: Invalid or blank request found. + action: "" + - code: NHCX-1014 + message: Unable to send protocol response to sender. + action: "" + - code: NHCX-1015 + message: Invalid response received from receiver. + action: "" + - code: NHCX-1016 + message: Invalid Api Action, please check the request action for this correlationId before trying again + action: "" + - code: NHCX-1017 + message: Invalid response received from receiver + action: "" + - code: NHCX-1018 + message: Invalid ABHA number received. ABHA number should be sent in the format XX-XXXX-XXXX-XXXX + action: "" +x-abdm-errors-standard-payer: + source: Standard payer codes, PAYR-1001 to PAYR-1020. Sent by A payer implementing the published standard; they arrive inside the sealed response. + codes: + - code: PAYR-1001 + message: Error while decrypting request. Please reprocess the request encrypting with valid certificate of the payer. + action: "" + - code: PAYR-1002 + message: Error while encrypting request. Please update encryption certificate in NHCX. + action: "" + - code: PAYR-1003 + message: Error while connecting to NHCX. System will try to resend the message to NHCX after some time. + action: "" + - code: PAYR-1004 + message: Provider is not registered with the payer for requested policy. + action: "" + - code: PAYR-1005 + message: Beneficiary is not a covered member for requested policy. Please enroll beneficiary for the policy and try again. + action: "" + - code: PAYR-1006 + message: Policy does not exist. Please try with a valid policy. + action: "" + - code: PAYR-1007 + message: Requested policy is expired. Please try with a valid policy. + action: "" + - code: PAYR-1008 + message: Eligible coverage amount of the beneficiary for the requested policy is insufficient to process the request. + action: "" + - code: PAYR-1009 + message: Requested items are not valid or not covered. Please try again with valid or covered items. + action: "" + - code: PAYR-1010 + message: Preauthorization is required to process the request but was not obtained. + action: "" + - code: PAYR-1011 + message: Enhancement request can not be processed as the prior approved package/procedure does not support enhancement. + action: "" + - code: PAYR-1012 + message: Claim amount requested is more than the preauthorization approved amount. + action: "" + - code: PAYR-1013 + message: No prior approval for the requested procedures/packages obtained. + action: "" + - code: PAYR-1014 + message: Date of birth of the beneficiary can not be after date of service. + action: "" + - code: PAYR-1015 + message: Date of service cannot be after date of death. + action: "" + - code: PAYR-1016 + message: Duplicate claim submitted based on service codes and dates. + action: "" + - code: PAYR-1017 + message: Amount calculations are not correct. Please verify calculated amount. + action: "" + - code: PAYR-1018 + message: Time limit for submission expired. + action: "" + - code: PAYR-1019 + message: Requested additional information was not received or was not received within time limit + action: "" + - code: PAYR-1020 + message: Unable to process payment as no valid bank details found for the provider. + action: "" +x-abdm-errors-reference-payer: + source: Reference payer codes, PAYR-1001 to PAYR-1520. Sent by the PMJAY reference implementation; they arrive inside the sealed response. + codes: + - code: PAYR-1001 + message: Error occurred while decrypting payload for receiver code with correlation id . + action: "" + - code: PAYR-1002 + message: Error occurred while encrypting payload for receiver code with correlation id . + action: "" + - code: PAYR-1003 + message: Invalid workflow requested. Hence request will not be processed further. + action: "" + - code: PAYR-1004 + message: Received FHIR bundle is malformed. Please correct the bundle and try again. + action: "" + - code: PAYR-1005 + message: Maximum time limit exceeded in receiving the request. Please try again. + action: "" + - code: PAYR-1006 + message: Invalid name in request. Hence request will not be processed further. + action: "" + - code: PAYR-1007 + message: Invalid gender in request. Hence request will not be processed further. + action: "" + - code: PAYR-1008 + message: Invalid FHIR bundle received. Hence request will not be processed further. + action: "" + - code: PAYR-1009 + message: No identifier found for patient component. Hence request will not be processed further. https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html + action: "" + - code: PAYR-1010 + message: No type found for patient component identifier. Hence request will not be processed further. https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html + action: "" + - code: PAYR-1011 + message: No identifier found for claim component. Hence request will not be processed further. + action: "" + - code: PAYR-1012 + message: No type found for claim component identifier. Hence request will not be processed further. + action: "" + - code: PAYR-1013 + message: No identifier found for organization component for provider. Hence request will not be processed further. + action: "" + - code: PAYR-1014 + message: No type found for organization component identifier for provider. Hence request will not be processed further. + action: "" + - code: PAYR-1015 + message: No identifier found for organization component for payer. Hence request will not be processed further. + action: "" + - code: PAYR-1016 + message: No type found for organization component identifier for payer. Hence request will not be processed further. + action: "" + - code: PAYR-1017 + message: No task code received. Hence request will not be processed further. + action: "" + - code: PAYR-1018 + message: No task reason code received. Hence request will not be processed further. + action: "" + - code: PAYR-1019 + message: Invalid sequence received in supporting info element. Hence request will not be processed further. + action: "" + - code: PAYR-1020 + message: Invalid category received in supporting info element for sequence %s. Hence request will not be processed further. + action: "" + - code: PAYR-1021 + message: Invalid code received in supporting info element for sequence %s. Hence request will not be processed further. + action: "" + - code: PAYR-1023 + message: Invalid procedure category received for procedure component. Hence request will not be processed further. + action: "" + - code: PAYR-1024 + message: Invalid procedure status received for procedure component. Hence request will not be processed further. + action: "" + - code: PAYR-1025 + message: Invalid procedure sequence received for procedure component. Hence request will not be processed further. + action: "" + - code: PAYR-1026 + message: No procedure component found for reference in claim component. Hence request will not be processed further. + action: "" + - code: PAYR-1027 + message: Invalid item id found for item in claim component. Hence request will not be processed further. + action: "" + - code: PAYR-1028 + message: Invalid item sequence received for item in claim component. Hence request will not be processed further. + action: "" + - code: PAYR-1029 + message: Invalid bundle id received for FHIR bundle. Hence request will not be processed further. + action: "" + - code: PAYR-1030 + message: Invalid questionnaire id received in FHIR bundle for questionnaire component. Hence request will not be processed further. + action: "" + - code: PAYR-1031 + message: Invalid url received for bundle entry in FHIR bundle. Hence request will not be processed further. Please reach out to technical team. + action: "" + - code: PAYR-1032 + message: Invalid purpose received for coverage eligibility request. Hence request will not be processed further. Please try again with valid purpose details. + action: "" + - code: PAYR-1033 + message: No items received for coverage eligibility purpose. Since items are mandatory for the requested purpose, hence request will not be processed further. Please try again with valid item details. + action: "" + - code: PAYR-1034 + message: Invalid procedure code received. Please try again with valid procedure details. + action: "" + - code: PAYR-1035 + message: Invalid policy code received. Please try again with valid policy details. + action: "" + - code: PAYR-1036 + message: Invalid attachment received in supporting info with sequence number %s. Please try again with valid attachment details as attachment value is expected. If issue is not resolved, please reach out to technical team. + action: "" + - code: PAYR-1037 + message: No identifier found for communication component. Hence request will not be processed further. + action: "" + - code: PAYR-1038 + message: No type found for communication component identifier. Hence request will not be processed further. + action: "" + - code: PAYR-1039 + message: No payload found for communication component. Hence request will not be processed further. + action: "" + - code: PAYR-1040 + message: No component found for given reference. Hence request will not be processed further. + action: "" + - code: PAYR-1041 + message: No identifier found for procedure component. Hence request will not be processed further. + action: "" + - code: PAYR-1042 + message: No type found for procedure component identifier. Hence request will not be processed further. + action: "" + - code: PAYR-1043 + message: Date received in the request does not adhere to the NRCES date datatype format. Hence request will not be processed further. Please refere to the date format in NRCES portal. + action: "" + - code: PAYR-1044 + message: Date and time received in the request does not adhere to the NRCES date datatype format. Hence request will not be processed further. Please refere to the date time format in NRCES portal. + action: "" + - code: PAYR-1045 + message: Invalid quantity received for item. Hence request will not be processed further. + action: "" + - code: PAYR-1046 + message: No value or timing details received for supporting info for sequence %s. Hence request will not be processed further. Please reach out to technical team. + action: "" + - code: PAYR-1047 + message: Invalid reference received in supporting info with sequence number %s. Please try again with valid resource as reference value. + action: "" + - code: PAYR-1048 + message: No reference resource received for supporting info with sequence number %s. Please try again with valid resource for reference value. + action: "" + - code: PAYR-1049 + message: Invalid FHIR bundle received. Hence request will not be processed further. please reach out to technical team. + action: "" + - code: PAYR-1050 + message: No type found for practitioner component identifier. Hence request will not be processed further. + action: "" + - code: PAYR-1051 + message: No section found for composition component. Hence request will not be processed further. + action: "" + - code: PAYR-1052 + message: No references found in composition section. Hence request will not be processed further. + action: "" + - code: PAYR-1053 + message: Invalid reference found in child sections of composition section. Hence request will not be processed further. + action: "" + - code: PAYR-1054 + message: No section content found for composition component. Hence request will not be processed further. + action: "" + - code: PAYR-1055 + message: Invalid subject type found for composition component. This should be of type Patient. Hence request will not be processed further. Please try again with valid subject type for the composition. + action: "" + - code: PAYR-1056 + message: Invalid contact organization found for subject in composition component. This should be of type Organization. Hence request will not be processed further. Please try again with valid data. + action: "" + - code: PAYR-1057 + message: Invalid general practioner type found for subject in composition component. This should be of type Organization/Practitioner/PractitionerRole. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html + action: "" + - code: PAYR-1058 + message: Invalid managing organization type found for subject in composition component. This should be of type Organization. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html + action: "" + - code: PAYR-1059 + message: Invalid encounter type found for composition/observation component. This should be of type Encounter. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-DiagnosticReportRecord.html + action: "" + - code: PAYR-1060 + message: No subject found for encounter in composition component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + action: "" + - code: PAYR-1061 + message: Invalid subject type found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + action: "" + - code: PAYR-1062 + message: No episode of care found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + action: "" + - code: PAYR-1063 + message: Invalid episode of care type found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + action: "" + - code: PAYR-1064 + message: No based on found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + action: "" + - code: PAYR-1065 + message: Invalid based on type found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + action: "" + - code: PAYR-1066 + message: No appointment found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + action: "" + - code: PAYR-1067 + message: Invalid appointment type found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + action: "" + - code: PAYR-1068 + message: No reason reference found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + action: "" + - code: PAYR-1069 + message: Invalid reason reference type found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + action: "" + - code: PAYR-1070 + message: No author found for composition component. Hence request will not be processed further. + action: "" + - code: PAYR-1071 + message: Invalid author type found for composition component. This should be of type Practitioner / PractitionerRole / Organization / Patient / Device / RelatedPerson. Hence request will not be processed further. Please try again with valid author type for the composition. + action: "" + - code: PAYR-1072 + message: No procedure reference received for procedure element in claim resource. Hence request will not be processed further. + action: "" + - code: PAYR-1073 + message: No based on found for observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Observation.html + action: "" + - code: PAYR-1074 + message: Invalid based on type found for observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Observation.html + action: "" + - code: PAYR-1075 + message: No part of found for observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Observation.html + action: "" + - code: PAYR-1076 + message: Invalid part of type found for observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Observation.html + action: "" + - code: PAYR-1077 + message: No subject found for observation component. Hence request will not be processed further. + action: "" + - code: PAYR-1078 + message: Invalid subject type found for observation component. This should be of type Patient. Hence request will not be processed further. Please try again with valid subject type for the observation. + action: "" + - code: PAYR-1079 + message: No care team details received. Hence request will not be processed further. Please add the care team details and try again. + action: "" + - code: PAYR-1080 + message: Invalid HPR details received for practioner resource with url %s. Hence request will not be processed further. Please try again with valid HPR id. + action: "" + - code: PAYR-1081 + message: Invalid service date received for item with sequence %s in claim resource. Hence request will not be processed further. Please try again with valid item service date. + action: "" + - code: PAYR-1082 + message: Invalid title received for composition for supporting info with sequence %s in claim resource. Hence request will not be processed further. Please try again with valid composition title. + action: "" + - code: PAYR-1083 + message: No HPR details found for the practitioner for resource %s. Hence request will not be processed further. Please send the details in the identifier for Practitioner resource with category code as HPIN. + action: "" + - code: PAYR-1084 + message: No questionnaire response resource found for url %s. Hence request will not be processed further. Please add the resources for all the references given in the FHIR bundle and try again. + action: "" + - code: PAYR-1085 + message: Invalid questionnaire response resource type found in the FHIR bundle for url %s. Hence request will not be processed further. + action: "" + - code: PAYR-1086 + message: No procedure resource found for url %s. Hence request will not be processed further. Please add the resources for all the references given in the FHIR bundle and try again. + action: "" + - code: PAYR-1087 + message: Invalid procedure resource type found in the FHIR bundle for url %s. Hence request will not be processed further. Procedure resource type is expected. + action: "" + - code: PAYR-1088 + message: Invalid composition details. + action: "" + - code: PAYR-1089 + message: No billing items found. Hence request will not be processed further. Please try again with valid billing items. + action: "" + - code: PAYR-1090 + message: No identifier found for coverage component. Hence request will not be processed further. + action: "" + - code: PAYR-1091 + message: No type found for coverage component identifier. Hence request will not be processed further. + action: "" + - code: PAYR-1092 + message: Something went wrong while processing request, kindly intiate new request + action: "" + - code: PAYR-1093 + message: No subject found for encounter in composition component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + action: "" + - code: PAYR-1094 + message: Invalid subject type found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html + action: "" + - code: PAYR-1095 + message: Invalid discharge information received for claim request. Hence request will not be processed further. Please send the discharge information in supporting info in claim resource, with category as DIS (refer - https://www.nrces.in/ndhm/fhir/r4/ValueSet-ndhm-supportinginfo-category.html), and codes in LAMA/DAMA/DTH/DTM (refer - https://www.nrces.in/ndhm/fhir/r4/ValueSet-ndhm-supportinginfo-code.html). + action: "" + - code: PAYR-1096 + message: Invalid death date received for claim request. Hence request will not be processed further. Please send the death date information in supporting info in claim resource, with category as ONS (refer - https://www.nrces.in/ndhm/fhir/r4/ValueSet-ndhm-supportinginfo-category.html), and code as DTM (refer - https://www.nrces.in/ndhm/fhir/r4/ValueSet-ndhm-supportinginfo-code.html). + action: "" + - code: PAYR-1097 + message: No payload found in the request. Please ensure that the request that is being sent, contains encrypted payload within the mandatory payload properties. + action: "" + - code: PAYR-1098 + message: Value type received as %s for category - OTH and code - EDT for item with sequence %s in supporting info in claim resource. In supporting info list, item with category - OTH and code - EDT combination is used to get the registration date. So the registration date should be sent as timing (date or period) or as a string value, adhering to the NRCES standards, with the category - OTH and code - EDT. + action: "" + - code: PAYR-1099 + message: Value type received as %s for category - ONS and code - DSDE for item with sequence %s in supporting info in claim resource. In supporting info list, item with category - ONS and code - DSDE combination is used to get the discharge date. So the discharge date should be sent as timing (date or period) or as a string value, adhering to the NRCES standards, with the category - ONS and code - DSDE. + action: "" +x-abdm-errors-observed: + source: Observed live codes, ERR-PYR-. Sent by the PMJAY reference implementation, on none of its published sheets; they arrive inside the sealed response. + codes: + - code: ERR-PYR-CLM-007 + message: No prior preauthorization or claim record found for case number + action: On none of the seven sheets. The SHA HP sandbox sent it for a claim raised under a number of its own rather than the preauthorisation's. diff --git a/catalogue/openapi/nhcx/v1/nhcx-payment-notice.yaml b/catalogue/openapi/nhcx/v1/nhcx-payment-notice.yaml new file mode 100644 index 000000000..f93b2ff26 --- /dev/null +++ b/catalogue/openapi/nhcx/v1/nhcx-payment-notice.yaml @@ -0,0 +1,850 @@ +# NHCX payment notice, from the NHCX package's Bruno folder apis/06-payment-notice. +# +# Written by the package's system/build-ekadocs.mjs (make ekadocs); change the .bru +# requests there and port again rather than editing this file. +# +# Rules this file follows: catalogue/openapi/CONVENTIONS.md +openapi: 3.1.1 +info: + x-portal: + module: payment-notice + label: Payment notice + position: 6 + title: NHCX payment notice + summary: Every other flow exchanges decisions; the payment notice is the only one that tells the hospital whether the money actually moved. + description: |- + The Payment notice calls on the National Health Claims Exchange (NHCX): 4 operations, and 2 callbacks you host. + + Every other flow exchanges decisions; the payment notice is the only one that tells the hospital whether the money actually moved. + + Guides that use these calls: [Payment notice and acknowledgement](/docs/nhcx/v1/reference/fhir/payment-notice-and-acknowledgement). + version: nhcx-v1 + license: + name: MIT + identifier: MIT + contact: + name: NHCX sandbox + url: https://hcxsbx.abdm.gov.in + x-abdm-gateway: nhcx + x-abdm-module: payment-notice + x-abdm-phase: 1 + x-abdm-roles: + - provider + - payer +x-abdm-sources: + - file: nhcx-package/apis/06-payment-notice + role: upstream + hash: sha256:ecbc5eba98524e6d102f3375c652f11a4aab2a32272cbef94c0993e8efe0d0f6 + note: The package's Bruno collection, one request per operation. + - file: nhcx-package/baseurl.yaml + role: upstream + hash: sha256:88515b7b29c6b349a131e016c80774436ea16a29738db743b4cc3a24cbd42453 + note: The sandbox and production hosts. +servers: + - url: https://apisbx.abdm.gov.in/hcx + description: Sandbox, NHCX exchange. + - url: https://apisprod.nha.gov.in/hcx + description: Production. +tags: + - name: Payment notice + description: Every other flow exchanges decisions; the payment notice is the only one that tells the hospital whether the money actually moved. + - name: Adapter + description: Exposed for the NHCX adapter deployment rather than for direct integration. +security: + - bearerAuth: [] +paths: + /v1/paymentnotice/request: + post: + operationId: payment_notice_v1_paymentnotice_request + x-abdm-atom: nhcx.endpoint.paymentnotice-request + x-abdm-use-case: Payment notice + tags: + - Payment notice + summary: Payment notice request + description: |- + Payer pushes a Task bundle with PaymentNotice and PaymentReconciliation (amount, TDS, UTR) to the provider via NHCX after approving a claim. + + ### Business purpose + + Every other flow exchanges decisions; the payment notice is the only one that tells the hospital whether the money actually moved. It formally notifies the provider that a payment has been initiated, processed or settled against an approved claim, carrying the net amount, TDS deduction, payment date and the UTR. Hospitals need it to reconcile bank receipts to claims and close the episode; payers need it as the structured, auditable record of settlement. + + ### When to use + + Payer-initiated, after the final claim is approved (workflow 26). The same bundle shape is sent up to three times as the money progresses: 30 PAYMENT_INITIATED, 31 PAYMENT_PROCESSED and 33 PAYMENT_SETTLED, when the UTR becomes available in PaymentReconciliation.paymentIdentifier.value. The NHA status sheet frames these as x-hcx-status request.initiated because the payer is authoring a new request to the provider; the workbook sample shows x-hcx-workflow_id 11 as a placeholder. The bundle is a Task with code deliver and status requested, plus PaymentNotice (paymentStatus paid), PaymentReconciliation and both Organisations. + + ### Preconditions + + - The claim has received a response.complete approval and a payment has been initiated in the payer's banking system. + - The payer holds a valid Bearer token and has fetched the provider's certificate; the bundle is JWE-encrypted for the provider. + - Protected header carries request.initiated, a fresh correlation UUID for this notice cycle (the workbook says same as the API caller ID), the payer as sender and the provider as recipient, and an IST timestamp. + - PaymentNotice.amount and PaymentReconciliation.paymentAmount carry the net amount; detail lines itemise TDS and Payment; the claim number is carried as identifier type CLN. + - Valid provider bank details exist on the payer side (PAYR-1020 otherwise). + + ### Postconditions + + NHCX returns HTTP 202 Accepted with a StatusSuccessResponse acknowledgement (entity_type payment) and forwards the bundle asynchronously to the provider's registered callback endpoint, which must acknowledge with 202 within 30 seconds. The provider then sends its own acknowledgement Task (status completed, output paymentack, workflow 17) on /v1/paymentnotice/on_request; only after that acknowledgement is the payment lifecycle considered closed. Protocol failures at the provider come back as a ProtocolResponse with x-hcx-error_details. Statuses 400, 404 and 500 carry the same schema. + + ### Common mistakes + + - Provider side: expecting a Claim or ClaimResponse; the payment notice is a Task bundle and the money fields live in PaymentReconciliation. + - Provider side: reading the UTR before workflow 33, or parsing the scroll-style UTR (for example UTR000000000001) as a bank RRN. + - Provider side: relying on Task.description text for logic; the published sample contains a typo (Recived the payment). + - Provider side: returning 200 or a malformed body on receipt, which triggers five retries and deletion. + - Payer side: sending the notice before the claim is closed by response.complete, or without valid provider bank details (PAYR-1020). + - Both sides: the FAQ's sandbox base URL for payment notice is printed without a slash between host and path; cross-check against the endpoint index. + + ### Best practices + + - Payer: send 30, 31 and 33 as the transfer progresses and populate paymentIdentifier with the UTR at 33; keep TDS and Payment detail lines consistent with the gross claim amount. + - Provider: persist the UTR, TDS and net amount against the claim for audit and dispute resolution, and mark the claim SETTLED only on 33. + - Provider: acknowledge with 202 within 30 seconds, be idempotent on correlation ID, then send the paymentack Task. + - Both: note the source conflict on whether the acknowledgement goes to /v1/paymentnotice/on_request or /v1/task/submit; the API contract supports on_request, so confirm with the counterparty during onboarding. + - Both: use IST timestamps and echo the correlation ID through the acknowledgement. + + ### Related scenario + + Three days after approving claim CL0000000001 for 2430 INR, the state health agency initiates a bank transfer of 2187 INR after 243 INR TDS. Its bridge builds a Task bundle with code deliver, a PaymentNotice with amount 2187 and status paid, and a PaymentReconciliation with the TDS and Payment detail lines, and posts it to /v1/paymentnotice/request under workflow 30. NHCX returns 202 and delivers it to the hospital, which acknowledges within 30 seconds. When the transfer settles the payer sends a second notice under 33 carrying the UTR; the hospital persists it and responds on /v1/paymentnotice/on_request with a paymentack Task. + + ### Specification + + Chapter [Payment notice and acknowledgement](/docs/nhcx/v1/reference/fhir/payment-notice-and-acknowledgement) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - $ref: "#/components/parameters/XHcxSenderCode" + - $ref: "#/components/parameters/XHcxRecipientCode" + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxWorkflowId" + - $ref: "#/components/parameters/XHcxTimestamp" + - $ref: "#/components/parameters/XHcxStatus" + - $ref: "#/components/parameters/XHcxBenAbhaId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOi4uLn0.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: NHCX returns HTTP 202 Accepted with a StatusSuccessResponse acknowledgement (entity_type payment) and forwards the bundle asynchronously to the provider's registered callback endpoint, which must acknowledge with 202 within 30 seconds. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 27/02/2026 15:36:09:004 + api_call_id: c3d2e1f0-a9b8-4c7d-9e6f-5a4b3c2d1e0f + correlation_id: c3d2e1f0-a9b8-4c7d-9e6f-5a4b3c2d1e0f + result: + sender_code: 1518@hcx + recipient_code: 1000004446@hcx + entity_type: payment + protocol_status: request.queued + error: + code: "" + message: "" + /internal/v1/paymentnotice/request: + post: + operationId: payment_notice_internal_v1_paymentnotice_request + x-abdm-use-case: Adapter + tags: + - Adapter + summary: Payment notice request (internal) (adapter) + description: |- + Internal twin of /v1/paymentnotice/request (operationId paymentNoticeRequestPostInternal) with the same JWEPayload body and response set. Exposed for the NHCX adapter deployment rather than for direct integration. + + ### Business purpose + + The paymentnotice service publishes its request operation twice, at /v1 and at /internal/v1, with identical descriptions, request bodies and response sets. Only the operationId differs, by an Internal suffix. The /internal prefix is the route the NHCX adapter sits on: a participant running the adapter alongside its own system calls the internal path, and the adapter handles the encryption, headers and gateway hop. A participant integrating directly against NHCX calls the public path and does that work itself. No separate business purpose is documented for the internal route beyond that. + + ### When to use + + Use it only when you are running the NHCX adapter and it is configured to serve this path; otherwise call /v1/paymentnotice/request. Everything else is unchanged: the same JWEPayload body, the same x-hcx-* protected header, the same workflow discriminators and the same asynchronous callback. The specs do not document what makes the internal variant different beyond the operationId, so treat it as a mirror of the public path and confirm with NHCX onboarding before pointing production at it. + + ### Preconditions + + Identical to /v1/paymentnotice/request. Nothing additional is documented for the internal route, beyond an adapter deployment that actually serves the /internal prefix. + + ### Postconditions + + NHCX returns HTTP 202 Accepted with a StatusSuccessResponse acknowledgement (entity_type payment) and forwards the bundle asynchronously to the provider's registered callback endpoint, which must acknowledge with 202 within 30 seconds. The provider then sends its own acknowledgement Task (status completed, output paymentack, workflow 17) on /v1/paymentnotice/on_request; only after that acknowledgement is the payment lifecycle considered closed. Protocol failures at the provider come back as a ProtocolResponse with x-hcx-error_details. Statuses 400, 404 and 500 carry the same schema. + + ### Common mistakes + + - Assuming a different body or different semantics for the internal route; the spec gives it the same JWEPayload body and the same responses. + - Calling it without an adapter deployment behind it and then chasing a 404. + - Every pitfall of the public path applies unchanged. + + ### Best practices + + - Default to /v1/paymentnotice/request and keep the internal path as a configuration option only. + - Share one client implementation across both paths, so header hygiene, encryption and correlation handling cannot diverge between them. + - Record which variant carried each correlation ID, for support conversations. + + ### Related scenario + + A vendor reading the paymentnotice OpenAPI document sees paymentNoticeRequestPostInternal sitting beside its public twin and asks which one to build against. The answer is the public path, unless NHCX onboarding has given them an adapter deployment, in which case the adapter takes the bundle unencrypted on the internal path and does the JWE and the gateway hop for them. The end-to-end flow is identical either way. + + ### Specification + + Chapter [Payment notice and acknowledgement](/docs/nhcx/v1/reference/fhir/payment-notice-and-acknowledgement) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - $ref: "#/components/parameters/XHcxSenderCode" + - $ref: "#/components/parameters/XHcxRecipientCode" + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxWorkflowId" + - $ref: "#/components/parameters/XHcxTimestamp" + - $ref: "#/components/parameters/XHcxStatus" + - $ref: "#/components/parameters/XHcxBenAbhaId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOi4uLn0.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: NHCX returns HTTP 202 Accepted with a StatusSuccessResponse acknowledgement (entity_type payment) and forwards the bundle asynchronously to the provider's registered callback endpoint, which must acknowledge with 202 within 30 seconds. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 27/02/2026 15:36:09:004 + api_call_id: c3d2e1f0-a9b8-4c7d-9e6f-5a4b3c2d1e0f + correlation_id: c3d2e1f0-a9b8-4c7d-9e6f-5a4b3c2d1e0f + result: + sender_code: 1518@hcx + recipient_code: 1000004446@hcx + entity_type: payment + protocol_status: request.queued + error: + code: "" + message: "" + /v1/paymentnotice/on_request: + post: + operationId: payment_notice_v1_paymentnotice_on_request + x-abdm-atom: nhcx.endpoint.paymentnotice-on-request + x-abdm-use-case: Payment notice + tags: + - Payment notice + summary: Payment notice acknowledgement + description: |- + Provider acknowledges a payment notice with a Task bundle (status completed, output paymentack), closing the payment lifecycle via NHCX. + + ### Business purpose + + The acknowledgement confirms to the payer that the provider has received and recorded the payment notice for a specific claim. It closes the payment lifecycle from the provider side and completes the audit trail from claim approval through settlement. Failure to acknowledge does not block the payer, but the acknowledgement is required for complete lifecycle tracking, which matters for reconciliation, dispute resolution and scheme reporting. + + ### When to use + + Called by the provider after processing a /v1/paymentnotice/request message, using the same correlation ID, with x-hcx-workflow_id 17 PAYMENT_RECEIVED and x-hcx-status response.complete (the NHA sheet lists 17 Payment Notice Received as response.complete). The plaintext is a Task with status completed, intent order, code status from the HL7 financialtaskcode system, output[0] paymentack (Payment is acknowledged) and output[1] claimNumber carrying the acknowledged claim number; Task.requester is the provider and Task.owner the payer, the reverse of the notice. The handbook narrative alternatively places this acknowledgement on /v1/task/submit; the OpenAPI contract and the Payment use-case document support this endpoint. + + ### Preconditions + + - A payment notice with this correlation ID has been received and acknowledged with 202 (NHCX-1010 if NHCX has no record of it). + - The provider holds a valid Bearer token and the payer's certificate, and encrypts the acknowledgement Task for the payer. + - x-hcx-correlation_id echoes the notice; x-hcx-api_call_id is new; the provider is sender and the payer is recipient. + - Task.output[0].valueCodeableConcept.coding.code is paymentack and Task.output[1].valueString is the claim number from the notice; Task.status is completed. + - x-hcx-status is response.complete, or response.error with x-hcx-error_details for a protocol-level problem. + + ### Postconditions + + NHCX returns HTTP 202 Accepted with a StatusSuccessResponse acknowledgement (entity_type payment) and forwards the Task to the payer asynchronously; the payer's endpoint must acknowledge with 202 within 30 seconds or NHCX retries up to five times. If the payer cannot process the acknowledgement (invalid provider, decryption failure, missing mandatory protocol attributes) it returns a protocol response with x-hcx-error_details populated. On success the payment lifecycle for that claim is closed on both sides. + + ### Common mistakes + + - Sending the acknowledgement as a JWEPayload of a different resource type or with the workbook's alternative output text (ACKNOWLEDGED, RECEIVED) instead of paymentack. + - Keeping the notice's Task direction; on the acknowledgement requester must be the provider and owner the payer. + - Minting a new correlation ID instead of echoing the notice's, or reusing a correlation ID that NHCX has deleted after failed deliveries. + - Using the wrong status; the response leg carries response.complete, not request.initiated. + - Skipping the acknowledgement altogether because the payer is not blocked by it, which leaves the lifecycle open in NHCX tracking. + - Payer side: returning 200 or a non-conforming body on receipt, which is treated as an error and retried. + + ### Best practices + + - Send the acknowledgement only after the UTR, TDS and net amount have been persisted against the claim. + - Echo the claim number from PaymentNotice.identifier (type CLN) into Task.output[1].valueString so the payer can match it without decrypting the original. + - Confirm with the payer during onboarding whether it expects the acknowledgement here or on /v1/task/submit, given the documented source conflict. + - Be idempotent: if the same notice is redelivered, acknowledge again with the same content rather than creating a second ledger entry. + - Log api_call_id and correlation ID for the acknowledgement so the closed lifecycle can be evidenced. + + ### Related scenario + + The hospital finance team receives the settlement notice under workflow 33 for claim CL0000000001 with UTR UTR000000000001, net 2187 INR and TDS 243 INR. After matching the bank credit and persisting the UTR, the HMIS builds a Task with status completed, code status, output paymentack and claimNumber CL0000000001, encrypts it for the payer and posts it to /v1/paymentnotice/on_request under workflow 17 with the notice's correlation ID. NHCX returns 202 and delivers it to the payer's bridge, which acknowledges within 30 seconds; the claim is now closed on both ledgers. + + ### Specification + + Chapter [Payment notice and acknowledgement](/docs/nhcx/v1/reference/fhir/payment-notice-and-acknowledgement) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + - name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - name: x-hcx-workflow_id + in: header + required: false + description: Which step, or which case. See the two readings below. Optional on the envelope. + schema: + type: string + example: "17" + - $ref: "#/components/parameters/XHcxTimestamp" + - name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: response.complete + - $ref: "#/components/parameters/XHcxBenAbhaId" + - $ref: "#/components/parameters/XHcxDebugFlag" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOi4uLn0.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: NHCX returns HTTP 202 Accepted with a StatusSuccessResponse acknowledgement (entity_type payment) and forwards the Task to the payer asynchronously; the payer's endpoint must acknowledge with 202 within 30 seconds or NHCX retries up to five times. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 27/02/2026 10:06:19:310 + api_call_id: b1a2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d + correlation_id: c3d2e1f0-a9b8-4c7d-9e6f-5a4b3c2d1e0f + result: + sender_code: 1000004446@hcx + recipient_code: 1518@hcx + entity_type: payment + protocol_status: request.dispatched + error: + code: "" + message: "" + /internal/v1/paymentnotice/on_request: + post: + operationId: payment_notice_internal_v1_paymentnotice_on_request + x-abdm-use-case: Adapter + tags: + - Adapter + summary: Payment notice acknowledgement (internal) (adapter) + description: |- + Internal twin of /v1/paymentnotice/on_request (operationId paymentNoticeOnRequestPostInternal) with the same JWEPayload body and response set. Exposed for the NHCX adapter deployment rather than for direct integration. + + ### Business purpose + + The paymentnotice service publishes its on_request operation twice, at /v1 and at /internal/v1, with identical descriptions, request bodies and response sets. Only the operationId differs, by an Internal suffix. The /internal prefix is the route the NHCX adapter sits on: a participant running the adapter alongside its own system calls the internal path, and the adapter handles the encryption, headers and gateway hop. A participant integrating directly against NHCX calls the public path and does that work itself. No separate business purpose is documented for the internal route beyond that. + + ### When to use + + Use it only when you are running the NHCX adapter and it is configured to serve this path; otherwise call /v1/paymentnotice/on_request. Everything else is unchanged: the same JWEPayload body, the same x-hcx-* protected header, the same workflow discriminators and the same asynchronous callback. The specs do not document what makes the internal variant different beyond the operationId, so treat it as a mirror of the public path and confirm with NHCX onboarding before pointing production at it. + + ### Preconditions + + Identical to /v1/paymentnotice/on_request. Nothing additional is documented for the internal route, beyond an adapter deployment that actually serves the /internal prefix. + + ### Postconditions + + NHCX returns HTTP 202 Accepted with a StatusSuccessResponse acknowledgement (entity_type payment) and forwards the Task to the payer asynchronously; the payer's endpoint must acknowledge with 202 within 30 seconds or NHCX retries up to five times. If the payer cannot process the acknowledgement (invalid provider, decryption failure, missing mandatory protocol attributes) it returns a protocol response with x-hcx-error_details populated. On success the payment lifecycle for that claim is closed on both sides. + + ### Common mistakes + + - Assuming a different body or different semantics for the internal route; the spec gives it the same JWEPayload body and the same responses. + - Calling it without an adapter deployment behind it and then chasing a 404. + - Every pitfall of the public path applies unchanged. + + ### Best practices + + - Default to /v1/paymentnotice/on_request and keep the internal path as a configuration option only. + - Share one client implementation across both paths, so header hygiene, encryption and correlation handling cannot diverge between them. + - Record which variant carried each correlation ID, for support conversations. + + ### Related scenario + + A vendor reading the paymentnotice OpenAPI document sees paymentNoticeOnRequestPostInternal sitting beside its public twin and asks which one to build against. The answer is the public path, unless NHCX onboarding has given them an adapter deployment, in which case the adapter takes the bundle unencrypted on the internal path and does the JWE and the gateway hop for them. The end-to-end flow is identical either way. + + ### Specification + + Chapter [Payment notice and acknowledgement](/docs/nhcx/v1/reference/fhir/payment-notice-and-acknowledgement) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + - name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - name: x-hcx-workflow_id + in: header + required: false + description: Which step, or which case. See the two readings below. Optional on the envelope. + schema: + type: string + example: "17" + - $ref: "#/components/parameters/XHcxTimestamp" + - name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: response.complete + - $ref: "#/components/parameters/XHcxBenAbhaId" + - $ref: "#/components/parameters/XHcxDebugFlag" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOi4uLn0.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: NHCX returns HTTP 202 Accepted with a StatusSuccessResponse acknowledgement (entity_type payment) and forwards the Task to the payer asynchronously; the payer's endpoint must acknowledge with 202 within 30 seconds or NHCX retries up to five times. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 27/02/2026 10:06:19:310 + api_call_id: b1a2c3d4-e5f6-4a7b-8c9d-0e1f2a3b4c5d + correlation_id: c3d2e1f0-a9b8-4c7d-9e6f-5a4b3c2d1e0f + result: + sender_code: 1000004446@hcx + recipient_code: 1518@hcx + entity_type: payment + protocol_status: request.dispatched + error: + code: "" + message: "" +webhooks: + v1_paymentnotice_request: + post: + operationId: payment_notice_webhook_v1_paymentnotice_request + x-abdm-atom: nhcx.callback.paymentnotice-request + x-abdm-triggered-by: payment_notice_v1_paymentnotice_request + x-abdm-use-case: Webhooks + tags: + - Payment notice + summary: Receive payment notice request + description: |- + Hosted by the provider. The exchange posts this message to the `endpoint_url` you registered, at `/v1/paymentnotice/request`, with the headers and the sealed payload the sender posted. Answer HTTP 202 with the receipt first and process afterwards; [Receiving a callback](/docs/nhcx/v1/getting-started/receiving-a-callback) has the rules. + + Payer pushes a Task bundle with PaymentNotice and PaymentReconciliation (amount, TDS, UTR) to the provider via NHCX after approving a claim. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - $ref: "#/components/parameters/XHcxSenderCode" + - $ref: "#/components/parameters/XHcxRecipientCode" + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxWorkflowId" + - $ref: "#/components/parameters/XHcxTimestamp" + - $ref: "#/components/parameters/XHcxStatus" + - $ref: "#/components/parameters/XHcxBenAbhaId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOi4uLn0.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: Received. The receipt names the message it answers; the answer itself follows as a call of your own. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 04/09/2026 11:46:41:305 + api_call_id: + correlation_id: + result: + sender_code: 1000003538@hcx + recipient_code: 1000004446@hcx + entity_type: preauth + protocol_status: request.queued + error: + code: "" + message: "" + v1_paymentnotice_on_request: + post: + operationId: payment_notice_webhook_v1_paymentnotice_on_request + x-abdm-atom: nhcx.callback.paymentnotice-on-request + x-abdm-triggered-by: payment_notice_v1_paymentnotice_on_request + x-abdm-use-case: Webhooks + tags: + - Payment notice + summary: Receive payment notice acknowledgement + description: |- + Hosted by the payer. The exchange posts this message to the `endpoint_url` you registered, at `/v1/paymentnotice/on_request`, with the headers and the sealed payload the sender posted. Answer HTTP 202 with the receipt first and process afterwards; [Receiving a callback](/docs/nhcx/v1/getting-started/receiving-a-callback) has the rules. + + Provider acknowledges a payment notice with a Task bundle (status completed, output paymentack), closing the payment lifecycle via NHCX. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + - name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - name: x-hcx-workflow_id + in: header + required: false + description: Which step, or which case. See the two readings below. Optional on the envelope. + schema: + type: string + example: "17" + - $ref: "#/components/parameters/XHcxTimestamp" + - name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: response.complete + - $ref: "#/components/parameters/XHcxBenAbhaId" + - $ref: "#/components/parameters/XHcxDebugFlag" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOi4uLn0.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: Received. The receipt names the message it answers; the answer itself follows as a call of your own. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 04/09/2026 11:46:41:305 + api_call_id: + correlation_id: + result: + sender_code: 1000003538@hcx + recipient_code: 1000004446@hcx + entity_type: preauth + protocol_status: request.queued + error: + code: "" + message: "" +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + description: "On every NHCX call, the token goes in a header called `bearer_auth`, with the word `Bearer` and a space in front. The sources are not unanimous: the authentication page and the FAQ both write the example as `Authorization`, and the notification endpoint uses `Authorization`. The safe course, and what the adapter does, is to send both headers with the same value." + parameters: + BearerAuth: + name: bearer_auth + in: header + required: true + description: It is `bearer_auth`, not `Authorization`, on NHCX's own endpoints. + schema: + type: string + example: Bearer + XHcxSenderCode: + name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + XHcxRecipientCode: + name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + XHcxApiCallId: + name: x-hcx-api_call_id + in: header + required: true + description: Fresh on every message, including responses. Mandatory on the envelope. + schema: + type: string + example: + XHcxRequestId: + name: x-hcx-request_id + in: header + required: false + description: One per originating request. The Open Protocol page marks it Mandatory; the Technical Specifications page marks it Optional. Optional on the envelope. + schema: + type: string + example: + XHcxCorrelationId: + name: x-hcx-correlation_id + in: header + required: true + description: The thread. See the rule below. Mandatory on the envelope. + schema: + type: string + example: + XHcxWorkflowId: + name: x-hcx-workflow_id + in: header + required: false + description: Which step, or which case. See the two readings below. Optional on the envelope. + schema: + type: string + example: "30" + XHcxTimestamp: + name: x-hcx-timestamp + in: header + required: true + description: See the format note below. Mandatory on the envelope. + schema: + type: string + example: + XHcxStatus: + name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: request.initiated + XHcxBenAbhaId: + name: x-hcx-ben-abha-id + in: header + required: true + description: The beneficiary's ABHA number. Mandatory on every exchange, including those with no beneficiary in the payload. Mandatory on the envelope. + schema: + type: string + example: "91711234567890" + XHcxDebugFlag: + name: x-hcx-debug_flag + in: header + required: false + description: "`Error`, `Info` or `Debug`. A server may ignore it. Optional on the envelope." + schema: + type: string + example: INFO +x-abdm-errors: + notes: "Codes any exchange call can meet are recorded once, in the [Other](/docs/nhcx/v1/api/other) specification: the gateway's NHCX- codes, the standard payer codes, and the reference payer's structure and transport codes. The reference payer's other codes sit with the exchange they reject: coverage eligibility, preauthorisation, claim and insurance plan. [Reading error codes](/docs/nhcx/v1/reference/error-code-guide) explains the code spaces." diff --git a/catalogue/openapi/nhcx/v1/nhcx-preauth.yaml b/catalogue/openapi/nhcx/v1/nhcx-preauth.yaml new file mode 100644 index 000000000..b472bfb34 --- /dev/null +++ b/catalogue/openapi/nhcx/v1/nhcx-preauth.yaml @@ -0,0 +1,1110 @@ +# NHCX pre-authorisation, from the NHCX package's Bruno folder apis/03-preauth. +# +# Written by the package's system/build-ekadocs.mjs (make ekadocs); change the .bru +# requests there and port again rather than editing this file. +# +# Rules this file follows: catalogue/openapi/CONVENTIONS.md +openapi: 3.1.1 +info: + x-portal: + module: preauth + label: Pre-authorisation + position: 3 + title: NHCX pre-authorisation + summary: Pre-authorisation is the provider's formal request for the payer's approval to deliver a specific treatment to a covered beneficiary. + description: |- + The Pre-authorisation calls on the National Health Claims Exchange (NHCX): 4 operations, and 2 callbacks you host. + + Pre-authorisation is the provider's formal request for the payer's approval to deliver a specific treatment to a covered beneficiary. + + Guides that use these calls: [Building and sending a JWE](/docs/nhcx/v1/getting-started/building-and-sending-a-jwe), [Preauthorisation request](/docs/nhcx/v1/reference/fhir/preauthorisation-request), [Preauthorisation response](/docs/nhcx/v1/reference/fhir/preauthorisation-response), [Preauthorisation enhancement](/docs/nhcx/v1/reference/fhir/preauthorisation-enhancement), [Preauthorisation query and answer](/docs/nhcx/v1/reference/fhir/preauthorisation-query-and-answer). + version: nhcx-v1 + license: + name: MIT + identifier: MIT + contact: + name: NHCX sandbox + url: https://hcxsbx.abdm.gov.in + x-abdm-gateway: nhcx + x-abdm-module: preauth + x-abdm-phase: 1 + x-abdm-roles: + - provider + - payer +x-abdm-sources: + - file: nhcx-package/apis/03-preauth + role: upstream + hash: sha256:270ab9c7c4783d9042ee4c4adbd8141d8fd69037d358a330808f23e3d945deca + note: The package's Bruno collection, one request per operation. + - file: nhcx-package/baseurl.yaml + role: upstream + hash: sha256:88515b7b29c6b349a131e016c80774436ea16a29738db743b4cc3a24cbd42453 + note: The sandbox and production hosts. + - file: nhcx-package/nhcx-error.yaml + role: upstream + hash: sha256:d24ac927ed4dd722e60d7bd1d6fed15de370cc29f750d68999ee56fac93c941b + note: The error codes. +servers: + - url: https://apisbx.abdm.gov.in/hcx + description: Sandbox, NHCX exchange. + - url: https://apisprod.nha.gov.in/hcx + description: Production. +tags: + - name: Pre-authorisation + description: Pre-authorisation is the provider's formal request for the payer's approval to deliver a specific treatment to a covered beneficiary. + - name: Adapter + description: Exposed for the NHCX adapter deployment rather than for direct integration. +security: + - bearerAuth: [] +paths: + /v1/preauth/submit: + post: + operationId: preauth_v1_preauth_submit + x-abdm-atom: nhcx.endpoint.preauth-submit + x-abdm-use-case: Pre-authorisation + tags: + - Pre-authorisation + summary: Pre-authorisation submit + description: |- + Provider submits, resubmits, enhances or answers a query on a pre-authorisation Claim bundle (Claim.use preauthorization); NHCX routes it to the payer. + + ### Business purpose + + Pre-authorisation is the provider's formal request for the payer's approval to deliver a specific treatment to a covered beneficiary. An approved preAuthRef is the payer's binding commitment to reimburse the approved amount and is required before the final claim can proceed through NHCX. Settling the money question before the patient enters theatre protects the hospital from unpaid treatment, gives the payer control over admissibility, and gives the patient certainty about cashless cover. + + ### When to use + + Called after eligibility has confirmed cover and the mandatory documents are in hand. The same endpoint carries several business steps; the x-hcx-workflow_id header (and the optional x-hcx-use_case header with values New, Enhancement or Resubmit) is the discriminator: 12 PREAUTH_REQUEST_INITIATED for a new preauth; 121 PREAUTH_REQUEST_RESUBMITTED after a query or rejection; 19 PREAUTH_QUERY_RESPONSE_SUBMITTED to answer a payer query received under 24; 13 ENHANCEMENT_REQUEST_INITIATED for an additional amount on an already approved preauth, with 131 answering an enhancement query (241); and 14 DISCHARGE_SUBMITTED for the provisional pre-discharge submission that the claim chapter describes for non-PMJAY schemes (answered by 261, 262 or 263), with 141 answering a discharge query. Send x-hcx-status request.initiated on every one of these. Cancellation is not sent here; it goes to /v1/task/submit (PC01 or 122). + + ### Preconditions + + - Provider is an active NHCX participant with a valid NPI facility code and a current Bearer token. + - Patient resource carries the PMJAY Member ID and ABHA number; an active Coverage resource with a valid policy identifier is included. + - Diagnosis (ICD-10), procedure (NRCes ndhm-procedure-code), care team and supportingInfo are present, and the mandatory documents named by the InsurancePlan or the eligibility auth-requirements response are attached. + - For a new PMJAY preauth, either biometric authentication or the Authentication Consent questionnaire response is included (PAYR-1256, PAYR-1271). + - For 13, 19, 121 or 131 a prior preauth in the right state exists (PAYR-1212, PAYR-1214, PAYR-1218, PAYR-1219 otherwise) and the message reuses the episode's correlation identity. + - Payer certificate fetched, bundle JWE-encrypted, recipient code taken from processingID, timestamp in IST. + + ### Postconditions + + NHCX returns HTTP 202 Accepted with a StatusSuccessResponse acknowledgement (entity_type preauth, protocol_status request.queued or request.dispatched). This is not an adjudication; the gateway validates structure and open headers, then forwards asynchronously. The payer may first acknowledge under workflow 20, then answer on /v1/preauth/on_submit with a ClaimResponseBundle: 21 approved (preAuthRef issued), 23 rejected, 24 queried, 22 enhancement approved or 241 enhancement queried, 261, 262 or 263 for discharge. Protocol failures return a ProtocolResponse with x-hcx-error_details. Errors marked 400, 404 and 500 carry the same schema. + + ### Common mistakes + + - Answering a query (24) with a fresh 12 instead of 19, or answering an enhancement query (241) with 19 instead of 131; both arrive on the same callback and are easily crossed. + - Sending an enhancement (13) against a preauth that is not yet approved (PAYR-1212) or while another case is in progress (PAYR-1213), or a new 12 when an approved preauth already exists (PAYR-1217). + - Reusing a correlation ID across cycles (NHCX-1006) or after a failure, when NHCX has marked it inactive. + - Leaving out x-hcx-workflow_id and x-hcx-use_case because the spec marks them Optional; without them the payer cannot tell an enhancement from a duplicate. + - Item and amount errors: PAYR-1017 incorrect calculations, PAYR-1209 net amount not greater than zero, PAYR-1248 invalid item code, PAYR-1254 missing STG questionnaire response, PAYR-1270 sending LM100 at preauth stage. + - Branching on ClaimResponse.outcome alone when the callback arrives; complete means approved or rejected depending on adjudication reason. + + ### Best practices + + - Build one ClaimBundle and switch Claim.use between preauthorization and claim; keep careTeamSequence, diagnosisSequence, procedureSequence and informationSequence internally consistent. + - Always send both x-hcx-workflow_id and x-hcx-use_case, and persist them with the correlation ID and the case number. + - Attach every document the auth-requirements response listed (MAND codes) before submitting; the document list is per package, not static. + - Raise enhancements while the patient is admitted, not retrospectively at discharge (PAYR-1018 time limit expired). + - Persist preAuthRef from an approved or partially approved response; it is required at final claim. + - Implement v1/error and /v1/status so a preauth that never reached the payer is visible at the desk. + + ### Related scenario + + After the eligibility callback confirms cover for corneal grafting (SE012A) and lists the required documents, the hospital builds a Claim bundle with use preauthorization, ICD-10 H18.6, a total of 13700 INR and the investigation and consent attachments, and posts it to /v1/preauth/submit under workflow 12 with use_case New. NHCX returns 202. The payer queries under 24 asking for detailed ICPs; the hospital answers on the same endpoint under 19 with the same correlation ID. Approval arrives under 21 with preAuthRef PREAUTH-HP-2026-78901. Two days later the surgeon needs a higher bed category, so the hospital posts an enhancement under 13 with use_case Enhancement, and after discharge it moves to /v1/claim/submit. + + ### Specification + + Chapter [Preauthorisation request](/docs/nhcx/v1/reference/fhir/preauthorisation-request) of the NHCX integration specification. + + ### Also sent as pre-authorisation enhancement + + The same address, with other headers and body. + + Provider asks for more against an approved pre-authorisation, a longer stay or an added package, on the same endpoint and case number as the first request, under workflow 13 with x-hcx-use_case Enhancement. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - $ref: "#/components/parameters/XHcxSenderCode" + - $ref: "#/components/parameters/XHcxRecipientCode" + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxWorkflowId" + - $ref: "#/components/parameters/XHcxTimestamp" + - $ref: "#/components/parameters/XHcxStatus" + - $ref: "#/components/parameters/XHcxBenAbhaId" + - $ref: "#/components/parameters/XHcxUseCase" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + examples: + v1_preauth_submit: + summary: Pre-authorisation submit + value: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOi4uLn0.encrypted_key.iv.ciphertext.tag + v1_preauth_enhancement: + summary: Pre-authorisation enhancement + value: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOi4uLn0.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: NHCX returns HTTP 202 Accepted with a StatusSuccessResponse acknowledgement (entity_type preauth, protocol_status request.queued or request.dispatched). + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 19/03/2026 11:46:35:120 + api_call_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890 + correlation_id: 11223344-5566-7788-99aa-bbccddeeff00 + result: + sender_code: 1000004446@hcx + recipient_code: 1518@hcx + entity_type: preauth + protocol_status: request.queued + error: + code: "" + message: "" + /internal/v1/preauth/submit: + post: + operationId: preauth_internal_v1_preauth_submit + x-abdm-use-case: Adapter + tags: + - Adapter + summary: Pre-authorisation submit (internal) (adapter) + description: |- + Internal twin of /v1/preauth/submit (operationId preauthSubmitPostInternal) with the same JWEPayload body and response set. Exposed for the NHCX adapter deployment rather than for direct integration. + + ### Business purpose + + The preauth service publishes its submit operation twice, at /v1 and at /internal/v1, with identical descriptions, request bodies and response sets. Only the operationId differs, by an Internal suffix. The /internal prefix is the route the NHCX adapter sits on: a participant running the adapter alongside its own system calls the internal path, and the adapter handles the encryption, headers and gateway hop. A participant integrating directly against NHCX calls the public path and does that work itself. No separate business purpose is documented for the internal route beyond that. + + ### When to use + + Use it only when you are running the NHCX adapter and it is configured to serve this path; otherwise call /v1/preauth/submit. Everything else is unchanged: the same JWEPayload body, the same x-hcx-* protected header, the same workflow discriminators and the same asynchronous callback. The specs do not document what makes the internal variant different beyond the operationId, so treat it as a mirror of the public path and confirm with NHCX onboarding before pointing production at it. + + ### Preconditions + + Identical to /v1/preauth/submit. Nothing additional is documented for the internal route, beyond an adapter deployment that actually serves the /internal prefix. + + ### Postconditions + + NHCX returns HTTP 202 Accepted with a StatusSuccessResponse acknowledgement (entity_type preauth, protocol_status request.queued or request.dispatched). This is not an adjudication; the gateway validates structure and open headers, then forwards asynchronously. The payer may first acknowledge under workflow 20, then answer on /v1/preauth/on_submit with a ClaimResponseBundle: 21 approved (preAuthRef issued), 23 rejected, 24 queried, 22 enhancement approved or 241 enhancement queried, 261, 262 or 263 for discharge. Protocol failures return a ProtocolResponse with x-hcx-error_details. Errors marked 400, 404 and 500 carry the same schema. + + ### Common mistakes + + - Assuming a different body or different semantics for the internal route; the spec gives it the same JWEPayload body and the same responses. + - Calling it without an adapter deployment behind it and then chasing a 404. + - Every pitfall of the public path applies unchanged. + + ### Best practices + + - Default to /v1/preauth/submit and keep the internal path as a configuration option only. + - Share one client implementation across both paths, so header hygiene, encryption and correlation handling cannot diverge between them. + - Record which variant carried each correlation ID, for support conversations. + + ### Related scenario + + A vendor reading the preauth OpenAPI document sees preauthSubmitPostInternal sitting beside its public twin and asks which one to build against. The answer is the public path, unless NHCX onboarding has given them an adapter deployment, in which case the adapter takes the bundle unencrypted on the internal path and does the JWE and the gateway hop for them. The end-to-end flow is identical either way. + + ### Specification + + Chapter [Preauthorisation request](/docs/nhcx/v1/reference/fhir/preauthorisation-request) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - $ref: "#/components/parameters/XHcxSenderCode" + - $ref: "#/components/parameters/XHcxRecipientCode" + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxWorkflowId" + - $ref: "#/components/parameters/XHcxTimestamp" + - $ref: "#/components/parameters/XHcxStatus" + - $ref: "#/components/parameters/XHcxBenAbhaId" + - $ref: "#/components/parameters/XHcxUseCase" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOi4uLn0.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: NHCX returns HTTP 202 Accepted with a StatusSuccessResponse acknowledgement (entity_type preauth, protocol_status request.queued or request.dispatched). + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 19/03/2026 11:46:35:120 + api_call_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890 + correlation_id: 11223344-5566-7788-99aa-bbccddeeff00 + result: + sender_code: 1000004446@hcx + recipient_code: 1518@hcx + entity_type: preauth + protocol_status: request.queued + error: + code: "" + message: "" + /v1/preauth/on_submit: + post: + operationId: preauth_v1_preauth_on_submit + x-abdm-atom: nhcx.endpoint.preauth-on-submit + x-abdm-use-case: Pre-authorisation + tags: + - Pre-authorisation + summary: Pre-authorisation callback + description: |- + Payer returns the ClaimResponseBundle for a pre-authorisation (approved, partially approved, queried or rejected) to the provider via NHCX. + + ### Business purpose + + This callback carries the payer's decision on a preauth. For the hospital it is the moment the money question is settled: an approval with a preAuthRef lets treatment proceed under a binding commitment, a partial approval tells the desk the amount was capped and why, a query says what evidence is missing, and a rejection closes the request. For the payer it is the channel through which adjudication results, package-rate caps and query text reach the provider in a structured, auditable form. + + ### When to use + + Called by the payer or its TPA after adjudicating a /v1/preauth/submit message, using the same correlation ID. The x-hcx-workflow_id identifies the outcome: 20 received, 21 approved, 23 rejected, 24 queried, 22 enhancement approved, 241 enhancement queried, 231 enhancement denied, 261, 262 and 263 for discharge. The NHA status sheet frames approvals and rejections as response.complete and queries (24, 241) as request.initiated because the payer is authoring a new request to the provider. ClaimResponse.outcome is complete for approved and rejected, partial for partially approved and queried; adjudication[0].reason.coding.code (approved, queried, cancelled) is the real discriminator. + + ### Preconditions + + - A preauth request with this correlation ID exists in NHCX and has not been deleted after failed deliveries (NHCX-1010 otherwise). + - The payer holds a valid Bearer token and the provider's certificate, and encrypts the ClaimResponseBundle for the provider. + - x-hcx-correlation_id is echoed from the request; x-hcx-api_call_id is new; sender and recipient codes are swapped. + - x-hcx-status is response.complete, response.partial or response.error; on error the body is a ProtocolResponse with x-hcx-error_details mandatory. + - preAuthRef is populated on approval and partial approval; processNote explains any reduction; clinical or business error detail stays inside the encrypted resource. + + ### Postconditions + + HTTP 202 Accepted with the StatusSuccessResponse acknowledgement (entity_type preauth) from NHCX, then asynchronous delivery to the provider's registered /v1/preauth/on_submit. The provider must acknowledge with 202 within 30 seconds; otherwise NHCX retries, and after five failures the request is deleted and the sender is notified via v1/error. On an approved or partially approved response the provider persists preAuthRef and may treat; on a query the conversation stays open awaiting 19, 131 or 121; on a rejection the preauth is closed and a new case number is needed to proceed. + + ### Common mistakes + + - Provider side: branching on outcome alone; complete plus reason cancelled is a rejection, complete plus approved is an approval. + - Provider side: treating the pipe-delimited query audit trail (USER~datetime~type~comment~trust) as a FHIR coding and failing to parse it. + - Provider side: returning 200 or a bare body instead of the 202 acceptance shape, which triggers retries and eventual deletion. + - Payer side: minting a new correlation ID, or sending a JWEPayloadResponse where a ProtocolResponse is expected (PAYR-1517). + - Payer side: using the superseded status spelling; the sources show both response.fail and response.error for failures, and the technical specification vocabulary is response.error. + - Both sides: relying on the position of ClaimResponse.total[] entries rather than total[].category.coding.code. + + ### Best practices + + - Provider: acknowledge first, adjudicate later; queue the decrypt and state change and be idempotent on correlation ID. + - Provider: branch on x-hcx-workflow_id, ClaimResponse.outcome and adjudication[0].reason.coding.code together, and surface processNote text to the desk. + - Provider: persist preAuthRef and the payer identifier (identifier[0].value) against the case for the claim stage. + - Payer: fill disposition, adjudication categories (submitted, eligible, copay, benefit) and processNote so a partial approval is explainable. + - Payer: put protocol errors in x-hcx-error_details with catalogued codes and business errors inside the encrypted ClaimResponse. + - Provider: expose the callback on a domain name on an India-based server and whitelist the NHCX NAT IPs. + + ### Related scenario + + The insurer's adjudication engine reviews a corneal grafting preauth submitted for 25000 INR and caps it at the package rate of 13700 INR. Its bridge builds a ClaimResponseBundle with outcome partial, preAuthRef PREAUTH-HP-2026-78902 and a processNote explaining the cap, sets x-hcx-workflow_id 21 and x-hcx-status response.complete with the request's correlation ID, encrypts it for the hospital and posts to /v1/preauth/on_submit. NHCX acknowledges with 202 and delivers it to the hospital, whose callback acknowledges inside 30 seconds and shows the desk the reduced amount and reason. Treatment proceeds, and after discharge the hospital submits the final claim on /v1/claim/submit referencing that preAuthRef. + + ### Specification + + Chapter [Preauthorisation response](/docs/nhcx/v1/reference/fhir/preauthorisation-response) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + - name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - name: x-hcx-workflow_id + in: header + required: false + description: Which step, or which case. See the two readings below. Optional on the envelope. + schema: + type: string + example: "21" + - $ref: "#/components/parameters/XHcxTimestamp" + - name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: response.complete + - $ref: "#/components/parameters/XHcxBenAbhaId" + - $ref: "#/components/parameters/XHcxDebugFlag" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOi4uLn0.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: HTTP 202 Accepted with the StatusSuccessResponse acknowledgement (entity_type preauth) from NHCX, then asynchronous delivery to the provider's registered /v1/preauth/on_submit. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 19/03/2026 11:46:35:120 + api_call_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890 + correlation_id: 11223344-5566-7788-99aa-bbccddeeff00 + result: + sender_code: 1518@hcx + recipient_code: 1000004446@hcx + entity_type: preauth + protocol_status: request.dispatched + error: + code: "" + message: "" + /internal/v1/preauth/on_submit: + post: + operationId: preauth_internal_v1_preauth_on_submit + x-abdm-use-case: Adapter + tags: + - Adapter + summary: Pre-authorisation callback (internal) (adapter) + description: |- + Internal twin of /v1/preauth/on_submit (operationId preauthOnSubmitPostInternal) with the same JWEPayload body and response set. Exposed for the NHCX adapter deployment rather than for direct integration. + + ### Business purpose + + The preauth service publishes its on_submit operation twice, at /v1 and at /internal/v1, with identical descriptions, request bodies and response sets. Only the operationId differs, by an Internal suffix. The /internal prefix is the route the NHCX adapter sits on: a participant running the adapter alongside its own system calls the internal path, and the adapter handles the encryption, headers and gateway hop. A participant integrating directly against NHCX calls the public path and does that work itself. No separate business purpose is documented for the internal route beyond that. + + ### When to use + + Use it only when you are running the NHCX adapter and it is configured to serve this path; otherwise call /v1/preauth/on_submit. Everything else is unchanged: the same JWEPayload body, the same x-hcx-* protected header, the same workflow discriminators and the same asynchronous callback. The specs do not document what makes the internal variant different beyond the operationId, so treat it as a mirror of the public path and confirm with NHCX onboarding before pointing production at it. + + ### Preconditions + + Identical to /v1/preauth/on_submit. Nothing additional is documented for the internal route, beyond an adapter deployment that actually serves the /internal prefix. + + ### Postconditions + + HTTP 202 Accepted with the StatusSuccessResponse acknowledgement (entity_type preauth) from NHCX, then asynchronous delivery to the provider's registered /v1/preauth/on_submit. The provider must acknowledge with 202 within 30 seconds; otherwise NHCX retries, and after five failures the request is deleted and the sender is notified via v1/error. On an approved or partially approved response the provider persists preAuthRef and may treat; on a query the conversation stays open awaiting 19, 131 or 121; on a rejection the preauth is closed and a new case number is needed to proceed. + + ### Common mistakes + + - Assuming a different body or different semantics for the internal route; the spec gives it the same JWEPayload body and the same responses. + - Calling it without an adapter deployment behind it and then chasing a 404. + - Every pitfall of the public path applies unchanged. + + ### Best practices + + - Default to /v1/preauth/on_submit and keep the internal path as a configuration option only. + - Share one client implementation across both paths, so header hygiene, encryption and correlation handling cannot diverge between them. + - Record which variant carried each correlation ID, for support conversations. + + ### Related scenario + + A vendor reading the preauth OpenAPI document sees preauthOnSubmitPostInternal sitting beside its public twin and asks which one to build against. The answer is the public path, unless NHCX onboarding has given them an adapter deployment, in which case the adapter takes the bundle unencrypted on the internal path and does the JWE and the gateway hop for them. The end-to-end flow is identical either way. + + ### Specification + + Chapter [Preauthorisation response](/docs/nhcx/v1/reference/fhir/preauthorisation-response) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + - name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - name: x-hcx-workflow_id + in: header + required: false + description: Which step, or which case. See the two readings below. Optional on the envelope. + schema: + type: string + example: "21" + - $ref: "#/components/parameters/XHcxTimestamp" + - name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: response.complete + - $ref: "#/components/parameters/XHcxBenAbhaId" + - $ref: "#/components/parameters/XHcxDebugFlag" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOi4uLn0.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: HTTP 202 Accepted with the StatusSuccessResponse acknowledgement (entity_type preauth) from NHCX, then asynchronous delivery to the provider's registered /v1/preauth/on_submit. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 19/03/2026 11:46:35:120 + api_call_id: a1b2c3d4-e5f6-7890-abcd-ef1234567890 + correlation_id: 11223344-5566-7788-99aa-bbccddeeff00 + result: + sender_code: 1518@hcx + recipient_code: 1000004446@hcx + entity_type: preauth + protocol_status: request.dispatched + error: + code: "" + message: "" +webhooks: + v1_preauth_submit: + post: + operationId: preauth_webhook_v1_preauth_submit + x-abdm-atom: nhcx.callback.preauth-submit + x-abdm-triggered-by: preauth_v1_preauth_submit + x-abdm-use-case: Webhooks + tags: + - Pre-authorisation + summary: Receive pre-authorisation submit + description: |- + Hosted by the payer. The exchange posts this message to the `endpoint_url` you registered, at `/v1/preauth/submit`, with the headers and the sealed payload the sender posted. Answer HTTP 202 with the receipt first and process afterwards; [Receiving a callback](/docs/nhcx/v1/getting-started/receiving-a-callback) has the rules. + + Provider submits, resubmits, enhances or answers a query on a pre-authorisation Claim bundle (Claim.use preauthorization); NHCX routes it to the payer. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - $ref: "#/components/parameters/XHcxSenderCode" + - $ref: "#/components/parameters/XHcxRecipientCode" + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxWorkflowId" + - $ref: "#/components/parameters/XHcxTimestamp" + - $ref: "#/components/parameters/XHcxStatus" + - $ref: "#/components/parameters/XHcxBenAbhaId" + - $ref: "#/components/parameters/XHcxUseCase" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + examples: + v1_preauth_submit: + summary: Pre-authorisation submit + value: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOi4uLn0.encrypted_key.iv.ciphertext.tag + v1_preauth_enhancement: + summary: Pre-authorisation enhancement + value: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOi4uLn0.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: Received. The receipt names the message it answers; the answer itself follows as a call of your own. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 04/09/2026 11:46:41:305 + api_call_id: + correlation_id: + result: + sender_code: 1000003538@hcx + recipient_code: 1000004446@hcx + entity_type: preauth + protocol_status: request.queued + error: + code: "" + message: "" + v1_preauth_on_submit: + post: + operationId: preauth_webhook_v1_preauth_on_submit + x-abdm-atom: nhcx.callback.preauth-on-submit + x-abdm-triggered-by: preauth_v1_preauth_on_submit + x-abdm-use-case: Webhooks + tags: + - Pre-authorisation + summary: Receive pre-authorisation callback + description: |- + Hosted by the provider. The exchange posts this message to the `endpoint_url` you registered, at `/v1/preauth/on_submit`, with the headers and the sealed payload the sender posted. Answer HTTP 202 with the receipt first and process afterwards; [Receiving a callback](/docs/nhcx/v1/getting-started/receiving-a-callback) has the rules. + + Payer returns the ClaimResponseBundle for a pre-authorisation (approved, partially approved, queried or rejected) to the provider via NHCX. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + - name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - name: x-hcx-workflow_id + in: header + required: false + description: Which step, or which case. See the two readings below. Optional on the envelope. + schema: + type: string + example: "21" + - $ref: "#/components/parameters/XHcxTimestamp" + - name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: response.complete + - $ref: "#/components/parameters/XHcxBenAbhaId" + - $ref: "#/components/parameters/XHcxDebugFlag" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOi4uLn0.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: Received. The receipt names the message it answers; the answer itself follows as a call of your own. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 04/09/2026 11:46:41:305 + api_call_id: + correlation_id: + result: + sender_code: 1000003538@hcx + recipient_code: 1000004446@hcx + entity_type: preauth + protocol_status: request.queued + error: + code: "" + message: "" +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + description: "On every NHCX call, the token goes in a header called `bearer_auth`, with the word `Bearer` and a space in front. The sources are not unanimous: the authentication page and the FAQ both write the example as `Authorization`, and the notification endpoint uses `Authorization`. The safe course, and what the adapter does, is to send both headers with the same value." + parameters: + BearerAuth: + name: bearer_auth + in: header + required: true + description: It is `bearer_auth`, not `Authorization`, on NHCX's own endpoints. + schema: + type: string + example: Bearer + XHcxSenderCode: + name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + XHcxRecipientCode: + name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + XHcxApiCallId: + name: x-hcx-api_call_id + in: header + required: true + description: Fresh on every message, including responses. Mandatory on the envelope. + schema: + type: string + example: + XHcxRequestId: + name: x-hcx-request_id + in: header + required: false + description: One per originating request. The Open Protocol page marks it Mandatory; the Technical Specifications page marks it Optional. Optional on the envelope. + schema: + type: string + example: + XHcxCorrelationId: + name: x-hcx-correlation_id + in: header + required: true + description: The thread. See the rule below. Mandatory on the envelope. + schema: + type: string + example: + XHcxWorkflowId: + name: x-hcx-workflow_id + in: header + required: false + description: Which step, or which case. See the two readings below. Optional on the envelope. + schema: + type: string + example: "12" + XHcxTimestamp: + name: x-hcx-timestamp + in: header + required: true + description: See the format note below. Mandatory on the envelope. + schema: + type: string + example: + XHcxStatus: + name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: request.initiated + XHcxBenAbhaId: + name: x-hcx-ben-abha-id + in: header + required: true + description: The beneficiary's ABHA number. Mandatory on every exchange, including those with no beneficiary in the payload. Mandatory on the envelope. + schema: + type: string + example: "91711234567890" + XHcxUseCase: + name: x-hcx-use_case + in: header + required: false + description: Values differ by exchange, see below. Optional on the envelope. + schema: + type: string + example: New + XHcxDebugFlag: + name: x-hcx-debug_flag + in: header + required: false + description: "`Error`, `Info` or `Debug`. A server may ignore it. Optional on the envelope." + schema: + type: string + example: INFO +x-abdm-errors: + notes: "Codes any exchange call can meet are recorded once, in the [Other](/docs/nhcx/v1/api/other) specification: the gateway's NHCX- codes, the standard payer codes, and the reference payer's structure and transport codes. The reference payer's other codes sit with the exchange they reject: coverage eligibility, preauthorisation, claim and insurance plan. [Reading error codes](/docs/nhcx/v1/reference/error-code-guide) explains the code spaces." +x-abdm-errors-reference-payer: + source: Reference payer codes, PAYR-1001 to PAYR-1520. Sent by the PMJAY reference implementation; they arrive inside the sealed response. + codes: + - code: PAYR-1201 + message: Invalid claimed amount received for case number %s. Please try again with a valid claim amount. Claimed amount should be greater than INR 0 and less than equals to balance wallet amount of the beneficiary. + action: "" + - code: PAYR-1202 + message: Invalid speciality code received as %s for item %s for case number %s. Please try again with valid data. Speciality code is available as the code of the category for specific cost of plan in isurance plan. + action: "" + - code: PAYR-1203 + message: Invalid speciality description received as %s for procedure %s for case number %s. Please try again with valid data. Speciality description is available as the display of the category for specific cost of plan in isurance plan. + action: "" + - code: PAYR-1204 + message: Invalid procedure code received as %s for case number %s. Please try again with valid data. Procedure code is available as the code of the type for benefit component, of specific cost, of plan in isurance plan. + action: "" + - code: PAYR-1205 + message: Invalid procedure description received as %s for procedure %s for case number %s. Please try again with valid data. Procedure description is available as the display of the type for benefit component, of specific cost, of plan in isurance plan. + action: "" + - code: PAYR-1206 + message: Invalid procedure type received as %s for procedure %s for case number %s. Please try again with valid data. + action: "" + - code: PAYR-1207 + message: Invalid procedure factor received as %s for procedure %s for case number %s. Please try again with valid data. + action: "" + - code: PAYR-1208 + message: Invalid procedure quantity received as %s for item %s for case number %s. Please try again with valid data. Item quantity should be greater than 1. + action: "" + - code: PAYR-1209 + message: Invalid net amount received as INR %s for item %s for case number %s. Please try again with valid data. Item net amount should be greater than INR 0. + action: "" + - code: PAYR-1210 + message: Invalid procedure status received as %s for procedure %s for case number %s. Please try again with valid data. + action: "" + - code: PAYR-1211 + message: Requested beneficary details and careplan details does not match any criteria for processing the case at this hospital. Please try again with valid data. + action: "" + - code: PAYR-1212 + message: No previous preauthorization approved record found for the enhancement request for case number %s. Hence request will not be processed further. Please initiate a new preauthorization. + action: "" + - code: PAYR-1213 + message: Existing case in progress found for case number %s. Hence enhancement request will not be accepted. Please try after the adjudication is completed for the current case. + action: "" + - code: PAYR-1214 + message: No previous preauthorization approved record found for the resubmission request for case number %s. Hence request will not be processed further. Please initiate a new preauthorization. + action: "" + - code: PAYR-1215 + message: Existing case in progress found for case number %s. Hence resubmission request will not be accepted. Please try after the adjudication is completed for the current case. + action: "" + - code: PAYR-1216 + message: Existing case in progress found for case number %s. Hence new preauthorization request will not be accepted. + action: "" + - code: PAYR-1217 + message: Previous preauthorization approved record found for the new preauthorization request for case number %s. Hence request will not be processed further. Please initiate enhancement/resubmission. + action: "" + - code: PAYR-1218 + message: No queried preauthorization record found for the query update request for case number %s. Hence request will not be processed further. + action: "" + - code: PAYR-1219 + message: Case number %s is not queried. Hence query updation request will not be processed further. + action: "" + - code: PAYR-1220 + message: Invalid investigation description received as %s for investigation code %s for case number %s. Please try again with valid data. + action: "" + - code: PAYR-1221 + message: Invalid investigation code received as %s for case number %s. Please try again with valid data. + action: "" + - code: PAYR-1222 + message: Invalid investigation status received as %s for investigation %s for case number %s. Please try again with valid data. + action: "" + - code: PAYR-1223 + message: Invalid investigation attachment received for investigation %s for case number %s. Please try again with valid data. + action: "" + - code: PAYR-1224 + message: Invalid implant description received as %s for implant code %s for case number %s. Please try again with valid data. + action: "" + - code: PAYR-1225 + message: Invalid implant code received as %s for case number %s. Please try again with valid data. + action: "" + - code: PAYR-1226 + message: Invalid implant status received as %s for investigation %s for case number %s. Please try again with valid data. + action: "" + - code: PAYR-1227 + message: Invalid implant attachment received for investigation %s for case number %s. Please try again with valid data. + action: "" + - code: PAYR-1228 + message: Invalid implant quantity received as %s for implant %s for case number %s. Please try again with valid data. + action: "" + - code: PAYR-1229 + message: Invalid implant net amount received as INR %s for implant %s for case number %s. Please try again with valid data. + action: "" + - code: PAYR-1230 + message: Invalid implant unit price received as INR %s for implant %s for case number %s. Please try again with valid data. + action: "" + - code: PAYR-1231 + message: Claim has already been raised for case number %s. Hence preauthorization request will not be accepted. + action: "" + - code: PAYR-1232 + message: No investigation found for case number %s. Investigation details are mandatory for private hospitals. + action: "" + - code: PAYR-1233 + message: Patient liability is not aplicable for the hospital and beneficiary do not have enough wallet balance with deficit amount INR %s for the requested preauthorization for case number %s. + action: "" + - code: PAYR-1234 + message: No preauthorization record found for case number %s. Hence the request will not be processed. + action: "" + - code: PAYR-1235 + message: Insufficient wallet balance. Hence the request will not be processed. + action: "" + - code: PAYR-1236 + message: Invalid claim type (in-patient/out-patient) received. Hence the request will not be processed. + action: "" + - code: PAYR-1237 + message: Beneficiary is having an active preauthorization request at %s. Hence the request will not be processed. Kindly inform %s to cancel the active preauthorization request or raise a claim to proceed with current preauthorization. + action: "" + - code: PAYR-1238 + message: Beneficiary is having an active preauthorization request at this hospital with reference number %s. Hence the request will not be processed. Kindly cancel the active preauthorization request or raise a claim to proceed with current preauthorization. + action: "" + - code: PAYR-1239 + message: Hospital configuration not found. Please contact support team. + action: "" + - code: PAYR-1240 + message: No details found for the requested procedures in the system. + action: "" + - code: PAYR-1241 + message: Invalid registration date received for case number %s. Hence the request will not be processed. + action: "" + - code: PAYR-1242 + message: Invalid registration date format received for case number %s. Hence the request will not be processed. + action: "" + - code: PAYR-1243 + message: Invalid admission date received for case number %s. Hence the request will not be processed. + action: "" + - code: PAYR-1244 + message: Invalid admission date format received for case number %s. Hence the request will not be processed. + action: "" + - code: PAYR-1245 + message: Rule failure. + action: The SHA HP sandbox sent this code as "Only one conservative procedure can be booked for a case", on an enhancement that added a second Conservative package. + - code: PAYR-1246 + message: Invalid payer id received as %s. Please try again with valid payer id. + action: "" + - code: PAYR-1247 + message: Payer details for payer id %s is not received from HCX for the request. Hence the request will not be processed. + action: "" + - code: PAYR-1248 + message: Invalid item code received as %s for item sequence %s case number %s. Please try again with valid data. + action: "" + - code: PAYR-1249 + message: Invalid item sequence received as %s for case number %s. Please try again with valid data. + action: "" + - code: PAYR-1250 + message: Requested policy %s is not listed. Please try again with valid policy code. + action: "" + - code: PAYR-1251 + message: No billable treatment plan received for case number %s. Please try again with valid treatment plan data. + action: "" + - code: PAYR-1252 + message: Case number %s is not in active preauthorization state with the current status of the case with the payer system is %s. Hence the preauthorization can not be cancelled. Only the cases with current status as preauthorization submitted or preauthorization approved can be cancelled. + action: "" + - code: PAYR-1253 + message: Case number %s is already cancelled. Hence the preauthorization can not be cancelled again. Only the cases with current status as preauthorization submitted or preauthorization approved can be cancelled. + action: "" + - code: PAYR-1254 + message: Response for STG Questionnaire id %s is mandatory for procedure code %s. Hence the preauthorization request will not be processed as the questionnaire response is not received for procedure code. + action: "" + - code: PAYR-1255 + message: Case number %s is already cancelled. Hence no preauthorization request will be accepted for this case number. New preauthorization request needs to be raised with new case/reference number to proceed further. + action: "" + - code: PAYR-1256 + message: Response for Authentication Consent Questionnaire is missing for case number %s. This must be sent if the biometric authentication for patient is not available. For new preauthorization request, either biometric authentication for patient or response for Authentication Consent questionnaire must be sent. Please check/update the insurance plan for the policy for the details of the questionnaire. Please adhere to the response of the coverage eligibility for auth-requirements purpose to check the mandatory documents to be attached with the request + action: "" + - code: PAYR-1257 + message: Payment is initiated for case number %s. Hence the preauthorization can not be cancelled again. Only the cases with current status as preauthorization submitted or preauthorization approved can be cancelled + action: "" + - code: PAYR-1258 + message: Payment is accomplished/cleared for case number %s. Hence the preauthorization can not be cancelled again. Only the cases with current status as preauthorization submitted or preauthorization approved can be cancelled + action: "" + - code: PAYR-1259 + message: DOB is missing for new born for the case number (%s) with correlation id as (%s) at (%s) + action: "" + - code: PAYR-1260 + message: DOB cannot be a future date for the case number (%s) with correlation id as (%s) at (%s) + action: "" + - code: PAYR-1261 + message: Invalid new born details for the case number (%s) with correlation id as (%s) at (%s) + action: "" + - code: PAYR-1262 + message: Gender is mandatory for the new born beneficiary + action: "" + - code: PAYR-1263 + message: Documents are mandatory for the new born beneficiary + action: "" + - code: PAYR-1264 + message: Documents are mandatory for the new born beneficiary + action: "" + - code: PAYR-1265 + message: Documents are mandatory for the new born beneficiary + action: "" + - code: PAYR-1266 + message: Documents are mandatory for the new born beneficiary + action: "" + - code: PAYR-1267 + message: Beneficiary is having an active preauthorization request for new born case at this hospital with reference number %s. Hence the request will not be processed. Kindly cancel the active preauthorization request or raise a claim to proceed with current preauthorization + action: "" + - code: PAYR-1268 + message: Beneficiary is having an active preauthorization request for new born case at %s. Hence the request will not be processed. Kindly inform %s to cancel the active preauthorization request or raise a claim to proceed with current preauthorization + action: "" + - code: PAYR-1269 + message: Date of birth received for new born beneficiary exceeds 6 years before the current date. New born cases can be raised only for the beneficiary whose date of birth is within 6 years of current date + action: "" + - code: PAYR-1270 + message: Item LM100 is not applicable for preauthorization request. This item is expected/mandated only during claim submission if the patient is discharged after/during surgery under LAMA/DAMA category for PMJAY cases. + action: "" + - code: PAYR-1271 + message: No value received for link id %s for Authentication Consent Questionnaire for preauthorization request. This must be sent if the biometric authentication for patient is not available. For new preauthorization request, either biometric authentication for patient or response for Authentication Consent questionnaire must be sent. Please check/update the insurance plan for the policy for the details of the questionnaire. Please adhere to the response of the coverage eligibility for auth-requirements purpose to check the mandatory documents to be attached with the request. + action: "" + - code: PAYR-1272 + message: Invalid biometric user token received. Please try again with valid valid biometric details of the beneficiary. For any issues with biometric, please try with Authentication Consent Questionnaire, details for which has been received in response for coverage eligibliity auth-requirements. + action: "" + - code: PAYR-1273 + message: No questionnaire found for the received selection. Please validate the questionnaire url from insurance plan/coverage auth-requirements response. + action: "" diff --git a/catalogue/openapi/nhcx/v1/nhcx-predetermination.yaml b/catalogue/openapi/nhcx/v1/nhcx-predetermination.yaml new file mode 100644 index 000000000..1ddbbf3d6 --- /dev/null +++ b/catalogue/openapi/nhcx/v1/nhcx-predetermination.yaml @@ -0,0 +1,478 @@ +# NHCX predetermination, from the NHCX package's Bruno folder apis/04-predetermination. +# +# Written by the package's system/build-ekadocs.mjs (make ekadocs); change the .bru +# requests there and port again rather than editing this file. +# +# Rules this file follows: catalogue/openapi/CONVENTIONS.md +openapi: 3.1.1 +info: + x-portal: + module: predetermination + label: Predetermination + position: 4 + title: NHCX predetermination + summary: A hospital planning a treatment can learn the benefit a payer would approve for it before the patient is admitted, and plan the admission and the patient's share of the cost around the answer. + description: |- + The Predetermination calls on the National Health Claims Exchange (NHCX): 2 operations, and 2 callbacks you host. + + A hospital planning a treatment can learn the benefit a payer would approve for it before the patient is admitted, and plan the admission and the patient's share of the cost around the answer. + + Guides that use these calls: [Predetermination, status and search](/docs/nhcx/v1/reference/fhir/predetermination-status-and-search). + version: nhcx-v1 + license: + name: MIT + identifier: MIT + contact: + name: NHCX sandbox + url: https://hcxsbx.abdm.gov.in + x-abdm-gateway: nhcx + x-abdm-module: predetermination + x-abdm-phase: 1 + x-abdm-roles: + - provider + - payer +x-abdm-sources: + - file: nhcx-package/apis/04-predetermination + role: upstream + hash: sha256:da5c7e0c3ac3d14b8cc2d9fec234a206902baec3deda955354e07fd1172554ad + note: The package's Bruno collection, one request per operation. + - file: nhcx-package/baseurl.yaml + role: upstream + hash: sha256:88515b7b29c6b349a131e016c80774436ea16a29738db743b4cc3a24cbd42453 + note: The sandbox and production hosts. +servers: + - url: https://apisbx.abdm.gov.in/hcx + description: Sandbox, NHCX exchange. + - url: https://apisprod.nha.gov.in/hcx + description: Production. +tags: + - name: Predetermination + description: A hospital planning a treatment can learn the benefit a payer would approve for it before the patient is admitted, and plan the admission and the patient's share of the cost around the answer. +security: + - bearerAuth: [] +paths: + /v1/predetermination/submit: + post: + operationId: predetermination_v1_predetermination_submit + x-abdm-atom: nhcx.endpoint.predetermination-submit + x-abdm-use-case: Predetermination + tags: + - Predetermination + summary: Predetermination request + description: |- + Provider asks the payer what it would approve for a proposed treatment before committing to a pre-authorisation. The bundle has the pre-authorisation's shape with `Claim.use` `predetermination`. This is use case B9. + + ### Business purpose + + A hospital planning a treatment can learn the benefit a payer would approve for it before the patient is admitted, and plan the admission and the patient's share of the cost around the answer. The payer gives an estimate only. Nothing is reserved, and the treatment still needs a pre-authorisation when it happens. + + ### When to use + + Before a planned admission, with a payer that has confirmed it supports predetermination. The exchange is specified but seldom used, so confirm support with the payer before building it. Send `x-hcx-status` `request.initiated` with a new correlation ID. The payer's answer, use case C11, arrives on `/v1/predetermination/on_submit`. + + ### Preconditions + + - The payer has confirmed that it answers predetermination requests. + - The bundle carries `Claim`, `Patient`, the provider and payer `Organization`, `Coverage`, `Practitioner` and `Procedure`, shaped as in the pre-authorisation chapters. + - `Claim.use` is `predetermination`, and `Claim.identifier[0].value` carries your predetermination reference. + - A valid session token, the recipient's certificate, and the bundle sealed as a JWE in `payload`, with the protected headers mirrored onto the wire. + - A fresh `x-hcx-api_call_id` and a new `x-hcx-correlation_id` for the cycle. + + ### Postconditions + + NHCX returns HTTP 202 with the acknowledgement and forwards the request asynchronously. The payer answers on `/v1/predetermination/on_submit` with a `ClaimResponse` whose `use` is `predetermination`, carrying the estimated approved benefit in `ClaimResponse.total` under category `benefit`. Nothing is reserved against the policy. + + ### Common mistakes + + - Building the exchange before the payer has confirmed it supports it. + - Leaving `Claim.use` as `preauthorization` when reusing the pre-authorisation builder. + - Treating the estimate as an approval and skipping the pre-authorisation at admission. + - Reusing a correlation ID from an earlier cycle, which NHCX refuses as a duplicate (`NHCX-1006`). + + ### Best practices + + - Reuse the pre-authorisation bundle builder and change only `Claim.use` and the reference. + - Store the answer against the planned case, labelled as an estimate. + - Key the request on its correlation ID, and host `/v1/error` so an undelivered request does not look like one still under review. + + ### Related scenario + + A hospital planning an elective admission asks the payer what it would approve for procedure `MG004A`. It builds the pre-authorisation bundle with `Claim.use` `predetermination` and reference `PD0000000001`, posts it here with a new correlation ID, and gets 202 back. The payer's `ClaimResponse` arrives later on `/v1/predetermination/on_submit` with an estimated benefit of 15500.00. The desk records it as an estimate, and raises a pre-authorisation when the patient is admitted. + + ### Specification + + Chapter [Predetermination, status and search](/docs/nhcx/v1/reference/fhir/predetermination-status-and-search) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - $ref: "#/components/parameters/XHcxSenderCode" + - $ref: "#/components/parameters/XHcxRecipientCode" + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxTimestamp" + - $ref: "#/components/parameters/XHcxStatus" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: + responses: + "202": + description: NHCX returns HTTP 202 with the acknowledgement and forwards the request asynchronously. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 19/03/2026 11:46:35:120 + api_call_id: "{{$guid}}" + correlation_id: "{{correlationId}}" + error: + code: "" + message: "" + /v1/predetermination/on_submit: + post: + operationId: predetermination_v1_predetermination_on_submit + x-abdm-atom: nhcx.endpoint.predetermination-on-submit + x-abdm-use-case: Predetermination + tags: + - Predetermination + summary: Predetermination callback + description: |- + Payer returns its estimate for a predetermination request to the provider: a `ClaimResponse` with `use` `predetermination` and the benefit it would approve. This is use case C11. + + ### Business purpose + + The callback carries the payer's view of what it would pay for a proposed treatment, so the hospital can plan the admission and counsel the patient before any money is committed. For the payer it is the record of the estimate it gave. + + ### When to use + + Called by the payer after it has assessed a request received on `/v1/predetermination/submit`, echoing that request's correlation ID with `x-hcx-status` `response.complete`. Only payers that have agreed to support predetermination send it. + + ### Preconditions + + - A predetermination request with this correlation ID exists in NHCX. A callback for an unknown one is refused with `NHCX-1010`. + - The bundle carries `ClaimResponse`, `Patient`, the payer and provider `Organization` and `Coverage`. + - `ClaimResponse.use` is `predetermination`, and the estimated approved benefit is in `ClaimResponse.total` under category `benefit`. + - The payer holds a valid session token and the provider's certificate, and seals the bundle for the provider. + - `x-hcx-correlation_id` echoes the request, `x-hcx-api_call_id` is new, and the sender and recipient codes are swapped. + + ### Postconditions + + NHCX returns HTTP 202 with the acknowledgement and delivers the callback to the provider, which must answer 202 with a receipt within 30 seconds. A delivery that is not acknowledged is retried five times, after which the exchange retires the correlation ID and reports the failure on `/v1/error`. The estimate reserves nothing against the policy. + + ### Common mistakes + + - Minting a new correlation ID instead of echoing the request's. + - Reading the estimate as an approval on the provider side. + - The provider answering with anything other than 202 and the receipt, which triggers retries. + + ### Best practices + + - Provider: acknowledge first, then decrypt, then store the estimate against the planned case. + - Provider: make the handler idempotent, since a missed receipt means the same message arrives again with the same `x-hcx-api_call_id`. + - Payer: explain the estimate in `ClaimResponse.disposition`, as the reference sample does. + + ### Related scenario + + A payer receives a predetermination request for procedure `MG004A` under reference `PD0000000001`. Its adjudicator assesses the proposed treatment, and the payer posts a `ClaimResponse` with `use` `predetermination`, outcome `complete` and a benefit total of 15500.00 to this endpoint on the request's correlation ID. The hospital's callback answers 202 within 30 seconds and files the figure as an estimate for the planned admission. + + ### Specification + + Chapter [Predetermination, status and search](/docs/nhcx/v1/reference/fhir/predetermination-status-and-search) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - $ref: "#/components/parameters/XHcxSenderCode" + - $ref: "#/components/parameters/XHcxRecipientCode" + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxTimestamp" + - name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: response.complete + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: + responses: + "202": + description: NHCX returns HTTP 202 with the acknowledgement and delivers the callback to the provider, which must answer 202 with a receipt within 30 seconds. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 19/03/2026 11:46:35:120 + api_call_id: "{{$guid}}" + correlation_id: "{{correlationId}}" + error: + code: "" + message: "" +webhooks: + v1_predetermination_submit: + post: + operationId: predetermination_webhook_v1_predetermination_submit + x-abdm-atom: nhcx.callback.predetermination-submit + x-abdm-triggered-by: predetermination_v1_predetermination_submit + x-abdm-use-case: Webhooks + tags: + - Predetermination + summary: Receive predetermination request + description: |- + Hosted by the payer. The exchange posts this message to the `endpoint_url` you registered, at `/v1/predetermination/submit`, with the headers and the sealed payload the sender posted. Answer HTTP 202 with the receipt first and process afterwards; [Receiving a callback](/docs/nhcx/v1/getting-started/receiving-a-callback) has the rules. + + Provider asks the payer what it would approve for a proposed treatment before committing to a pre-authorisation. The bundle has the pre-authorisation's shape with `Claim.use` `predetermination`. This is use case B9. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - $ref: "#/components/parameters/XHcxSenderCode" + - $ref: "#/components/parameters/XHcxRecipientCode" + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxTimestamp" + - $ref: "#/components/parameters/XHcxStatus" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: + responses: + "202": + description: Received. The receipt names the message it answers; the answer itself follows as a call of your own. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 04/09/2026 11:46:41:305 + api_call_id: + correlation_id: + result: + sender_code: 1000003538@hcx + recipient_code: 1000004446@hcx + entity_type: preauth + protocol_status: request.queued + error: + code: "" + message: "" + v1_predetermination_on_submit: + post: + operationId: predetermination_webhook_v1_predetermination_on_submit + x-abdm-atom: nhcx.callback.predetermination-on-submit + x-abdm-triggered-by: predetermination_v1_predetermination_on_submit + x-abdm-use-case: Webhooks + tags: + - Predetermination + summary: Receive predetermination callback + description: |- + Hosted by the provider. The exchange posts this message to the `endpoint_url` you registered, at `/v1/predetermination/on_submit`, with the headers and the sealed payload the sender posted. Answer HTTP 202 with the receipt first and process afterwards; [Receiving a callback](/docs/nhcx/v1/getting-started/receiving-a-callback) has the rules. + + Payer returns its estimate for a predetermination request to the provider: a `ClaimResponse` with `use` `predetermination` and the benefit it would approve. This is use case C11. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - $ref: "#/components/parameters/XHcxSenderCode" + - $ref: "#/components/parameters/XHcxRecipientCode" + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxTimestamp" + - name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: response.complete + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: + responses: + "202": + description: Received. The receipt names the message it answers; the answer itself follows as a call of your own. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 04/09/2026 11:46:41:305 + api_call_id: + correlation_id: + result: + sender_code: 1000003538@hcx + recipient_code: 1000004446@hcx + entity_type: preauth + protocol_status: request.queued + error: + code: "" + message: "" +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + description: "On every NHCX call, the token goes in a header called `bearer_auth`, with the word `Bearer` and a space in front. The sources are not unanimous: the authentication page and the FAQ both write the example as `Authorization`, and the notification endpoint uses `Authorization`. The safe course, and what the adapter does, is to send both headers with the same value." + parameters: + BearerAuth: + name: bearer_auth + in: header + required: true + description: It is `bearer_auth`, not `Authorization`, on NHCX's own endpoints. + schema: + type: string + example: Bearer + XHcxSenderCode: + name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: + XHcxRecipientCode: + name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: + XHcxApiCallId: + name: x-hcx-api_call_id + in: header + required: true + description: Fresh on every message, including responses. Mandatory on the envelope. + schema: + type: string + example: + XHcxCorrelationId: + name: x-hcx-correlation_id + in: header + required: true + description: The thread. See the rule below. Mandatory on the envelope. + schema: + type: string + example: + XHcxTimestamp: + name: x-hcx-timestamp + in: header + required: true + description: See the format note below. Mandatory on the envelope. + schema: + type: string + example: + XHcxStatus: + name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: request.initiated +x-abdm-errors: + notes: "Codes any exchange call can meet are recorded once, in the [Other](/docs/nhcx/v1/api/other) specification: the gateway's NHCX- codes, the standard payer codes, and the reference payer's structure and transport codes. The reference payer's other codes sit with the exchange they reject: coverage eligibility, preauthorisation, claim and insurance plan. [Reading error codes](/docs/nhcx/v1/reference/error-code-guide) explains the code spaces." diff --git a/catalogue/openapi/nhcx/v1/nhcx-registry.yaml b/catalogue/openapi/nhcx/v1/nhcx-registry.yaml new file mode 100644 index 000000000..38e337b64 --- /dev/null +++ b/catalogue/openapi/nhcx/v1/nhcx-registry.yaml @@ -0,0 +1,2232 @@ +# NHCX participant registry, from the NHCX package's Bruno folder apis/10-registry. +# +# Written by the package's system/build-ekadocs.mjs (make ekadocs); change the .bru +# requests there and port again rather than editing this file. +# +# Rules this file follows: catalogue/openapi/CONVENTIONS.md +openapi: 3.1.1 +info: + x-portal: + module: registry + label: Participant registry + position: 10 + title: NHCX participant registry + summary: Every NHCX API call, whether a registry lookup, a certificate fetch or a claim submission, is rejected unless it carries a valid Bearer token, so this is the first call any integration makes and... + description: |- + The Participant registry calls on the National Health Claims Exchange (NHCX): 23 operations. + + Every NHCX API call, whether a registry lookup, a certificate fetch or a claim submission, is rejected unless it carries a valid Bearer token, so this is the first call any integration makes and the first thing to check when a working integration starts failing. + + Guides that use these calls: [Creating and updating a participant](/docs/nhcx/v1/getting-started/creating-and-updating-a-participant), [Finding participants and policies](/docs/nhcx/v1/getting-started/finding-participants-and-policies), [Fetching a recipient certificate](/docs/nhcx/v1/getting-started/fetching-a-recipient-certificate), [Get your sandbox credentials](/docs/nhcx/v1/getting-started/get-your-sandbox-credentials), [Quickstart](/docs/nhcx/v1/getting-started/quickstart), [The recipient cannot decrypt your message](/docs/nhcx/v1/troubleshooting/the-recipient-cannot-decrypt). + version: nhcx-v1 + license: + name: MIT + identifier: MIT + contact: + name: NHCX sandbox + url: https://hcxsbx.abdm.gov.in + x-abdm-gateway: nhcx + x-abdm-module: registry + x-abdm-phase: 1 + x-abdm-roles: + - provider + - payer +x-abdm-sources: + - file: nhcx-package/apis/10-registry + role: upstream + hash: sha256:24a781be25eb64996be9a7eb98c1f941a9dc74485129740b4831edcc54c55df0 + note: The package's Bruno collection, one request per operation. + - file: nhcx-package/baseurl.yaml + role: upstream + hash: sha256:88515b7b29c6b349a131e016c80774436ea16a29738db743b4cc3a24cbd42453 + note: The sandbox and production hosts. +servers: + - url: https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice + description: Sandbox, Participant service. + - url: https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice + description: Production. +tags: + - name: Participant registry + description: Every NHCX API call, whether a registry lookup, a certificate fetch or a claim submission, is rejected unless it carries a valid Bearer token, so this is the first call any integration makes and the first thing to check when a working integration starts failing. +security: + - bearerAuth: [] +paths: + /get/session: + post: + operationId: registry_get_session + x-abdm-atom: nhcx.endpoint.get-session + x-abdm-use-case: Participant registry + tags: + - Participant registry + summary: Get session token + description: |- + Exchanges the participant's client_id and client_secret (OAuth 2.0 client credentials) for a Bearer access_token valid for 1200 seconds. + + ### Business purpose + + Every NHCX API call, whether a registry lookup, a certificate fetch or a claim submission, is rejected unless it carries a valid Bearer token, so this is the first call any integration makes and the first thing to check when a working integration starts failing. It answers the question of who is calling the gateway. It is deliberately separate from payload confidentiality: a request can be perfectly encrypted and still fail with 401, and vice versa. + + ### When to use + + Call it at start-up and whenever the cached token is close to expiry. The Integration Handbook documents it as POST /get/session on host apisbx.abdm.gov.in with Content-Type application/x-www-form-urlencoded and body client_id=&client_secret=&grant_type=client_credentials. The response carries access_token, expires_in 1200 and token_type Bearer. Both sandbox-exit checklists list /get/session as the auth-token API. Note that the FAQ instead lists https://dev.abdm.gov.in/api/hiecm/gateway/v3/sessions as the Session API, and the OpenAPI entry (operationId getSession) calls the operation internal and returns ParticipantSessionResponse with a single accessToken field; confirm the current host with your onboarding contact. There is no refresh token: renewal is simply another client-credentials call. + + ### Preconditions + + - client_id and client_secret issued at the end of onboarding; client_secret is generated by the NHCX instance, stored encrypted and never returned by any registry API, so a lost secret must be reissued. + - Credentials scoped to the right environment; sandbox credentials do not work against production and vice versa. + - Content-Type application/x-www-form-urlencoded with grant_type=client_credentials fixed; the two secrets are the only variables. + - No Bearer token is needed for this call itself. + + ### Postconditions + + HTTP 200 with { access_token, expires_in: 1200, token_type: Bearer }. The access_token is a JWT that should be treated as opaque; place it in the Authorization (bearer_auth) header as Bearer on every subsequent call. Its lifetime is 1200 seconds (20 minutes); after that any call returns 401. The OpenAPI schema names the field accessToken and omits expiry, so read whichever key is present and assume 1200 seconds when expires_in is absent. A 400 indicates a malformed body. Nothing asynchronous follows. + + ### Common mistakes + + - Not implementing automatic refresh, so calls that worked minutes ago start returning 401 or 401 Unauthorized - Sender is not authorized to execute the operation once 20 minutes pass. + - Sending the token without the Bearer prefix in bearer_auth, which also produces a plain 401. + - Using the wrong Content-Type (JSON instead of form-urlencoded), omitting grant_type=client_credentials, or misspelling a credential field, which yields 400. + - Minting a fresh token for every transaction instead of caching it. + - Continuing to use a cached client_secret after the instance rotated it; every token minted from the old secret stops working. + - Pairing a sandbox token with the production gateway. + + ### Best practices + + - Cache the token in memory keyed by environment and refresh proactively at roughly 80 to 90 percent of the lifetime computed from the expires_in actually received. + - Serialise refresh behind a lock so concurrent workers do not fire simultaneous token requests. + - On any 401, discard the cached token, mint a new one and replay the original request exactly once; if the second attempt also fails, stop and alert, since the credentials are wrong or revoked. + - Never log the access_token or client_secret; log the expiry timestamp instead. + - Store secrets so they can be rotated without a code deploy. + - The token is validated by ABDM, so a 401 on any NHCX call carries no hint that expiry is the cause; treat 401 as refresh-and-retry first. + + ### Related scenario + + At 09:00 a hospital's claims engine starts and POSTs its client_id and client_secret to /get/session, receiving an access_token with expires_in 1200. It caches the token and immediately calls /fetch/certs for the payer it will submit to. At 09:17 a background timer renews the token before the 20-minute mark, so the /v1/preauth/submit sent at 09:21 carries a fresh Bearer header. Later a worker receives a 401 after a network stall; it drops the cached token, calls /get/session once more, replays the request and succeeds. Had the second attempt also failed, the engine would have alerted operations rather than looping. + + ### Specification + + Chapter [Base URLs](/docs/nhcx/v1/getting-started/base-urls) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + _contentType: + type: string + client_id: + type: string + client_secret: + type: string + grant_type: + type: string + example: + _contentType: application/x-www-form-urlencoded + client_id: + client_secret: + grant_type: client_credentials + responses: + "200": + description: "HTTP 200 with { access_token, expires_in: 1200, token_type: Bearer }." + content: + application/json: + schema: + type: object + properties: + access_token: + type: string + expires_in: + type: integer + token_type: + type: string + example: + access_token: eyJhbGciOiJSUzI1NiIs... + expires_in: 1200 + token_type: Bearer + /participant/update: + post: + operationId: registry_participant_update + x-abdm-atom: nhcx.endpoint.participant-update + x-abdm-use-case: Participant registry + tags: + - Participant registry + summary: Participant update (v1) + description: |- + Updates a participant's registry record; participant_code and roles are mandatory, every other field (certificate, endpoint, contacts, status) is optional. + + ### Business purpose + + Participant details change over the life of an integration: callback endpoints move, encryption certificates are rotated annually, contact numbers and payment details change. The registry is the source of truth that the gateway routes from, so those changes must land there, not just in the participant's own configuration. This v1 update lets an organisation amend any attribute of its full record in one synchronous call, and the sandbox onboarding document names it as the way to update the bridge URL, the encryption certificate or any other attribute. + + ### When to use + + Use it after registration whenever a registry attribute must change. The FAQ lists the sandbox Update Participant URL as https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/participant/update, while production onboarding documents the narrower /v2/participant/update plus /update/validate for certificate and bridge changes. It is a plain JSON registry call outside the JWE protocol, with no workflow or x-hcx-status codes. For a certificate-only change without passcode validation, /v2/update/cert is the documented shortcut. + + ### Preconditions + + - The participant already exists and you hold its participant_code. + - Bearer token with the Bearer prefix in bearer_auth, plus Accept and Content-Type: application/json. + - Body per ParticipantUpdateBody: participant_code and roles are the only required fields; participant_name, scheme_code, linked_registry_codes, address, contact fields, status, signing_cert_path, encryption_cert, endpoint_url and payment_details are optional. + - If updating encryption_cert, the new certificate is Base64-encoded and its private key is already deployed on the callback host. + - Linked registry codes must validate. + + ### Postconditions + + HTTP 200 with a string body (the OpenAPI declares string; the sandbox onboarding document shows the participant code echoed back, for example 100001@sbx). The registry record now carries the amended values, and because the gateway reads endpoint_url and encryption_cert from the registry on every leg, callback routing and counterparties' certificate fetches reflect the change from the next call onwards, subject to their 24-hour certificate cache. No asynchronous callback follows. Failures use the 400/404/500 ErrorResponse envelope. + + ### Common mistakes + + - Omitting roles on a partial update; it is required even when the change has nothing to do with roles, and its absence yields a 400. + - Copying v2 field names (participantcode, encryptioncert, endpointurl) into this snake_case body. + - Setting an endpoint_url that uses an IP address or port, or a server outside India, which breaks callback delivery at go-live. + - Rotating the certificate in the registry before the new private key is live on the callback host, so inbound callbacks can no longer be decrypted. + - Missing the Accept header or the Bearer prefix. + + ### Best practices + + - Read the current record with /participant/search first and send the full intended state, so a partial body does not unintentionally blank optional fields. + - Rotate certificates in two phases and keep the old private key for at least 24 hours, the documented certificate cache TTL. + - Confirm callback reachability (domain name, India-based host, NAT IPs 3.109.99.210, 13.126.152.0 and 13.200.129.223 whitelisted) before pointing endpoint_url at a new host. + - Log the change with who requested it; registry changes affect where encrypted health data is delivered. + + ### Related scenario + + A hospital migrates its claims callback service to a new domain. Before touching the registry the team deploys the service, verifies the NHCX NAT IPs are whitelisted and copies the existing PKCS8 private key across. They fetch a Bearer token via /get/session, read the current record with /participant/search, and call /participant/update with participant_code, roles and the new endpoint_url. The registry returns 200. The next /v1/preauth/on_submit callback from the payer arrives at the new domain and is acknowledged with 202 within 30 seconds. + + ### Specification + + Chapter [Your certificate](/docs/nhcx/v1/getting-started/your-certificate) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + participant_code: + type: string + participant_name: + type: string + scheme_code: + type: string + roles: + type: array + items: + type: string + primaryEmail: + type: string + phone: + type: array + items: + type: string + primaryMobile: + type: string + endpoint_url: + type: string + signing_cert_path: + type: string + encryption_cert: + type: string + example: + participant_code: + participant_name: Test Hospital + scheme_code: PMJAY + roles: + - "10001" + primaryEmail: integration@hospital.example + phone: + - "01123456789" + primaryMobile: "9876543210" + endpoint_url: https://nhcx.hospital.example + signing_cert_path: "" + encryption_cert: + responses: + "200": + description: HTTP 200 with a string body (the OpenAPI declares string; the sandbox onboarding document shows the participant code echoed back, for example 100001@sbx). + content: + application/json: + schema: + type: object + properties: + _contentType: + type: string + _body: + type: string + example: + _contentType: string + _body: 100001@sbx + /v2/participant/update: + post: + operationId: registry_v2_participant_update + x-abdm-atom: nhcx.endpoint.v2-participant-update + x-abdm-use-case: Participant registry + tags: + - Participant registry + summary: Participant certificate and bridge update (v2) + description: |- + Stages a change to a participant encryption certificate and/or endpoint URL; returns a transactionid for passcode confirmation via /update/validate. + + ### Business purpose + + Exactly two operational values rotate over a participant's life: the public encryption certificate that counterparties encrypt claims data with, and the endpoint (bridge) URL that the gateway delivers callbacks to. Both are security-sensitive, so the v2 update takes only those fields and gates the change behind an SMS passcode to the registered mobile number. It is step 3 of the production onboarding sequence, where a newly confirmed participant publishes its certificate for the first time, and the documented route for annual key rotation thereafter. + + ### When to use + + Use it immediately after creation confirmation (/validate) to upload encryptioncert and endpointurl, and again whenever either value changes; always follow with GET /update/validate within 24 hours. The production URL is https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice/v2/participant/update. If only the certificate changes and passcode validation is not wanted, /v2/update/cert is the documented alternative. This is a synchronous JSON registry call with no workflow or x-hcx-status codes. + + ### Preconditions + + - participantcode is a valid code already registered in NHCX and its creation confirmation has been completed. + - The certificate (public key) is Base64-encoded; the update validation explicitly requires this. + - Bearer token in bearer_auth with the Bearer prefix, Accept and Content-Type: application/json. + - ParticipantCertUpdateRequest: participantcode required; encryptioncert and endpointurl optional (the base URL). + - The new private key is already deployed on the callback host so decryption works the moment the change goes live. + + ### Postconditions + + HTTP 200 with ParticipantCertUpdateResp: participant_code, status and transactionid. A passcode is sent to the registered mobile number; the pair is valid for 24 hours and each new trigger replaces it. The change is not live until GET /update/validate succeeds, after which /fetch/certs returns the new certificate and callbacks go to the new endpoint. Counterparties may serve a cached copy for up to 24 hours. Errors use the 400/404/500 ErrorResponse envelope. + + ### Common mistakes + + - Calling it before creation has been confirmed with /validate; the validations require a confirmed participant code. + - Sending the raw PEM instead of the Base64-encoded certificate. + - Using v1 field names (participant_code, encryption_cert, endpoint_url) in this flattened lowercase body. + - Treating the 200 as completion and skipping /update/validate, so the old certificate stays live. + - Re-triggering the update while a passcode is pending, invalidating the earlier transaction id. + - Losing the transaction id, which forces the update to be issued again. + + ### Best practices + + - Prepare the new key pair, deploy the PKCS8 private key to the callback host and only then publish the certificate. + - Keep the previous private key available for at least 24 hours after validation to decrypt callbacks encrypted against a cached certificate. + - Persist transactionid with its 24-hour expiry and complete /update/validate promptly. + - Rotate encryption keys once a year, matching the 365-day validity of the self-signed certificate. + - Verify the new endpointurl is a domain name on an India-based server with the NHCX NAT IPs whitelisted before submitting. + + ### Related scenario + + A TPA has just confirmed its production participant with /validate. Its engineers generate a 2048-bit RSA key, a 365-day self-signed X.509 certificate, Base64-encode it and deploy the private key to the callback host. They call /v2/participant/update with participantcode, encryptioncert and endpointurl; the response returns status and a transactionid, and the registered phone receives a passcode. After GET /update/validate succeeds, the first provider to call /fetch/certs for the TPA receives the new certificate and can encrypt a pre-authorisation for it. + + ### Specification + + Chapter [Your certificate](/docs/nhcx/v1/getting-started/your-certificate) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + participantcode: + type: string + encryptioncert: + type: string + endpointurl: + type: string + example: + participantcode: XXXXX7583@hcx + encryptioncert: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t... + endpointurl: https://nhcx.demotpa.example.in + responses: + "200": + description: "HTTP 200 with ParticipantCertUpdateResp: participant_code, status and transactionid." + content: + application/json: + schema: + type: object + properties: + participant_code: + type: string + status: + type: string + transactionid: + type: string + example: + participant_code: XXXXX7583@hcx + status: Update initiated + transactionid: 1vouv8tlz2tnl-1fpspjhwj07c6 + /participant/search: + post: + operationId: registry_participant_search + x-abdm-atom: nhcx.endpoint.participant-search + x-abdm-use-case: Participant registry + tags: + - Participant registry + summary: Participant search + description: |- + Reads a participant's full registry record by participant_code, including roles, status, encryption_cert and endpoint_url. + + ### Business purpose + + Before addressing a transaction to a counterparty, an integrator needs to know that the participant exists, is active, holds the expected role and publishes an encryption certificate and callback endpoint. The registry is the phone book of NHCX, and this call is the direct lookup by code. Providers use it to inspect a payer they have selected; payers use it to confirm the sender of an inbound request; everyone uses it to verify their own record after an update. + + ### When to use + + Call it once a participant_code is known, typically after /fetch/participants/list has produced candidates, or before building the first JWE for a new recipient. It is also the natural post-update check after /participant/update, /v2/participant/update or /v2/update/cert. It is a synchronous JSON registry call with no workflow or x-hcx-status codes. /participant/details takes the same body and returns the same response; the OpenAPI identifies it only as the v2 variant. + + ### Preconditions + + - A Bearer token from /get/session in bearer_auth with the Bearer prefix; Accept and Content-Type: application/json. + - The target's participant_code in xxxxx@hcx (or @sbx) form, exactly the value later placed in x-hcx-recipient_code. + - Sandbox base https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/participant/search; production under https://apis.abdm.gov.in/pmjay/hcx. + + ### Postconditions + + HTTP 200 with ParticipantSearchResponse: timestamp (Unix timestamp when the request is sent) and participants, an array of full participant records with participant_code, linked_registry_codes, participant_name, scheme_code, roles, address, primaryEmail, additionalEmail, phone, primaryMobile, additionalMobile, status, signing_cert_path, encryption_cert, endpoint_url and payment_details. No state changes and no callback. An unknown code returns 404 with the ErrorResponse envelope; 400 and 500 are the other documented outcomes. + + ### Common mistakes + + - Passing participantid or participantcode instead of the snake_case participant_code this body requires. + - Assuming a record in the registry means the participant can transact; status must be Active, and NHCX-1003 (receiver not registered) still results if the code is wrong or inactive. + - Reading encryption_cert as the certificate content when it is documented as a URI or file path to the certificate; use /fetch/certs to obtain the key material. + - Forgetting the Accept header, which causes rejection before business logic. + - Sending an expired token and misreading the flat 401. + + ### Best practices + + - Cache the record for the session and re-read it when a transport error (NHCX-1001) or decrypt failure (PAYR-1001/PAYR-1002) suggests stale routing or key data. + - Check roles and status before selecting the counterparty for x-hcx-recipient_code. + - Call it against your own code after every registry update to confirm the change is live. + - Never log payment_details from the response. + - Treat the participants array as possibly empty and handle 404 gracefully. + + ### Related scenario + + A hospital's TPA desk has selected a payer code from /fetch/participants/list for a PMJAY patient. Before submitting anything the integration calls /participant/search with that participant_code and receives the payer's record: roles include payer, status is Active, scheme_code matches, and endpoint_url and encryption_cert are populated. The engine stores the code as the payerId that will become x-hcx-recipient_code, calls /fetch/certs to obtain the actual certificate, and then encrypts and sends /v1/coverageeligibility/check. + + ### Specification + + Chapter [Creating and updating a participant](/docs/nhcx/v1/getting-started/creating-and-updating-a-participant) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + participant_code: + type: string + example: + participant_code: 1518@hcx + responses: + "200": + description: "HTTP 200 with ParticipantSearchResponse: timestamp (Unix timestamp when the request is sent) and participants, an array of full participant records with participant_code, linked_registry_codes, participant_name, scheme_code, roles, address, primaryEmail, additionalEmail, phone, primaryMobile, additionalMobile, status, signing_cert_path, encryption_cert, endpoint_url and payment_details." + content: + application/json: + schema: + type: object + properties: + timestamp: + type: integer + participants: + type: array + items: + type: object + properties: + participant_code: + type: string + participant_name: + type: string + linked_registry_codes: + type: array + items: + type: string + scheme_code: + type: string + roles: + type: array + items: + type: string + status: + type: array + items: + type: string + primaryEmail: + type: string + primaryMobile: + type: string + encryption_cert: + type: string + endpoint_url: + type: string + example: + timestamp: 1716204567358 + participants: + - participant_code: 1518@hcx + participant_name: Demo Insurance Company + linked_registry_codes: + - 125@payer + scheme_code: default + roles: + - payer + status: + - Active + primaryEmail: claims@demoinsurer.example.in + primaryMobile: "9800000001" + encryption_cert: https://registry.example.in/certs/1518.pem + endpoint_url: https://nhcx.demoinsurer.example.in + /participant/details: + post: + operationId: registry_participant_details + x-abdm-atom: nhcx.endpoint.participant-details + x-abdm-use-case: Participant registry + tags: + - Participant registry + summary: Participant details (v2 search) + description: |- + V2 variant of participant search: takes participant_code and returns the matching full registry records. + + ### Business purpose + + This is the second of two endpoints that read a single participant by code. It exists as the v2 generation of the registry lookup (operationId participantV2SearchPost) and serves the same business need as /participant/search: confirming that a counterparty exists, is active, holds the expected role and publishes an encryption certificate and callback endpoint before any encrypted transaction is addressed to it. + + ### When to use + + Use it wherever /participant/search would be used: after payer discovery via /fetch/participants/list, before the first JWE to a new recipient, or to verify your own record after an update. The OpenAPI gives both endpoints the identical description and the same ParticipantSearchReq and ParticipantSearchResponse schemas, and documents no behavioural difference beyond the operationId; the chapter advises treating them as interchangeable unless your HCX instance says otherwise. Synchronous JSON, no workflow or x-hcx-status codes. + + ### Preconditions + + - Bearer token from /get/session in bearer_auth with the Bearer prefix; Accept and Content-Type: application/json. + - Body per ParticipantSearchReq: participant_code (string, required) in xxxxx@hcx or @sbx form. + - Served under the participanthcxservice prefix on the environment gateway base. + + ### Postconditions + + HTTP 200 with ParticipantSearchResponse: timestamp and a participants array of full participant records (participant_code, linked_registry_codes, participant_name, scheme_code, roles, address, contact fields, status, signing_cert_path, encryption_cert, endpoint_url, payment_details). Read-only; nothing changes and no callback follows. 400, 404 and 500 return the ErrorResponse envelope with timestamp and error code, message and trace. + + ### Common mistakes + + - Expecting a different or richer response than /participant/search; the documented schemas are identical. + - Using participantcode or participantid instead of participant_code. + - Treating encryption_cert (a URI or file path in the schema) as the PEM itself instead of calling /fetch/certs. + - Omitting the Accept header or the Bearer prefix. + - Hard-coding one of the two lookup paths without a fallback when the instance serves only the other. + + ### Best practices + + - Wrap both lookup endpoints behind one client function so the path can be switched by configuration. + - Check status and roles before choosing a recipient code. + - Cache the record and refresh on routing or decryption errors rather than on every transaction. + - Do not log payment_details. + + ### Related scenario + + A payer's inbound gateway receives a /v1/claim/submit whose protected header names x-hcx-sender_code 100001@sbx. Before decrypting and processing, its integration calls /participant/details with that participant_code to confirm the sender is a registered provider with status Active and to record participant_name for the adjudication file. The claim is then decrypted with the payer's private key and passed to the claims team, whose decision goes back on /v1/claim/on_submit. + + ### Specification + + Chapter [Creating and updating a participant](/docs/nhcx/v1/getting-started/creating-and-updating-a-participant) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + participant_code: + type: string + example: + participant_code: 100001@sbx + responses: + "200": + description: "HTTP 200 with ParticipantSearchResponse: timestamp and a participants array of full participant records (participant_code, linked_registry_codes, participant_name, scheme_code, roles, address, contact fields, status, signing_cert_path, encryption_cert, endpoint_url, payment_details)." + content: + application/json: + schema: + type: object + properties: + timestamp: + type: integer + participants: + type: array + items: + type: object + properties: + participant_code: + type: string + participant_name: + type: string + linked_registry_codes: + type: array + items: + type: string + roles: + type: array + items: + type: string + status: + type: array + items: + type: string + primaryEmail: + type: string + primaryMobile: + type: string + encryption_cert: + type: string + endpoint_url: + type: string + example: + timestamp: 1716204567358 + participants: + - participant_code: 100001@sbx + participant_name: Demo Multispeciality Hospital + linked_registry_codes: + - IN2910001234@hfr + roles: + - provider + status: + - Active + primaryEmail: claims@demohospital.example.in + primaryMobile: "9800000000" + encryption_cert: https://registry.example.in/certs/100001.pem + endpoint_url: https://nhcx.demohospital.example.in + /fetch/participants/list: + post: + operationId: registry_fetch_participants_list + x-abdm-atom: nhcx.endpoint.fetch-participants-list + x-abdm-use-case: Participant registry + tags: + - Participant registry + summary: Fetch participants list + description: |- + Payer discovery: lists participants filtered by role, registration date window and optional entity type; the first step of the cashless workflow. + + ### Business purpose + + A patient is not cashless merely by having insurance. The hospital must first discover which payer to deal with, and that payer's participantcode becomes the payerId used for NHCX routing and the x-hcx-recipient_code header. This endpoint is the discovery workhorse: it returns every participant of a given role registered within a date window, which is how a hospital builds its payer picker and how a payer sees the providers on the exchange. It is item 1 of the provider sandbox-exit checklist. + + ### When to use + + Call it at the very start of the handbook's fixed operational order: payer search, payer selection, policy discovery, policy cache normalisation, effective payer resolution, InsurancePlan and benefit retrieval, optional eligibility verification, then preauth submission. Refresh the list periodically rather than per patient. Sandbox URL https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/fetch/participants/list. Synchronous JSON; no workflow or x-hcx-status codes. + + ### Preconditions + + - Bearer token in bearer_auth with the Bearer prefix; Accept and Content-Type: application/json. + - FetchParticipantRequest: role (PAYER, PROVIDER or TPA), fromdate and todate in dd/MM/yyyy format only, all required; entitytype optional (for example Gov). + - A date window wide enough to cover the registration dates of the participants you expect; the handbook example spans 01/04/2021 to 20/03/2026. + + ### Postconditions + + HTTP 200 with ParticipantListResponse: a participantdetails array of ParticipantDetails with participantcode, participantname, address and state. The handbook notes the response shape is not stable and the documented search logic normalises participantdetails, participants or a raw array. No state changes and no callback. 400, 404 and 500 carry the ErrorResponse envelope. In the sandbox, the dummy payer 1000003538@hcx is the counterparty you will find and use. + + ### Common mistakes + + - Supplying dates in ISO or any format other than dd/MM/yyyy. + - Using a date window that is too narrow, which silently drops payers that registered outside it. + - Expecting a name filter; there is none, so text search and GOVT versus PRIVATE classification (from entitytype) must be done client-side. + - Being misled by the OpenAPI description, which is copy-pasted from the update API; the request schema defines the real behaviour. + - Parsing only participantdetails and breaking when the instance returns participants or a raw array. + - Missing Accept header or Bearer prefix. + + ### Best practices + + - Fetch once with a wide window, cache the list, and filter by name and scheme type locally, as the handbook's internal payers endpoint does. + - Accept all three response shapes defensively. + - Follow selection with /participant/search or /participant/details to confirm status and roles, and /fetch/certs to obtain the certificate before encrypting. + - Remove any hard-coded reference to 1000003538@hcx at go-live; production counterparties are resolved from this call. + - Refresh the cached list on a schedule so newly registered payers appear. + + ### Related scenario + + A hospital's admission desk opens the cashless screen for a patient holding a government scheme card. The integration has already called /fetch/participants/list with role PAYER, a window from 01/04/2021 to today and entitytype Gov, and cached the result. The desk types the scheme name, the client filters the cached list, and the operator selects the state health agency's participantcode. The engine then calls /participant/get/policies to link the patient's policy, /fetch/certs for the payer certificate, and submits /v1/insuranceplan/request followed by /v1/preauth/submit. + + ### Specification + + Chapter [Creating and updating a participant](/docs/nhcx/v1/getting-started/creating-and-updating-a-participant) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + role: + type: string + fromdate: + type: string + todate: + type: string + entitytype: + type: string + example: + role: PAYER + fromdate: 01/04/2021 + todate: 20/03/2026 + entitytype: Gov + responses: + "200": + description: "HTTP 200 with ParticipantListResponse: a participantdetails array of ParticipantDetails with participantcode, participantname, address and state." + content: + application/json: + schema: + type: object + properties: + participantdetails: + type: array + items: + type: object + properties: + participantcode: + type: string + participantname: + type: string + address: + type: string + state: + type: string + example: + participantdetails: + - participantcode: 1000003538@hcx + participantname: NHCX Dummy Payer + address: New Delhi + state: Delhi + - participantcode: 1518@hcx + participantname: Demo Insurance Company + address: Bengaluru + state: Karnataka + /fetch/certs: + post: + operationId: registry_fetch_certs + x-abdm-atom: nhcx.endpoint.fetch-certs + x-abdm-use-case: Participant registry + tags: + - Participant registry + summary: Fetch certificate + description: |- + Returns a participant's public encryption certificate (PEM X.509 or SPKI key) by participantid; cache it for 24 hours and use it to build the JWE. + + ### Business purpose + + Every NHCX payload is encrypted end-to-end for exactly one recipient so that even the exchange cannot read the clinical and financial content it routes. That guarantee rests on each participant publishing a public certificate in the registry at onboarding. This call is how a sender obtains a counterparty's certificate before encrypting a request or a callback for it. It is item 3 of both sandbox-exit checklists and the endpoint the Integration Handbook names in its encryption steps. + + ### When to use + + Call it before encrypting the first message to a recipient and whenever the 24-hour cache entry for that participantid expires or is evicted after a decrypt or encrypt failure. Providers fetch the payer's certificate before /v1/coverageeligibility/check, /v1/preauth/submit and /v1/claim/submit; payers fetch the provider's certificate before encrypting on_* callbacks. Handbook call: POST /fetch/certs on host apisbx.abdm.gov.in/pmjay/sbxhcx with bearer_auth Bearer . Synchronous; no workflow or x-hcx-status codes. + + ### Preconditions + + - Bearer token from /get/session in bearer_auth with the Bearer prefix; Content-Type: application/json (add Accept: application/json per the common-mistakes guidance). + - ParticipantCertRequest with the single required field participantid, the recipient's participant code in @hcx form, identical to the value you will place in x-hcx-recipient_code. + - The recipient has completed onboarding with a certificate registered (mandatory at creation). + + ### Postconditions + + HTTP 200 with a string body containing a PEM-encoded X.509 certificate or an SPKI public key, as uploaded by that participant. Import X.509 first and fall back to SPKI (keys under roughly 400 bytes are typically SPKI), then use the key with RSA-OAEP-256 for alg and A256GCM for enc. Nothing changes in the registry and no callback follows. 400, 404 and 500 return the ErrorResponse envelope; an unregistered code is a 404 here and NHCX-1003 at the gateway. + + ### Common mistakes + + - Fetching the certificate before every request instead of caching for 24 hours, adding a round trip to the critical path of every claim. + - Assuming the response is always a full X.509 certificate and failing when a participant uploaded a bare SPKI key. + - Encrypting with the sender's own certificate instead of the recipient's; the recipient's private key then cannot open it, surfacing as PAYR-1001 decrypt errors. + - Passing participant_code or participantcode instead of participantid. + - Serving a stale cached certificate after the counterparty rotated its key; PAYR-1001 or PAYR-1002 is the signal to evict and re-fetch. + - Sending the token without the Bearer prefix or omitting Accept. + + ### Best practices + + - Cache per participantid with a 24-hour TTL, plus a negative path that evicts and re-fetches on encrypt or decrypt failures. + - Implement the import routine as X.509 first, SPKI fallback, treating the 400-byte size hint as diagnostic rather than a hard branch. + - Use the documented algorithm pair RSA-OAEP-256 and A256GCM. + - Re-fetch from the production registry at go-live; sandbox certificates do not carry over. + - Expect annual key rotation by counterparties; the 24-hour cache bounds exposure to a rotation you were not told about. + + ### Related scenario + + A hospital is about to send its first pre-authorisation to payer 1518@hcx. The engine checks its certificate cache, finds no entry, and calls /fetch/certs with participantid 1518@hcx and a Bearer token. The response is a PEM X.509 certificate, which is parsed and cached for 24 hours. The engine builds the JWE protected header with x-hcx-sender_code, x-hcx-recipient_code 1518@hcx and the other x-hcx headers, encrypts the FHIR bundle with RSA-OAEP-256 and A256GCM using the fetched key, and POSTs to /v1/preauth/submit. Later that week the payer rotates its certificate; a PAYR-1001 on the next submission triggers eviction and a fresh fetch. + + ### Specification + + Chapter [Finding participants and policies](/docs/nhcx/v1/getting-started/finding-participants-and-policies) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + participantid: + type: string + example: + participantid: 1518@hcx + responses: + "200": + description: HTTP 200 with a string body containing a PEM-encoded X.509 certificate or an SPKI public key, as uploaded by that participant. + content: + application/json: + schema: + type: object + properties: + _contentType: + type: string + _body: + type: string + example: + _contentType: string + _body: |- + -----BEGIN CERTIFICATE----- + MIIDdzCCAl+gAwIBAgIEbXq... + -----END CERTIFICATE----- + /fetch/certs/path: + post: + operationId: registry_fetch_certs_path + x-abdm-use-case: Participant registry + tags: + - Participant registry + summary: Fetch certificate path + description: |- + Companion to /fetch/certs: takes the same participantid body and returns a string described as the participant's certificate path. + + ### Business purpose + + The registry stores a participant's encryption certificate as a URI or file path in the encryption_cert field, and this endpoint exposes that reference for a given participant. It exists alongside /fetch/certs, which the Integration Handbook names as the call to use when obtaining key material for encryption. Both serve the same underlying need, resolving a counterparty's public key before building a JWE, but the OpenAPI documents them identically and does not describe how their returned strings differ. + + ### When to use + + Use it only if your HCX instance or onboarding contact tells you to; the chapter's guidance is to treat /fetch/certs as the one to use for encryption. Both endpoints are POST, both carry the Registry APIs tag, both take ParticipantCertRequest and both declare a string 200 response with 400, 404 and 500 ErrorResponse outcomes. It is a synchronous JSON registry call with no workflow or x-hcx-status codes. + + ### Preconditions + + - Bearer token from /get/session in bearer_auth with the Bearer prefix; Accept and Content-Type: application/json. + - ParticipantCertRequest with participantid (required), the target's participant code in @hcx form. + - The target participant has completed onboarding with an encryption certificate registered. + + ### Postconditions + + HTTP 200 with a string body. The spec describes the operation (fetchCertsPath) with the same text as /fetch/certs, so the precise content of the string beyond being a certificate path is not documented. No registry state changes and no callback. Errors use the ErrorResponse envelope on 400, 404 and 500. + + ### Common mistakes + + - Assuming this returns the same PEM as /fetch/certs and feeding a path string into a key-import routine. + - Choosing it over /fetch/certs for encryption without instance-specific guidance; the handbook names /fetch/certs. + - Passing participant_code instead of participantid. + - Omitting Accept or the Bearer prefix on the token. + + ### Best practices + + - Prefer /fetch/certs for obtaining key material; use this endpoint only where the instance documents a use for the path form. + - If you do use it, log the returned string shape once so a change in behaviour is noticed. + - Apply the same 24-hour cache discipline keyed by participantid. + - Keep both calls behind one client function so the choice is a configuration switch. + + ### Related scenario + + An integrator building a registry inspection tool for a TPA wants to show, for each payer, where the registry references its certificate as well as the certificate itself. The tool obtains a Bearer token, calls /fetch/certs/path with participantid 1518@hcx and displays the returned path string, then calls /fetch/certs for the PEM used for actual encryption. The production claims engine itself only uses /fetch/certs, as the Integration Handbook prescribes, before each /v1/claim/submit. + + ### Specification + + Chapter [Finding participants and policies](/docs/nhcx/v1/getting-started/finding-participants-and-policies) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + participantid: + type: string + example: + participantid: 1518@hcx + responses: + "200": + description: HTTP 200 with a string body. + content: + application/json: + schema: + type: object + properties: + _contentType: + type: string + _body: + type: string + example: + _contentType: string + _body: + /v2/update/cert: + post: + operationId: registry_v2_update_cert + x-abdm-atom: nhcx.endpoint.v2-update-cert + x-abdm-use-case: Participant registry + tags: + - Participant registry + summary: Update certificate (v2, no passcode) + description: |- + Replaces a participant's public encryption certificate by participantId without passcode validation; the same schema is echoed back on success. + + ### Business purpose + + Encryption keys are recommended to be rotated once a year, and a compromised key must be replaced immediately. The passcode-gated /v2/participant/update is the safer general route, but it needs a person with the registered phone and a 24-hour confirmation step. This endpoint exists for certificate-only updates without that validation, so an organisation can publish a new public certificate quickly. Only the certificate changes; the endpoint URL is untouched. + + ### When to use + + Use it for scheduled annual rotation or emergency replacement of the certificate when passcode validation is not wanted. The production URL is https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice/v2/update/cert. To change the callback URL as well, use /v2/participant/update instead. It is the last item of the certificates checklist alongside the v2 participant update. Synchronous JSON; no workflow or x-hcx-status codes. + + ### Preconditions + + - Bearer token from /get/session in bearer_auth with the Bearer prefix; Accept and Content-Type: application/json. + - UpdateCertV2 body: participantId and certificate, both mandatory; the certificate must be Base64-encoded (the NHA steps produce a self-signed X.509 RSA certificate, then Base64-encode the whole PEM text). + - The matching new private key, in PKCS8 form, is already deployed on the callback host. + - Note the camelCase field participantId, unlike participant_code (v1) and participantcode (v2 update). + + ### Postconditions + + HTTP 200 with the UpdateCertV2 schema echoed back (participantId and certificate). The registry's encryption certificate for that participant is replaced, so /fetch/certs returns the new one from the next call; counterparties may serve a cached copy for up to 24 hours. No transactionid is issued and no /update/validate step follows. No callback. 400, 404 and 500 use the ErrorResponse envelope. + + ### Common mistakes + + - Sending the raw PEM rather than the Base64-encoded certificate, which the validation explicitly requires. + - Using participant_code, participantcode or encryptioncert; this schema is participantId and certificate. + - Publishing the new certificate before the new private key is live on the callback host, so inbound callbacks fail to decrypt (PAYR-1001 on the counterparty side, undecryptable payloads on yours). + - Discarding the old private key immediately, even though counterparties can hold the old certificate for 24 hours. + - Trying to change the endpoint URL here; only the certificate is accepted. + + ### Best practices + + - Rotate in two phases: deploy the new PKCS8 private key, publish the certificate, and keep the old key for at least 24 hours. + - Generate a 2048-bit RSA key and a 365-day self-signed X.509 certificate so the validity matches the annual rotation recommendation. + - Verify with /participant/search or a /fetch/certs call against your own code that the new certificate is served. + - Restrict who can call this endpoint inside your organisation, since it replaces the key that protects all inbound health data without a passcode. + - Notify the ecosystem promptly if rotation is due to suspected compromise, as the protocol expects. + + ### Related scenario + + A hospital's security audit finds its NHCX private key was copied to a shared drive. The team generates a new 2048-bit RSA key pair and 365-day self-signed certificate, deploys the PKCS8 private key to the callback host and Base64-encodes the certificate. With a Bearer token they call /v2/update/cert with participantId XXXXX7583@hcx and the certificate; the registry echoes the schema back. They keep the old key available for one day so payers still holding the cached certificate can be decrypted, then destroy it. The next /v1/preauth/on_submit from the payer, encrypted against the new certificate, decrypts cleanly. + + ### Specification + + Chapter [Your certificate](/docs/nhcx/v1/getting-started/your-certificate) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + participantId: + type: string + certificate: + type: string + example: + participantId: XXXX@hcx + certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t... + responses: + "200": + description: HTTP 200 with the UpdateCertV2 schema echoed back (participantId and certificate). + content: + application/json: + schema: + type: object + properties: + participantId: + type: string + certificate: + type: string + example: + participantId: XXXX@hcx + certificate: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t... + /get/linked/registry/mst: + post: + operationId: registry_get_linked_registry_mst + x-abdm-use-case: Participant registry + tags: + - Participant registry + summary: Get linked registry master (internal) + description: |- + Internal-use participant-service operation that fetches the linked registry master; listed in the OpenAPI but not intended for integrators. + + ### Business purpose + + The participant registry can be extended from or linked to external registries such as the ABDM Health Facility Registry and the payer registry, and participant records carry linked_registry_codes in identifier@registry form with supported registry codes configured at instance level. This operation, described in the OpenAPI as for internal use and fetching the linked registry, appears to serve that master configuration to the platform itself. It is documented here for completeness of the 63-endpoint index, not as an integration point. + + ### When to use + + Do not call it from an integration. The Participant Registry chapter names it, together with /get/session in its OpenAPI form, as one of two internal-use endpoints that should not be called by integrators. If you need registry linkage information for a participant, read linked_registry_codes from /participant/search or /participant/details, and use the Valid Registry Enums (HFR 10001, NIN 10002, ROHINI 10003, PAYER 10004) documented for onboarding. No workflow or x-hcx-status codes apply. + + ### Preconditions + + - Served under the participanthcxservice prefix with the Registry APIs tag, so the usual bearer_auth Bearer token and Accept: application/json headers would apply. + - The OpenAPI entry documents no request body and no parameters. + - Access to internal operations is controlled by the NHCX instance provider; the chapter states integrators should not call it. + + ### Postconditions + + The OpenAPI declares a 200 response of type string, with 400 Client Error, 404 Resource not found and 500 Downstream systems down each returning the ErrorResponse envelope (timestamp plus error code, message and trace). No state change is described and no callback follows. The content of the returned string is not documented. + + ### Common mistakes + + - Treating it as a public registry lookup and building a dependency on an operation the platform reserves for internal use. + - Confusing it with linked_registry_codes on a participant record, which is the documented way to see a participant's external registry identifiers. + - Confusing the registry master with the Valid Registry Enums used in registrytype during onboarding. + + ### Best practices + + - Leave it out of client libraries and Postman collections used for certification. + - Source registry codes from the onboarding documentation and participant records instead. + - If an onboarding contact directs you to it, record their exact instruction, since the specification documents neither a body nor the response content. + + ### Related scenario + + While generating a client from the participanthcxservice OpenAPI document, a hospital integrator notices /get/linked/registry/mst next to /participant/search and asks whether to wire it into the payer picker. The answer from the documentation is no: it is an internal operation, and the picker should be built on /fetch/participants/list, with each selected payer confirmed through /participant/search and its linked_registry_codes read from that record. The generated method is left unused and excluded from the sandbox-exit test evidence. + + ### Specification + + Chapter [Creating and updating a participant](/docs/nhcx/v1/getting-started/creating-and-updating-a-participant) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + _body: + type: string + example: + _body: No request body or parameters are documented in the OpenAPI entry for this internal operation. + responses: + "200": + description: The OpenAPI declares a 200 response of type string, with 400 Client Error, 404 Resource not found and 500 Downstream systems down each returning the ErrorResponse envelope (timestamp plus error code, message and trace). + content: + application/json: + schema: + type: object + properties: + _contentType: + type: string + _body: + type: string + example: + _contentType: string + _body: + /participant/link/abha/policy: + post: + operationId: registry_participant_link_abha_policy + x-abdm-atom: nhcx.endpoint.participant-link-abha-policy + x-abdm-use-case: Participant registry + tags: + - Participant registry + summary: Link ABHA number to policies + description: |- + Payer-side write that links a beneficiary's ABHA number and member id to one or more products, so provider policy lookups can find them. + + ### Business purpose + + NHCX does not hold a national policy database of its own. Payers push their beneficiary-to-product links into the participant registry with this call, and providers pull them back with /participant/get/policies. Without a link, a hospital's policy lookup returns nothing and the patient cannot be processed as cashless on NHCX, regardless of what the admission record says. The insurer benefits by making its members discoverable; the hospital benefits by getting the payerId, memberId and productId it needs for every downstream claim call. + + ### When to use + + Use it when a policy is issued or renewed, when a member is added to a product, and after any de-link that must be re-established (for example, when an insurance company moves from one TPA to another). It sits at the very start of the member lifecycle, well before any coverage-eligibility, preauthorisation or claim workflow (workflow codes 12, 121, 13 and so on) is triggered. In the sandbox exit checklist for payers it is use case 1, Link ABHA with Policy, followed by Get Policy and De-Link. + + ### Preconditions + + - A valid Bearer token from the client-credentials call (POST /get/session, form-urlencoded client_id, client_secret, grant_type=client_credentials); tokens last 1200 seconds, so refresh before expiry. + - HTTP headers Accept: application/json, Content-Type: application/json and bearer_auth: Bearer (the participant service uses bearer_auth, not Authorization). + - Base path for the participant service: https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice (sandbox) or https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice (production). + - This is a synchronous plain-JSON registry call: no JWE envelope, no x-hcx-* protocol headers and no correlation id are involved. + - The caller must be the participant named as payerid (the insurance company) or as processingid (its TPA), and the token must be minted with the client_id used when that participant was created. + - Both the payer and, where applicable, the TPA must already exist in the registry with their own participant codes; every payer has an individual participant code even when it sits under a TPA. + + ### Postconditions + + On success the service returns HTTP 200 with ParticipantLinkAbhaResponse, whose two optional fields are result (a string) and errormessage (errorcode and errordescription). There is no asynchronous callback; the write is immediately visible to /participant/get/policies and /V2/participant/get/policies keyed by ABHA number, member id or mobile number. The linked payerid and processingid become the values that providers later resolve as the payer and the receiver code for NHCX routing. Failures return 400, 404 or 500 with the ErrorResponse envelope (timestamp plus Error with code, message and trace). + + ### Common mistakes + + - Calling with a token minted from a client_id other than the one used at participant creation for the payer or TPA; NHA lists this as common mistake 10 and the call is refused even though the token itself is valid. + - Confusing payerid and processingid: payerid is always the insurance company's own participant code; processingid is only the TPA code when the payer is mapped under a TPA. + - Trying to move a payer to a new TPA by re-linking in place; the documented path is de-link, then link again with the new TPA's code as processingid. + - Omitting one of the required fields (requestid, abhanumber, memberid, payerid, policies with productid and productname) or reusing a non-UUID requestid, which returns 400 with the ErrorResponse envelope. + - Sending the token without the Bearer prefix, or omitting the Accept header, both of which reject the call before business logic (401 or 400). + + ### Best practices + + - Generate a fresh UUID for requestid on every call and log it with the response so a duplicate submission can be traced. + - Keep the ABHA number in the form the member layer expects (the identifier table and get/policies documentation both specify ABHA without hyphens) and store it in that form. + - Make sure productid and productname exactly match the payer's product catalogue as registered through /product/link, because providers will later match on these values. + - Cache and proactively refresh the Bearer token; retry once on 401 with a new token, then stop and alert. + - After linking, verify the result with /participant/get/policies using the same identifier before telling the provider the member is ready. + + ### Related scenario + + A private insurer onboards a new group policy for a corporate client and issues a family floater to a beneficiary who already holds an ABHA. Its policy administration system has previously registered the product through /product/link and now calls /participant/link/abha/policy with the beneficiary's ABHA number, member id, the insurer's own participant code as payerid and the TPA's code as processingid. A week later the beneficiary is admitted to a network hospital; the hospital's desk calls /participant/get/policies with the ABHA number, receives the linked details and uses the processingid as x-hcx-recipient_code for the coverage-eligibility check and the preauthorisation that follow. + + ### Specification + + Chapter [Creating and updating a participant](/docs/nhcx/v1/getting-started/creating-and-updating-a-participant) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + requestid: + type: string + abhanumber: + type: string + mobilenumber: + type: string + memberid: + type: string + payerid: + type: string + policies: + type: array + items: + type: object + properties: + productid: + type: string + productname: + type: string + processingid: + type: string + example: + requestid: 7f3f2a4e-0c6b-4b7a-9e2d-2c1f8a5b6d90 + abhanumber: "12345678910111" + mobilenumber: "9876543210" + memberid: MEM-2026-000123 + payerid: 100234@sbx + policies: + - productid: PRD-FLOATER-01 + productname: Family Floater Gold + processingid: 100235@sbx + responses: + "200": + description: On success the service returns HTTP 200 with ParticipantLinkAbhaResponse, whose two optional fields are result (a string) and errormessage (errorcode and errordescription). + content: + application/json: + schema: + type: object + properties: + result: + type: string + example: + result: success + /V2/participant/link/abha/policy: + post: + operationId: registry_v2_participant_link_abha_policy + x-abdm-atom: nhcx.endpoint.v2-participant-link-abha-policy + x-abdm-use-case: Participant registry + tags: + - Participant registry + summary: Link ABHA number to policies (V2) + description: |- + V2 variant of the ABHA policy link; same ParticipantLinkAbhaRequest body and ParticipantLinkAbhaResponse as the unversioned call. + + ### Business purpose + + This endpoint serves the same business need as /participant/link/abha/policy: it lets a payer (or the TPA processing on its behalf) record which products a beneficiary holds, keyed by ABHA number and member id, so that providers can discover the policy and route claims correctly. The OpenAPI document exposes it as operation participantLinkAbhaPolicyV2 with an identical request and response schema to the v1 path; the documentation does not describe any behavioural difference beyond the path and operationId. + + ### When to use + + Use it in exactly the situations where the v1 link call applies: policy issue, renewal, member addition, or re-linking after a de-link when a payer changes TPA. It belongs to the member-layer setup that precedes every claim-side workflow (coverage eligibility, preauthorisation with workflow code 12, enhancement with code 13, claim). Choose this path or the v1 path consistently across your integration; the docs give no reason to mix them. + + ### Preconditions + + - A valid Bearer token from the client-credentials call (POST /get/session, form-urlencoded client_id, client_secret, grant_type=client_credentials); tokens last 1200 seconds, so refresh before expiry. + - HTTP headers Accept: application/json, Content-Type: application/json and bearer_auth: Bearer (the participant service uses bearer_auth, not Authorization). + - Base path for the participant service: https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice (sandbox) or https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice (production). + - This is a synchronous plain-JSON registry call: no JWE envelope, no x-hcx-* protocol headers and no correlation id are involved. + - The token must belong to the participant named as payerid or processingid, generated with the client_id used at participant creation. + - Note the capital V in the path (/V2/participant/...), which differs from the lower-case /v2/ used by the init and validate variants. + + ### Postconditions + + A successful call returns HTTP 200 with ParticipantLinkAbhaResponse (optional result string and optional errormessage with errorcode and errordescription). No asynchronous callback follows; the beneficiary's products are immediately discoverable through /participant/get/policies or /V2/participant/get/policies. Errors come back as 400, 404 or 500 with the registry ErrorResponse envelope. The link can later be reversed only through the de-link endpoints, which check that the caller is the payerid or processingid participant. + + ### Common mistakes + + - Calling with a token minted from a client_id other than the one used at participant creation for the payer or TPA; NHA lists this as common mistake 10 and the call is refused even though the token itself is valid. + - Confusing payerid and processingid: payerid is always the insurance company's own participant code; processingid is only the TPA code when the payer is mapped under a TPA. + - Trying to move a payer to a new TPA by re-linking in place; the documented path is de-link, then link again with the new TPA's code as processingid. + - Omitting one of the required fields (requestid, abhanumber, memberid, payerid, policies with productid and productname) or reusing a non-UUID requestid, which returns 400 with the ErrorResponse envelope. + - Sending the token without the Bearer prefix, or omitting the Accept header, both of which reject the call before business logic (401 or 400). + - Lower-casing the path to /v2/participant/link/abha/policy, which is not the same route; the lower-case /v2/ prefix belongs to the init and validate pair. + + ### Best practices + + - Generate a fresh UUID for requestid on every call and log it with the response so a duplicate submission can be traced. + - Keep the ABHA number in the form the member layer expects (the identifier table and get/policies documentation both specify ABHA without hyphens) and store it in that form. + - Make sure productid and productname exactly match the payer's product catalogue as registered through /product/link, because providers will later match on these values. + - Cache and proactively refresh the Bearer token; retry once on 401 with a new token, then stop and alert. + - After linking, verify the result with /participant/get/policies using the same identifier before telling the provider the member is ready. + + ### Related scenario + + A TPA that processes claims for several insurers migrates its integration to the V2 participant APIs. When one of its insurers issues a new individual health policy, the TPA's system calls /V2/participant/link/abha/policy with the insurer's participant code as payerid and its own code as processingid, listing the product from the insurer's catalogue. The TPA then confirms the link with /V2/participant/get/policies using the member's ABHA number. When the beneficiary later visits a hospital, the provider resolves the processingid as the receiver code and submits the coverage-eligibility check and preauthorisation to the TPA. + + ### Specification + + Chapter [Creating and updating a participant](/docs/nhcx/v1/getting-started/creating-and-updating-a-participant) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + requestid: + type: string + abhanumber: + type: string + mobilenumber: + type: string + memberid: + type: string + payerid: + type: string + policies: + type: array + items: + type: object + properties: + productid: + type: string + productname: + type: string + processingid: + type: string + example: + requestid: 0b1d6c1e-6a5f-4d3c-8b9a-4f2e7c0d1a22 + abhanumber: "12345678910111" + mobilenumber: "9876543210" + memberid: MEM-2026-000123 + payerid: 100234@sbx + policies: + - productid: PRD-INDIV-07 + productname: Individual Health Silver + processingid: 100235@sbx + responses: + "200": + description: A successful call returns HTTP 200 with ParticipantLinkAbhaResponse (optional result string and optional errormessage with errorcode and errordescription). + content: + application/json: + schema: + type: object + properties: + result: + type: string + example: + result: success + /v2/participant/link/abha/policy/init: + post: + operationId: registry_v2_participant_link_abha_policy_init + x-abdm-use-case: Participant registry + tags: + - Participant registry + summary: Initiate ABHA policy link (v2) + description: |- + First half of the two-step v2 link: submits the ABHA policy link request, to be confirmed with a passcode via the validate endpoint. + + ### Business purpose + + The init variant exists so that a policy link can be confirmed out of band before it takes effect. It takes the same ParticipantLinkAbhaRequest as the direct link calls but pairs with GET /v2/participant/link/abha/policy/validate, which accepts a passcode and transactionId. This mirrors the passcode-confirmed pattern already used for participant creation (/validate) and update (/update/validate), giving payers and TPAs an approval gate on member-layer writes. The documentation describes the pairing but does not detail how the passcode is delivered for this endpoint. + + ### When to use + + Use it when your NHCX instance requires the confirmed (init then validate) form of linking rather than the single-call form. It is part of member-layer setup and precedes any claim-side workflow. Call init with the full link request, keep the transaction identifier the flow returns, and then complete the link with the validate call carrying passcode and transactionId. If the confirmation is never completed, the link should not be assumed to exist; verify with /participant/get/policies. + + ### Preconditions + + - A valid Bearer token from the client-credentials call (POST /get/session, form-urlencoded client_id, client_secret, grant_type=client_credentials); tokens last 1200 seconds, so refresh before expiry. + - HTTP headers Accept: application/json, Content-Type: application/json and bearer_auth: Bearer (the participant service uses bearer_auth, not Authorization). + - Base path for the participant service: https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice (sandbox) or https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice (production). + - This is a synchronous plain-JSON registry call: no JWE envelope, no x-hcx-* protocol headers and no correlation id are involved. + - The caller must be the participant named as payerid or processingid, with a token minted from the client_id used at participant creation. + - The request body is ParticipantLinkAbhaRequest: requestid (UUID), abhanumber, memberid, payerid and policies (productid, productname) are required; mobilenumber and processingid are optional. + + ### Postconditions + + The service answers synchronously with HTTP 200 and ParticipantLinkAbhaResponse (optional result and errormessage). Per the documented pattern, the link is then confirmed by GET /v2/participant/link/abha/policy/validate with the passcode and transactionId; the docs do not state that the link is visible in policy lookups before that confirmation. There is no NHCX callback. Errors return 400, 404 or 500 with the ErrorResponse envelope. For the sibling participant flows the transaction id and passcode are valid for 24 hours; the docs do not state a separate validity for the policy link pair. + + ### Common mistakes + + - Treating init as the complete link and never calling /v2/participant/link/abha/policy/validate, then reporting that get/policies returns nothing. + - Using a token from a client_id other than the one used at participant creation for the payer or TPA (common mistake 10 in the NHA list); linking is refused for unauthorised parties. + - Mixing the case of the path: init and validate live under lower-case /v2/, while the direct V2 link uses /V2/. + - Swapping payerid and processingid, or omitting required fields such as requestid, memberid or the policies array. + + ### Best practices + + - Persist the requestid you sent and the transaction identifier you receive together, so the validate step can be completed by a different process or after a restart. + - Complete the validate step promptly; the sibling participant create and update passcodes expire after 24 hours, so do not assume a longer window here. + - Use the same product identifiers as registered through /product/link. + - Confirm the outcome with /participant/get/policies before informing the provider or beneficiary. + - Refresh the Bearer token proactively and retry once on 401. + + ### Related scenario + + An insurer's policy administration team is required by its NHCX instance to confirm member links by passcode. When a new policy is issued, the system posts the ParticipantLinkAbhaRequest to /v2/participant/link/abha/policy/init and records the transaction identifier. The authorised operator receives the passcode and the system calls GET /v2/participant/link/abha/policy/validate with passcode and transactionId to complete the link. The team then checks /V2/participant/get/policies for the member's ABHA number and, satisfied, closes the case; the hospital will discover the policy on the beneficiary's next admission. + + ### Specification + + Chapter [Creating and updating a participant](/docs/nhcx/v1/getting-started/creating-and-updating-a-participant) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + requestid: + type: string + abhanumber: + type: string + mobilenumber: + type: string + memberid: + type: string + payerid: + type: string + policies: + type: array + items: + type: object + properties: + productid: + type: string + productname: + type: string + processingid: + type: string + example: + requestid: 3c9e8d2f-5b4a-4e1c-9f7d-8a6b5c4d3e21 + abhanumber: "12345678910111" + mobilenumber: "9876543210" + memberid: MEM-2026-000123 + payerid: 100234@sbx + policies: + - productid: PRD-FLOATER-01 + productname: Family Floater Gold + processingid: 100235@sbx + responses: + "200": + description: The service answers synchronously with HTTP 200 and ParticipantLinkAbhaResponse (optional result and errormessage). + content: + application/json: + schema: + type: object + properties: + result: + type: string + example: + result: success + /v2/participant/link/abha/policy/validate: + get: + operationId: registry_v2_participant_link_abha_policy_validate + x-abdm-use-case: Participant registry + tags: + - Participant registry + summary: Validate ABHA policy link (v2) + description: |- + Second half of the two-step v2 link: confirms an initiated ABHA policy link with the passcode and transactionId query parameters. + + ### Business purpose + + This GET endpoint closes the approval loop opened by /v2/participant/link/abha/policy/init. By requiring a passcode tied to a transactionId, it ensures that a member-layer write attributed to a payer or TPA was actually authorised by that organisation, in the same way that participant creation and update are confirmed through /validate and /update/validate. The value to the ecosystem is trust in the registry: providers rely on the policy lookup, so the links behind it should be deliberate and traceable. + + ### When to use + + Call it after a successful init call, once the passcode is available, passing both required query parameters: passcode (string) and transactionId (string). It is the last step of the confirmed link flow and must be completed before the link is relied on. It has no role in claim-side workflows (eligibility, preauthorisation, claim) beyond making the member discoverable so that those flows can start. + + ### Preconditions + + - A prior POST /v2/participant/link/abha/policy/init that returned a transaction identifier. + - The passcode associated with that transaction; the documentation for the sibling participant flows says the passcode is specific to each transaction id and valid for 24 hours. + - A valid Bearer token in bearer_auth: Bearer , plus Accept: application/json; there is no request body, and no JWE or x-hcx-* headers are involved. + - The participant service base path, sandbox https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice. + + ### Postconditions + + On success the endpoint returns HTTP 200 with ParticipantLinkAbhaResponse (optional result and errormessage). The initiated link is confirmed and the beneficiary's products become discoverable through the policy lookup endpoints. No asynchronous callback follows. Errors return 400, 404 or 500 with the ErrorResponse envelope. If the transaction cannot be found or the passcode is wrong, the documented remedy for the sibling participant flows is to trigger the init request again, which generates a new transaction id and passcode. + + ### Common mistakes + + - Sending passcode and transactionId in a JSON body instead of as query parameters; this is a GET with two required query parameters. + - Using a transactionId from a different init call or from a participant create/update flow. + - Letting the passcode age out; the sibling flows document a 24-hour validity for transaction id and passcode. + - Calling with a token from a client_id other than the one used at participant creation, which fails the link authorisation check. + - Omitting the Accept header or the Bearer prefix on bearer_auth. + + ### Best practices + + - URL-encode both query parameters and log the transactionId with the outcome. + - Treat a 404 or an errormessage as a signal to restart from init rather than retrying the same passcode indefinitely. + - Verify the confirmed link with /participant/get/policies using the same ABHA number. + - Keep the init and validate calls under the same participant token so the identity check passes. + + ### Related scenario + + A TPA's operations desk initiated a policy link for a new member earlier in the day through /v2/participant/link/abha/policy/init and stored the transaction identifier against the case. When the authorised approver supplies the passcode, the system calls GET /v2/participant/link/abha/policy/validate?passcode=...&transactionId=... and receives a 200 with a result string. The desk then runs /V2/participant/get/policies for the member's ABHA number, sees the product listed, and closes the linking task; the next call in the member's journey will be the hospital's coverage-eligibility check. + + ### Specification + + Chapter [Creating and updating a participant](/docs/nhcx/v1/getting-started/creating-and-updating-a-participant) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + responses: + "200": + description: On success the endpoint returns HTTP 200 with ParticipantLinkAbhaResponse (optional result and errormessage). + content: + application/json: + schema: + type: object + properties: + result: + type: string + example: + result: success + /participant/delink/abha/policy: + post: + operationId: registry_participant_delink_abha_policy + x-abdm-atom: nhcx.endpoint.participant-delink-abha-policy + x-abdm-use-case: Participant registry + tags: + - Participant registry + summary: De-link ABHA policies + description: |- + Removes specific products from a member's policy link for a payer, keyed on payerid, memberid and the products listed. + + ### Business purpose + + Policies lapse, members leave a product, and insurance companies move between TPAs. This call is the only documented way to reverse a link written through /participant/link/abha/policy, which keeps the registry honest so that providers do not route claims against coverage that no longer exists. Because there is no in-place re-parenting operation, de-link followed by a fresh link is also the documented procedure when a payer changes its processing TPA. The insurer and TPA control their own data; providers get accurate policy lookups. + + ### When to use + + Use it when a product should no longer be discoverable for a member: policy termination, member removal, product migration, or the first half of a TPA change. It belongs to the member layer and precedes no claim-side workflow; it is the payer's use case 3 in the sandbox exit checklist (Link, Get Policy, De-Link). Do not use it to correct an ABHA number, which is what /update/abhanumber is for. + + ### Preconditions + + - A valid Bearer token from the client-credentials call (POST /get/session, form-urlencoded client_id, client_secret, grant_type=client_credentials); tokens last 1200 seconds, so refresh before expiry. + - HTTP headers Accept: application/json, Content-Type: application/json and bearer_auth: Bearer (the participant service uses bearer_auth, not Authorization). + - Base path for the participant service: https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice (sandbox) or https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice (production). + - This is a synchronous plain-JSON registry call: no JWE envelope, no x-hcx-* protocol headers and no correlation id are involved. + - The caller must be the participant named as payerid or processingid when the policies were linked; NHCX extracts the client id from the token and allows the call only on a match. + - The body is ParticipantDeLinkAbhaRequest: requestid (UUID), payerid, memberid and policies (productid, productname) are required; processingid is optional. There is no abhanumber field. + + ### Postconditions + + A successful call returns HTTP 200 with ParticipantDeLinkAbhaResponse and the listed products are no longer returned by /participant/get/policies for that payer and member. No asynchronous callback follows. If the caller is not the linking payer or TPA the call is refused with an error message; if a listed product is not linked the response carries "There is no policies with requested details". Other failures return 400, 404 or 500 with the ErrorResponse envelope. To re-establish coverage, call the link endpoint again, optionally with a new processingid. + + ### Common mistakes + + - Calling from a participant that is neither the payerid nor the processingid used at link time; NHCX checks the client id in the token, not the body, and refuses the call (common mistake 10). + - Listing a product that is not actually linked for that payerid and memberid, which returns the error message "There is no policies with requested details". + - Including abhanumber or mobilenumber in the body; the de-link request is keyed on payerid, memberid and the products listed, and has no ABHA field. + - Expecting provider-side caches to update: the handbook documents the policy cache as permanent with no TTL, so a de-linked policy keeps appearing until the provider passes forceRefresh: true. + - Using a token generated with a different client_id from the one used when the payer or TPA participant was created. + + ### Best practices + + - De-link only the specific products that need removing; the policies array is the unit of work. + - When moving an insurer to a new TPA, follow the documented order: de-link the existing policies, then link them again with the new TPA's participant code as processingid. + - Generate a fresh UUID for requestid on every call and log it with the response. + - Confirm the result with /participant/get/policies afterwards, and remember that providers may need a forced refresh of their own policy cache. + - Refresh the Bearer token proactively and retry once on 401 before escalating. + + ### Related scenario + + An insurance company ends its contract with one TPA and appoints another. Its integration first calls /participant/get/policies to enumerate the products linked for each affected member, then calls /participant/delink/abha/policy for each member with the insurer's participant code as payerid, the member id and the products to remove. Once every de-link returns success, it calls /participant/link/abha/policy again with the new TPA's participant code as processingid. Hospitals that have cached these members' policies are told to refresh, so that their next coverage-eligibility check is addressed to the new TPA. + + ### Specification + + Chapter [Creating and updating a participant](/docs/nhcx/v1/getting-started/creating-and-updating-a-participant) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + requestid: + type: string + payerid: + type: string + memberid: + type: string + policies: + type: array + items: + type: object + properties: + productid: + type: string + productname: + type: string + processingid: + type: string + example: + requestid: 9a7c5e3d-1b2f-4c8a-b6d4-0e9f8a7b6c55 + payerid: 100234@sbx + memberid: MEM-2026-000123 + policies: + - productid: PRD-FLOATER-01 + productname: Family Floater Gold + processingid: 100235@sbx + responses: + "200": + description: A successful call returns HTTP 200 with ParticipantDeLinkAbhaResponse and the listed products are no longer returned by /participant/get/policies for that payer and member. + content: + application/json: + schema: + type: object + properties: + result: + type: string + example: + result: success + /V2/participant/delink/abha/policy: + post: + operationId: registry_v2_participant_delink_abha_policy + x-abdm-atom: nhcx.endpoint.v2-participant-delink-abha-policy + x-abdm-use-case: Participant registry + tags: + - Participant registry + summary: De-link ABHA policies (V2) + description: |- + V2 variant of the ABHA policy de-link; same ParticipantDeLinkAbhaRequest body and response as the unversioned call. + + ### Business purpose + + This endpoint performs the same member-layer removal as /participant/delink/abha/policy: it takes products out of a member's link for a given payer so that providers stop discovering lapsed or migrated coverage. The OpenAPI document exposes it as participantDeLinkAbhaPolicyV2 with an identical request and response schema; the documentation does not describe any behavioural difference beyond the path and operationId. It is the natural partner of /V2/participant/link/abha/policy for integrations that have standardised on the V2 paths. + + ### When to use + + Use it in the same situations as the v1 de-link: policy termination, member removal, product migration, or as the first step when an insurer changes TPA (de-link, then link again with the new processingid). It is part of member-layer maintenance and is not tied to any claim workflow code. Pair it consistently with the V2 link and V2 get-policies calls. + + ### Preconditions + + - A valid Bearer token from the client-credentials call (POST /get/session, form-urlencoded client_id, client_secret, grant_type=client_credentials); tokens last 1200 seconds, so refresh before expiry. + - HTTP headers Accept: application/json, Content-Type: application/json and bearer_auth: Bearer (the participant service uses bearer_auth, not Authorization). + - Base path for the participant service: https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice (sandbox) or https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice (production). + - This is a synchronous plain-JSON registry call: no JWE envelope, no x-hcx-* protocol headers and no correlation id are involved. + - The caller must be the payerid or processingid participant from the original link, using a token minted with the client_id used at participant creation. + - Body: requestid (UUID), payerid, memberid and policies are required; processingid is optional; there is no abhanumber field. + - Note the capital V in /V2/. + + ### Postconditions + + On success the service returns HTTP 200 with ParticipantDeLinkAbhaResponse and the products are no longer visible through the get-policies endpoints for that payer and member. There is no callback. An unauthorised caller is refused with an error message, and a product that is not linked yields "There is no policies with requested details". Other errors use the 400/404/500 ErrorResponse envelope. Provider-side policy caches are documented as permanent, so they will keep the old answer until forced to refresh. + + ### Common mistakes + + - Calling from a participant that is neither the payerid nor the processingid used at link time; NHCX checks the client id in the token, not the body, and refuses the call (common mistake 10). + - Listing a product that is not actually linked for that payerid and memberid, which returns the error message "There is no policies with requested details". + - Including abhanumber or mobilenumber in the body; the de-link request is keyed on payerid, memberid and the products listed, and has no ABHA field. + - Expecting provider-side caches to update: the handbook documents the policy cache as permanent with no TTL, so a de-linked policy keeps appearing until the provider passes forceRefresh: true. + - Using a token generated with a different client_id from the one used when the payer or TPA participant was created. + - Lower-casing the path; /v2/participant/delink/abha/policy is not a documented route. + + ### Best practices + + - De-link only the specific products that need removing; the policies array is the unit of work. + - When moving an insurer to a new TPA, follow the documented order: de-link the existing policies, then link them again with the new TPA's participant code as processingid. + - Generate a fresh UUID for requestid on every call and log it with the response. + - Confirm the result with /participant/get/policies afterwards, and remember that providers may need a forced refresh of their own policy cache. + - Refresh the Bearer token proactively and retry once on 401 before escalating. + + ### Related scenario + + A TPA is informed by one of its insurers that a corporate group policy has been cancelled mid-term. The TPA's system lists the affected members from its own records, calls /V2/participant/get/policies to confirm what NHCX currently holds, and then calls /V2/participant/delink/abha/policy per member with the insurer's participant code as payerid, its own code as processingid and the cancelled product. Each success is logged against the member. When a former member later presents at a hospital, the provider's policy lookup (after a forced cache refresh) no longer shows the product, and the desk proceeds as a self-pay case rather than submitting a coverage-eligibility check. + + ### Specification + + Chapter [Creating and updating a participant](/docs/nhcx/v1/getting-started/creating-and-updating-a-participant) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + requestid: + type: string + payerid: + type: string + memberid: + type: string + policies: + type: array + items: + type: object + properties: + productid: + type: string + productname: + type: string + processingid: + type: string + example: + requestid: c4d2e1f0-8b7a-4c6d-9e5f-1a2b3c4d5e66 + payerid: 100234@sbx + memberid: MEM-2026-000123 + policies: + - productid: PRD-INDIV-07 + productname: Individual Health Silver + processingid: 100235@sbx + responses: + "200": + description: On success the service returns HTTP 200 with ParticipantDeLinkAbhaResponse and the products are no longer visible through the get-policies endpoints for that payer and member. + content: + application/json: + schema: + type: object + properties: + result: + type: string + example: + result: success + /participant/get/policies: + post: + operationId: registry_participant_get_policies + x-abdm-atom: nhcx.endpoint.participant-get-policies + x-abdm-use-case: Participant registry + tags: + - Participant registry + summary: Get beneficiary policies + description: |- + Looks up the policies linked to a beneficiary by ABHA number, member id or mobile number, returning the payer and product details needed for claims. + + ### Business purpose + + This is the provider's window into the member layer that payers populate through the link API. A hospital cannot submit a coverage-eligibility check, preauthorisation or claim until it knows the payer participant code, member id and product for the patient, and this call is where those values come from. The handbook lists policy discovery as step three of the fixed cashless sequence (payer search, payer selection, policy discovery, cache normalisation, effective payer resolution, InsurancePlan retrieval, optional eligibility, preauth). Payers and TPAs also use it to verify that their links were recorded. + + ### When to use + + Call it after patient registration or admission, when the desk needs to confirm that the patient is linked to a scheme or policy, and again (with a forced refresh) whenever a payer-side change is suspected. It precedes /v1/insuranceplan/request, /v1/coverageeligibility/check and /v1/preauth/submit (workflow code 12). If no payer id can be derived from the result, the backend must refuse preauth with "Unable to resolve payerId from policy bundle. Please fetch eligibility/policies before pre-auth submission." It is use case 2 in both the provider and payer sandbox exit checklists. + + ### Preconditions + + - A valid Bearer token from the client-credentials call (POST /get/session, form-urlencoded client_id, client_secret, grant_type=client_credentials); tokens last 1200 seconds, so refresh before expiry. + - HTTP headers Accept: application/json, Content-Type: application/json and bearer_auth: Bearer (the participant service uses bearer_auth, not Authorization). + - Base path for the participant service: https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice (sandbox) or https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice (production). + - This is a synchronous plain-JSON registry call: no JWE envelope, no x-hcx-* protocol headers and no correlation id are involved. + - The beneficiary must already have been linked by the payer or TPA; if no link exists the lookup returns nothing regardless of the hospital's own records. + - Body is FetchParticipantPoliciesRequest with two required strings: identifiertype (AbhaNumber, MemberId or MobileNo) and identifiervalue; ABHA must be supplied without hyphens. + + ### Postconditions + + The service answers synchronously with HTTP 200 and ParticipantListResponse: an optional participantdetails array whose entries carry optional participantcode, participantname, address and state. No callback follows. Integrators cache the normalised result keyed by patient (the handbook documents this cache as permanent, with forceRefresh: true as the only bypass) and resolve payerId, memberId, productId, productName and policyNumber from it. NHA guidance stresses that the processingID in the response, not the PayerID, is what goes into x-hcx-recipient_code. Failures return 400, 404 or 500 with the ErrorResponse envelope. + + ### Common mistakes + + - Sending the ABHA number with hyphens; the identifier table specifies ABHA without hyphens for this lookup and a hyphenated value is a common cause of an empty result. + - Using the PayerID from the response as x-hcx-recipient_code; NHA's common mistake 7 says providers must use the processingID from the get/Policies response as the receiver code, otherwise NHCX-1003 (receiver not registered) or PAYR-1331 follows. + - Trying only one identifier type; the handbook prescribes a cascade of AbhaNumber, then MemberId, then MobileNo. + - Dereferencing fields blindly; every field of ParticipantDetails is optional and the response shape may arrive as participantdetails, participants or a raw array. + - Trusting a permanent policy cache after a payer-side change instead of passing forceRefresh: true. + + ### Best practices + + - Normalise the ABHA number (strip separators) before the call and try identifiers in the documented priority order: ABHA, then MemberId from the latest admission, then mobile number. + - Cache successful lookups keyed by patient, but expose a forceRefresh path and use it as the first diagnostic step when a preauth is rejected for a coverage mismatch. + - Store payerId, memberId, productId, productName and policyNumber from the result; these feed x-hcx-recipient_code, the Coverage and Patient identifiers and the InsurancePlan lookup. + - If the lookup yields nothing, fall back to a coverage-eligibility check with purpose discovery to obtain the active policy code. + - Keep the token fresh; retry once on 401. + + ### Related scenario + + A patient is admitted to a network hospital and the registration desk captures an ABHA number and a member id. The HMIS has already called /fetch/participants/list to discover payers, and now calls /participant/get/policies with identifiertype AbhaNumber and the hyphen-free ABHA value. The response is normalised and cached against the patient, and the processingID becomes the receiver code. The desk then requests the plan through /v1/insuranceplan/request, optionally runs /v1/coverageeligibility/check, and submits the preauthorisation with /v1/preauth/submit; when the payer later queries a coverage detail, the desk forces a refresh of this lookup before responding. + + ### Specification + + Chapter [Creating and updating a participant](/docs/nhcx/v1/getting-started/creating-and-updating-a-participant) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + identifiertype: + type: string + identifiervalue: + type: string + example: + identifiertype: AbhaNumber + identifiervalue: "12345678910111" + responses: + "200": + description: "The service answers synchronously with HTTP 200 and ParticipantListResponse: an optional participantdetails array whose entries carry optional participantcode, participantname, address and state." + content: + application/json: + schema: + type: object + properties: + participantdetails: + type: array + items: + type: object + properties: + participantcode: + type: string + participantname: + type: string + address: + type: string + state: + type: string + example: + participantdetails: + - participantcode: 100234@sbx + participantname: Demo Health Insurance Co + address: Plot 12, Sector 5, Gurugram + state: Haryana + /V2/participant/get/policies: + post: + operationId: registry_v2_participant_get_policies + x-abdm-atom: nhcx.endpoint.v2-participant-get-policies + x-abdm-use-case: Participant registry + tags: + - Participant registry + summary: Get beneficiary policies (V2) + description: |- + V2 variant of the beneficiary policy lookup; same FetchParticipantPoliciesRequest body and ParticipantListResponse as the unversioned call. + + ### Business purpose + + This endpoint answers the same question as /participant/get/policies: which payer products is this beneficiary linked to, and therefore which payer or TPA should the hospital address. The OpenAPI document exposes it as getParticipantGetPoliciesV2 with an identical request and response schema and the same Registry APIs tag; the documentation records no behavioural difference beyond the path. Integrations that use the V2 link and de-link calls typically read back through this endpoint. + + ### When to use + + Use it at the same point in the journey as the v1 lookup: after registration, before InsurancePlan retrieval, coverage eligibility and preauthorisation (workflow code 12), and whenever a cached policy needs to be re-validated with forceRefresh. Payers and TPAs use it to confirm a link or de-link they have just written. Pick one of the two get-policies paths and use it consistently. + + ### Preconditions + + - A valid Bearer token from the client-credentials call (POST /get/session, form-urlencoded client_id, client_secret, grant_type=client_credentials); tokens last 1200 seconds, so refresh before expiry. + - HTTP headers Accept: application/json, Content-Type: application/json and bearer_auth: Bearer (the participant service uses bearer_auth, not Authorization). + - Base path for the participant service: https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice (sandbox) or https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice (production). + - This is a synchronous plain-JSON registry call: no JWE envelope, no x-hcx-* protocol headers and no correlation id are involved. + - A payer or TPA must already have linked the beneficiary. + - Body: identifiertype (AbhaNumber, MemberId or MobileNo) and identifiervalue, both required; ABHA without hyphens. + - Note the capital V in /V2/. + + ### Postconditions + + Returns HTTP 200 with ParticipantListResponse (optional participantdetails array of participantcode, participantname, address, state). No callback follows. The result is normalised and cached by the caller; the handbook documents that cache as permanent until forceRefresh: true is passed. The processingID from the response is the receiver code for NHCX routing, and payerId, memberId, productId, productName and policyNumber are resolved from the cached policies for the preauth. Errors return 400, 404 or 500 with the ErrorResponse envelope. + + ### Common mistakes + + - Sending the ABHA number with hyphens; the identifier table specifies ABHA without hyphens for this lookup and a hyphenated value is a common cause of an empty result. + - Using the PayerID from the response as x-hcx-recipient_code; NHA's common mistake 7 says providers must use the processingID from the get/Policies response as the receiver code, otherwise NHCX-1003 (receiver not registered) or PAYR-1331 follows. + - Trying only one identifier type; the handbook prescribes a cascade of AbhaNumber, then MemberId, then MobileNo. + - Dereferencing fields blindly; every field of ParticipantDetails is optional and the response shape may arrive as participantdetails, participants or a raw array. + - Trusting a permanent policy cache after a payer-side change instead of passing forceRefresh: true. + - Lower-casing the path to /v2/participant/get/policies, which is not a documented route. + + ### Best practices + + - Normalise the ABHA number (strip separators) before the call and try identifiers in the documented priority order: ABHA, then MemberId from the latest admission, then mobile number. + - Cache successful lookups keyed by patient, but expose a forceRefresh path and use it as the first diagnostic step when a preauth is rejected for a coverage mismatch. + - Store payerId, memberId, productId, productName and policyNumber from the result; these feed x-hcx-recipient_code, the Coverage and Patient identifiers and the InsurancePlan lookup. + - If the lookup yields nothing, fall back to a coverage-eligibility check with purpose discovery to obtain the active policy code. + - Keep the token fresh; retry once on 401. + + ### Related scenario + + A TPA has just linked a new member through /V2/participant/link/abha/policy and wants to verify the write before closing the ticket. It calls /V2/participant/get/policies with identifiertype AbhaNumber and the member's hyphen-free ABHA number and sees the product returned. Months later the same member is admitted; the hospital's HMIS runs the identifier cascade (ABHA, then member id, then mobile) against this endpoint, caches the result, and proceeds to /v1/insuranceplan/request and /v1/preauth/submit addressed to the TPA's participant code taken from processingID. + + ### Specification + + Chapter [Creating and updating a participant](/docs/nhcx/v1/getting-started/creating-and-updating-a-participant) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + identifiertype: + type: string + identifiervalue: + type: string + example: + identifiertype: MemberId + identifiervalue: MEM-2026-000123 + responses: + "200": + description: Returns HTTP 200 with ParticipantListResponse (optional participantdetails array of participantcode, participantname, address, state). + content: + application/json: + schema: + type: object + properties: + participantdetails: + type: array + items: + type: object + properties: + participantcode: + type: string + participantname: + type: string + address: + type: string + state: + type: string + example: + participantdetails: + - participantcode: 100234@sbx + participantname: Demo Health Insurance Co + address: Plot 12, Sector 5, Gurugram + state: Haryana + /update/abhanumber: + post: + operationId: registry_update_abhanumber + x-abdm-use-case: Participant registry + tags: + - Participant registry + summary: Update ABHA number + description: |- + Replaces a placeholder (dummy) ABHA number with the beneficiary's real ABHA number in the ABHA_AUTH_TRANSACTION table. + + ### Business purpose + + Beneficiaries are sometimes onboarded before their real ABHA is known, using a placeholder value. Because the member layer and the Patient resource both key on the ABHA number, a placeholder that is never corrected leaves the beneficiary undiscoverable and breaks the identifier rules for claim bundles. This endpoint, tagged Retrieving API and implemented by updateAbhaNumberController, lets the placeholder be swapped for the real number so that later policy lookups and claim transactions line up. The docs describe it as updating the ABHA number in the ABHA_AUTH_TRANSACTION table. + + ### When to use + + Use it once the beneficiary's genuine ABHA number becomes available after an onboarding that used a dummy value, and before relying on ABHA-keyed policy lookups or building Patient identifiers for coverage-eligibility, preauth (workflow code 12) or claim bundles. The documentation does not restrict which participant role calls it, so treat it as a member-data correction step rather than part of any transaction workflow. + + ### Preconditions + + - A valid Bearer token from the client-credentials call (POST /get/session, form-urlencoded client_id, client_secret, grant_type=client_credentials); tokens last 1200 seconds, so refresh before expiry. + - HTTP headers Accept: application/json, Content-Type: application/json and bearer_auth: Bearer (the participant service uses bearer_auth, not Authorization). + - Base path for the participant service: https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice (sandbox) or https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice (production). + - This is a synchronous plain-JSON registry call: no JWE envelope, no x-hcx-* protocol headers and no correlation id are involved. + - Both the placeholder and the real ABHA must be known; the body is UpdateAbhaRequest with two optional strings, dummyAbha and realAbha. + - The gateway's error catalogue expects ABHA numbers in XX-XXXX-XXXX-XXXX form (NHCX-1018), while the member layer stores them without hyphens; the docs do not state which form this endpoint expects, so follow your instance's guidance. + + ### Postconditions + + A successful call returns HTTP 200 with UpdateAbhaResponse, which carries optional successMessage and errorMessage strings. Unusually for this service, the 400, 404 and 500 responses also use UpdateAbhaResponse rather than the registry ErrorResponse envelope, so clients must read errorMessage rather than Error.code on failure. No callback follows. After the update, policy lookups and Patient identifiers should use the real ABHA; any provider-side policy cache built on the placeholder needs a forced refresh. + + ### Common mistakes + + - Parsing failures as ErrorResponse; this endpoint returns UpdateAbhaResponse for 400, 404 and 500 as well as for success. + - Sending an empty body; both fields are optional in the schema, but the operation is meaningless without dummyAbha and realAbha. + - Inconsistent ABHA formatting between systems: NHCX-1018 requires XX-XXXX-XXXX-XXXX at the gateway, while x-hcx-ben-abha-id and the member-layer lookups take the number without hyphens. + - Forgetting to refresh cached policies and stored Patient identifiers that still carry the placeholder. + - Omitting the Accept header or the Bearer prefix on bearer_auth. + + ### Best practices + + - Record both the placeholder and the real ABHA with the timestamp of the change for audit purposes. + - Read successMessage and errorMessage on every response and treat a non-200 status as failure even if the body parses. + - Immediately re-run /participant/get/policies with forceRefresh: true for the affected beneficiary. + - Keep the ABHA formatting rule per field: hyphen-free for member lookups and x-hcx-ben-abha-id, XX-XXXX-XXXX-XXXX where NHCX-1018 applies. + - Never log the token; log the ABHA change with the request identifier only. + + ### Related scenario + + A state scheme enrols a beneficiary in a hurry with a dummy ABHA so that a policy can be linked and an emergency admission can proceed. After discharge the beneficiary completes ABHA creation and the real number is captured. The payer's system calls /update/abhanumber with dummyAbha and realAbha, receives a successMessage, and then calls /participant/get/policies with forceRefresh to make sure the real ABHA resolves the linked product. The hospital's billing team, preparing the final claim, refreshes its own policy cache so that the Claim bundle's Patient identifiers carry the PMJAY member id and the real hyphen-free ABHA. + + ### Specification + + Chapter [Participants and policies](/docs/nhcx/v1/registries) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + dummyAbha: + type: string + realAbha: + type: string + example: + dummyAbha: "99999999999999" + realAbha: "12345678910111" + responses: + "200": + description: A successful call returns HTTP 200 with UpdateAbhaResponse, which carries optional successMessage and errorMessage strings. + content: + application/json: + schema: + type: object + properties: + successMessage: + type: string + example: + successMessage: ABHA number updated successfully + /product/link: + post: + operationId: registry_product_link + x-abdm-use-case: Participant registry + tags: + - Participant registry + summary: Link payer product + description: |- + Registers a product (product id and name) against a payer's participant code, so that it can be referenced in ABHA policy links. + + ### Business purpose + + Products are the payer's catalogue entries that policies[].productid and productname refer to when a beneficiary is linked. This Retrieving API call, described in the OpenAPI document as the API to list products by the payers or insurance companies, is how an insurer places a product in the registry under its own participant code. Doing so makes the product ownership resolvable through /product/getowner and gives providers a stable productId and productName to match against when they resolve coverage for InsurancePlan and preauth. + + ### When to use + + Use it when a payer introduces a new product, and before any /participant/link/abha/policy call that references that product. It is part of payer-side catalogue setup, ahead of member linking and well ahead of any claim-side workflow. When a product is retired, the counterpart /product/delink removes it. The documentation does not describe versioning or renaming of products; treat a rename as de-link and re-link. + + ### Preconditions + + - A valid Bearer token from the client-credentials call (POST /get/session, form-urlencoded client_id, client_secret, grant_type=client_credentials); tokens last 1200 seconds, so refresh before expiry. + - HTTP headers Accept: application/json, Content-Type: application/json and bearer_auth: Bearer (the participant service uses bearer_auth, not Authorization). + - Base path for the participant service: https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice (sandbox) or https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice (production). + - This is a synchronous plain-JSON registry call: no JWE envelope, no x-hcx-* protocol headers and no correlation id are involved. + - The payer or insurance company must already be a registered participant with its own participant code. + - Body is ProductLinkRequest with all three fields required: productid, productname and participantcode. + + ### Postconditions + + On success the endpoint returns HTTP 200 with ParticipantCreateResponse, whose single optional field participant_code is the machine-generated participant identifier on the HCX instance. No callback follows. The product becomes the value that /product/getowner resolves back to the owning participant and that policy links refer to. Failures return 400, 404 or 500 with the ErrorResponse envelope (timestamp plus Error with code, message and trace). + + ### Common mistakes + + - Omitting one of the three required fields; productid, productname and participantcode are all mandatory. + - Using a participantcode in the wrong casing or from the wrong environment (sandbox codes look like 100001@sbx, production codes end in @hcx). + - Referencing a product in a policy link before it has been linked here, so provider-side product matching later fails. + - Expecting product details in the response; only participant_code is returned. + - Missing the Accept header or the Bearer prefix on bearer_auth. + + ### Best practices + + - Keep productid values stable and unique within the payer; providers use productId for product-level matching and productName as the practical policy or coverage code for plan lookup. + - Register products before linking members, and verify with /product/getowner that the product resolves to your participant code. + - Log the participant_code returned with the product identifiers for reconciliation. + - Refresh the Bearer token proactively and retry once on 401. + + ### Related scenario + + An insurer launches a new family floater plan. Before its policy administration system can link any member, it calls /product/link with the product id, the product name that hospitals will see, and the insurer's participant code, receiving its participant_code back in the response. It then checks /product/getowner with the product id to confirm ownership, and begins linking members with /participant/link/abha/policy. Hospitals that later call /participant/get/policies will see the product id and name, use productName for the InsurancePlan lookup and productId for coverage matching in the preauth. + + ### Specification + + Chapter [Participants and policies](/docs/nhcx/v1/registries) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + productid: + type: string + productname: + type: string + participantcode: + type: string + example: + productid: PRD-FLOATER-01 + productname: Family Floater Gold + participantcode: 100234@sbx + responses: + "200": + description: On success the endpoint returns HTTP 200 with ParticipantCreateResponse, whose single optional field participant_code is the machine-generated participant identifier on the HCX instance. + content: + application/json: + schema: + type: object + properties: + participant_code: + type: string + example: + participant_code: 100234@sbx + /product/delink: + post: + operationId: registry_product_delink + x-abdm-use-case: Participant registry + tags: + - Participant registry + summary: De-link payer product + description: |- + Removes a product (product id and name) from a payer's participant code in the registry. + + ### Business purpose + + When a payer withdraws a product from the market or replaces it, the registry entry created by /product/link should be removed so that it is no longer resolvable and cannot be referenced by new member links. The OpenAPI document describes this Retrieving API call as the API to de-link products by the payers or insurance companies. Keeping the catalogue accurate protects providers from matching on retired products when they resolve coverage for InsurancePlan and preauthorisation. + + ### When to use + + Use it when a product is discontinued or renamed (the docs give no rename operation, so de-link and re-link), after the member links that reference it have been handled through /participant/delink/abha/policy. It is a payer-side catalogue maintenance step and is not tied to any claim workflow code. The documentation does not state whether de-linking a product that still has member links is refused, so remove member links first. + + ### Preconditions + + - A valid Bearer token from the client-credentials call (POST /get/session, form-urlencoded client_id, client_secret, grant_type=client_credentials); tokens last 1200 seconds, so refresh before expiry. + - HTTP headers Accept: application/json, Content-Type: application/json and bearer_auth: Bearer (the participant service uses bearer_auth, not Authorization). + - Base path for the participant service: https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice (sandbox) or https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice (production). + - This is a synchronous plain-JSON registry call: no JWE envelope, no x-hcx-* protocol headers and no correlation id are involved. + - The payer or insurance company must already be a registered participant with its own participant code. + - Body is ProductLinkRequest with all three fields required: productid, productname and participantcode. + + ### Postconditions + + On success the endpoint returns HTTP 200 with ParticipantCreateResponse containing the optional participant_code. No callback follows. The product should no longer resolve to the payer through /product/getowner. Failures return 400, 404 or 500 with the ErrorResponse envelope. Provider-side policy caches are documented as permanent, so a product that hospitals have already cached will still appear there until they pass forceRefresh: true. + + ### Common mistakes + + - Sending only productid; ProductLinkRequest requires productid, productname and participantcode for de-link as well. + - De-linking a product while members are still linked to it, then finding those member links inconsistent; de-link members first. + - Using a participantcode from the wrong environment or with wrong casing. + - Assuming providers see the change immediately; their cached policies persist without TTL. + - Missing the Accept header or sending the token without the Bearer prefix. + + ### Best practices + + - Enumerate and de-link affected member policies before removing the product. + - Use the exact productid and productname that were registered with /product/link. + - Verify afterwards with /product/getowner that the product no longer resolves to your participant code. + - Log the request and the returned participant_code for audit. + - Refresh the Bearer token proactively and retry once on 401. + + ### Related scenario + + An insurer retires its old Individual Health Silver product at the end of a policy year, having migrated every member to a successor product. Its system first runs /participant/delink/abha/policy for each member still linked to the old product, then calls /product/delink with the product id, product name and the insurer's participant code. A confirmation call to /product/getowner shows the product no longer resolves. The insurer notifies its network hospitals, whose desks force a refresh of cached policies so that the next coverage-eligibility check and preauthorisation reference the successor product. + + ### Specification + + Chapter [Participants and policies](/docs/nhcx/v1/registries) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + productid: + type: string + productname: + type: string + participantcode: + type: string + example: + productid: PRD-INDIV-07 + productname: Individual Health Silver + participantcode: 100234@sbx + responses: + "200": + description: On success the endpoint returns HTTP 200 with ParticipantCreateResponse containing the optional participant_code. + content: + application/json: + schema: + type: object + properties: + participant_code: + type: string + example: + participant_code: 100234@sbx + /product/getowner: + post: + operationId: registry_product_getowner + x-abdm-use-case: Participant registry + tags: + - Participant registry + summary: Get product owner + description: |- + Resolves a product id to the participant code of the payer that owns it. + + ### Business purpose + + Given only a product identifier, an integrator often needs to know which payer stands behind it. This Retrieving API call takes a ProductOwnerRequest with productid and returns ParticipantCreateResponse, whose participant_code is the owning participant's identifier on the HCX instance. That makes it a useful bridge between a product seen on a policy document or in a policy lookup and the participant code that must go into routing. Note that the OpenAPI description reads "This API is to generate the product Id and product Name", which does not match the response schema; the source does not resolve this conflict. + + ### When to use + + Use it when you hold a product id but not the payer participant code, for example while normalising a policy lookup or verifying a newly linked product. It is a synchronous helper in the member layer, used before InsurancePlan retrieval, coverage eligibility or preauthorisation rather than during them. Payers use it after /product/link or /product/delink to confirm the registry state. + + ### Preconditions + + - A valid Bearer token from the client-credentials call (POST /get/session, form-urlencoded client_id, client_secret, grant_type=client_credentials); tokens last 1200 seconds, so refresh before expiry. + - HTTP headers Accept: application/json, Content-Type: application/json and bearer_auth: Bearer (the participant service uses bearer_auth, not Authorization). + - Base path for the participant service: https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice (sandbox) or https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice (production). + - This is a synchronous plain-JSON registry call: no JWE envelope, no x-hcx-* protocol headers and no correlation id are involved. + - Body is ProductOwnerRequest with a single optional string, productid; supply it, since the lookup has no other input. + - The product must have been registered by its payer through /product/link. + + ### Postconditions + + Returns HTTP 200 with ParticipantCreateResponse containing the optional participant_code of the owning participant. No callback follows and no state changes. Failures return 400, 404 or 500 with the ErrorResponse envelope. The returned code identifies the payer (the payerid used in policy links); remember that for NHCX routing the receiver code should come from the processingID given by the get-policies response, which may be a TPA rather than this owner. + + ### Common mistakes + + - Using the returned participant_code directly as x-hcx-recipient_code when the payer is processed by a TPA; NHA's common mistake 7 says the receiver code is the processingID from get/Policies. + - Expecting product name or other product details in the response; only participant_code is returned. + - Sending an empty body; productid is optional in the schema but the lookup needs it. + - Confusing this endpoint with /participant/getProductIdName, which carries the same description but a different request shape. + - Omitting the Accept header or the Bearer prefix. + + ### Best practices + + - Treat the result as the product owner (payerid), then resolve the effective receiver through the policy lookup. + - Cache owner lookups by productid; ownership changes rarely and only through /product/link and /product/delink. + - Handle a missing participant_code gracefully; every field in the response is optional. + - Refresh the Bearer token proactively and retry once on 401. + + ### Related scenario + + A hospital receives a scanned policy card that shows only a product id, and the patient's ABHA-based policy lookup returned more than one payer. The HMIS calls /product/getowner with the product id and gets back the participant code of the insurer that owns it, which lets the desk pick the right entry from the /participant/get/policies result. With the matched policy in hand the system reads the processingID as the receiver code, requests the plan through /v1/insuranceplan/request and goes on to submit the preauthorisation. + + ### Specification + + Chapter [Participants and policies](/docs/nhcx/v1/registries) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + productid: + type: string + example: + productid: PRD-FLOATER-01 + responses: + "200": + description: Returns HTTP 200 with ParticipantCreateResponse containing the optional participant_code of the owning participant. + content: + application/json: + schema: + type: object + properties: + participant_code: + type: string + example: + participant_code: 100234@sbx + /participant/getProductIdName: + post: + operationId: registry_participant_getproductidname + x-abdm-use-case: Participant registry + tags: + - Participant registry + summary: Get product id and name + description: |- + Retrieving API described as generating the product id and product name; declared with a bare string request body and a participant-code response. + + ### Business purpose + + The OpenAPI document describes this endpoint with the same sentence as /product/getowner, "This API is to generate the product Id and product Name", and it belongs to the payer product lifecycle alongside /product/link, /product/delink and /product/getowner. Its documented purpose is to resolve product identity information within the participant service. The specification is thin: the request body is declared as a bare string, the response is ParticipantCreateResponse (participant_code only), and the operationId participantCreatePost is reused from the participant-creation endpoints, so treat the operationId as non-unique. + + ### When to use + + Use it only where your NHCX instance documents a concrete contract for it, typically when you need product identity resolved from a string key held by the participant service. It plays no part in claim-side workflows and is not listed in either sandbox exit checklist. For resolving a product to its owning payer, /product/getowner has the clearer request schema; for discovering a member's products, use /participant/get/policies. + + ### Preconditions + + - A valid Bearer token from the client-credentials call (POST /get/session, form-urlencoded client_id, client_secret, grant_type=client_credentials); tokens last 1200 seconds, so refresh before expiry. + - HTTP headers Accept: application/json, Content-Type: application/json and bearer_auth: Bearer (the participant service uses bearer_auth, not Authorization). + - Base path for the participant service: https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice (sandbox) or https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice (production). + - This is a synchronous plain-JSON registry call: no JWE envelope, no x-hcx-* protocol headers and no correlation id are involved. + - The request body is declared in the OpenAPI document as a bare JSON string rather than an object; the docs do not say what the string should contain. + - The product concerned should have been registered by its payer through /product/link. + + ### Postconditions + + Returns HTTP 200 with ParticipantCreateResponse, whose only field, participant_code, is optional. No callback follows and no state change is documented. Failures return 400, 404 or 500 with the ErrorResponse envelope. Because the description promises a product id and name while the schema returns a participant code, verify the actual body returned by your instance before depending on either interpretation. + + ### Common mistakes + + - Posting a JSON object when the schema declares a bare string body, or the reverse, and getting a 400. + - Expecting productid and productname fields in the response; the declared response carries only participant_code. + - Confusing it with /product/getowner because both carry the same description. + - Matching on operationId participantCreatePost in generated clients, which collides with the participant-creation operations. + - Omitting the Accept header or the Bearer prefix on bearer_auth. + + ### Best practices + + - Confirm the request and response contract against your instance's live OpenAPI document before integrating. + - Prefer /product/getowner for owner resolution and /participant/get/policies for member products; use this call only where it is specifically required. + - Log both the raw request string and the full response body so the actual behaviour can be reconciled with the specification. + - Keep the Bearer token fresh and retry once on 401. + + ### Related scenario + + A TPA's integration team is generating a client from the participant service OpenAPI document and notices that /participant/getProductIdName shares its operationId with participant creation and its description with /product/getowner. Rather than wire it into the admission flow, they exercise it once in the sandbox with a product key, record the participant_code returned, and decide to rely on /product/getowner and /participant/get/policies for production. The member journey therefore runs link, get policies, InsurancePlan request and preauthorisation without this call. + + ### Specification + + Chapter [Participants and policies](/docs/nhcx/v1/registries) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + _note: + type: string + _body: + type: string + example: + _note: The OpenAPI document declares the request body as a bare JSON string; shown here as the string value that would be posted. + _body: PRD-FLOATER-01 + responses: + "200": + description: Returns HTTP 200 with ParticipantCreateResponse, whose only field, participant_code, is optional. + content: + application/json: + schema: + type: object + properties: + participant_code: + type: string + example: + participant_code: 100234@sbx +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + description: "On every NHCX call, the token goes in a header called `bearer_auth`, with the word `Bearer` and a space in front. The sources are not unanimous: the authentication page and the FAQ both write the example as `Authorization`, and the notification endpoint uses `Authorization`. The safe course, and what the adapter does, is to send both headers with the same value." + parameters: + BearerAuth: + name: bearer_auth + in: header + required: true + description: It is `bearer_auth`, not `Authorization`, on NHCX's own endpoints. + schema: + type: string + example: Bearer diff --git a/catalogue/openapi/nhcx/v1/nhcx-session.yaml b/catalogue/openapi/nhcx/v1/nhcx-session.yaml new file mode 100644 index 000000000..8f8d33608 --- /dev/null +++ b/catalogue/openapi/nhcx/v1/nhcx-session.yaml @@ -0,0 +1,184 @@ +# NHCX session, from the NHCX package's Bruno folder apis/01-session. +# +# Written by the package's system/build-ekadocs.mjs (make ekadocs); change the .bru +# requests there and port again rather than editing this file. +# +# Rules this file follows: catalogue/openapi/CONVENTIONS.md +openapi: 3.1.1 +info: + x-portal: + module: session + label: Session + position: 1 + title: NHCX session + summary: The token does not come from NHCX. + description: |- + The Session calls on the National Health Claims Exchange (NHCX): 1 operation. + + The token does not come from NHCX. + + Guides that use these calls: [Session token](/docs/nhcx/v1/getting-started/session-token), [Quickstart](/docs/nhcx/v1/getting-started/quickstart). + version: nhcx-v1 + license: + name: MIT + identifier: MIT + contact: + name: NHCX sandbox + url: https://hcxsbx.abdm.gov.in + x-abdm-gateway: nhcx + x-abdm-module: session + x-abdm-phase: 1 + x-abdm-roles: + - provider + - payer +x-abdm-sources: + - file: nhcx-package/apis/01-session + role: upstream + hash: sha256:04dbfe1121fdee8812399abb612d00cac445a312b9a88dc30881f34ce2b1059b + note: The package's Bruno collection, one request per operation. + - file: nhcx-package/baseurl.yaml + role: upstream + hash: sha256:88515b7b29c6b349a131e016c80774436ea16a29738db743b4cc3a24cbd42453 + note: The sandbox and production hosts. +servers: + - url: https://dev.abdm.gov.in + description: Sandbox, ABDM session token. + - url: https://apis.abdm.gov.in + description: Production. ABDM's published production gateway. Confirm it in your onboarding letter. +tags: + - name: Session + description: The token does not come from NHCX. +security: + - bearerAuth: [] +paths: + /api/hiecm/gateway/v3/sessions: + post: + operationId: session_session_token + x-abdm-atom: nhcx.endpoint.session-token + x-abdm-use-case: Session + tags: + - Session + summary: Session token + description: |- + Mints the ABDM gateway session token that every NHCX call carries, from the client ID and secret issued for Milestone 1. + + ### Business purpose + + The token does not come from NHCX. It comes from the ABDM gateway, and one token serves every call: the participant service, the use-case endpoints and the status check. Nothing else in this collection works without it, which is why the post-response script below stores it in `token`, so that running this request once arms the rest of the collection. + + ### When to use + + Before the first call, and again whenever the token you hold is more than a few minutes old or any call answers `401`. Build against this v3 address. + + ### Preconditions + + - Milestone 1 is complete and you hold its client ID and secret. + - `REQUEST-ID` is a fresh UUID generated for this call. + - `TIMESTAMP` is the current time in UTC, ISO 8601 with milliseconds and a trailing `Z`, as in `2026-09-04T06:15:51.975Z`, taken from a synchronised system clock. + - `X-CM-ID` is `sbx` on the sandbox. + - The body carries `grantType` `client_credentials`, which the v3 address requires. + + ### Postconditions + + The gateway returns `accessToken`, `expiresIn`, `refreshToken` and `tokenType` `bearer`. On every NHCX call the token goes in `bearer_auth` as `Bearer `. Some pages and the notification endpoint use `Authorization` instead, so this collection sends both with the same value. The documents put the token's life at 300, 1200 and 6000 seconds in different places, so do not rely on any of them. + + ### Common mistakes + + - Reusing a `REQUEST-ID` copied from an example instead of generating a new one. + - A `TIMESTAMP` built by hand or read from a drifted clock, which is refused. + - Omitting `grantType`, as older samples do, which the v3 address rejects. + - Sending the token without the `Bearer ` prefix, the portal's own example of a `401`. + - Retrying a `401` with the same token. It fails the same way. + - Writing the token or the client secret to a log. + + ### Best practices + + - Keep the token together with the time you got it, and fetch a new one before a call if it is more than a few minutes old. + - On any `401`, get a new token and retry that call once. + - Send the token on both `bearer_auth` and `Authorization`. + - Keep the clock synchronised with NTP and let a date library format the timestamp. + + ### Related scenario + + A hospital's integration starts its first eligibility check of the day. It posts this request with a new `REQUEST-ID`, the current UTC `TIMESTAMP` and `X-CM-ID` `sbx`, stores the `accessToken` with the time it arrived, and sends it on the check as `bearer_auth: Bearer `. Later a claim call answers `401 Sender is not authorized to execute the operation`. The integration mints a fresh token, retries the claim once, and it goes through. + + ### Specification + + Chapter [Base URLs](/docs/nhcx/v1/getting-started/base-urls) of the NHCX integration specification. + security: [] + parameters: + - $ref: "#/components/parameters/RequestId" + - $ref: "#/components/parameters/Timestamp" + - $ref: "#/components/parameters/XCmId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + clientId: + type: string + clientSecret: + type: string + grantType: + type: string + example: + clientId: + clientSecret: + grantType: client_credentials + responses: + "200": + description: The gateway returns `accessToken`, `expiresIn`, `refreshToken` and `tokenType` `bearer`. + content: + application/json: + schema: + type: object + properties: + accessToken: + type: string + expiresIn: + type: integer + refreshTokenIn: + type: integer + refreshToken: + type: string + tokenType: + type: string + example: + accessToken: eyJhbGciOiJSUzI1NiIs... + expiresIn: 300 + refreshTokenIn: 300 + refreshToken: eyJhbGciOiJSUzI1NiIs... + tokenType: bearer +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + description: "On every NHCX call, the token goes in a header called `bearer_auth`, with the word `Bearer` and a space in front. The sources are not unanimous: the authentication page and the FAQ both write the example as `Authorization`, and the notification endpoint uses `Authorization`. The safe course, and what the adapter does, is to send both headers with the same value." + parameters: + RequestId: + name: REQUEST-ID + in: header + required: true + description: "`REQUEST-ID` is a fresh UUID that you generate for every call. Sending the same one twice is the mistake to avoid; generate it, do not copy it from an example." + schema: + type: string + example: + Timestamp: + name: TIMESTAMP + in: header + required: true + description: "`TIMESTAMP` is the current time in UTC, ISO 8601 with milliseconds and a trailing `Z`, as in `2026-09-04T06:15:51.975Z`. A clock that has drifted will be refused, so take the time from the system rather than constructing it by hand. How to produce it in each language is at the end of this chapter." + schema: + type: string + example: + XCmId: + name: X-CM-ID + in: header + required: true + description: "`X-CM-ID` names the environment. It is `sbx` on the sandbox. The mirror and the adapter both use lowercase." + schema: + type: string + example: sbx diff --git a/catalogue/openapi/nhcx/v1/nhcx-status.yaml b/catalogue/openapi/nhcx/v1/nhcx-status.yaml new file mode 100644 index 000000000..ea9a71834 --- /dev/null +++ b/catalogue/openapi/nhcx/v1/nhcx-status.yaml @@ -0,0 +1,789 @@ +# NHCX status and search, from the NHCX package's Bruno folder apis/08-status. +# +# Written by the package's system/build-ekadocs.mjs (make ekadocs); change the .bru +# requests there and port again rather than editing this file. +# +# Rules this file follows: catalogue/openapi/CONVENTIONS.md +openapi: 3.1.1 +info: + x-portal: + module: status + label: Status and search + position: 8 + title: NHCX status and search + summary: Asynchronous exchanges lose messages, stall in queues and outlive the shift of the desk operator who started them. + description: |- + The Status and search calls on the National Health Claims Exchange (NHCX): 3 operations, and 3 callbacks you host. + + Asynchronous exchanges lose messages, stall in queues and outlive the shift of the desk operator who started them. + + Guides that use these calls: [Predetermination, status and search](/docs/nhcx/v1/reference/fhir/predetermination-status-and-search), [Accepted with 202, and no callback arrives](/docs/nhcx/v1/troubleshooting/accepted-then-no-callback), [Responses arrive against the wrong request](/docs/nhcx/v1/troubleshooting/responses-arrive-against-the-wrong-request). + version: nhcx-v1 + license: + name: MIT + identifier: MIT + contact: + name: NHCX sandbox + url: https://hcxsbx.abdm.gov.in + x-abdm-gateway: nhcx + x-abdm-module: status + x-abdm-phase: 1 + x-abdm-roles: + - provider + - payer +x-abdm-sources: + - file: nhcx-package/apis/08-status + role: upstream + hash: sha256:e5e337293f9f33700c21ac9873f20c627e22a26e0cbb9338ef46acb6ac3cbfe2 + note: The package's Bruno collection, one request per operation. + - file: nhcx-package/baseurl.yaml + role: upstream + hash: sha256:88515b7b29c6b349a131e016c80774436ea16a29738db743b4cc3a24cbd42453 + note: The sandbox and production hosts. +servers: + - url: https://apisbx.abdm.gov.in/hcx + description: Sandbox, NHCX exchange. + - url: https://apisprod.nha.gov.in/hcx + description: Production. +tags: + - name: Status and search + description: Asynchronous exchanges lose messages, stall in queues and outlive the shift of the desk operator who started them. +security: + - bearerAuth: [] +paths: + /v1/status: + post: + operationId: status_v1_status + x-abdm-atom: nhcx.endpoint.status + x-abdm-use-case: Status and search + tags: + - Status and search + summary: Status check + description: |- + Sender asks NHCX where its own in-flight request stands; the gateway answers request.queued or request.dispatched, and only dispatched yields a callback. + + ### Business purpose + + Asynchronous exchanges lose messages, stall in queues and outlive the shift of the desk operator who started them. The Status API exists so the original sender can find out which side of the exchange is holding a request without resubmitting it and creating a duplicate. It answers the hospital desk's most common question, where is my preauth, by telling it whether the gateway has forwarded the request to the payer at all. Providers, payers and TPAs all benefit because it separates gateway delay from payer delay before anyone escalates. + + ### When to use + + Call it after a submission whose callback has not arrived within your operational tolerance, for example a preauth (workflow 12) or claim (workflow 15) still awaiting its on_submit. It is only for requests you originated; x-hcx-correlation_id carries the x-hcx-api_call_id of the request being checked (the Status sheet: "same as API caller ID of the request that requires a status check"). Send x-hcx-status request.initiated. x-hcx-workflow_id and x-hcx-use_case (New, Enhancement or Resubmit) are optional on this call; x-hcx-ben-abha-id is mandatory. If the reply is request.queued, the payer has never seen the request and no callback will come; if request.dispatched, the payer holds it and will answer on the status callback. + + ### Preconditions + + - You are the original sender of the request being queried and have its api_call_id persisted. + - Valid Bearer token; the request body is a JWE per RFC-7516 like every protocol API. + - The payload inside the JWE is an empty string: no bundle, no Task, no resource. The Status sheet of the requests-and-responses workbook says "Payload should be empty string". The sandbox exit checklists word it as the "encrypted payload of request for which the status is seeking for" and describe no bundle for it. + - Protected header with sender_code, recipient_code, a fresh api_call_id, the original request's api_call_id as correlation_id, an IST timestamp and status request.initiated. + - HTTP headers Accept, Content-Type and bearer_auth. + + ### Postconditions + + The gateway validates the request and returns the protocol status synchronously in the HTTP response: HTTP 202 with a StatusSuccessResponse whose result carries sender_code, recipient_code, entity_type and protocol_status of request.queued or request.dispatched. On request.queued nothing further happens; the original request is still inside NHCX. On request.dispatched the gateway forwards the status request to the recipient, who responds asynchronously on the status callback (named /v1/on_status and /hcx/on_status in different sentences of the source). A 404 against a correlation id you believe you sent strongly suggests the original submission never landed; NHCX-1012 reports no records for the api caller id. + + ### Common mistakes + + - Minting a fresh correlation id for the status call itself instead of setting it to the original request's api_call_id; this is the single most common status-integration error and yields NHCX-1012 or 404. + - Polling in a tight loop; a request.queued answer means the gateway is still working and there is no callback for that branch. + - Resubmitting the original request after a request.queued response, which duplicates it (NHCX-1006). + - Reading the Appendix C lifecycle statuses (request.acknowledged, request.queried, request.complete) as Status API outcomes; the API returns only the two gateway values. + - Querying a correlation id after NHCX deleted it following five failed deliveries; it is gone. + - Querying a request another participant originated; senders may only query their own. + + ### Best practices + + - Persist the correlation id against the case record before every submission so a status check is always possible. + - Use a bounded, spaced schedule tied to the correlation id, then escalate; do not poll aggressively. + - Branch on protocol_status: wait on request.queued, expect the status callback on request.dispatched. + - Use a fresh x-hcx-api_call_id per status call and IST timestamps. + - Treat Status as transport position only; the decision lives in the original on_ callback or a Search for the claim document. + - Implement the status callback and v1/error so both branches of the answer have somewhere to land. + + ### Related scenario + + A hospital's TPA desk submitted a preauth on /v1/preauth/submit at 09:00 and by 13:00 nothing has arrived on /v1/preauth/on_submit. Rather than resubmit, the integration posts /v1/status with the preauth's correlation id. The synchronous reply shows protocol_status request.dispatched, so the request is with the payer, not stuck at the gateway; the desk stops worrying about a lost message and waits for the status callback and the eventual preauth decision. Had the reply been request.queued, the desk would have waited on the gateway and, if the delay persisted, escalated to NHCX support with the correlation id. + + ### Specification + + Chapter [NHCX adapter (Optional)](/docs/nhcx/v1/getting-started/nhcx-adapter) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - $ref: "#/components/parameters/XHcxSenderCode" + - $ref: "#/components/parameters/XHcxRecipientCode" + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxTimestamp" + - $ref: "#/components/parameters/XHcxStatus" + - $ref: "#/components/parameters/XHcxBenAbhaId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOiIxMDAwMDA0NDQ2QGhjeCJ9.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: "The gateway validates the request and returns the protocol status synchronously in the HTTP response: HTTP 202 with a StatusSuccessResponse whose result carries sender_code, recipient_code, entity_type and protocol_status of request.queued or request.dispatched." + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 25/08/2026 13:00:00:215 + api_call_id: e5f6a7b8-c9d0-1234-ef01-345678901234 + correlation_id: 11223344-5566-7788-99aa-bbccddeeff00 + result: + sender_code: 1000004446@hcx + recipient_code: 1518@hcx + entity_type: preauth + protocol_status: request.dispatched + error: + code: "" + message: "" + /v1/search/submit: + post: + operationId: status_v1_search_submit + x-abdm-atom: nhcx.endpoint.search-submit + x-abdm-use-case: Status and search + tags: + - Status and search + summary: Search submit + description: |- + Authorised entity such as NHA or IRDAI sends a Task to retrieve claim information for a case; the payer returns the documents on the search callback. + + ### Business purpose + + Regulators and scheme authorities need to see what was actually claimed and decided for a given case without being a party to the original exchange. The Search API is that privileged pull path: an authorised entity submits a Task naming the case, and the payer supplies the claim documents. It supports oversight, audit and dispute review, and it lets payers answer such requests through the same encrypted, correlated channel as everything else on NHCX. The documented callers are NHA and IRDAI; a provider integration usually implements only the responding side. + + ### When to use + + Use it when an authorised entity needs the claim documents for a known case number, for example during a regulatory audit or a dispute. It is a pull, not a lifecycle step, and sits outside the workflow-code sequence. The protected header's x-hcx-correlation_id carries the correlation id of the request being queried, and x-hcx-status is request.initiated. The result arrives asynchronously on /v1/search/on_submit with task type code=poll; if the search is for a claim document, the callback payload is the ClaimResponse for the reference number. + + ### Preconditions + + - The caller is an entity authorised to search claim information (the source names NHA and IRDAI) and is registered on NHCX with a valid Bearer token. + - Request body is a JWE per RFC-7516 with protocol headers per the ProtocolHeader schema. + - Domain payload is an encrypted Task built per the TaskBundle, with the entity being queried referenced in the about element using the sender's reference id. + - Protected header carries sender_code, recipient_code, a fresh api_call_id, the correlation id of the request being queried, an IST timestamp and status request.initiated. + - HTTP headers Accept, Content-Type and bearer_auth. + + ### Postconditions + + The gateway returns HTTP 202 with a StatusSuccessResponse (timestamp, api_call_id, correlation_id, result with sender_code, recipient_code, entity_type and protocol_status, and error), or 400, 404 or 500 in the same envelope. It forwards the Task to the payer, who responds later on /v1/search/on_submit with the claim document: a ClaimResponse whose basedOn carries the sender's reference id and whose about carries the recipient's reference id and the current status of the response entity. No case state changes; Search only reads. + + ### Common mistakes + + - Using Search as a general status lookup; Status answers where a request is, Search returns documents. + - Sending a CommunicationRequest as the domain payload; Search uses a Task (Status is the one that uses CommunicationRequest). + - Forgetting the about reference with the sender's reference id, leaving the payer with nothing to search for (PAYR-1102 Invalid search parameter requested). + - Minting a new correlation id rather than carrying the one for the request being queried. + - Calling it from a participant that is not an authorised entity; the description scopes it explicitly. + - Expecting the documents in the synchronous 202. + + ### Best practices + + - Reference the case in Task.about using the sender's own reference id and keep it consistent with the correlation id you carry. + - Persist the correlation id so the on_submit result can be matched. + - Use fresh api_call_id values, IST timestamps and request.initiated on the outbound header. + - Handle 404 as a signal that the correlation id is unknown to the gateway, not as a retry trigger. + - Implement v1/error and the on_submit receiver before submitting searches. + + ### Related scenario + + A scheme authority reviewing a grievance about a rejected claim needs the payer's adjudication record. Its integration posts /v1/search/submit with a Task whose about element names the case and whose header carries the claim's correlation id. The gateway acknowledges with 202 and forwards the Task to the payer. The payer's system locates the ClaimResponse for the reference number and returns it on /v1/search/on_submit with basedOn holding the authority's reference and about holding the payer's reference and current status. The authority then compares it with the provider's original /v1/claim/submit bundle. + + ### Specification + + Chapter [NHCX adapter (Optional)](/docs/nhcx/v1/getting-started/nhcx-adapter) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - $ref: "#/components/parameters/XHcxSenderCode" + - $ref: "#/components/parameters/XHcxRecipientCode" + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - name: x-hcx-correlation_id + in: header + required: true + description: The thread. See the rule below. Mandatory on the envelope. + schema: + type: string + example: + - $ref: "#/components/parameters/XHcxTimestamp" + - $ref: "#/components/parameters/XHcxStatus" + - $ref: "#/components/parameters/XHcxBenAbhaId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOiJOSEExQGhjeCJ9.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: The gateway returns HTTP 202 with a StatusSuccessResponse (timestamp, api_call_id, correlation_id, result with sender_code, recipient_code, entity_type and protocol_status, and error), or 400, 404 or 500 in the same envelope. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 25/08/2026 14:00:00:098 + api_call_id: f6a7b8c9-d0e1-2345-f012-456789012345 + correlation_id: 33445566-7788-99aa-bbcc-ddeeff001122 + result: + sender_code: 1000004446@hcx + recipient_code: 1518@hcx + entity_type: task + protocol_status: request.queued + error: + code: "" + message: "" + /v1/search/on_submit: + post: + operationId: status_v1_search_on_submit + x-abdm-atom: nhcx.endpoint.search-on-submit + x-abdm-use-case: Status and search + tags: + - Status and search + summary: Search result callback + description: |- + Callback returning a search result for task type code=poll; for a claim-document search the payload is the ClaimResponse for the reference number. + + ### Business purpose + + This is how a payer answers an authorised entity's search. It completes the oversight loop: the regulator or scheme authority asked for the claim documents for a case, and the payer returns the adjudication record through NHCX rather than by email or portal download. That keeps the answer encrypted, correlated to the original request and auditable. Providers benefit indirectly, because disputes and audits can be resolved from the record of what was actually submitted and decided rather than from reconstructed paperwork. + + ### When to use + + The payer calls it after receiving a /v1/search/submit Task, acknowledging it with 202 within 30 seconds and locating the requested documents. The task type code=poll is the discriminator that tells the recipient this is a search poll and not another Task-driven flow. For a claim document the domain payload is the ClaimResponse for the reference number, with basedOn holding the sender's reference id and about holding the recipient's reference id and the current status. Carry the same x-hcx-correlation_id as the search and a responder status such as response.complete. + + ### Preconditions + + - The inbound search Task was decrypted and its correlation id, status and workflow id captured; the 202 acceptance body was already returned. + - The payer is a registered participant with a valid Bearer token and the requester's certificate for encryption. + - The response is a JWE whose plaintext carries the ClaimResponse (for claim-document searches) with basedOn and about populated as documented; the loosely typed HcxOnSearchBody requires only a type property. + - Protected header echoes the search's x-hcx-correlation_id, carries a fresh api_call_id, an IST timestamp and a responder status. + + ### Postconditions + + The gateway returns HTTP 202 with the StatusSuccessResponse envelope (or 400, 404, 500 in the same shape) and delivers the result to the requester's registered endpoint, which must acknowledge with 202 within 30 seconds. The requester reads the recipient's reference id and the current status of the response entity from the about element. Nothing about the underlying claim changes; the search is read-only. The endpoint is tagged V1.0 APIs-Provider side because the callback is delivered to the provider side of the exchange, with operationId hcxOnSearchPost. + + ### Common mistakes + + - Returning the search result in the synchronous 202 instead of on this callback. + - Minting a new correlation id on the response so the requester cannot match it (NHCX-1010). + - Omitting basedOn or about, or swapping them: basedOn carries the sender's id, about the recipient's id and current status. + - Sending a Task or bare Bundle where the claim-document search expects the ClaimResponse resource. + - Reading the ClaimResponse outcome as approval without checking adjudication; a rejected claim still carries outcome complete. + - Missing the 30-second window on the inbound search, which causes redeliveries. + + ### Best practices + + - Key the search on the sender's reference id from Task.about and echo it in basedOn. + - Populate about with your own reference id and the current status so the requester needs no further call. + - Return 202 to the inbound search first, resolve documents asynchronously, then post this callback. + - Be idempotent on correlation id; the same search may be redelivered up to five times. + - Use a fresh api_call_id, IST timestamp and a responder status from response.complete, response.partial or response.error. + + ### Related scenario + + An insurer receives a search Task from the scheme authority for a claim its TPA rejected last quarter. The gateway-facing endpoint acknowledges with 202, and a worker retrieves the stored ClaimResponse for the reference number. The TPA posts /v1/search/on_submit with the ClaimResponse, basedOn set to the authority's reference id and about set to the insurer's claim id and current status, under the same correlation id as the search. The authority's system acknowledges within 30 seconds and the reviewer compares the adjudication against the provider's original claim and any reprocess Task submitted on /v1/task/submit. + + ### Specification + + Chapter [NHCX adapter (Optional)](/docs/nhcx/v1/getting-started/nhcx-adapter) of the NHCX integration specification. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + - name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - name: x-hcx-correlation_id + in: header + required: true + description: The thread. See the rule below. Mandatory on the envelope. + schema: + type: string + example: + - $ref: "#/components/parameters/XHcxTimestamp" + - name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: response.complete + - $ref: "#/components/parameters/XHcxBenAbhaId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOiIxNTE4QGhjeCJ9.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: The gateway returns HTTP 202 with the StatusSuccessResponse envelope (or 400, 404, 500 in the same shape) and delivers the result to the requester's registered endpoint, which must acknowledge with 202 within 30 seconds. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 25/08/2026 14:20:00:341 + api_call_id: a7b8c9d0-e1f2-3456-0123-567890123456 + correlation_id: 33445566-7788-99aa-bbcc-ddeeff001122 + result: + sender_code: 1518@hcx + recipient_code: 1000004446@hcx + entity_type: task + protocol_status: request.queued + error: + code: "" + message: "" +webhooks: + v1_status: + post: + operationId: status_webhook_v1_status + x-abdm-atom: nhcx.callback.status + x-abdm-triggered-by: status_v1_status + x-abdm-use-case: Webhooks + tags: + - Status and search + summary: Receive status check + description: |- + Hosted by the payer. The exchange posts this message to the `endpoint_url` you registered, at `/v1/status`, with the headers and the sealed payload the sender posted. Answer HTTP 202 with the receipt first and process afterwards; [Receiving a callback](/docs/nhcx/v1/getting-started/receiving-a-callback) has the rules. + + Sender asks NHCX where its own in-flight request stands; the gateway answers request.queued or request.dispatched, and only dispatched yields a callback. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - $ref: "#/components/parameters/XHcxSenderCode" + - $ref: "#/components/parameters/XHcxRecipientCode" + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - $ref: "#/components/parameters/XHcxCorrelationId" + - $ref: "#/components/parameters/XHcxTimestamp" + - $ref: "#/components/parameters/XHcxStatus" + - $ref: "#/components/parameters/XHcxBenAbhaId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOiIxMDAwMDA0NDQ2QGhjeCJ9.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: Received. The receipt names the message it answers; the answer itself follows as a call of your own. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 04/09/2026 11:46:41:305 + api_call_id: + correlation_id: + result: + sender_code: 1000003538@hcx + recipient_code: 1000004446@hcx + entity_type: preauth + protocol_status: request.queued + error: + code: "" + message: "" + v1_search_submit: + post: + operationId: status_webhook_v1_search_submit + x-abdm-atom: nhcx.callback.search-submit + x-abdm-triggered-by: status_v1_search_submit + x-abdm-use-case: Webhooks + tags: + - Status and search + summary: Receive search submit + description: |- + Hosted by the payer. The exchange posts this message to the `endpoint_url` you registered, at `/v1/search/submit`, with the headers and the sealed payload the sender posted. Answer HTTP 202 with the receipt first and process afterwards; [Receiving a callback](/docs/nhcx/v1/getting-started/receiving-a-callback) has the rules. + + Authorised entity such as NHA or IRDAI sends a Task to retrieve claim information for a case; the payer returns the documents on the search callback. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - $ref: "#/components/parameters/XHcxSenderCode" + - $ref: "#/components/parameters/XHcxRecipientCode" + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - name: x-hcx-correlation_id + in: header + required: true + description: The thread. See the rule below. Mandatory on the envelope. + schema: + type: string + example: + - $ref: "#/components/parameters/XHcxTimestamp" + - $ref: "#/components/parameters/XHcxStatus" + - $ref: "#/components/parameters/XHcxBenAbhaId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOiJOSEExQGhjeCJ9.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: Received. The receipt names the message it answers; the answer itself follows as a call of your own. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 04/09/2026 11:46:41:305 + api_call_id: + correlation_id: + result: + sender_code: 1000003538@hcx + recipient_code: 1000004446@hcx + entity_type: preauth + protocol_status: request.queued + error: + code: "" + message: "" + v1_search_on_submit: + post: + operationId: status_webhook_v1_search_on_submit + x-abdm-atom: nhcx.callback.search-on-submit + x-abdm-triggered-by: status_v1_search_on_submit + x-abdm-use-case: Webhooks + tags: + - Status and search + summary: Receive search result callback + description: |- + Hosted by the provider. The exchange posts this message to the `endpoint_url` you registered, at `/v1/search/on_submit`, with the headers and the sealed payload the sender posted. Answer HTTP 202 with the receipt first and process afterwards; [Receiving a callback](/docs/nhcx/v1/getting-started/receiving-a-callback) has the rules. + + Callback returning a search result for task type code=poll; for a claim-document search the payload is the ClaimResponse for the reference number. + parameters: + - $ref: "#/components/parameters/BearerAuth" + - name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + - name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + - $ref: "#/components/parameters/XHcxApiCallId" + - $ref: "#/components/parameters/XHcxRequestId" + - name: x-hcx-correlation_id + in: header + required: true + description: The thread. See the rule below. Mandatory on the envelope. + schema: + type: string + example: + - $ref: "#/components/parameters/XHcxTimestamp" + - name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: response.complete + - $ref: "#/components/parameters/XHcxBenAbhaId" + requestBody: + required: true + content: + application/json: + schema: + type: object + properties: + payload: + type: string + example: + payload: eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOiIxNTE4QGhjeCJ9.encrypted_key.iv.ciphertext.tag + responses: + "202": + description: Received. The receipt names the message it answers; the answer itself follows as a call of your own. + content: + application/json: + schema: + type: object + properties: + timestamp: + type: string + api_call_id: + type: string + correlation_id: + type: string + result: + type: object + properties: + sender_code: + type: string + recipient_code: + type: string + entity_type: + type: string + protocol_status: + type: string + error: + type: object + properties: + code: + type: string + message: + type: string + example: + timestamp: 04/09/2026 11:46:41:305 + api_call_id: + correlation_id: + result: + sender_code: 1000003538@hcx + recipient_code: 1000004446@hcx + entity_type: preauth + protocol_status: request.queued + error: + code: "" + message: "" +components: + securitySchemes: + bearerAuth: + type: http + scheme: bearer + description: "On every NHCX call, the token goes in a header called `bearer_auth`, with the word `Bearer` and a space in front. The sources are not unanimous: the authentication page and the FAQ both write the example as `Authorization`, and the notification endpoint uses `Authorization`. The safe course, and what the adapter does, is to send both headers with the same value." + parameters: + BearerAuth: + name: bearer_auth + in: header + required: true + description: It is `bearer_auth`, not `Authorization`, on NHCX's own endpoints. + schema: + type: string + example: Bearer + XHcxSenderCode: + name: x-hcx-sender_code + in: header + required: true + description: Your participant code. Mandatory on the envelope. + schema: + type: string + example: 1000004446@hcx + XHcxRecipientCode: + name: x-hcx-recipient_code + in: header + required: true + description: The recipient's. For a provider, the processor code from the policy lookup. Mandatory on the envelope. + schema: + type: string + example: 1518@hcx + XHcxApiCallId: + name: x-hcx-api_call_id + in: header + required: true + description: Fresh on every message, including responses. Mandatory on the envelope. + schema: + type: string + example: + XHcxRequestId: + name: x-hcx-request_id + in: header + required: false + description: One per originating request. The Open Protocol page marks it Mandatory; the Technical Specifications page marks it Optional. Optional on the envelope. + schema: + type: string + example: + XHcxCorrelationId: + name: x-hcx-correlation_id + in: header + required: true + description: The thread. See the rule below. Mandatory on the envelope. + schema: + type: string + example: + XHcxTimestamp: + name: x-hcx-timestamp + in: header + required: true + description: See the format note below. Mandatory on the envelope. + schema: + type: string + example: + XHcxStatus: + name: x-hcx-status + in: header + required: true + description: Where this message stands. Values below. Mandatory on the envelope. + schema: + type: string + example: request.initiated + XHcxBenAbhaId: + name: x-hcx-ben-abha-id + in: header + required: true + description: The beneficiary's ABHA number. Mandatory on every exchange, including those with no beneficiary in the payload. Mandatory on the envelope. + schema: + type: string + example: "91711234567890" +x-abdm-errors: + notes: "Codes any exchange call can meet are recorded once, in the [Other](/docs/nhcx/v1/api/other) specification: the gateway's NHCX- codes, the standard payer codes, and the reference payer's structure and transport codes. The reference payer's other codes sit with the exchange they reject: coverage eligibility, preauthorisation, claim and insurance plan. [Reading error codes](/docs/nhcx/v1/reference/error-code-guide) explains the code spaces." diff --git a/mcp/eval/README.md b/mcp/eval/README.md index 9296744bb..f56fe1a9c 100644 --- a/mcp/eval/README.md +++ b/mcp/eval/README.md @@ -5,11 +5,14 @@ catalogue atoms for scenario-phrased developer queries. Two check types: -- **Rank cases** (20): each query has a set of atom ids that genuinely answer +- **Rank cases** (28): each query has a set of atom ids that genuinely answer it. Scored by the rank of the first expected atom: hit@1, hit@3, hit@10, and MRR. Fifteen are the original scenario set; five come from a recorded - agent session that failed on the timestamp and encryption docs. -- **Content probes** (2): the top hit's snippet plus summary must contain + agent session that failed on the timestamp and encryption docs; eight are + NHCX cases phrased the way a hospital or insurer developer describes the + problem. The summary reports all 28 together and again by gateway, under + `by_gateway`, so a change to one gateway's atoms is visible on its own. +- **Content probes** (3): the top hit's snippet plus summary must contain required substrings (case-insensitive) and must not contain forbidden ones. These catch a refuted claim surviving in the surfaced text even when the right atom ranks first. Reported as pass/fail, separate from ranks. diff --git a/mcp/eval/retrieval_eval.py b/mcp/eval/retrieval_eval.py index 10a046791..3929462d0 100644 --- a/mcp/eval/retrieval_eval.py +++ b/mcp/eval/retrieval_eval.py @@ -79,6 +79,30 @@ {"hiecm.endpoint.m1-encrypt-value"}), ("my request got a 404 but the body has an ABDM error code", {"hiecm.concept.error-codes", "hiecm.error.abdm-1016"}), + # -- NHCX, the claims exchange: a hospital or insurer developer's words ---- + ("every call to the claims exchange comes back 401 even right after I get a token", + {"nhcx.troubleshooting.everything-returns-401", "nhcx.error.nhcx-401", + "nhcx.concept.session-token"}), + ("the insurer says it could not decrypt the claim message our hospital system sent", + {"nhcx.error.payr-1001", "nhcx.troubleshooting.recipient-cannot-decrypt", + "nhcx.concept.encryption-certificate", "nhcx.concept.jwe-envelope"}), + ("the exchange accepted my request with a 202 but the insurer's answer never reaches our server", + {"nhcx.troubleshooting.accepted-then-no-callback", + "nhcx.troubleshooting.callback-url-rejected", + "nhcx.sandbox.callback-url-requirements"}), + ("the patient has been discharged, send the final bill to the insurer", + {"nhcx.flow.claim-submit", "nhcx.endpoint.claim-submit"}), + ("should we get the insurer's approval before surgery or only ask for an estimate of what they would pay", + {"nhcx.decision.preauth-or-predetermination", "nhcx.flow.predetermination", + "nhcx.flow.preauth-submit"}), + ("our approval request has gone quiet, how do I find out whether the insurer received it", + {"nhcx.flow.status-check", "nhcx.endpoint.status", + "nhcx.decision.status-poll-or-wait"}), + ("find which insurer covers this patient from their health account number before sending anything", + {"nhcx.endpoint.participant-get-policies", "nhcx.endpoint.v2-participant-get-policies", + "nhcx.concept.policy-linking"}), + ("the exchange rejected my retry saying the correlation id was already used", + {"nhcx.error.nhcx-1006", "nhcx.concept.message-identifiers"}), ] # --------------------------------------------------------------------------- @@ -92,6 +116,10 @@ ("the api rejected my call saying invalid timestamp", ["utc"], []), + # From the summary of nhcx.error.nhcx-1006: a retry needs a new id. + ("the exchange rejected my retry saying the correlation id was already used", + ["new correlation id"], + []), ] @@ -145,17 +173,29 @@ def main() -> None: print(f" {'; '.join(reason)}") # -- summary -- - n = len(rows) - ranks = [r["rank"] for r in rows] + def scores(subset: list) -> dict: + ranks = [r["rank"] for r in subset] + n = len(ranks) + return { + "hit_at_1": sum(1 for r in ranks if r == 1), + "hit_at_3": sum(1 for r in ranks if r is not None and r <= 3), + "hit_at_10": sum(1 for r in ranks if r is not None and r <= 10), + "mrr": round(sum(1 / r for r in ranks if r is not None) / n, 3) if n else 0, + "n": n, + } + + # A case belongs to the gateway its expected atoms carry; shared atoms + # count with HIE-CM, whose cases they answer. + def gateway(row: dict) -> str: + return "nhcx" if all(e.startswith("nhcx.") for e in row["expect"]) else "hiecm+shared" + summary = { "name": name, - "hit_at_1": sum(1 for r in ranks if r == 1), - "hit_at_3": sum(1 for r in ranks if r is not None and r <= 3), - "hit_at_10": sum(1 for r in ranks if r is not None and r <= 10), - "mrr": round(sum(1 / r for r in ranks if r is not None) / n, 3), + **scores(rows), "content_pass": sum(1 for p in probes if p["passed"]), "content_total": len(probes), - "n": n, + "by_gateway": {g: scores([r for r in rows if gateway(r) == g]) + for g in ("hiecm+shared", "nhcx")}, } out_dir = Path(__file__).parent / "results" out_dir.mkdir(exist_ok=True) diff --git a/plugins/nhcx/.claude-plugin/plugin.json b/plugins/nhcx/.claude-plugin/plugin.json new file mode 100644 index 000000000..f2c63c770 --- /dev/null +++ b/plugins/nhcx/.claude-plugin/plugin.json @@ -0,0 +1,11 @@ +{ + "name": "nhcx", + "displayName": "NHCX", + "description": "Agent skills for building on the National Health Claims Exchange (NHCX), one per use case in episode order: nhcx-coverage, nhcx-insurance, nhcx-preauth, nhcx-claim, nhcx-payment, nhcx-communication and nhcx-reprocess. Each builds its use case into a hospital information system or a claims desk, held to the NHCX package's pinned FHIR bundles, and installs and runs alone.", + "version": "0.1.0", + "author": { + "name": "ABDM Developer Portal" + }, + "license": "MIT", + "keywords": ["nhcx", "claims", "insurance", "pmjay", "fhir", "healthcare", "india-health"] +} diff --git a/plugins/nhcx/skills/README.md b/plugins/nhcx/skills/README.md new file mode 100644 index 000000000..2e66d5685 --- /dev/null +++ b/plugins/nhcx/skills/README.md @@ -0,0 +1,25 @@ +# NHCX agent skills + +One skill per NHCX use case, in episode order: `nhcx-coverage`, +`nhcx-insurance`, `nhcx-preauth`, `nhcx-claim`, `nhcx-payment`, +`nhcx-communication` and `nhcx-reprocess`. Each builds its use case into a +hospital information system or a standalone claims desk, held to the pinned +FHIR bundles of the NHCX package. + +Each skill is a folder, not a single file: `SKILL.md` points into the folder's +own `core/`, `stages/`, `references/`, `fhir/`, `flow/`, `ui/`, `templates/` +and `scripts/`, and the shared files are repeated in every folder so any one +installs alone. `scripts/fetch-package.sh` fetches the NHCX package from +github.com/nha-in/nhcx-package into the project being built. + +Install all seven with `claude plugin install nhcx@abdm-portal`, after +`claude plugin marketplace add` for this repository, or one at a time with +`scripts/install-skill.sh `. The site build copies each folder +to `/skills//` and packs it as `/skills/.tar.gz`, which the site's +install commands unpack. + +They come from github.com/nha-in/nhcx-skills, taken from its working tree on +15 September 2026, over commit 0e7545f. Update them there and copy them across +again rather than editing them here. `npm run validate:skills` checks their +frontmatter and em dashes; they cite no Catalogue atom, so its Catalogue +checks do not reach them. diff --git a/plugins/nhcx/skills/nhcx-claim/SKILL.md b/plugins/nhcx/skills/nhcx-claim/SKILL.md new file mode 100644 index 000000000..a2b18433d --- /dev/null +++ b/plugins/nhcx/skills/nhcx-claim/SKILL.md @@ -0,0 +1,100 @@ +--- +name: nhcx-claim +description: Add the NHCX claim to a hospital information system or a standalone claims desk. Record the discharge (normal, LAMA, DAMA or death, with the surgery stage), file the claim (15) under the pre-auth's number, answer a claim query (161 on PMJAY) and read every answer (25, 26, 27, 291), held to the pinned bundles, including the LAMA collapse and the death rules. Starts by checking whether the app already files claims or records the discharge facts a claim needs, and whether the approved pre-auth it depends on exists, then builds, extends or reuses only what is missing. Self-contained; needs no other skill installed. Use for filing a claim, discharge variants, claim query answers, NHCX use cases B5, D9 and D10, flow steps F10 and F11. +--- + +# NHCX claim: the discharge and the final bill + +This skill takes an approved pre-authorisation to a decided claim. It records the discharge with its mode and stage, files the claim under the pre-auth's number with the payer's reference, answers a PMJAY claim query in-band, and reads the acknowledgement and the decision. + +Read `core/LADDER.md` first. It holds the ladder every NHCX skill walks: the definition of compliant, the stages, the workspace, how to run a stage, and the rules. This folder carries everything it needs and runs on its own; the other six NHCX skills are separate folders, and none of them has to be installed. Paths starting `core/`, `stages/`, `references/`, `fhir/`, `flow/`, `ui/`, `templates/` or `scripts/` are relative to this folder. Paths starting `nhcx-package/` are in the NHCX package, which `scripts/fetch-package.sh` fetches into the target project beside `nhcx-build/`; `references/material.md` names the package file of every pin by its label. + +## What this skill covers + +| | | +| --- | --- | +| Flow steps | F10 Record the discharge; F11 File the claim, and its query answer for a `resubmit` payer | +| Tabs | Claim (tab 7): the discharge card, documents for the claim, forms for the claim, everything attached for the claim, submit, the decision card | +| Wire | `v1/claim/submit`, `use claim`, workflow 15; 161 (PMJAY) or 151 (generic) for a query answer; 16 (generic only) to resubmit after a rejection. Answers: 25, then 26, 27 or 291 | +| Next actions | "Record the discharge", "File the claim", "Answer the claim query" (a `resubmit` payer), "Send the claim again" | +| Use cases | B5; D9 with its variants (normal; LAMA and DAMA before, during and after surgery; death); D10 | +| Modules | 7.7, the claim legs (15, 161, 151, 16); 7.8, the claim answers | +| Pins | `claim/request`, `claim/queryupdate`: `nhcx-package/fhir/B5/claim-{request,queryupdate}.json` | +| Payer fixtures | `nhcx-package/fhir/C7/*` (25, 26, 27, 291, generic and PMJAY); the live PMJAY shapes in `nhcx-package/fhir/D9` and `D10` | +| Tables | `claim_submission`: the claim leg and the discharge (mode, stage, discharged, surgery and death times) | +| FHIR | `fhir/FHIR.md` sections 4 (the claim leg, the LAMA collapse) and 5; `references/fhir-knowledge.md` sections 5 and 6 | + +Not here: the reprocess, release and status cards on the Claim tab (the reprocess use case, `nhcx-reprocess`); a `communication` payer's claim query (the communication use case, `nhcx-communication`). + +## Needs and hands on + +Needs: an approved or partial pre-auth with `preauth_ref` and `claim_ref`, the dossier and the Claim bundle builder (the pre-auth use case); the lines (the insurance use case). Stage 0 checks for them below, whichever way the app got them. + +Hands on: a filed claim with `claim_ref` and a decision: approved (with amounts and item verdicts, `deductible` included), rejected, partial or queried. Payment notices are matched against the claim number; a rejected or partial claim can be reprocessed. + +## Capability check + +Stage 0 (`stages/0-capability-check.md`) gives every capability below a verdict: search for the markers, run the check, record what was observed. + +### Own + +| Id | What | Look for | Present when (observed) | +| --- | --- | --- | --- | +| `claim.discharge` | F10: mode (normal, LAMA, DAMA, death), stage (before, during, after surgery), discharge, surgery and death times | a discharge mode on the encounter or the claim leg; `lama`, `dama`, `death`, `expired` | A discharge records each mode; a death needs its time; LAMA and DAMA need a stage; recording is refused unless a pre-auth is approved or partial | +| `claim.claim-bundle` | 7.7's builder, extended with the claim legs | `"use": "claim"`, `LM100`, `DSDE`, `DTM`, `HDS`, `DIS`, `preAuthRef` | The `claim/request` and `claim/queryupdate` pins pass; `Claim.id` equals the pre-auth's claim number and `insurance[0].preAuthRef` is the payer's; a death claim carries `ONS/DTM`; LAMA or DAMA before or during surgery carries one `LM100` item and nothing else; after the extension, the three pre-auth Claim pins still pass | +| `claim.send` | F11: `submit_claim` and the choice of send kind | `v1/claim/submit`, workflow ids `15`, `161`, `151`, `16` | With the 7.1 stub: 15 first; 161 on a PMJAY query and 151 on a generic one; 16 after a generic rejection and never on PMJAY; refused before any HTTP call without an approved pre-auth, without a recorded discharge or the discharge summary, or with an amount above the approved amount | +| `claim.response-reader` | 7.8 on the claim thread | `verdict_status`, workflow ids `25`, `26`, `27`, `291` | `submitting` on the 25, `approved` on the 26, `queried` on the 27, `rejected` on the 291; item verdicts keep `deductible` and the payer's reasons verbatim | +| `claim.query-answer` | F11 continued, a `resubmit` payer: 161 | `queryupdate`, `CQD` on the claim leg | The `claim/queryupdate` pin passes; the answer goes on a new correlation id; an empty reply is refused before sending | +| `claim.screens` | The Claim tab | the discharge card, the claim card | The claim card opens only after a discharge; for LAMA or DAMA before or during surgery it says the approved packages are voided and the claim will carry `LM100` only; the decision card renders from the stored answer | + +### Foundation + +All six capabilities in `core/FOUNDATION.md`. `foundation.storage` is partial until `claim_submission` holds the discharge columns; `foundation.state` until `case_stage` has the `claim` branch and `next_actions` the labels above. + +### Prerequisites + +The pre-auth use case (`nhcx-preauth`) and the insurance use case (`nhcx-insurance`) own these. The checks are here, so neither skill need be installed. + +| Capability | Why | Look for | Present when (observed) | +| --- | --- | --- | --- | +| `preauth.send`, `preauth.response-reader` | The claim needs an approved or partial pre-auth and its `preAuthRef` (ERR-PYR-CLM-007 otherwise) | a pre-auth leg with `txn_id`, `correlation_id`, `preauth_ref`; a ClaimResponse reader | A pre-auth sent with a stubbed client on `v1/preauth/submit` (workflow 12), then fed `nhcx-package/fhir/C5/C5-received-wf20.json` and `C5-approved-wf21.json` on its correlation id, ends `approved` with `preauth_ref` set | +| `preauth.claim-bundle` | One builder; the claim legs extend it | a Claim bundle builder with `leg` and `flow` arguments | Fed the pin's data, it produces `preauth/request` byte for byte (compared without `factor`); if it is missing, this skill stops rather than write a second builder | +| `preauth.dossier` | Diagnoses, the care team, documents and forms ride the claim too | diagnosis, care team, document and form answer tables per episode | An episode holds ICD-10 diagnoses, a care team member with an HPIN, documents with the plan's codes and answered forms | +| `insurance.lines` | The lines, and `LM100` at the plan's rate | a line table priced from the plan | Lines carry the plan's rate as `unit_price`, integer quantities, and tiers with `parent_code` | + +### Host facts + +How the discharge is recorded, and whether it carries a mode, a stage, a surgery time and a death time; procedures and surgery times; the discharge summary document; invoice lines for reconciliation. + +## The ladder, for this skill + +| Stage | What is specific here | +| --- | --- | +| 0 | The tables above. | +| 1 | Confirm the shared page, or write it if this skill runs first on the app. Own rows: B5, D9, D10. | +| 2 | Risks: the claim under the pre-auth's number (ERR-PYR-CLM-007); PMJAY bills the package alone at the whole amount; no claim resubmit on PMJAY, where a decided claim is reprocessed; 151 on PMJAY is PAYR-1321, so 161; a death without `DTM` is PAYR-1096; a package on a LAMA or DAMA claim before or during surgery is PAYR-1362; the consent form at the claim (PAYR-1363) and the guideline forms (PAYR-1365). | +| 3 | The host facts above. | +| 4 | The discharge fields' sources; the Claim bundle's claim-leg source map; `preAuthRef` from the ClaimResponse; the claim answer's destinations. If this skill maps first, every table's home too. | +| 5 | The Claim tab; actions F10 and F11. | +| 6 | The claim parts of 7.7 and 7.8; the foundation modules stage 0 found absent or partial. | +| 7 | Extend the one builder; never write a second. | +| 8 | The rows of 7.7 and 7.8 that name the claim legs, and the pre-auth rows of 7.7 again, since the builder changed. | +| 9 | Two pin comparisons; reader tests on 25, 26, 27 and 291; matrix rows B5, D9, D9 LAMA or DAMA, D9 death and D10; every discharge variant in `references/flow-knowledge.md` section 6; the cross-cutting rows on the claim thread. | +| 10 | Rung 1. Rung 3 walks B5. Rung 4 walks D9 and its variants, and D10. | +| 11 | This skill's section. | + +## Rules for these legs + +- The claim goes under the pre-auth's claim number, with the payer's `preAuthRef`. +- On the claim, procedures are `completed`, and the discharge scalars, `HDS` (the plan's summary code), `ONS/PSP`, `ONS/DSDE` and `DIS` ride it. +- LAMA or DAMA before or during surgery: one `LM100` item at the plan's rate, no tier, nothing else. After surgery the package stands. +- A death carries `ONS/DTM` and the death forms. +- There is no separate discharge submission on PMJAY; the discharge rides on the claim. +- The discharge summary is always attached, with the documents the ruling deferred to the claim and the consent form again. +- A claim refused at the door offers "Send the claim again" while a send kind remains, else "Ask for a reprocess". + +## Done when + +- Every gate in this skill's block of `nhcx-build/STATE.md` is closed with evidence. +- The two claim pins pass, and the three pre-auth Claim pins still pass after the extension. +- The compliance points in `core/LADDER.md` hold for F10 and F11. diff --git a/plugins/nhcx/skills/nhcx-claim/core/FOUNDATION.md b/plugins/nhcx/skills/nhcx-claim/core/FOUNDATION.md new file mode 100644 index 000000000..2037811b9 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-claim/core/FOUNDATION.md @@ -0,0 +1,65 @@ +# The foundation: what every skill stands on + +Six modules carry every leg, and no one skill owns them. Every skill's stage 0 checks them. The first skill that finds one absent or partial builds or extends it in its own stage 7, and records itself as `Built by` in the Foundation block of `nhcx-build/STATE.md`. Later skills find it present and reuse it. An HMIS that already has one (an NHCX integration, a webhook door, a claims table) has it `existing`. + +| Id | Module | What | Every skill adds | +| --- | --- | --- | --- | +| `foundation.transport` | 7.1 | Settings; the one transport behind `send` (the app's existing NHCX integration, the build's own, or nhcx-adapter when the user asked for it); the policy lookup; the outbound archive | Nothing; it sends through it | +| `foundation.storage` | 7.2 | The episode table with its claim number, payer and recipient codes, stage and sub-stage; the leg tables | The leg tables its `SKILL.md` lists, in its own migration | +| `foundation.callback` | 7.3 | The transport's receiving end and the door: dedupe, archive before apply, match by correlation id then claim number, the door refusal, the poll fallback where there is a ledger | Its readers, wired into the door's dispatch | +| `foundation.state` | 7.11 | The payer adapter table; `case_stage`, `stamp_case`, `next_actions` | The stage branches and next-action rows for its legs, labels verbatim from `flow/flow.json` | +| `foundation.screens` | 7.12 | The case screen shell: the eight tabs in the flow's order, the status line and actions, the JSON state address, the page-load polls, the cases list | Its own tabs and screens | +| `foundation.shell` | 7.13 | Standalone only: patients, admissions, practitioners, diagnoses, documents, settings, the run script | Nothing; `not applicable` in integrate mode | + +## Recognising each one + +For each capability: what to search for, what must be observed for it to be present, and what makes it partial. Search code, dependencies, migrations, configuration and tests. Run every check offline, with the network stubbed. + +### `foundation.transport` (7.1) + +- Look for an NHCX integration of the app's own: `x-hcx-`, `JWEPayload`, `RSA-OAEP-256`, `A256GCM`, a JOSE library among the dependencies, `bearer_auth`, a sessions URL on the ABDM gateway, `participanthcxservice`, `fetch/certs`, `participant/get/policies`, routes ending in `on_submit`, `on_check` or `on_request`, a vendor's NHCX or HCX client, a gateway service the app calls. Look also for nhcx-adapter already in use: `/fhir/out/`, `/out/v1/`, `jwe_headers`, an adapter URL setting, `/ledger/thread/`, `/internal/txn/related`. +- Present when: what was found meets the contract in `references/transport-knowledge.md` section 2, observed through 7.1's Validate rows 1 to 6 (and row 7 for an app that seals its own messages), with the network stubbed and a test key pair for the seal; and `send` is one function a test can replace. +- Partial when: it sends but misses a contract item (no `x-hcx-ben-abha-id`, the `payerid` as the recipient, no ids back to the caller, no archive) or cannot be stubbed. Extend it in place (`references/transport-knowledge.md` section 4). Never add a second transport beside it. +- Absent when: the app has no NHCX integration. The transport is then `own`, built from `references/transport-knowledge.md` section 3, unless the user has asked for nhcx-adapter. +- nhcx-adapter is never the answer to a partial or absent transport unless the user asked for it. Do not suggest it. + +### `foundation.storage` (7.2) + +- Look for: tables or models with `claim_no`, `correlation_id`, `txn_id`, `sub_stage`; migrations that mention claim, preauth or nhcx. +- Present when: observed on a migrated scratch database, or read from the schema file and confirmed by a migration run: the episode table has a unique claim number, member id, policy code, payer code, recipient code, patient and encounter keys, `stage` and `sub_stage`; every leg table this skill needs exists with `txn_id`, `correlation_id`, `api_call_id` and `thread_correlation_id`; the migration runs twice without error; deleting an episode removes its children (7.2 Validate, rows 2, 3, 5 and 6). For `nhcx-communication` and `nhcx-payment`, also row 4: the correlation id on their tables is unique by constraint. +- Partial when: the episode exists but a leg table this skill needs does not, a leg table lacks `thread_correlation_id` or `api_call_id`, or the episode keeps no `recipient_code`. The skill adds its tables and columns in a new migration. + +### `foundation.callback` (7.3) + +- Look for: routes under `/v1/` ending in `on_submit`, `on_check`, `on_request`, `/v1/error`, or a route with `callback` in it; `JWEPayload`, `ProtocolResponse`, `x-hcx-correlation_id`, `x-hcx-api_call_id`, a receipt with `protocol_status`. +- Present when: 7.3 Validate rows 1 to 5, 7 and 8 are observed by calling the receiving end with deliveries of the transport's kind (every inbound path reaches it; an unreadable body is archived and changes nothing; one api call id delivered twice changes state once and is `ignored`; an unknown correlation id is answered and archived under `unmatched`; a delivery is archived even when the apply raises; no outbound call during a delivery; the inbound authentication of the kind). Row 6, the door refusal, is checked by each skill on its own thread. +- Partial when: it receives but routes by path instead of by correlation id, lacks the dedupe, archives after applying, answers the exchange with anything but the 202 receipt (`own`, `existing`), hosts no `/v1/error`, or, with `adapter`, has no poll fallback. Extend it; there is one door. +- A skill whose reader is not wired into the door is partial for its own capability, not for the door. + +### `foundation.state` (7.11) + +- Look for: `query_mode`, `resubmit`, `1518`, a workflow id table (`"12"`, `"PC01"`, `"161"`), `sub_stage`, `next_actions`, a stamp after each write. +- Present when: 7.11 Validate rows 1 to 3 are observed (`adapter_for` with `1518@hcx` and `1518` gives PMJAY and an unknown code gives generic; the PMJAY workflow table equals `references/flow-knowledge.md` section 2; an override changes one kind only), and rows 4 to 7 hold on the seeded states the legs built so far can reach. +- Partial when: the payer table exists and the stage machine does not, or the stage machine lacks this skill's stage branches or labels. Each skill adds its own. + +### `foundation.screens` (7.12) + +- Look for: routes like `/claims`, `/claims/`, `/claims//state`; the tab keys `eligibility`, `plan`, `lines`, `validate`, `preauth`, `communication`, `claim`, `payments`. +- Present when: 7.12 Validate rows 1, 3, 8 and 9 are observed on the shell (the eight tabs in the flow's order with the flow's labels; routes answer 200 for a seeded case and 404 for an unknown one; no input or select named for a rate, a payer name, a `preAuthRef`, a UTR or a status; the state address returns `stage`, `sub_stage`, `next_actions` and `legs`). Rows 4 to 7 belong to the skills whose tabs they test. +- Partial when: the case screen exists without some tabs, without the status line, or without the state address. +- An HMIS with its own screens: the shell may live inside them, for example a panel on the admission screen that opens the case. Present is judged on the eight tabs and the state address, not on the look. + +### `foundation.shell` (7.13, standalone only) + +- Present when: every row of 7.13's Validate section is observed. +- In integrate mode: `not applicable`. The HMIS is the shell; stage 3 finds its patients, admissions, practitioners and documents. + +## Who builds what + +| Verdict at stage 0 | What the running skill does | +| --- | --- | +| `absent` | Builds it in stage 7, before its own modules. 7.1 and 7.3 whole, for the transport chosen at stage 1. 7.2: the episode table and this skill's leg tables. 7.11: the payer adapter table whole, and this skill's stage branches and labels. 7.12: the shell with all eight tabs present in order, its own tabs filled, the others showing their empty state. 7.13 whole, in standalone mode. | +| `partial` | Extends it in the existing code, for the difference stage 0 named, and runs the module's whole Validate section after. | +| `present` | Reuses it. Stage 8 still runs the rows this skill depends on. | + +Record: the Foundation row in `STATE.md` with `Built by` (the skill, or `existing`), and the module record `nhcx-build/7-modules/7.N.md` with a part for each skill that touched it. diff --git a/plugins/nhcx/skills/nhcx-claim/core/LADDER.md b/plugins/nhcx/skills/nhcx-claim/core/LADDER.md new file mode 100644 index 000000000..7a6f3f12b --- /dev/null +++ b/plugins/nhcx/skills/nhcx-claim/core/LADDER.md @@ -0,0 +1,185 @@ +# The NHCX build ladder + +This skill is one of seven NHCX skills, one per use case: `nhcx-coverage`, `nhcx-insurance`, `nhcx-preauth`, `nhcx-claim`, `nhcx-communication`, `nhcx-payment` and `nhcx-reprocess`. Each is a folder of its own and runs on its own: it carries this ladder, the stages, the module files, the references, the flow, the templates and the fetch script. The seven copies of these are the same; only `SKILL.md` differs. This file holds what they share. `SKILL.md` says which flow steps, legs, capabilities, modules, pins and test rows are this skill's own, and what it needs from the use cases before it. + +## Paths + +Paths that start with `core/`, `stages/`, `references/`, `fhir/`, `flow/`, `ui/`, `templates/` or `scripts/` are relative to this skill's folder, the one that holds `SKILL.md`. Paths that start with `nhcx-package/` are in the NHCX package, fetched into the target project beside `nhcx-build/` (below). Paths that start with `nhcx-build/` are the workspace in the target project. + +## Getting the material + +Pins, payer fixtures and docs come from the NHCX package, published at https://github.com/nha-in/nhcx-package. `scripts/fetch-package.sh` downloads the latest release, unpacks it to `nhcx-package/` beside `nhcx-build/` and verifies its MANIFEST (pass a link or a local path to use a different build). `references/material.md` says what the package holds, gives the file of every pin by its label (`preauth/request` is `nhcx-package/fhir/B3/preauth-request.json`), and lists what it does not hold. Read it once, at stage 0. + +## What the skills produce + +Software that raises cashless claims on the National Health Claims Exchange (NHCX) with a private insurer and with PMJAY, in one of two shapes: + +| Mode | You start with | You end with | +| --- | --- | --- | +| `integrate` | A working hospital information system (HMIS, EMR, HIS, billing system) in any language | The same system, with a claims module that speaks NHCX through its transport, kept in sidecar tables and removable | +| `standalone` | Nothing | A self-contained claims desk: its own patients, admissions, documents and screens, speaking NHCX through a transport of its own | + +Every message goes through one transport, chosen at stage 1 from three (`references/transport-knowledge.md` section 1): + +| Transport | When | What the build does | +| --- | --- | --- | +| `existing` | Stage 0 found the app already speaks NHCX: its own client, a vendor gateway, an SDK | Wraps it behind 7.1's `send` and 7.3's door, and closes its gaps; never replaces it | +| `own` | The app has no NHCX integration, and the user has not asked for nhcx-adapter | Builds the protocol into the app from NHA's published chapters: the ABDM session token, the key and certificate, the participant record, the recipient's certificate, the JWE, the callback and its receipt | +| `adapter` | Only when the user asks for nhcx-adapter | Downloads it from https://github.com/nha-in/nhcx-adapter/releases and talks plain FHIR to it (`references/api-knowledge.md`) | + +Never propose nhcx-adapter; use it only when the user asks for it. Whichever the transport, the rest of the build sees the same two things: `send`, and a door that receives `{meta, jwe_headers, fhir}`. + +## The seven skills + +One skill per use case. Together they walk the whole flow in `flow/FLOW.md`; each one alone builds its slice. This folder builds only its own row. The others are named so that a verdict can say which skill owns a missing piece. + +| Skill | Flow steps | Legs | Use cases | Pins | +| --- | --- | --- | --- | --- | +| `nhcx-coverage` | F1, F2, F3 | policy search; `v1/coverageeligibility/check` purpose `discovery`, `validation`, `benefits` | A2, B1, D3 | `coverage/{discovery,validation,benefits}` | +| `nhcx-insurance` | F4, F7 | `v1/insuranceplan/request`; lines quoted from the plan | B2, D1 | `insurance` | +| `nhcx-preauth` | F5, F6, F8, F9, F9a, F9b for a `resubmit` payer, F9c, F9d, F9e | auth requirements; `v1/preauth/submit` 12, 19, 13, 131 and predetermination; cancel PC01 | B3, B8 cancel, B9, D2, D4 to D8 | `coverage/authrequirements`, `preauth/{request,enhancement,queryupdate,cancel}` | +| `nhcx-claim` | F10, F11 | `v1/claim/submit` 15; 161 (PMJAY) or 151 (generic); 16 (generic) | B5, D9, D10 | `claim/{request,queryupdate}` | +| `nhcx-communication` | F9b and the claim query for a `communication` payer, F12b | `v1/communication/request` in; `v1/communication/on_request` out | B4 | `communication/response`, and the `communication/request` reader | +| `nhcx-payment` | F12 | `v1/paymentnotice/request` in; `v1/paymentnotice/on_request` out on 17 or the notice's own id | B7, D13 | `payment/notice-ack` | +| `nhcx-reprocess` | F13 | `v1/task/submit`: reprocess and release on 36, status; 37 and the status Task read | A5, B8 reprocess, D11, D12 | `claim/{reprocess,release}` | + +`flow/flow.json` names the skills of every step in `skills`. Fifteen pins, each owned by exactly one skill, plus the communication request read as the sixteenth comparison. + +### The order they depend on + +The use cases depend on one another in the order the episode happens. A full build runs the seven skills top to bottom. Any one can run alone on an app that already has what it needs; stage 0 establishes whether it does, with the checks in this skill's `SKILL.md` under "Prerequisites". The other skills do not have to be installed for that check. + +| Skill | Needs | Because | +| --- | --- | --- | +| `nhcx-coverage` | nothing | It opens the episode | +| `nhcx-insurance` | coverage: an episode with an `eligible` verdict | The plan is fetched for an eligible episode's policy | +| `nhcx-preauth` | coverage (eligible, and its builder for auth requirements); insurance (plan ready, lines quoted) | Items, prices, documents and forms come from the plan; F9 holds `eligible` | +| `nhcx-claim` | preauth: an approved or partial pre-auth with its `preAuthRef`, the dossier, the Claim builder | The claim goes under the pre-auth's number, built by the same builder | +| `nhcx-communication` | preauth or claim: a leg the payer can ask about, with its bundle as sent | A query names a Claim; the reply lifts entries from the bundle sent | +| `nhcx-payment` | claim: a filed claim | A notice is matched by the claim number | +| `nhcx-reprocess` | claim: a decided claim; payment for a release; preauth for status on a pre-auth | A reprocess reopens a decided claim; a release follows a short payment | + +## The foundation + +Six modules carry every leg and belong to no one skill: 7.1 (the transport), 7.2 (storage), 7.3 (the callback door), 7.11 (state and payer adapters), 7.12 (the case screen shell) and 7.13 (the standalone shell). Every skill's stage 0 checks them. The first skill that finds one absent builds it; a skill that runs later on the same app finds it present and reuses it. `core/FOUNDATION.md` says how to recognise each and what makes it present. + +## What compliant means + +Every skill is held to the same points, for its own legs: + +1. Every hospital-side leg the skill owns (`references/flow-knowledge.md` section 1) is sent with its workflow id, and every payer answer on it is read. +2. Every bundle the skill sends matches its pin in `nhcx-package/fhir` byte for byte, `created` excepted. +3. The callback door answers 2xx fast, dedupes on `x-hcx-api_call_id`, archives before it applies, and matches by correlation id first. +4. No screen shows a decision the exchange has not sent, and nothing the exchange already said is retyped. +5. The offline tests pass, and the report says honestly which rungs of the test pyramid were climbed. +6. The software walks the flow in `flow/FLOW.md`, step for step: the same steps in the same order, the same tabs with the same names, the same guards, the same action labels. The flow is copied, never redesigned. +7. Nothing the app already did is built a second time. Every capability stage 0 found present is reused, and validated and tested like new code. + +## The flow + +An NHCX provider desk walks one path from policy search to settlement, and a build from these skills walks it. `flow/FLOW.md` is that path: thirteen steps with their branches, the case screen's eight tabs in order, the status line, the action labels the desk sees, the guards before every send, and what runs on every page load. `flow/flow.json` is the same, machine-readable, with step ids `F1` to `F13`. Read FLOW.md whole at stage 1; stage 4 copies the steps, stage 5 puts the screens on them, stage 7 implements them by id, stage 8 checks every step has a route. An agent that reorders, merges or renames these steps has left the skill. + +## The ladder + +Twelve stages, 0 to 11. Each has one file under `stages/`, reads the artefacts of the stages before it, writes into `nhcx-build/` in the target project, and ends at a gate. A gate is a list of conditions a reader can check without trusting you. Do not start a stage until the gate before it is closed, and never close a gate by asserting it; close it by pointing at the evidence. + +This skill runs every stage over its own slice. Stage 1 is shared with any other NHCX skill that runs on the same app: the first writes it and later ones confirm it. Parts of stages 3 to 6 are the episode's, not the skill's: the first skill to reach them writes those parts whole, and later skills build on them. + +| Stage | File | Scope | Writes | Gate closes when | +| --- | --- | --- | --- | --- | +| 0 | `stages/0-capability-check.md` | this skill | `nhcx-build/0-capability.md` section, `nhcx-build/capabilities.json` entries | Every own, foundation and prerequisite capability has a verdict with observed evidence | +| 1 | `stages/1-idea.md` | shared | `nhcx-build/1-idea.md` | The mode, the payers, the scope of every step with its skill, and the constraints are written and the user has agreed | +| 2 | `stages/2-planning.md` | this skill | `nhcx-build/2-planning.md` section, this skill's block in `nhcx-build/STATE.md` | Every later stage has a size and a proof; every module has its action from stage 0 | +| 3 | `stages/3-discovery.md` | shared rows; this skill's host facts | `nhcx-build/3-discovery.md` | Every host fact this skill needs is answered with proof, or marked as a gap | +| 4 | `stages/4-flow-and-data-mapping.md` | the flow and table homes episode-wide; this skill's bundles | `nhcx-build/4-flow-data-mapping.md`, `nhcx-build/mapping.json` | Every table has a home, every leg the four ids, every bundle of this skill a source map | +| 5 | `stages/5-screen-plan.md` | the case screen shell episode-wide; this skill's tabs | `nhcx-build/5-screen-plan.md`, `nhcx-build/screens.json` | Every value on this skill's screens names its message; the honesty rules hold | +| 6 | `stages/6-code-plan.md` | this skill's modules; the client and configuration episode-wide | `nhcx-build/6-code-plan.md`, `nhcx-build/modules.json` | Every module this skill touches has files, dependencies, a pin and an action | +| 7 | `stages/7-write-code/README.md` and `7.N-*.md` | what stage 0 found absent or partial | Code, plus `nhcx-build/7-modules/7.N.md` | Each module's "Done when" list is met, in order | +| 8 | `stages/8-validate-modules.md` | every module part this skill owns, reused ones included | `nhcx-build/8-validation.md`, `nhcx-build/8-validation/7.N.json` | Every row passes, or carries a named, accepted exception | +| 9 | `stages/9-write-tests.md` | this skill's pins, readers and matrix rows | Test code, plus `nhcx-build/9-tests.md` | Every row this skill owns has a test, or a written reason it cannot | +| 10 | `stages/10-run-tests.md` | this skill's tests | `nhcx-build/10-test-run.md` and the raw outputs | The offline rung passes; the higher rungs are run only when the user starts the services | +| 11 | `stages/11-build-report.md` | this skill | `nhcx-build/11-report.md` section | The report is written from the artefacts, names every gap, and a stranger could resume from it | + +Stage 7 is a module ladder of its own, 7.1 to 7.13. Each module file carries its own Build, Pseudo code, Validate and Tests sections, and names the skills that build it; stage 8 runs the Validate sections and stage 9 writes the Tests sections, so a module is never validated against a checklist written somewhere else. + +## The workspace + +Everything this skill writes lives in one folder in the target project, so the work can be resumed, reviewed and deleted as a unit. When several NHCX skills work on one app they share that folder, whichever skill folder each runs from: each adds its own section or entries and leaves the others alone. + +``` +nhcx-build/ + STATE.md the gate ledger: the shared rows, the foundation, one block per skill + capabilities.json every capability checked, its verdict and its evidence; read and written by every skill + 0-capability.md one section per skill; scratch checks under 0-capability/ + 1-idea.md shared + 2-planning.md one section per skill + 3-discovery.md shared; each row says which skill answered it + 4-flow-data-mapping.md the flow and table homes, then one section per skill; plus mapping.json + 5-screen-plan.md the case screen shell, then one section per skill; plus screens.json + 6-code-plan.md the client and configuration, then one section per skill; plus modules.json + 7-modules/7.1.md .. 7.13.md one record per module; a shared module has a part per skill + 8-validation.md one section per skill; plus 8-validation/7.N.json, each row tagged with its skill + 9-tests.md one section per skill + 10-test-run.md one section per skill; plus 10-test-run/-*.log + 11-report.md a summary across skills, then one section per skill + NOTES.md every place a skill was silent, ambiguous or wrong +``` + +`templates/` holds the skeleton of each artefact. Copy the skeleton, fill it, keep its headings: later stages find things by heading. + +## How to run a stage + +1. Read `nhcx-build/STATE.md`. If stage 1 in the Shared block is open, and this skill's stage 0 is closed, run stage 1. Otherwise find the first open gate in this skill's block. That is the stage to run; do not skip ahead and do not redo a closed stage unless the user asks. +2. Read the stage file. Read the artefacts it lists under Inputs, and this skill's `SKILL.md` row for the stage. Read the references it names, in the sections it names. +3. Do the work. Write the artefact from its template, in this skill's section. +4. Walk the gate. For each condition, write the evidence into STATE.md: a file path, a line, a command and its output. A condition with no evidence stays open. Every artefact that names a step, a tab or an action uses the ids and words from `flow/flow.json`. +5. If a gate needs the user (stage 0 when a prerequisite is missing; stage 1 always when it is first written; stage 10 rungs 3 and 4 always), stop and ask. Otherwise continue to the next stage. + +Resuming later is step 1 again. Nothing lives in your memory; everything lives in `nhcx-build/`. + +You may be asked to run one stage alone with the earlier artefacts already written. Treat those as closed; do not rewrite them. + +## Rules that hold throughout + +- Reading and offline commands only until stage 10 says otherwise. Never start a service or send live traffic unless the user asks. +- Never edit the files in `nhcx-package/`. They are the truth you are held to. +- Build only what stage 0 found absent or partial. A capability found present is reused through its existing code, never built a second time: two transports or two callback doors break the rule that one module sends and one receives. +- Present means a check was observed passing. Code that looks right is partial until its check has run. +- Never build another skill's capability inside this one. When a prerequisite is missing, stop and say which skill owns it. +- When this skill extends a module another skill built, it re-runs that skill's Validate rows for the module. The rows are in the module file, which every skill folder carries. +- This skill writes its own section of a shared artefact and leaves the other skills' sections alone. +- Never hard-code a document code, a package code or a questionnaire url. Take them from the payer's plan or auth-requirements answer. +- Every outbound leg stores three things from the transport's answer: `txn_id`, `correlation_id` and `api_call_id`. Every message is addressed to the policy's processor (`recipient_code`) and carries the beneficiary's ABHA. Every inbound message is matched by `x-hcx-correlation_id` first and by the claim number inside the bundle second. +- Take the decisions from the module files (Build, Rules, Pseudo code) and `fhir/FHIR.md`, and write them in the target's language and conventions. Never invent a shape the pins do not show. +- Write `nhcx-build/NOTES.md` as you go. A fact the skill does not give you is a gap to record, never a guess to bury in code. +- No em dashes anywhere you write. Short sentences. Tables for anything with more than three columns of fact. +- Do not claim a rung of the test pyramid was climbed when it was not. The report's value is its honesty. + +## Reference map + +| File | Holds | Read at | +| --- | --- | --- | +| `core/FOUNDATION.md` | The six foundation capabilities: how to recognise each, what makes it present, who builds it | Stage 0, stage 7 when building one | +| `references/flow-knowledge.md` | The episode and its legs, every workflow id, the two payer kinds, the classification rule, stage vocabulary, the use-case catalogue, rules no document states | Stages 1, 2, 4, 7.4 to 7.11 | +| `references/transport-knowledge.md` | The three transports and when each applies; the contract `send` and the door rely on; building the protocol yourself from NHA's chapters (token, key and certificate, participant record, policy lookup, recipient certificate, JWE, callback and receipt, status and `/v1/error`); wrapping an existing integration; getting nhcx-adapter when asked | Stages 0, 1, 4, 6, 7.1, 7.3 | +| `references/api-knowledge.md` | The nhcx-adapter contract, read only when the user chose the adapter: config, routes, envelope and answer, delivery, ledger, kit endpoints, curl | 7.1 and 7.3, adapter only | +| `references/fhir-knowledge.md` | Every bundle sent and received, element ids, HPIN, consent questionnaires, supportingInfo, LM100, ONS and DTM, the TaskBundle reply, where the pins live, the validator | Stages 4, 6, 7.4 to 7.10, 8 | +| `references/errors-and-debugging.md` | PAYR and ERR codes with meaning and fix, gateway errors, reading a ledger thread, correlation mistakes, redelivery, sandbox pace | Stages 8, 10, 11 | +| `references/testing-knowledge.md` | The test pyramid, the test-case matrix per use case, a skeleton offline test | Stages 2, 9, 10 | +| `fhir/FHIR.md` | The FHIR guide: every bundle sent and read, entries in pinned order, the code systems, pseudo code for each builder and reader, the refusal each rule guards against | Stages 0, 4, 6, 7.4 to 7.10, 8 | +| `ui/UI-GUIDE.md` | The screens: the two honesty rules, where every value comes from, a layout per screen, the state words, pseudo code for the status line, the timeline and the actions | Stages 5, 7.12, 7.13 | +| `flow/FLOW.md`, `flow/flow.json` | The one path an episode walks: steps F1 to F13 and their skills, the tab order, the action labels, the guards, the page-load polls | Stage 1 whole; stages 4, 5, 7, 8 by step id | +| `references/material.md` | Where the pins, fixtures and docs live: the NHCX package, the pin map, what the package lacks | Stage 0, and whenever a cited file is needed | + +## Keeping the seven copies in step + +Everything in this folder except `SKILL.md` is the same in all seven skill folders. A change to one of these files is made in all seven. `diff -r --exclude=SKILL.md` between any two skill folders prints nothing when they agree. + +## Deliverables + +- This skill's sections of `nhcx-build/`, every gate in its STATE.md block closed with evidence or open with a reason. +- Its verdicts in `capabilities.json`, each with the check that decided it. +- Schema additions for its legs (integrate) or its tables in the whole schema (standalone), under the target's conventions. +- Builders and readers for every leg it owns, each compared with its pin in the offline test. +- Its tabs and screens, deriving every state from received messages. +- Tests covering its rows of the matrix, a run record, and a report section a stranger could act on. diff --git a/plugins/nhcx/skills/nhcx-claim/fhir/FHIR.md b/plugins/nhcx/skills/nhcx-claim/fhir/FHIR.md new file mode 100644 index 000000000..90b85cbae --- /dev/null +++ b/plugins/nhcx/skills/nhcx-claim/fhir/FHIR.md @@ -0,0 +1,658 @@ +# NHCX FHIR: the bundles a hospital sends and reads + +Every bundle here is held to a pin in the NHCX package, under `nhcx-package/fhir/B*`. Read `../references/fhir-knowledge.md` for the why; this file is the how. The pseudo code is language-neutral: a `dict` is a JSON object, a `list` is a JSON array, and `ref(url)` is `{"reference": url}`. + +## 1. Conventions every bundle follows + +"Validator" below is the HL7 FHIR validator with the NRCeS `ndhm.in` IG, run as `../references/fhir-knowledge.md` section 11 describes. + +| Rule | Detail | Refusal if broken | +| --- | --- | --- | +| Bundle | `resourceType Bundle`, `type collection`, `id` fixed per shape, `meta.profile` = the NRCES bundle profile | validator error | +| Entries | Every entry has an absolute `fullUrl` under `https://nhcx.abdm.gov.in/...`; every `reference` resolves to a `fullUrl` in the same bundle | validator error, PAYR-10xx | +| Profiles | Every resource carries `meta.profile` = `https://nrces.in/ndhm/fhir/r4/StructureDefinition/` | validator warning | +| No timestamps on requests | No `meta.versionId`, `meta.lastUpdated`, bundle `timestamp` (the communication reply is the exception) | none, but the pin differs | +| Money | `{"value": n, "currency": "INR"}`; whole numbers as integers, never `3300.0` | pin differs | +| Instants | IST with `+05:30`, seconds precision | PAYR on dates | +| Identifiers | Typed with a `type.coding` from the NDHM identifier-type system or HL7 v2-0203, `system` where the pin has one | PAYR-1083 and kin | + +### Code systems, named once + +``` +NDHM = "https://nrces.in/ndhm/fhir/r4/CodeSystem/" +PROFILE = "https://nrces.in/ndhm/fhir/r4/StructureDefinition/" +BASE = "https://nhcx.abdm.gov.in" +HL7 = "http://terminology.hl7.org/CodeSystem/" +SNOMED = "http://snomed.info/sct" +ICD10 = "http://hl7.org/fhir/sid/icd-10" +HPR = "https://hpr.abdm.gov.in" + +ID_TYPE = NDHM + "ndhm-identifier-type-code" # PMJAY, ABHA, HPID, HPIN, CLN +V2_0203 = HL7 + "v2-0203" # MB, MD, NH, NPI, NIIP +V2_0360 = HL7 + "v2-0360" # qualification degrees +ORG_TYPE = HL7 + "organization-type" # prov, pay +ACT_CODE = HL7 + "v3-ActCode" # HIP +REL = HL7 + "subscriber-relationship" # self +PRIORITY = HL7 + "processpriority" # normal +CARE_ROLE = HL7 + "claimcareteamrole" # primary, assist +DX_TYPE = HL7 + "ex-diagnosistype" # admitting +DX_ONADM = HL7 + "ex-diagnosis-on-admission" # yes +FIN_TASK = HL7 + "financialtaskcode" # poll, cancel, reprocess, release, status +FIN_INPUT = HL7 + "financialtaskinputtype" # include +COMM_CAT = HL7 + "communication-category" # notification + +BENEFIT_CAT = NDHM + "ndhm-benefit-category" # Claim.item.category (specialty) +PROC_CODE = NDHM + "ndhm-procedure-code" # Claim.item.productOrService (package) +PROGRAM = NDHM + "ndhm-program-code" # AB-PMJAY +SI_CATEGORY = NDHM + "ndhm-supportinginfo-category" # INV, ONS, OTH, HDS, DIS, NMI, INF, STG +SI_CODE = NDHM + "ndhm-supportinginfo-code" # ADDD, EDT, PSP, DSDE, DTM, DTH, LAMA, DAMA, CQD, ODN +DOC_CODE = BASE + "/document-code" # the plan's MANDxxxx codes, else ODN +TASK_INPUT = NDHM + "ndhm-task-input-type-code" # policyNumber, providerId, claimNumber, intimationNumber, document +TASK_INPUT_X = BASE + "/task-input-type" # amount +TASK_OUTPUT = NDHM + "ndhm-task-output-type" # status +TASK_OUTVAL = NDHM + "ndhm-task-output-value" # paymentack +TASK_CODES = NDHM + "ndhm-task-codes" # deliver +REASON = NDHM + "ndhm-reason-code" # treatmentplanchanged, claimrejected, partialpayment, rejectiondisputed +CAT_CODE = BASE + "/category-code" # CoverageEligibilityRequest.item.category +PRODUCT_CODE = BASE + "/product-code" # CoverageEligibilityRequest.item.productOrService +PROC_TYPE = BASE + "/procedure-type" # conservative, medical, surgical +DOC_TYPE_EXT = settings.document_type_extension_url # on a Communication attachment; participant-defined (nhcx-package/docs/05-FHIR Reference/17-Communication.md). + # The communication/response pin carries its author's own url: the pin comparison sets this from the pin. +``` + +### Shared helpers + +``` +function cc(system, code, display=null): # CodeableConcept + coding = {"code": code}; if system: coding.system = system; if display: coding.display = display + return {"coding": [coding]} + +function typed_id(type_system, type_code, type_display, value, system=null): + out = {"type": cc(type_system, type_code, type_display), "value": value} + if system: out.system = system # put "system" before "value" as the pins do; canonical JSON sorts anyway + return out + +function entry(url, resource): return {"fullUrl": url, "resource": resource} + +function profile(name): return {"profile": [PROFILE + name]} + +function bundle(id, profile_name, entries): # profile_name: "ClaimBundle", "TaskBundle", "CoverageEligibilityRequestBundle" + return {"resourceType": "Bundle", "id": id, "meta": profile(profile_name), "type": "collection", "entry": entries} + +function organization(role, identifier_code, identifier_display, id_value, name, res_id=null): + o = {"resourceType": "Organization", "meta": profile("Organization"), + "identifier": [typed_id(V2_0203, identifier_code, identifier_display, id_value, BASE)], + "type": [cc(ORG_TYPE, role, "Healthcare Provider" if role == "prov" else "Payer")], "name": name} + if res_id: o.id = res_id + return o + +function provider_org(facility, res_id=null): return organization("prov", "NPI", "National provider identifier", facility.hfr_id, facility.name, res_id) +function payer_org(payer, res_id=null): return organization("pay", "NIIP", "National Insurance Payor Identifier (Payor)", strip_hcx(payer.participant_code), payer.name, res_id) +function strip_hcx(code): return code.split("@")[0] + +function money(v): return {"value": int(v) if v == int(v) else round(v, 2), "currency": "INR"} +``` + +## 2. Coverage eligibility request + +Pins: `coverage/{discovery,validation,benefits,authrequirements}`. Sent on `v1/coverageeligibility/check`, workflow id = the case number. Purposes: `discovery` (who covers this person), `validation` (is the policy in force), `benefits` (balances), `auth-requirements` (rule on the quoted items). + +Entries, in order: CoverageEligibilityRequest, Patient, provider Organization, payer Organization, Location, Coverage, PractitionerRole. + +``` +function build_coverage_request(d): + # d: purpose, member_id, policy_code (null on discovery), facility{hfr_id,name}, payer{participant_code,name}, created, items[] (benefits, auth-requirements only) + U = BASE + cer = {"resourceType": "CoverageEligibilityRequest", "meta": profile("CoverageEligibilityRequest"), + "identifier": [{"system": BASE}], "status": "active", + "priority": cc(PRIORITY, "normal", "Normal"), "purpose": [d.purpose], + "patient": ref(U + "/patient"), "created": d.created, + "enterer": ref(U + "/practitioner-role"), "provider": ref(U + "/provider"), + "insurer": ref(U + "/payer"), "facility": ref(U + "/location"), + "insurance": [{"focal": true, "coverage": ref(U + "/coverage")}]} + if d.purpose in ("benefits", "auth-requirements"): + cer.item = [eligibility_item(i) for i in d.items] + patient = {"resourceType": "Patient", "meta": profile("Patient"), + "identifier": [typed_id(ID_TYPE, "PMJAY", "Pradhan Mantri Jan Aarogya Yojana (PMJAY) ID", d.member_id), + typed_id(V2_0203, "MB", "Member Number", d.member_id)]} # no name, no demographics + coverage = {"resourceType": "Coverage", "meta": profile("Coverage"), + "identifier": [typed_id(V2_0203, "NH", "National Health Plan Identifier", d.policy_code or "NONE")], + "status": "active", "type": cc(ACT_CODE, "HIP", "health insurance plan policy"), + "subscriber": ref(U + "/patient"), "subscriberId": d.member_id, "beneficiary": ref(U + "/patient"), + "relationship": cc(REL, "self"), "payor": [ref(U + "/payer")]} + location = {"resourceType": "Location", "name": d.facility.name, "managingOrganization": ref(U + "/provider")} + role = {"resourceType": "PractitionerRole", "meta": profile("PractitionerRole"), + "code": [cc(SNOMED, "307988006", "Medical technician")]} + return bundle("coverage-" + d.purpose.replace("-", "") + "-request-generic", "CoverageEligibilityRequestBundle", [ + entry(U + "/coverage-eligibility/request", cer), entry(U + "/patient", patient), + entry(U + "/provider", provider_org(d.facility)), entry(U + "/payer", payer_org(d.payer)), + entry(U + "/location", location), entry(U + "/coverage", coverage), entry(U + "/practitioner-role", role)]) + +function eligibility_item(i): + # i: category{code,display}, code, display, quantity (integer), tiers[] {code, display} + out = {"category": cc(CAT_CODE, i.category.code, i.category.display), + "productOrService": cc(PRODUCT_CODE, i.code, i.display), + "quantity": {"value": int(i.quantity)}} + if i.tiers: out.modifier = [cc(null, t.code, t.display) for t in i.tiers] # no system on a tier + return out +``` + +Bundle ids: `coverage-discovery-request-generic`, `coverage-validation-request-generic`, `coverage-benefits-request-generic`, `coverage-authrequirements-request-generic`. + +### Reader: CoverageEligibilityResponse + +The payer echoes the request's entries and appends its own; take the last of each type. + +``` +function parse_validation_bundle(b): + resp = last(b, "CoverageEligibilityResponse"); pat = last(b, "Patient"); cov = last(b, "Coverage") + out = {"outcome": resp.outcome, "disposition": resp.disposition, "inforce": resp.insurance[0].inforce, + "auth_required": any(item.authorizationRequired for item in resp.insurance[0].item or []), + "allowed": null, "used": null} + for item in resp.insurance[0].item or []: + for ben in item.benefit or []: + if ben.allowedMoney and (out.allowed is null or ben.allowedMoney.value > out.allowed): + out.allowed = ben.allowedMoney.value; out.used = (ben.usedMoney or {}).value or 0 + out.patient = {"name": pat.name[0].text, "gender": pat.gender, "birthDate": pat.birthDate, + "abha": first_identifier(pat, "ABHA"), "photo": pat.photo[0].data if pat.photo else null} + out.coverage = {"class": cov.class[0].name if cov.class else null, "period": cov.period} + return out +# status: eligible if inforce else not-eligible; balance shown = allowed - used +``` + +### Reader: the auth-requirements ruling + +``` +function parse_auth_bundle(b): + resp = last(b, "CoverageEligibilityResponse"); items = []; requirements = [] + for item in resp.insurance[0].item or []: + items.append({"code": item.productOrService.coding[0].code, "authorised": item.authorizationRequired, + "excluded": item.excluded, "benefit": item.benefit[0] if item.benefit else null}) + for sup in item.authorizationSupporting or []: + text = sup.text or "" # the scheme overloads free text + r = {"line": item.productOrService.coding[0].code, "code": sup.coding[0].code if sup.coding else null, + "display": sup.coding[0].display if sup.coding else text} + if "fullUrl:" in text: r.kind = "form"; r.url = after("fullUrl:", text).strip(); r.stage = "pre" + else: r.kind = "document"; r.stage = "post" if "Type: post" in text else "pre" + r.at_preauth = (r.kind == "form") or (r.stage == "pre") + requirements.append(r) + return {"items": items, "requirements": requirements} +``` + +## 3. Insurance plan request + +Pin: `insurance`. Sent on `v1/insuranceplan/request`, workflow id = the case number. One entry. + +``` +function build_plan_request(policy_code, provider_id): + task = {"resourceType": "Task", "meta": profile("Task"), "status": "requested", "intent": "order", + "code": cc(FIN_TASK, "poll"), + "input": [{"type": cc(TASK_INPUT, "policyNumber"), "valueString": policy_code}, + {"type": cc(TASK_INPUT, "providerId"), "valueString": provider_id}]} + return bundle("insurance-request-generic", "TaskBundle", [entry(BASE + "/insurance/request", task)]) +# no id, no authoredOn, no requester; at least one input is mandatory +``` + +### Reader: the plan + +``` +function parse_plan_bundle(b): + plan = first(b, "InsurancePlan"); forms = {q.url: q for q in all(b, "Questionnaire")} + benefits = {} # keyed by package code + for p in plan.plan or []: # shape 1: package-based + for sc in p.specificCost or []: + specialty = sc.category.coding[0] + for ben in sc.benefit or []: + code = ben.type.coding[0].code; row = benefits.setdefault(code, new_benefit(code, ben.type.coding[0].display, specialty)) + for cost in ben.cost or []: + kind = cost.type.coding[0].code # Procedure | Implant | Stratification + if kind == "Procedure": row.rate = cost.value.value; row.kind = "Procedure" + else: row.extras.append({"kind": kind, "code": cost.qualifiers[0].coding[0].code, "display": cost.qualifiers[0].coding[0].display, "amount": cost.value.value}) + row.conditions.update(read_conditions(ben.extension)); row.requirements += read_requirements(ben.extension) + for cov in plan.coverage or []: # shape 2: coverage-based + for ben in cov.benefit or []: + code = ben.type.coding[0].code; row = benefits.setdefault(code, new_benefit(code, ben.type.coding[0].display, cov.type.coding[0])) + for lim in ben.limit or []: + if lim.code.coding[0].code == code: row.rate = lim.value.value + else: row.extras.append({"kind": "Stratification", "code": lim.code.coding[0].code, "display": lim.code.coding[0].display, "amount": lim.value.value}) + row.conditions.update(read_conditions(ben.extension)); row.requirements += read_requirements(ben.extension) + policy_requirements = read_requirements(plan.extension) # policy-wide: identity proof, consent forms + return {"plan": {"id": plan.id, "name": plan.name}, "benefits": list(benefits.values()), + "policy_requirements": policy_requirements, + "forms": [{"url": u, "title": q.title, "kind": "stg" if "/stgquestionnaire/" in u else "policy", + "questions": [{"linkId": it.linkId, "text": it.prefix or it.text, "type": it.type, + "options": [o.valueString or o.valueCoding.display for o in it.answerOption or []], + "default": first_selected(it)} for it in q.item]} for u, q in forms.items()]} + +function read_conditions(exts): # extension url family "...Claim-Condition": children named by their url tail + out = {} + for e in exts or []: + if "Claim-Condition" in e.url: + for child in e.extension or []: out[tail(child.url)] = child.valueString or child.valueBoolean or child.valueCodeableConcept.coding[0].code + return out + +function read_requirements(exts): # "...Claim-SupportingInfoRequirement": one nested requirement per document + out = [] + for e in exts or []: + if "Claim-SupportingInfoRequirement" in e.url: + for req in e.extension or []: + r = {} + for f in req.extension or []: + if tail(f.url) == "category": r.category = f.valueCodeableConcept.coding[0].code + if tail(f.url) == "code": r.code = f.valueCodeableConcept.coding[0].code; r.display = f.valueCodeableConcept.coding[0].display + if tail(f.url) == "documentationUrl": r.url = f.valueUri or f.valueString + out.append(r) + return out +``` + +## 4. The Claim bundle + +Pins: `preauth/request`, `preauth/enhancement`, `preauth/queryupdate`, `claim/request`, `claim/queryupdate`. One builder, three switches: `leg` (`preauth`, `claim`, `predetermination`), `flow` (`request`, `enhancement`, `queryupdate`), `use` (`preauthorization`, `claim`, `predetermination`). + +Entries, in order: Claim, Patient, provider Organization (id 1), payer Organization (id 2), Coverage (id 1), Practitioner (one per care team member), Procedure (one per package line), QuestionnaireResponse (one per answered form). + +``` +function claim_bundle(leg, use, d): + # d: flow, claim_no, created, admission{admitted_at, discharged_at, surgery_at, death_at, mode, stage}, + # patient{member_id, abha, name, phone, gender, birthDate}, facility, payer, policy_code, + # care_team[] {hpid, licence, hpin, name, qualification_code, qualification_display, specialty_snomed, specialty_display}, + # diagnoses[] {code, display}, lines[] (procedures and implants, each with tiers[]), documents[] {code, category, content_type, bytes, title}, + # forms[] {url, answers[] {linkId, type, value}}, program_code (AB-PMJAY or null), factor_rule (pmjay or null), + # preauth_ref (claim leg), summary{code, content_type, bytes, title} (claim leg), query_reply (queryupdate) + U = BASE; anchor = U + "/" + leg + "/" + d.flow + practitioners = [practitioner_resource(m, n + 1) for n, m in enumerate(d.care_team)] + procedures = [procedure_resource(line, n + 1, completed = (leg == "claim"), when = d.admission.surgery_at or d.admission.admitted_at) for n, line in enumerate(package_lines(d.lines))] + (qrs, form_refs) = questionnaire_responses(d.forms, d.created) + (si, si_refs) = supporting_info(d, leg, form_refs) + claim = {"resourceType": "Claim", "id": d.claim_no, "meta": profile("Claim"), + "identifier": [typed_id(ID_TYPE, "CLN", "Claim number", d.claim_no, BASE)], + "status": "active", "type": cc(SNOMED, "737481003", "Inpatient care management (procedure)"), "use": use, + "patient": ref(U + "/patient"), + "billablePeriod": {"start": d.admission.admitted_at, "end": d.admission.discharged_at or planned_end(d)}, + "created": d.created, "insurer": ref(U + "/payer"), "provider": ref(U + "/provider"), + "priority": cc(PRIORITY, "normal", "Normal"), + "careTeam": [{"sequence": n + 1, "provider": ref(practitioner_url(n)), + "role": cc(CARE_ROLE, "primary" if n == 0 else "assist", "Primary provider" if n == 0 else "Assisting Provider"), + "qualification": cc(SNOMED, m.specialty_snomed, m.specialty_display)} for n, m in enumerate(d.care_team)], + "supportingInfo": si, + "diagnosis": [{"sequence": n + 1, "diagnosisCodeableConcept": cc(ICD10, dx.code, dx.display), + "type": [cc(DX_TYPE, "admitting", "Admitting Diagnosis")], "onAdmission": cc(DX_ONADM, "yes", "Yes")} for n, dx in enumerate(d.diagnoses)], + "procedure": [{"id": "Procedure/" + str(n + 1), "sequence": n + 1, + "type": [cc(PROC_TYPE, line.procedure_type.lower(), line.procedure_type)], # from the plan's ProcedureType condition + "date": d.admission.surgery_at or d.admission.admitted_at, + "procedureReference": {"reference": U + "/procedure/" + str(n + 1), "display": line.display}} for n, line in enumerate(package_lines(d.lines))], + "insurance": [{"sequence": 1, "focal": true, "coverage": ref(U + "/coverage")}], + "item": claim_items(d, si_refs), + "total": money(sum(item.net.value for item in items))} + if leg == "claim": claim.insurance[0].preAuthRef = [d.preauth_ref] # the payer's ClaimResponse.preAuthRef + entries = [entry(anchor, claim), entry(U + "/patient", patient_resource(d.patient)), + entry(U + "/provider", provider_org(d.facility, "1")), entry(U + "/payer", payer_org(d.payer, "2")), + entry(U + "/coverage", coverage_resource(d.policy_code, d.patient.member_id))] + entries += [entry(practitioner_url(n), p) for n, p in enumerate(practitioners)] + entries += [entry(U + "/procedure/" + str(n + 1), p) for n, p in enumerate(procedures)] + entries += [entry(U + "/questionnaireresponse/" + str(n + 1), q) for n, q in enumerate(qrs)] + return bundle(leg + "-" + d.flow + "-request-generic", "ClaimBundle", entries) + # preauth-request-generic, preauth-enhancement-request-generic, preauth-queryupdate-request-generic, claim-request-generic, claim-queryupdate-request-generic + +function practitioner_url(n): return BASE + "/practitioner" + ("" if n == 0 else "/" + str(n + 1)) + +function patient_resource(p): + ids = [typed_id(ID_TYPE, "PMJAY", "Pradhan Mantri Jan Aarogya Yojana (PMJAY) ID", p.member_id)] + if p.abha: ids.append(typed_id(ID_TYPE, "ABHA", "Ayushman Bharat Health Account (ABHA) ID", p.abha)) + ids.append(typed_id(V2_0203, "MB", "Member Number", p.member_id)) + return {"resourceType": "Patient", "id": "1", "meta": profile("Patient"), "identifier": ids, + "name": [{"text": p.name}], "telecom": [{"system": "phone", "value": p.phone}], "gender": p.gender, "birthDate": p.birthDate} + +function practitioner_resource(m, n): + ids = [typed_id(ID_TYPE, "HPID", "Healthcare Professional ID (HPID)", m.hpid or m.hpin, BASE)] + if m.licence: ids.append(typed_id(V2_0203, "MD", "Medical License number", m.licence, BASE)) + ids.append(typed_id(ID_TYPE, "HPIN", "Health Practitioner ID issued by NDHM", m.hpin, HPR)) # PAYR-1083 without it + return {"resourceType": "Practitioner", "id": str(n), "meta": profile("Practitioner"), "identifier": ids, + "name": [{"text": m.name}], "qualification": [{"code": cc(V2_0360, m.qualification_code, m.qualification_display)}]} + +function coverage_resource(policy_code, member_id): + return {"resourceType": "Coverage", "id": "1", "meta": profile("Coverage"), + "identifier": [typed_id(V2_0203, "NH", "National Health Plan Identifier", policy_code)], + "status": "active", "type": cc(ACT_CODE, "HIP", "health insurance plan policy"), + "subscriber": ref(BASE + "/patient"), "subscriberId": member_id, "beneficiary": ref(BASE + "/patient"), + "relationship": cc(REL, "self"), "payor": [ref(BASE + "/payer")]} + +function procedure_resource(line, n, completed, when): + return {"resourceType": "Procedure", "id": str(n), "meta": profile("Procedure"), + "status": "completed" if completed else "preparation", + "code": {"coding": [{"system": SNOMED, "code": "71388002", "display": "Procedure"}], "text": line.display}, + "subject": ref(BASE + "/patient"), "performedDateTime": when} +``` + +### Items: one per procedure or implant, never per tier + +``` +function package_lines(lines): return [l for l in lines if l.kind in ("procedure", "implant")] # tiers ride on their parent + +function claim_items(d, si_refs): + groups = package_lines(d.lines); factors = procedure_factors(groups, d.factor_rule) + items = [] + for n, line in enumerate(groups): + tiers = [t for t in d.lines if t.kind == "tier" and t.parent_code == line.code] + net = line.amount + sum(t.amount for t in tiers) + item = {"id": "Item/" + str(n + 1), "sequence": n + 1, "careTeamSequence": [1], "diagnosisSequence": [1], + "procedureSequence": [n + 1], "informationSequence": si_refs, # every supportingInfo sequence + "category": cc(BENEFIT_CAT, line.category.code, line.category.display), + "productOrService": cc(PROC_CODE, line.code, line.display)} + if tiers: item.modifier = [cc(null, t.code, t.display) for t in tiers] + if d.program_code: item.programCode = [cc(PROGRAM, d.program_code, "Ayushman Bharat Pradhan Mantri Jan Arogya Yojana (AB-PMJAY)")] + item.servicedPeriod = {"start": day(d.admission.admitted_at), "end": day(d.admission.discharged_at or planned_end(d))} + item.quantity = {"value": int(line.quantity)} + item.unitPrice = money(net / line.quantity) + if factors: item.factor = factors[n] + item.net = money(net) + items.append(item) + return items + +function procedure_factors(groups, rule): + # PMJAY multiple-procedure rule: by cost rank, 1, 0.5, 0.25; a generic payer sends no factor + if rule != "pmjay" or len(groups) < 2: return null # the single-item pins carry factor 0.5 (their own contradiction); compare without it + ranked = sorted(range(len(groups)), key = lambda i: -groups[i].amount) + return {i: [1, 0.5, 0.25][min(rank, 2)] for rank, i in enumerate(ranked)} +``` + +### supportingInfo: the table, then the numbering + +``` +function supporting_info(d, leg, form_refs): + si = [] + for doc in d.documents: # one per attached file; never drop one + si.append({"category": cc(SI_CATEGORY, doc.category or "INV", display_for(doc.category or "INV")), + "code": cc(DOC_CODE, doc.code or "ODN", doc.title), # the plan's code, else ODN + "valueAttachment": {"contentType": doc.content_type, "data": base64(doc.bytes), "title": doc.title}}) + if leg == "claim": + si.append({"category": cc(SI_CATEGORY, "HDS", "Discharge summary"), "code": cc(DOC_CODE, d.summary.code or "HDS", d.summary.title), + "valueAttachment": {"contentType": d.summary.content_type, "data": base64(d.summary.bytes), "title": d.summary.title}}) + si.append(scalar("ONS", "ADDD", "Admission date -Discharge date", d.admission.admitted_at)) + si.append(scalar("OTH", "EDT", "EncounterDateTime", d.admission.admitted_at)) + if leg == "claim": + if d.admission.surgery_at: si.append(scalar("ONS", "PSP", "Procedure start", d.admission.surgery_at)) + si.append(scalar("ONS", "DSDE", "Discharge date", d.admission.death_at or d.admission.discharged_at)) + if d.admission.mode == "death": si.append(scalar("ONS", "DTM", "Date and time of death", d.admission.death_at)) # PAYR-1096 without it + code = {"normal": "DTH", "lama": "LAMA", "dama": "DAMA", "death": "DTM"}[d.admission.mode] + si.append(scalar("DIS", code, display_for(code), stage_words(d.admission.stage))) # "Before Surgery" | "During Surgery" | "After Surgery" + if d.flow == "queryupdate": + si.append(scalar("NMI", "CQD", "Claim query detail", d.query_reply)) # the desk's words; PMJAY reads its answer from here + for (form, url) in form_refs: # one per answered form + cat = "STG" if form.kind == "stg" else "INF"; code = "STG" if form.kind == "stg" else "ODN" + si.append({"category": cc(SI_CATEGORY, cat, display_for(cat)), "code": cc(SI_CODE, code, display_for(code)), "valueReference": ref(url)}) + for n, s in enumerate(si): # number once, after assembly: PAYR-1019 without sequence + s.id = "SupportingInformation/" + str(n + 1); s.sequence = n + 1 + reorder(s, ["id", "sequence", "category", "code", "value*"]) + return (si, [s.sequence for s in si]) + +function scalar(cat, code, display, value): + return {"category": cc(SI_CATEGORY, cat, display_for(cat)), "code": cc(SI_CODE, code, display), "valueString": value} +``` + +### Questionnaire responses + +``` +function questionnaire_responses(forms, authored): + qrs = []; refs = [] + for n, form in enumerate(forms): + url = BASE + "/questionnaireresponse/" + str(n + 1) + qr = {"resourceType": "QuestionnaireResponse", "id": str(n + 1), "meta": profile("QuestionnaireResponse"), + "questionnaire": form.url, "status": "completed", "subject": ref(BASE + "/patient"), "authored": authored, + "item": [{"linkId": a.linkId, "answer": [typed_answer(a)]} for a in form.answers]} + qrs.append(qr); refs.append((form, url)) + return (qrs, refs) + +function typed_answer(a): + switch a.type: + "string", "text", "choice": return {"valueString": a.value} + "date", "dateTime": return {"valueDateTime": a.value} + "boolean": return {"valueBoolean": a.value} + "integer": return {"valueInteger": int(a.value)} + "decimal": return {"valueDecimal": a.value} + "attachment": return {"valueAttachment": {"contentType": a.content_type, "data": base64(a.bytes), "title": a.title}} +``` + +### Which forms and documents ride + +``` +function required_forms(case, stage): # stage: preauth | claim + if case.ruling: forms = [r for r in case.ruling.requirements if r.kind == "form" and (stage == "preauth" or r.stage != "pre")] + else: forms = plan_stg_forms(case.plan, case.lines) if stage == "preauth" else [] + return forms + policy_forms(case.plan) # consent every leg: PAYR-1256 / PAYR-1363; STG: PAYR-1254 / PAYR-1365 + +function required_documents(case, stage): + if case.ruling: return [r for r in case.ruling.requirements if r.kind == "document" and (r.stage == "pre") == (stage == "preauth")] + wanted = plan_documents(case.plan, case.lines) + return wanted if stage == "preauth" else [w for w in wanted if not attached_at_preauth(case, w.code)] +``` + +### The legs, and the LAMA collapse + +``` +function lines_for(case, leg): + if leg == "claim" and case.admission.mode in ("lama", "dama") and case.admission.stage in ("before", "during"): + return [{"kind": "procedure", "code": "LM100", "display": "Left against medical advice", "quantity": 1, + "amount": plan_rate(case.plan, "LM100") or 0, "category": lm100_category(case.plan)}] # PAYR-1362 if the package stays + return case.lines # LM100 never on a pre-auth: PAYR-1270 +``` + +| Leg | flow | use | Procedure status | Workflow | Extra | +| --- | --- | --- | --- | --- | --- | +| Pre-auth | `request` | `preauthorization` | `preparation` | 12 | fresh 12 after a rejection too (PAYR-1214 on 121) | +| Enhancement | `enhancement` | `preauthorization` | `preparation` | 13 | every line, old and new, same claim number; factors 1 and 0.5 | +| Query answer | `queryupdate` | `preauthorization` | `preparation` | 19 (131 after an enhancement query) | `NMI/CQD`; new correlation id | +| Claim | `request` | `claim` | `completed` | 15 | discharge scalars, `HDS`, `preAuthRef`, under the pre-auth's number (ERR-PYR-CLM-007) | +| Claim query answer | `queryupdate` | `claim` | `completed` | 161 (PMJAY), 151 (generic) | as the claim plus `NMI/CQD` | +| Predetermination | `request` | `predetermination` | `preparation` | 12 on `v1/preauth/submit` | no state effects | + +## 5. Reader: ClaimResponse + +Fed by every answer on a pre-auth, enhancement, claim or predetermination thread. Entries: ClaimResponse, Patient, two Organizations, Coverage. + +``` +function parse_claim_response(b): + r = first(b, "ClaimResponse") + status_adj = first(a for a in r.adjudication or [] if a.category.coding[0].code == "status") + out = {"use": r.use, "outcome": r.outcome, "disposition": r.disposition, + "status_reason": status_adj.reason.coding[0].code.lower() if status_adj else null, # submitted|approved|queried|rejected|cancelled + "preauth_ref": r.preAuthRef if is_string(r.preAuthRef) else (r.preAuthRef[0] if r.preAuthRef else null), + "claim_no": r.identifier[0].value if r.identifier else null, + "totals": {t.category.coding[0].code: t.amount.value for t in r.total or []}, # by category, never by position + "items": [], "notes": [n.text for n in r.processNote or []]} + for it in r.item or []: + adj = {a.category.coding[0].code: a for a in it.adjudication or []} + out.items.append({"sequence": it.itemSequence, + "status": adj.status.reason.coding[0].code.lower() if adj.status else null, + "eligible": adj.eligible.amount.value if adj.eligible else null, + "submitted": adj.submitted.amount.value if adj.submitted else null, + "reason": adj.reason.reason.coding[0].display if adj.reason else "", # verbatim, pipe-delimited USER~datetime~type~comment~trust + "eligpercent": adj.eligpercent.value if adj.eligpercent else null, + "deductible": adj.deductible.amount.value if adj.deductible else null}) + return out + +function verdict_status(p): # copy exactly; never read outcome alone + if p.outcome == "queued" or p.status_reason == "submitted": return "submitting" + if p.status_reason == "cancelled": return "rejected" + if p.status_reason == "queried": return "queried" + if p.outcome == "error": return "rejected" + if p.outcome == "partial": return "partial" if p.status_reason == "approved" else "queried" + if p.outcome == "complete": return "approved" if p.status_reason in ("approved", null) else "queried" + return "queried" + +function apply_claim_response(leg, p, envelope): + leg.status = verdict_status(p) + if p.preauth_ref: leg.preauth_ref = p.preauth_ref # never overwrite a value with an empty one + leg.eligible_amount = p.totals.get("eligible") or p.totals.get("benefit") + leg.submitted_amount = p.totals.get("submitted") + leg.approved_amount = p.totals.get("benefit") # what the screen shows as the decision + leg.items_json = p.items; leg.query_note = join(p.notes + [i.reason for i in p.items if i.reason]) + leg.thread_correlation_id = envelope.jwe_headers["x-hcx-correlation_id"] + leg.answered_at = now() if leg.status != "submitting" else leg.answered_at +``` + +Payer workflow ids are labels for the timeline only: 20 received, 21 approved, 22 enhancement approved, 23 rejected, 24 queried, 25 claim received, 26 approved, 27 queried, 291 rejected. The bundle decides the state. + +## 6. Task bundles the hospital sends + +Pins: `preauth/cancel`, `claim/reprocess`, `claim/release`, `payment/notice-ack`. Sent on `v1/task/submit` (the payment acknowledgement on `v1/paymentnotice/on_request`). Entries: Task, provider Organization, payer Organization. + +``` +function task_bundle(id, anchor, task, facility, payer): + return bundle(id, "TaskBundle", [entry(BASE + anchor, task), entry(BASE + "/provider", provider_org(facility)), entry(BASE + "/payer", payer_org(payer))]) + +function base_task(code, status, authored_on, description): + return {"resourceType": "Task", "meta": profile("Task"), "status": status, "intent": "order", + "code": cc(FIN_TASK, code), "description": description, "authoredOn": authored_on, + "requester": ref(BASE + "/provider"), "owner": ref(BASE + "/payer")} + +function task_input(code, display, value): return {"type": cc(TASK_INPUT, code, display), "valueString": value} +function based_on(claim_no): return [{"identifier": typed_id(ID_TYPE, "CLN", "Claim number", claim_no, BASE), "display": "Claim " + claim_no}] + +function cancel_task(claim_no, reason, authored_on, facility, payer): # workflow PC01 + t = base_task("cancel", "requested", authored_on, "Cancel the preauthorization " + claim_no) + t.reasonCode = cc(REASON, reason.code, reason.display) # treatmentplanchanged, ... + t.input = [task_input("claimNumber", "ClaimNumber", claim_no), task_input("intimationNumber", "IntimationNumber", claim_no)] + return task_bundle("preauth-cancel-request-generic", "/preauth/cancel", t, facility, payer) + +function reprocess_task(claim_no, member_id, reason, description, documents, authored_on, facility, payer): # workflow 36 + t = base_task("reprocess", "requested", authored_on, description) + t.reasonCode = cc(REASON, reason.code, reason.display) # claimrejected | partialpayment | rejectiondisputed + t.basedOn = based_on(claim_no) + t.input = [task_input("claimNumber", "ClaimNumber", claim_no), task_input("intimationNumber", "IntimationNumber", claim_no)] + t.input += [{"type": cc(TASK_INPUT, "document", "Document"), "valueAttachment": {"contentType": d.content_type, "data": base64(d.bytes), "title": d.title}} for d in documents] + t.for = {"identifier": typed_id(ID_TYPE, "PMJAY", "Pradhan Mantri Jan Aarogya Yojana (PMJAY) ID", member_id)} # MB on a generic payer + return task_bundle("claim-reprocess-request-generic", "/claim/reprocess", t, facility, payer) + +function release_task(claim_no, amount, authored_on, facility, payer): # workflow 36 + t = base_task("release", "requested", authored_on, "Release the balance amount for claim " + claim_no) + t.reasonCode = cc(REASON, "partialpayment", "Reprocess request due to partial payment by payer") + t.basedOn = based_on(claim_no) + t.input = [task_input("claimNumber", "ClaimNumber", claim_no), {"type": cc(TASK_INPUT_X, "amount", "Amount"), "valueMoney": money(amount)}] + return task_bundle("claim-release-request-generic", "/claim/release", t, facility, payer) + +function status_task(claim_no, authored_on, facility, payer): # workflow = the leg's correlation id; PMJAY refuses (PAYR-1018) + t = base_task("status", "requested", authored_on, "Status of " + claim_no) + t.input = [task_input("claimNumber", "ClaimNumber", claim_no)] + return task_bundle("claim-status-request-generic", "/claim/status", t, facility, payer) + +function payment_ack(claim_no, authored_on, facility, payer): # workflow 17 (PMJAY) or the notice's own id; x-hcx-correlation_id = the notice's + t = base_task("status", "completed", authored_on, "Received the payment for claim " + claim_no) + t.output = [{"type": cc(TASK_OUTPUT, "status", "Status"), "valueCodeableConcept": cc(TASK_OUTVAL, "paymentack", "Payment is acknowledged")}, + {"type": cc(TASK_INPUT, "claimNumber", "ClaimNumber"), "valueString": claim_no}] + return task_bundle("payment-notice-ack-generic", "/payment/notice-ack", t, facility, payer) +``` + +The pins and the build both carry `intimationNumber`, so the offline comparison diffs the pins unchanged. + +### Readers: PC02, 37, status + +``` +function parse_task_answer(b): + t = first(b, "Task"); cr = first(b, "ClaimResponse") # a 37 may carry a ClaimResponse queued + outputs = {o.type.coding[0].code: o for o in t.output or []} + return {"status": t.status, "code": t.code.coding[0].code, + "claim_status": (outputs.get("claimStatus") or outputs.get("status") or {}).valueCodeableConcept.coding[0].code if outputs else null, + "description": t.description, "queued": cr is not null and cr.outcome == "queued"} +# PC02: pre-auth -> cancelled, episode gets a fresh claim number, the withdrawn one stays on the leg +# 37: enquiry row -> answered; a fresh verdict follows on the claim's own thread +``` + +## 7. Communication + +Pins: `communication/request` (the payer's TaskBundle, the reader's input) and `communication/response` (the hospital's reply). On `v1/communication/request` in, `v1/communication/on_request` out, with the request's correlation id and workflow id echoed. + +``` +function parse_communication_request(b): + t = first(b, "Task"); cr = first(b, "CommunicationRequest") + return {"task_status": t.status, "intent": t.intent, "reason": t.reasonCode.coding[0].code.lower() if t.reasonCode else null, + "request_id": cr.id, "request_url": fullurl_of(b, cr), + "questions": [p.contentString for p in cr.payload or [] if p.contentString], + "about_claim": (cr.basedOn or [{}])[0].display, "claim_no": claim_no_in(b)} + +function classify_communication(adapter, reason, intent): + if adapter.query_mode == "resubmit": return "notification" + if intent == "proposal": return "notification" + if intent == "order": return "query" + if reason in (null, "additionalinfo", "questionnaire", "query"): return "query" + return "notification" # tatquery, grievance, walletupdate, policychange, claimarbitration + +function build_acknowledgement_bundle(request_bundle, facility): # a notification, sent back at once + b = deepcopy(request_bundle); t = first(b, "Task"); t.status = "completed" + move_first(b, "Organization", where = provider) # provider Organization first + return b + +function build_communication_bundle(q, text, documents, sent_leg_bundle, facility, payer, now): + # q: the parsed request; sent_leg_bundle: the pre-auth or claim bundle as sent (its Claim, Patient, Organizations, Practitioner, Coverage are lifted) + task_id = uuid(); comm_id = uuid() + comm = {"resourceType": "Communication", "id": comm_id, "meta": profile("Communication"), + "identifier": [{"value": q.request_identifier}], "basedOn": [{"reference": q.request_url, "display": "CommunicationRequest"}], # never inResponseTo + "status": "completed", "category": [cc(COMM_CAT, "notification")], "priority": "routine", + "about": [{"reference": claim_anchor(sent_leg_bundle), "display": "Claim " + claim_no}], + "sender": {"reference": BASE + "/provider", "display": "Organization"}, "recipient": [{"reference": BASE + "/payer", "display": "Organization"}], + "payload": [{"contentString": text}] + [{"contentAttachment": {"contentType": d.content_type, "data": base64(d.bytes), "title": d.title}, + "extension": [{"url": DOC_TYPE_EXT, "valueString": d.code}]} for d in documents]} + task = {"resourceType": "Task", "id": task_id, "meta": profile("Task"), "status": "completed", "intent": "order", + "code": cc(TASK_CODES, "deliver"), "reasonCode": cc(null, q.reason or "additionalinfo", "Additional information requested"), + "authoredOn": now, "requester": {"reference": BASE + "/provider", "display": "Organization"}, "owner": {"reference": BASE + "/payer", "display": "Organization"}, + "input": [{"type": cc(FIN_INPUT, "include"), "valueReference": {"reference": "urn:uuid:" + comm_id, "display": "Communication"}}]} + entries = [entry("urn:uuid:" + task_id, task), entry("urn:uuid:" + comm_id, comm), entry(q.request_url, q.request_resource)] + entries += [entry(e.fullUrl, e.resource) for e in sent_leg_bundle.entry if e.resource.resourceType in ("Claim", "Patient", "Organization", "Practitioner", "Coverage")] + b = bundle("communication-response-generic", "TaskBundle", entries) + b.meta.lastUpdated = now; b.timestamp = now # the IG example carries both; the only request that does + return b +``` + +Excluded from the byte comparison of the reply: `meta.lastUpdated`, `timestamp`, `authoredOn`, the two generated uuids. + +## 8. Payment notice + +Read on `v1/paymentnotice/request`. Entries: Task, PaymentNotice, PaymentReconciliation, two Organizations. + +``` +function parse_payment_notice(b): + pn = first(b, "PaymentNotice"); pr = first(b, "PaymentReconciliation"); t = first(b, "Task") + out = {"claim_no": pn.identifier[0].value if pn.identifier else claim_no_in(b), + "amount": pn.amount.value, "payment_status": pn.paymentStatus.coding[0].code, # paid | cleared | ... + "payment_date": pn.paymentDate, "utr": null, "details": []} + if pr: + out.utr = pr.paymentIdentifier.value if pr.paymentIdentifier else null + out.gross = pr.paymentAmount.value if pr.paymentAmount else null + out.details = [{"type": d.type.coding[0].code, "amount": d.amount.value if d.amount else null} for d in pr.detail or []] # deductions, TDS + if not out.utr and pn.payment and pn.payment.identifier: out.utr = pn.payment.identifier.value + return out +# record: one claim_payment row keyed on the message's correlation id (unique), matched by claim_no; then acknowledge with payment_ack() +``` + +## 9. Validate before you send + +``` +function validate_bundle(b, pin): # the offline gate, module 7.7 Validate + assert canonical(strip(b, ["created"])) == canonical(strip(pin, ["created"])) # plus the per-shape exclusions above + urls = {e.fullUrl for e in b.entry} + for r in all_references(b): assert r in urls or r.startswith("urn:uuid:") + c = first(b, "Claim") + if c: + for it in c.item: assert it.id and it.sequence + for p in c.procedure: assert p.id and p.sequence + for n, s in enumerate(c.supportingInfo): assert s.id and s.sequence == n + 1 + for pr in all(b, "Practitioner"): assert any(i.type.coding[0].code == "HPIN" and i.system == HPR for i in pr.identifier) + assert c.total.value == sum(it.net.value for it in c.item) + assert not any(it.productOrService.coding[0].code == "LM100" for it in c.item) or c.use == "claim" + assert no literal in the builder matches r"MAND\d+|MG\d+|/questionnaire/" +``` + +| Symptom | Refusal | +| --- | --- | +| an item without `id` | PAYR-1027 | +| a supportingInfo without `sequence` | PAYR-1019 | +| a Practitioner without `HPIN` | PAYR-1083 | +| a death claim without `ONS/DTM` | PAYR-1096, PAYR-1503 | +| a LAMA claim before surgery still carrying the package | PAYR-1362 | +| `LM100` on a pre-auth | PAYR-1270 | +| the consent form unanswered | PAYR-1256 (pre-auth), PAYR-1363 (claim) | +| a package's STG form unanswered | PAYR-1254, PAYR-1365 | +| a claim under its own number | ERR-PYR-CLM-007 | +| 121 after a rejection | PAYR-1214 | +| 151, 19 or 16 on `v1/claim/submit` to PMJAY | PAYR-1321 | +| a document outside pdf, jpg, jpeg, png; a Task the sandbox does not take; a misspelt intimation input on a reprocess | PAYR-1008 | diff --git a/plugins/nhcx/skills/nhcx-claim/flow/FLOW.md b/plugins/nhcx/skills/nhcx-claim/flow/FLOW.md new file mode 100644 index 000000000..312668e67 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-claim/flow/FLOW.md @@ -0,0 +1,228 @@ +# The flow: the one path a claim episode walks + +This is the reference flow for an NHCX provider desk: these steps, in this order, with these guards and these words. A build from this skill walks the same path. It does not redesign it, reorder it, merge steps, or invent screens the path does not have. Stage 4 copies it, stage 5 puts screens on it, stage 7 implements it step by step, stage 8 checks every step exists, and test drivers check the same through `flow.json`. + +## The shape + +One episode is one case (`claim` row). It has one list screen, one "new case" screen and one case screen. The case screen has tabs in the order the episode happens, and above the tabs one status line and the actions the case is waiting for. Everything else (inbox, payments across cases) is a view over the same rows. + +Tabs on the case screen, in this order and with these names: + +| # | Tab key | Tab label | Opens when | +| --- | --- | --- | --- | +| 1 | `eligibility` | Eligibility | always | +| 2 | `plan` | Insurance plan | always (empty until the plan is fetched) | +| 3 | `lines` | Line items | always (quoting refused until the plan is `ready`) | +| 4 | `validate` | Validate | always (the ruling on the quoted set) | +| 5 | `preauth` | Pre-authorisation | once the coverage verdict is `eligible` | +| 6 | `communication` | Communication | always (the payer's questions on both legs) | +| 7 | `claim` | Claim | always; its submit opens once a pre-auth is approved or partial | +| 8 | `payments` | Payments | always | + +The episode may also render on one page, with the same sections in the same order. Either shape is fine; the order and the gating are not negotiable. + +## Which skill builds which step + +Seven skills build this flow, one slice each (`core/LADDER.md`). `flow.json` names them per step in `skills`, the first named being the one that owns the step. + +| Steps | Skill | +| --- | --- | +| F1, F2, F3 | `nhcx-coverage` | +| F4, F7 | `nhcx-insurance` | +| F5, F6, F8, F9, F9a, F9c, F9d, F9e; F9b for a `resubmit` payer (19, 131) | `nhcx-preauth` | +| F10, F11; the claim query answer for a `resubmit` payer (161) | `nhcx-claim` | +| F9b and the claim query for a `communication` payer; F12b | `nhcx-communication` | +| F12 | `nhcx-payment` | +| F13 | `nhcx-reprocess` | + +The case screen, its tabs, the status line and actions, and the page-load polls are the foundation's (`core/FOUNDATION.md`): the first skill lays them out whole, and each skill fills its own tabs. + +## The status line and the actions + +Above the tabs: `stage / sub-stage` from `case_stage` (module 7.11) and the list from `next_actions`, first item highlighted. The labels are these, verbatim: + +| Stage | Sub-stage | Action offered (label, tab) | +| --- | --- | --- | +| any | an open query exists | "Answer the payer (n)", `communication` (leads every list) | +| `eligibility` | `draft`, `error`, `not-eligible` | "Check the cover", `eligibility` | +| `eligibility` | `eligible`, no plan `ready` | "Fetch the package master", `plan` | +| `eligibility` | plan ready, no lines | "Quote the treatment", `lines` | +| `eligibility` | lines quoted | "Send the pre-authorisation", `preauth` | +| `preauth` or `enhancement` | `queried` | "Answer the query", `preauth` (resubmit payer) or "Answer the payer's query", `communication` (communication payer) | +| `preauth` | `draft`, `refused` | "Send the pre-authorisation", `preauth` | +| `preauth` | `rejected` | "Send a fresh pre-authorisation", `preauth` | +| `preauth` | `approved`, `partial`, lines added since | "Send the enhancement (n added)", `preauth` | +| `preauth` | `approved`, `partial`, not discharged | "Record the discharge", `claim` | +| `preauth` | `approved`, `partial`, discharged | "File the claim", `claim` | +| `preauth` | `requested`, `answered`, `resubmitted` | "With the payer; ask where it stands", `preauth` | +| `claim` | `queried` | "Answer the claim query", `claim` or "Answer the payer's query", `communication` | +| `claim` | `rejected`, `partial` | "Ask for a reprocess", `claim` | +| `claim` | `requested`, `answered`, `resubmitted` | "With the payer; ask where it stands", `claim` | +| `claim` | `refused` | "Send the claim again", `claim` (while a send kind remains) else "Ask for a reprocess" | +| `claim` | `approved` | "Await the payment notice", `payments` | +| `payment` | a notice unacknowledged | "Acknowledge the payment notice", `payments` | +| `payment` | all acknowledged | "Settled", `payments` | + +## The steps + +Each step: where it happens, what must hold, what the user does, what the system does (module in brackets), what goes on the wire, what is stored, where the case stands afterwards, and what the screen shows next. Ids are `F1` to `F13` with letters for branches; `flow.json` carries the same ids. + +### F1. Policy search + +- Screen: Cases list, "New case", `GET /claims/new`. +- Holds: nothing. +- User: picks an identifier type (`MemberId`, `AbhaNumber`, `MobileNo`) and a value, presses "Search policies". +- System [7.4]: `search_policies` through the transport: the participant service's `participant/get/policies`; normalises each row (`member_id`, `policy_code` from `productid`, `payer_code` from `payerid`, `recipient_code` from `processingid`, `product_name`). NHCX-1016 (nothing linked) is an empty list, not an error. +- Screen: a table, one row per policy: beneficiary, product and policy, payer, ABHA, mobile, a "Select" button. No name and no photo yet; the payer returns those at F3. + +### F2. Open the case + +- Screen: the same, "Select" on a row; `POST /claims`. +- System [7.4, 7.2]: `create_claim` snapshots the policy (`member_id`, `policy_code`, `payer_code`, `recipient_code`, `policy_json`), mints the claim number, stamps `eligibility / draft`. +- Redirect: the case screen, Eligibility tab, "Claim opened." +- Next action: "Check the cover". + +### F3. Check the cover (coverage eligibility) + +- Screen: Eligibility tab, card "Coverage eligibility check": purpose select (`validation` default, `benefits`, `discovery`), policy code and member id shown from the snapshot, "Send to payer". +- Holds: member id; policy code for `validation` and `benefits`. +- System [7.4]: `run_check(purpose)`, workflow id = the claim number, status `checking`; the page shows "Awaiting payer" and refreshes; the answer arrives by callback [7.3] or poll. +- Wire: `v1/coverageeligibility/check`; `on_check` back. +- Stored: `txn_id`, `correlation_id`, `api_call_id`; on the answer `inforce`, `outcome`, `disposition`, allowed and used amounts, the payer's `Patient` (name, gender, DOB, address, ABHA, photo), `Coverage` class and period. +- After: `eligibility / eligible` or `not-eligible` (or `error` with the payer's words). A `ProtocolResponse` or a 404 on `txn/related` settles as `error`, never spins. +- Screen: card "Payer verdict": Sum insured, Utilised, Wallet balance (allowed less used), Disposition verbatim, In force, Pre-authorisation required, Checked at, Correlation. Beneficiary card fills with the payer's demographics. "Check again" allowed from any settled state. +- Next action: "Fetch the package master". + +### F4. Fetch the package master (insurance plan) + +- Screen: Insurance plan tab, "Fetch the plan" (or "Refresh"). +- Holds: `eligible`. +- System [7.5]: `reuse_plan` first (same policy, provider, payer, status `ready`: zero sends); else `request_plan`, status `fetching`, workflow id = the claim number. +- Wire: `v1/insuranceplan/request`; `on_request` back with the InsurancePlan and Questionnaires. +- Stored: `claim_plan` (`ready`, `empty` or `error`), `claim_plan_benefit` per package, `claim_plan_form` per url. Both published shapes merged on package code. +- Screen: a search over the master (name or code, specialty filter, procedure or implant), one row per package with rate, kind, "View"; a package view with rate, implants approved, tiers, conditions, documents wanted, the forms those point at as questions; an "All forms" page. Policy-wide requirements shown above the table. +- Next action: "Quote the treatment". + +### F5. Link the admission (integrate) or capture it (standalone) + +- Screen: Pre-authorisation tab, card "Link the admission" (opens once `eligible`). +- Holds: `eligible`. +- Integrate: list every current inpatient stay of the patient whose ABHA matches the payer's (digits only); "Link" stores `patient_id` and `encounter_id`, defaults the admission date from the encounter. Linking before `eligible` and to a stay that is not a current IPD admission is refused. "Unlink" keeps the draft. +- Standalone [7.13]: register the patient (from the payer's demographics) and admit them here; the same two keys are stored. +- Screen after: card "Linked admission" with ward, bed, admitted at, consultant. + +### F6. The dossier (pre-auth capture) + +- Screen: Pre-authorisation tab, once linked: the form, saved in one transaction by `save_preauth` [7.7 inputs]. +- Captured: admission date (required) and provisional discharge date (not before admission); ICD-10 diagnoses (at least one; read off the admission when it recorded them, else a picker); the treating doctor (the admission's consultant, else a picker; must have an HPIN); package case or non-package case toggle; documents (pdf, jpg, jpeg, png, each recorded against the payer requirement code it answers, else `ODN`). +- Estimated amount: always recomputed server-side from the lines (F7), never from the form. +- Guards: saving a package case with no line quoted is refused. + +### F7. Quote the treatment (lines from the plan) + +- Screen: Line items tab, "Choose line items", `GET /claims//lines`. Three parts: what is quoted (editable quantities, running total, "remove"); what the payer says goes with it (implants approved for the quoted procedures, the tiers each offers; anything already quoted drops out); the whole master to search. +- Holds: plan `ready`. Quoting anything before that is refused. +- System [7.5]: `add_line(kind, code, parent_code)`; price read from the plan at add time; `amount = rate x quantity` server-side; a tier is added through the procedure that offers it and carries `parent_code`. Refused: a code the plan lacks, a tier the procedure does not offer, a duplicate, a zero quantity. +- Forms: the chosen lines pull in the questionnaires the plan attaches (STG per package, policy forms always); they render on the Pre-authorisation tab and are answered there (`save_answers`, one row per question, file answers upload a document). +- Next action: "Send the pre-authorisation". + +### F8. Validate the set (auth requirements) + +- Screen: Validate tab, "Ask the payer" (also run silently before F9). +- Holds: at least one line. +- System [7.6]: `ensure_auth_requirements`: fingerprint the quoted set; send only when the fingerprint is new; never wait for the answer. +- Wire: `v1/coverageeligibility/check` with purpose `auth-requirements` and the items; `on_check` back (the PMJAY sandbox rarely answers). +- Stored: `claim_auth` (`checking` then `ready`), items authorised or excluded, requirements (document or form, code, url, stage `pre` or `post`, `at_preauth`). +- Screen: the ruling per line, the documents and forms it wants for each leg; the pre-auth and claim tabs read it to build their document and form cards. Without a ruling they fall back to the plan's list. + +### F9. Send the pre-authorisation + +- Screen: Pre-authorisation tab, card "Submit": what will be sent (lines, forms answered, documents attached, the total), "Send to payer". +- Holds (all before any HTTP call): `eligible`; an admission linked; an admission date; at least one diagnosis; at least one care team member with an HPIN; at least one line; every required form answered; every document the ruling or plan asks for at pre-auth attached. +- System [7.7]: `submit_preauth`: `preauth_send_kind` picks `preauth` (12); builds the Claim bundle (`preauth`, `request`); status `submitting`, `submission_kind`, `workflow_id`; stores the three ids; `thread_correlation_id` untouched until the payer answers. +- Wire: `v1/preauth/submit`, workflow 12. +- After: `preauth / requested`. +- Screen: "Awaiting payer", the timeline row for the send, Refresh. Next action: "With the payer; ask where it stands". + +#### F9a. The payer answers + +- Callback [7.3] or poll: first the acknowledgement (workflow 20, `outcome queued`, reason `submitted`): recorded, `preauth_ref` kept, the leg stays `submitting`. Then the decision on the same correlation id: `verdict_status` [7.8]. +- After: `approved` (21), `partial` (approved for less), `queried` (24), `rejected` (23). Never read `outcome` alone. +- Screen: Decision, Payer reference (`preAuthRef`), Approved amount (`total[benefit]`), Eligible amount, the item verdicts table (eligible, status, reason verbatim, eligible %, quantity), process notes verbatim. A door refusal shows as a flag with the payer's code and text, the thread restored. +- Next action per the table above. + +#### F9b. Answer a query + +- Resubmit payer (PMJAY): the query is inside the ClaimResponse (`query_note`). Screen: Pre-authorisation tab, the payer's words, a reply box, "Submit again". System: `submit_preauth(reply)` with kind `preauth_query_response` (19; 131 after an enhancement query), flow `queryupdate`, `NMI/CQD` = the reply, a new correlation id. After: `answered`, then the decision. +- Communication payer (generic): the query is a CommunicationRequest on a new thread, filed in `claim_query` (F12 inbox). Screen: Communication tab, the questions verbatim, a reply box, documents to attach (existing or new, each under the payer's code else `ODN`), "Send the reply". System [7.10]: `answer_query`: the TaskBundle reply on `v1/communication/on_request` with the request's correlation id and workflow id. The leg stays `queried` until the decision arrives on its own thread. An empty reply is refused before any HTTP call. + +#### F9c. Enhancement + +- Screen: Line items tab, add a line after a decision; the Pre-authorisation card shows "enhancement pending (n added)"; "Submit enhancement". +- Holds: `approved` or `partial`; no request in flight. +- System: `submit_preauth` with kind `enhancement` (13; `enhancement_resubmit` 131 on a query): the whole bundle again, every line old and new, same claim number, factors 1 and 0.5. After: `enhancement / requested`, then 22 (or 21 from the SHA), 231, 241. + +#### F9d. Cancel + +- Screen: Pre-authorisation tab, "Withdraw": a reason picker (the seven documented reasons) and a note, required for Other. Hidden once a claim has been raised; refused on a `rejected` pre-auth and twice. +- System [7.9]: `cancel_preauth`: Task `cancel`, workflow PC01, on its own thread (`cancel_correlation_id`), `cancelling`. +- After PC02: `cancelled`; the episode gets a fresh claim number, the withdrawn one stays on the leg. + +#### F9e. Predetermination (a quote) + +- Screen: Pre-authorisation tab, "Ask for a quote". +- System [7.7]: the very bundle F9 would send with `use predetermination`, on `v1/preauth/submit`, workflow 12, its own row (`asking` then `answered`). Nothing on the pre-auth changes. + +### F10. Record the discharge + +- Screen: Claim tab, card "Discharge": mode (Normal, LAMA, DAMA, Death), stage (Before, During, After surgery), discharge date and time, surgery date and time, death date and time (death only). +- Holds: a pre-auth `approved` or `partial`. +- Stored: on `claim_submission` (`draft`) or the encounter. +- Screen after: the claim card opens; for LAMA or DAMA before or during surgery it says the approved packages are voided and the claim will carry `LM100` only. +- Next action: "File the claim". + +### F11. File the claim + +- Screen: Claim tab, cards "Documents for the claim" (what the ruling deferred to this stage, plus the discharge summary, always), "Forms for the claim" (the consent again, and what the ruling deferred), "Everything attached for the claim" (any further pdf or image), "Submit the claim". +- Holds: discharge recorded; the discharge summary attached; every claim-stage form answered; amount not above the approved amount. +- System [7.7]: `submit_claim`: `claim_send_kind` (`claim` 15; `claim_query_response` 161 PMJAY or 151 generic; `claim_resubmit` 16 generic only); the Claim bundle (`claim`, `request`) under the pre-auth's claim number with `preAuthRef`, procedures `completed`, discharge scalars, `HDS`, `DIS`; `LM100` collapse when it applies. +- Wire: `v1/claim/submit`. +- After: `claim / requested`; then 25 (ack), 26 `approved`, 27 `queried`, 291 `rejected`, read as F9a. +- Screen: as the pre-auth card: decision, amounts, item verdicts with `deductible`, notes verbatim. + +#### F11, continued: claim query and reprocess + +- Query: as F9b, on the claim (161 or the Communication reply). +- Rejected or partial: "Ask for a reprocess" (F13). There is no claim resubmit on PMJAY. + +### F12. Payments + +- The payer starts it: `v1/paymentnotice/request` arrives on a new thread, matched by the claim number inside (a `CLN` identifier, then any untyped identifier on the notice, the reconciliation, the Task; never the bundle id), looked up against `claim_no` and every leg's `claim_ref`. +- System [7.10]: `record_payment`: one `claim_payment` row per notice, deduped on the notice's correlation id; details from the PaymentReconciliation; a payer that reuses the notice id updates the row. Then, at once and automatically, `acknowledge_payment`: Task `status` `completed`, output `paymentack`, to the notice's own sender, its correlation id echoed, workflow 17 (PMJAY) or the notice's own (generic). A failed acknowledgement is kept on the row; the notice is still recorded and the callback still answered 2xx. +- After: `payment / noticed` or `paid`. Paid is counted once per UTR, newest notice winning; an initiated notice without a UTR shows "Initiated, UTR awaited" and is not money received. +- Screen: Payments tab, one card per notice: status, amount, UTR as text, the breakdown, "Acknowledged at" or "Send the acknowledgement again". Across cases: the payments view. +- Next action: "Acknowledge the payment notice" while one is pending, else "Settled". + +### F12b. The inbox + +- Every CommunicationRequest is classified [7.10]: query, notification or note. Notifications are acknowledged at once (the payer's bundle back, Task `completed`) and the case left alone. Queries are filed `open` and lead every action list until answered (F9b). Notes are shown, never acted on. +- Screen: Communication tab on the case; the inbox view across cases, by kind and reason. + +### F13. The small exchanges + +- Status: "Ask where it stands" on the pre-auth and claim cards, while awaiting and after a decision; Task `status`, workflow = the leg's correlation id (fallback 13); not offered to a payer whose adapter refuses it (PMJAY, PAYR-1018). The answer fills the enquiry row; the leg is unchanged. +- Reprocess: on a decided claim not paid in full, "Send reprocess request" with a coded reason (`claimrejected`, `partialpayment`, `rejectiondisputed`), words, and documents; Task `reprocess`, workflow 36. The payer's `completed` Task (37) reopens the claim: the submission goes back to `requested` and the new verdict lands on the claim's own thread. +- Release: once part of an approved claim is paid, "Ask for the balance" with the amount owed; Task `release`, reason `partialpayment`, `valueMoney`, workflow 36. +- Each ask is its own `claim_enquiry` row on its own thread, shown on the card it belongs to, newest first. + +## What runs on every page load of the case + +In this order, before rendering, each bounded to one poll and a short timeout, never a send: coverage (`checking`), plan (`fetching`), ruling (`checking`), claim (`submitting`), predeterminations (`asking`), pre-auth (`submitting` or `cancelling`), enquiries (`asking`). Then the beneficiary card, the policy card, the verdict card, the status line and actions, the tabs. A "Refresh" button reloads the same tab. + +## What is not in the flow + +- No status control anywhere. Stage and sub-stage are derived. +- No manual acknowledgement of a payment notice as the only path; it goes automatically and the screen shows that it went. +- No "chase" button without the status exchange behind it. +- No separate discharge submission on PMJAY; the discharge rides on the claim. +- No claim resubmit on PMJAY; a decided claim is reprocessed. diff --git a/plugins/nhcx/skills/nhcx-claim/flow/flow.json b/plugins/nhcx/skills/nhcx-claim/flow/flow.json new file mode 100644 index 000000000..315d1a4b8 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-claim/flow/flow.json @@ -0,0 +1,818 @@ +{ + "source": "flow/FLOW.md", + "tabs": [ + { + "key": "eligibility", + "label": "Eligibility", + "opens": "always" + }, + { + "key": "plan", + "label": "Insurance plan", + "opens": "always" + }, + { + "key": "lines", + "label": "Line items", + "opens": "always; quoting refused until the plan is ready" + }, + { + "key": "validate", + "label": "Validate", + "opens": "always" + }, + { + "key": "preauth", + "label": "Pre-authorisation", + "opens": "coverage verdict eligible" + }, + { + "key": "communication", + "label": "Communication", + "opens": "always" + }, + { + "key": "claim", + "label": "Claim", + "opens": "always; submit once the pre-auth is approved or partial" + }, + { + "key": "payments", + "label": "Payments", + "opens": "always" + } + ], + "stages": [ + "eligibility", + "preauth", + "enhancement", + "claim", + "payment" + ], + "sub_stages": [ + "draft", + "checking", + "eligible", + "not-eligible", + "requested", + "resubmitted", + "answered", + "queried", + "approved", + "partial", + "rejected", + "cancelling", + "cancelled", + "refused", + "noticed", + "paid" + ], + "next_actions": [ + { + "when": "an open query exists", + "label": "Answer the payer (n)", + "tab": "communication", + "leads": true + }, + { + "stage": "eligibility", + "sub_stage": [ + "draft", + "error", + "not-eligible" + ], + "label": "Check the cover", + "tab": "eligibility" + }, + { + "stage": "eligibility", + "when": "no plan ready", + "label": "Fetch the package master", + "tab": "plan" + }, + { + "stage": "eligibility", + "when": "no lines", + "label": "Quote the treatment", + "tab": "lines" + }, + { + "stage": "eligibility", + "when": "lines quoted", + "label": "Send the pre-authorisation", + "tab": "preauth" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "queried" + ], + "label": "Answer the query", + "tab": "preauth", + "payer": "resubmit" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "queried" + ], + "label": "Answer the payer's query", + "tab": "communication", + "payer": "communication" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "draft", + "refused" + ], + "label": "Send the pre-authorisation", + "tab": "preauth" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "rejected" + ], + "label": "Send a fresh pre-authorisation", + "tab": "preauth" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "approved", + "partial" + ], + "when": "lines added since", + "label": "Send the enhancement (n added)", + "tab": "preauth" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "approved", + "partial" + ], + "when": "not discharged", + "label": "Record the discharge", + "tab": "claim" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "approved", + "partial" + ], + "when": "discharged", + "label": "File the claim", + "tab": "claim" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "requested", + "answered", + "resubmitted" + ], + "label": "With the payer; ask where it stands", + "tab": "preauth" + }, + { + "stage": "claim", + "sub_stage": [ + "queried" + ], + "label": "Answer the claim query", + "tab": "claim", + "payer": "resubmit" + }, + { + "stage": "claim", + "sub_stage": [ + "queried" + ], + "label": "Answer the payer's query", + "tab": "communication", + "payer": "communication" + }, + { + "stage": "claim", + "sub_stage": [ + "rejected", + "partial" + ], + "label": "Ask for a reprocess", + "tab": "claim" + }, + { + "stage": "claim", + "sub_stage": [ + "requested", + "answered", + "resubmitted" + ], + "label": "With the payer; ask where it stands", + "tab": "claim" + }, + { + "stage": "claim", + "sub_stage": [ + "refused" + ], + "label": "Send the claim again", + "tab": "claim", + "when": "a send kind remains, else Ask for a reprocess" + }, + { + "stage": "claim", + "sub_stage": [ + "approved" + ], + "label": "Await the payment notice", + "tab": "payments" + }, + { + "stage": "payment", + "when": "a notice unacknowledged", + "label": "Acknowledge the payment notice", + "tab": "payments" + }, + { + "stage": "payment", + "when": "all acknowledged", + "label": "Settled", + "tab": "payments" + } + ], + "steps": [ + { + "id": "F1", + "name": "Policy search", + "screen": "new case", + "tab": null, + "routes": [ + "GET /claims/new" + ], + "module": "7.4", + "skills": ["nhcx-coverage"], + "holds": [], + "user": "Search policies", + "sends": { + "path": "participant/get/policies", + "kind": "registry REST" + }, + "stores": [], + "after": null, + "shows": "one row per policy with Select" + }, + { + "id": "F2", + "name": "Open the case", + "screen": "new case", + "tab": null, + "routes": [ + "POST /claims" + ], + "module": "7.4", + "skills": ["nhcx-coverage"], + "holds": [], + "user": "Select", + "sends": null, + "stores": [ + "claim: member_id, policy_code, payer_code, recipient_code, policy_json, claim_no" + ], + "after": { + "stage": "eligibility", + "sub_stage": "draft" + }, + "next_action": "Check the cover" + }, + { + "id": "F3", + "name": "Check the cover", + "screen": "case", + "tab": "eligibility", + "routes": [ + "POST /claims//check" + ], + "module": "7.4", + "skills": ["nhcx-coverage"], + "holds": [ + "member id", + "policy code for validation and benefits" + ], + "user": "purpose, Send to payer", + "sends": { + "path": "v1/coverageeligibility/check", + "workflow": "", + "reply": "on_check" + }, + "stores": [ + "txn_id", + "correlation_id", + "api_call_id", + "inforce", + "outcome", + "disposition", + "allowed_amount", + "used_amount", + "patient demographics", + "coverage class and period" + ], + "after": { + "stage": "eligibility", + "sub_stage": "eligible|not-eligible|error" + }, + "shows": "Payer verdict: sum insured, utilised, wallet balance, disposition verbatim", + "next_action": "Fetch the package master" + }, + { + "id": "F4", + "name": "Fetch the package master", + "screen": "case", + "tab": "plan", + "routes": [ + "POST /claims//plan", + "GET /claims//plan/", + "GET /claims//plan/forms" + ], + "module": "7.5", + "skills": ["nhcx-insurance"], + "holds": [ + "eligible" + ], + "user": "Fetch the plan (reuse first)", + "sends": { + "path": "v1/insuranceplan/request", + "workflow": "", + "reply": "on_request" + }, + "stores": [ + "claim_plan", + "claim_plan_benefit", + "claim_plan_form" + ], + "after": { + "plan": "ready|empty|error" + }, + "shows": "searchable master, package view, all forms", + "next_action": "Quote the treatment" + }, + { + "id": "F5", + "name": "Link or capture the admission", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//link", + "POST /claims//unlink" + ], + "module": "7.13 or the HMIS", + "skills": ["nhcx-preauth"], + "holds": [ + "eligible" + ], + "user": "Link the admission", + "sends": null, + "stores": [ + "claim.patient_id", + "claim.encounter_id", + "admission date default" + ], + "after": null + }, + { + "id": "F6", + "name": "The dossier", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//preauth", + "POST /claims//documents", + "POST /claims//documents/required" + ], + "module": "7.7 inputs", + "skills": ["nhcx-preauth"], + "holds": [ + "linked" + ], + "user": "Save the dossier", + "sends": null, + "stores": [ + "claim_diagnosis", + "claim_care_team", + "claim_document (code, stage)", + "claim_item" + ], + "guards": [ + "admission date required", + "at least one diagnosis", + "doctor with HPIN", + "package case needs a line" + ] + }, + { + "id": "F7", + "name": "Quote the treatment", + "screen": "lines", + "tab": "lines", + "routes": [ + "GET /claims//lines", + "POST /claims//lines", + "POST /claims//lines/quantities", + "POST /claims//lines//delete", + "POST /claims//forms" + ], + "module": "7.5", + "skills": ["nhcx-insurance"], + "holds": [ + "plan ready" + ], + "user": "add procedure, implant or tier; quantities; answer the forms the lines pull in", + "sends": null, + "stores": [ + "claim_line (rate from the plan, parent_code on a tier)", + "claim_form_answer" + ], + "guards": [ + "code not in plan", + "tier not offered by the procedure", + "duplicate", + "zero quantity" + ], + "next_action": "Send the pre-authorisation" + }, + { + "id": "F8", + "name": "Validate the set", + "screen": "case", + "tab": "validate", + "routes": [ + "POST /claims//auth" + ], + "module": "7.6", + "skills": ["nhcx-preauth"], + "holds": [ + "at least one line" + ], + "user": "Ask the payer (validate)", + "sends": { + "path": "v1/coverageeligibility/check", + "purpose": "auth-requirements", + "workflow": "", + "reply": "on_check", + "awaited": false + }, + "stores": [ + "claim_auth (fingerprint)", + "claim_auth_item", + "claim_auth_requirement" + ], + "after": { + "auth": "checking|ready" + } + }, + { + "id": "F9", + "name": "Send the pre-authorisation", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//submit" + ], + "module": "7.7", + "skills": ["nhcx-preauth"], + "holds": [ + "eligible", + "linked", + "admission date", + "diagnosis", + "care team with HPIN", + "a line", + "required forms answered", + "required documents attached" + ], + "user": "Send to payer", + "sends": { + "path": "v1/preauth/submit", + "workflow": "12", + "kind": "preauth", + "reply": "on_submit 20 then 21|23|24" + }, + "stores": [ + "claim_preauth: submitting, submission_kind, workflow_id, txn_id, correlation_id, api_call_id, request_json" + ], + "after": { + "stage": "preauth", + "sub_stage": "requested" + }, + "next_action": "With the payer; ask where it stands" + }, + { + "id": "F9a", + "name": "The payer answers", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /nhcx/callback/v1/preauth/on_submit" + ], + "module": "7.8", + "skills": ["nhcx-preauth"], + "holds": [], + "user": null, + "reads": "20 queued (stay submitting, keep preauth_ref) then the decision via verdict_status", + "stores": [ + "status", + "preauth_ref", + "approved_amount", + "eligible_amount", + "items_json", + "query_note", + "thread_correlation_id" + ], + "after": { + "stage": "preauth", + "sub_stage": "approved|partial|queried|rejected" + }, + "shows": "decision, payer reference, approved amount, item verdicts, notes verbatim; door refusal as a flag" + }, + { + "id": "F9b", + "name": "Answer a query", + "screen": "case", + "tab": "preauth or communication", + "routes": [ + "POST /claims//submit (reply)", + "POST /claims//queries//reply" + ], + "module": "7.7 or 7.10", + "skills": ["nhcx-preauth", "nhcx-communication"], + "holds": [ + "queried" + ], + "user": "reply text and documents", + "sends": { + "resubmit": { + "path": "v1/preauth/submit", + "workflow": "19 or 131", + "flow": "queryupdate", + "new_thread": true + }, + "communication": { + "path": "v1/communication/on_request", + "workflow": "", + "correlation_id": "" + } + }, + "after": { + "stage": "preauth", + "sub_stage": "answered (resubmit) or queried until the decision (communication)" + } + }, + { + "id": "F9c", + "name": "Enhancement", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//submit" + ], + "module": "7.7", + "skills": ["nhcx-preauth"], + "holds": [ + "approved or partial", + "lines added", + "no request in flight" + ], + "user": "Submit enhancement", + "sends": { + "path": "v1/preauth/submit", + "workflow": "13 or 131", + "flow": "enhancement", + "whole_bundle": true + }, + "after": { + "stage": "enhancement", + "sub_stage": "requested" + } + }, + { + "id": "F9d", + "name": "Cancel", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//cancel" + ], + "module": "7.9", + "skills": ["nhcx-preauth"], + "holds": [ + "not rejected", + "not cancelled", + "no claim raised" + ], + "user": "Withdraw the pre-authorisation", + "sends": { + "path": "v1/task/submit", + "workflow": "PC01", + "task": "cancel", + "own_thread": true + }, + "after": { + "stage": "preauth", + "sub_stage": "cancelling then cancelled; fresh claim number" + } + }, + { + "id": "F9e", + "name": "Predetermination", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//predetermination" + ], + "module": "7.7", + "skills": ["nhcx-preauth"], + "holds": [ + "as F9" + ], + "user": "Ask for a quote", + "sends": { + "path": "v1/preauth/submit", + "workflow": "12", + "use": "predetermination" + }, + "after": { + "predetermination": "asking then answered; the pre-auth unchanged" + } + }, + { + "id": "F10", + "name": "Record the discharge", + "screen": "case", + "tab": "claim", + "routes": [ + "POST /claims//discharge" + ], + "module": "7.7 inputs", + "skills": ["nhcx-claim"], + "holds": [ + "approved or partial" + ], + "user": "mode (normal, lama, dama, death), stage, discharge, surgery and death times", + "sends": null, + "stores": [ + "claim_submission draft: discharge_mode, discharge_stage, dates" + ], + "next_action": "File the claim" + }, + { + "id": "F11", + "name": "File the claim", + "screen": "case", + "tab": "claim", + "routes": [ + "POST /claims//claim", + "POST /claims//claim/documents" + ], + "module": "7.7", + "skills": ["nhcx-claim", "nhcx-communication"], + "holds": [ + "discharge recorded", + "discharge summary attached", + "claim-stage forms answered", + "amount not above approved" + ], + "user": "Submit the claim", + "sends": { + "path": "v1/claim/submit", + "workflow": "15 (161 or 151 query answer; 16 generic resubmit)", + "kind": "claim", + "under": "the pre-auth's claim number", + "reply": "on_submit 25 then 26|27|291" + }, + "after": { + "stage": "claim", + "sub_stage": "requested then approved|queried|rejected|partial" + } + }, + { + "id": "F12", + "name": "Payments", + "screen": "case", + "tab": "payments", + "routes": [ + "POST /nhcx/callback/v1/paymentnotice/request", + "POST /claims//payments//ack", + "GET /claims/payments" + ], + "module": "7.10", + "skills": ["nhcx-payment"], + "holds": [], + "user": null, + "reads": "PaymentNotice matched by claim number; deduped on its correlation id", + "sends": { + "path": "v1/paymentnotice/on_request", + "workflow": "17 (PMJAY) or the notice's own", + "correlation_id": "", + "to": "the notice's sender", + "automatic": true + }, + "after": { + "stage": "payment", + "sub_stage": "noticed|paid" + }, + "next_action": "Acknowledge the payment notice, then Settled" + }, + { + "id": "F12b", + "name": "The inbox", + "screen": "inbox", + "tab": "communication", + "routes": [ + "POST /nhcx/callback/v1/communication/request", + "GET /claims/inbox", + "POST /claims//queries//acknowledge" + ], + "module": "7.10", + "skills": ["nhcx-communication"], + "holds": [], + "reads": "classify: query | notification | note", + "sends": { + "notification": { + "path": "v1/communication/on_request", + "automatic": true + } + }, + "after": { + "query": "open, leads every action list" + } + }, + { + "id": "F13", + "name": "Status, reprocess, release", + "screen": "case", + "tab": "preauth or claim", + "routes": [ + "POST /claims//status", + "POST /claims//reprocess", + "POST /claims//release" + ], + "module": "7.9", + "skills": ["nhcx-reprocess"], + "holds": [ + "status: payer allows it", + "reprocess: claim decided and not paid in full", + "release: part paid" + ], + "sends": { + "path": "v1/task/submit", + "workflow": "leg correlation id (status) or 36", + "own_thread": true + }, + "after": { + "enquiry": "asking then answered|error; a reprocess reopens the claim to requested" + } + } + ], + "page_load_polls": [ + "coverage checking", + "plan fetching", + "ruling checking", + "claim submitting", + "predeterminations asking", + "preauth submitting or cancelling", + "enquiries asking" + ], + "not_in_the_flow": [ + "a status control", + "a manual-only payment acknowledgement", + "a chase button without the status exchange", + "a separate discharge submission on PMJAY", + "a claim resubmit on PMJAY" + ] +} \ No newline at end of file diff --git a/plugins/nhcx/skills/nhcx-claim/references/api-knowledge.md b/plugins/nhcx/skills/nhcx-claim/references/api-knowledge.md new file mode 100644 index 000000000..3b07e901d --- /dev/null +++ b/plugins/nhcx/skills/nhcx-claim/references/api-knowledge.md @@ -0,0 +1,400 @@ +# API knowledge: the nhcx-adapter contract (optional transport) and the HMIS endpoints that face it + +Read this file only when the transport is nhcx-adapter, and use nhcx-adapter only when the user has asked for it (`references/transport-knowledge.md` section 1). Otherwise the build reaches NHCX through the app's existing integration or its own transport, and `references/transport-knowledge.md` sections 3 and 4 replace everything here. + +This file describes nhcx-adapter (https://github.com/nha-in/nhcx-adapter) as its release ships it, and the HMIS side a build needs to face it. A release carries the binary, `config.sample.json`, `serve.sh`, `stop.sh`, `update.sh` and `README.md`. `nhcx-package/docs/02-Getting Started/10-NHCX Adapter.md` covers the same adapter. When a detail matters, check the release README and `config.sample.json` for the version you run. + +## 1. What the adapter is + +One binary, one `config.json`, no database. You POST plain FHIR to it. It mints the protocol ids, fetches the recipient's certificate, encrypts a compact JWE, posts to the NHCX gateway, and records the exchange in a file ledger. NHCX callbacks reach it encrypted; it decrypts them and POSTs plain FHIR to your HMIS. Both directions are synchronous; there is no queue (release README, "How it works"). + +The same binary can front several participants at once. Inbound, `x-hcx-recipient_code` picks the profile whose key decrypts and whose callback receives. Outbound, `x-hcx-sender_code` picks who sends (release README, "Hosting several participants"). Encrypting for a code the same adapter holds is allowed. So one adapter can host a hospital and a test payer together, and a test between them needs no second gateway. + +## 2. Configuration + +File: `config.sample.json` in the release. `${NAME}` reads an environment variable; `@file` reads a file next to the config. Unknown keys are rejected. + +| Key | Default | What it does | +| --- | --- | --- | +| `env` | `sandbox` | `sandbox` or `production`. Picks the gateway (`https://apisbx.abdm.gov.in/hcx/v1` or `https://apis.abdm.gov.in/hcx/v1`), registry, session endpoint and `X-CM-ID` (`sbx` or `abdm`). | +| `listen` | `127.0.0.1:8090` | The HTTP listener. | +| `publicUrl` | empty | How NHCX reaches the adapter. Register `/in` as the participant's `endpoint_url`. | +| `apiKey` | `${NHCX_ADAPTER_API_KEY}` | The key your HMIS presents on `/out`, `/fhir/out`, `/ledger*`, `/token`. Demanded in production, honoured but not demanded in sandbox. `requireApiKey: true` closes a sandbox adapter. | +| `participant.participantId` | none; the sample carries an example code | Your registry code. `@hcx` is added if missing. | +| `participant.clientId`, `clientSecret` | `${NHCX_CLIENT_ID}`, `${NHCX_CLIENT_SECRET}` | ABDM credentials that mint the session token. | +| `participant.privateKey` | `@private_key.pem` | The RSA key of your registered certificate. | +| `participants[]` | `[]` | Further hosted identities. Each needs only `participantId` and `callback`; the rest is inherited. | +| `callback.url` | `http://127.0.0.1:8765/nhcx/callback` in the sample | Where decrypted messages are POSTed. | +| `callback.appendPath` | `true` | Appends the NHCX path: `.../callback` receives `v1/preauth/on_submit` at `.../callback/v1/preauth/on_submit`. | +| `callback.timeoutSeconds` | `20` | One delivery. NHCX wants its 202 within 30 seconds. | +| `callback.apiKey` | empty | Sent to your HMIS as `Authorization: Bearer `. | +| `callback.routes` | `{}` | Per-path overrides, used exactly as written: `{"v1/preauth/on_submit": "http://preauth-svc/hook"}`. | +| `callback.also` | absent | Extra targets for the same delivery (two systems behind one participant code). Every target must accept or NHCX redelivers to all. | +| `ledger.enabled`, `ledger.dir`, `ledger.retentionDays`, `ledger.storeBodies` | `true`, `data/ledger`, `30`, `true` | The traffic ledger. A hand-written config that leaves out `retentionDays` keeps every day. | +| `maxBodyBytes` | 8 MiB in the v1.0.1 README | Caps request bodies on both surfaces. A PMJAY package master is far larger: set 100 MiB (`104857600`) explicitly. | +| `panel.password`, `panel.path` | empty, `/panel` | The browser console; off until a password is set. | +| `auth.mode`, `auth.tokenTtlSeconds` | `sessions`, `1200` | How the ABDM token is obtained. | + +Minimal working config for one hospital: + +```json +{ + "env": "sandbox", + "listen": "127.0.0.1:8090", + "publicUrl": "https:///in", + "apiKey": "${NHCX_ADAPTER_API_KEY}", + "participant": { + "participantId": "@hcx", + "clientId": "${NHCX_CLIENT_ID}", + "clientSecret": "${NHCX_CLIENT_SECRET}", + "privateKey": "@private_key.pem" + }, + "callback": { "url": "http://127.0.0.1:/nhcx/callback", "appendPath": true, "apiKey": "" } +} +``` + +Start it with `./nhcx-adapter serve`, or `./serve.sh` from the release archive; `./stop.sh` stops a background server. It checks token, participant record, certificate and registered endpoint first and offers to fix each in a terminal (release README, "Startup checks"). `./nhcx-adapter check --no-tui` is the same as a health gate. `serve --no-tui --skip-checks` starts it with no prompts and no checks, for a script that has already checked. + +## 3. Routes + +| Route | Auth | Does | +| --- | --- | --- | +| `POST /out/{path...}` | API key | Send. `path` is the NHCX API path, `v1/preauth/submit`. | +| `POST /fhir/out/{path...}` | API key | Same handler, hcxkit's prefix. The client in section 11 sends here. | +| `POST /in/{path...}` | none | NHCX delivers here. Register `/in`. | +| `POST /v1/{path...}` | none | Alias of `/in` for a registry `endpoint_url` of `/`. | +| `GET /ledger` | API key | Newest first. Filters: `direction, entity, kind, status, sender, recipient, participant, correlation_id, workflow_id, since, until, before, limit` (1 to 500). `since` and `until` take RFC 3339, a date, or a duration such as `24h`. | +| `GET /ledger/stats` | API key | Counts by direction, status, entity. | +| `GET /ledger/thread/{cid}` | API key | Every message on one correlation id plus the derived state. | +| `GET /ledger/{id}` | API key | One message in full, bundle included. | +| `GET /token`, `POST /token/refresh` | API key | The ABDM session token, for calls the adapter does not make (registry, PMJAY payer service). `?participant=` for a hosted identity. | +| `GET /healthz`, `GET /readyz` | none | Liveness; readiness is 503 until a token is held. | +| `GET /panel` | its own password | Operator console: Live, Ledger, Send, Lookup, Setup. | +| `/internal/*` | none | hcxkit-compatible console API, section 8. | + +API key check: `Authorization: Bearer ` first, then `X-Api-Key: `. Constant-time compare. A miss answers `401 {"ok":false,"error":{"code":"UNAUTHORIZED","message":"missing or invalid API key"}}`. + +## 4. The outbound envelope + +The body must be a JSON object. Header precedence, lowest to highest: + +1. HTTP request headers named `x-hcx-*`. +2. The `jwe_headers` object (hcxkit spelling). +3. Top-level `x-hcx-*` keys. +4. Top-level short aliases: `sender`, `recipient`, `correlation_id`, `request_id`, `api_call_id`, `workflow_id`, `status`. + +The payload is `fhir`, else `payload`, else the body itself when it carries `resourceType`. Otherwise `400 INVALID_ENVELOPE`. + +The protected header names: + +``` +x-hcx-api_call_id x-hcx-request_id x-hcx-correlation_id x-hcx-timestamp +x-hcx-status x-hcx-sender_code x-hcx-recipient_code x-hcx-workflow_id +``` + +Completion rules: + +- Sender and recipient codes get `@hcx` appended if missing. +- `api_call_id`, `request_id`, `correlation_id` are kept only when they are plain 8-4-4-4-12 UUIDs; anything else is replaced with a fresh UUID. So a response must carry the request's `correlation_id` as a UUID or the thread is lost. +- `x-hcx-status` defaults to `request.initiated`, or `response.complete` when the last path segment starts with `on_`. +- `x-hcx-timestamp` defaults to now as `YYYY-MM-DDThh:mm:ss±hhmm`. The zone has no colon: `+0530`, not `+05:30`. +- An empty `x-hcx-workflow_id` is dropped, not sent. +- On an `on_` path with no usable correlation id, the adapter threads the message to the newest inbound request of that entity from that recipient. Do not rely on it; send the id. + +What a hospital sends on a normal leg: + +```json +{ + "jwe_headers": { + "x-hcx-sender_code": "@hcx", + "x-hcx-recipient_code": "@hcx", + "x-hcx-workflow_id": "12" + }, + "fhir": { "resourceType": "Bundle", "type": "collection", "...": "..." } +} +``` + +Add `"x-hcx-correlation_id": ""` only on the two reply legs: the communication reply on `v1/communication/on_request` and the payment acknowledgement on `v1/paymentnotice/on_request`. + +## 5. The outbound answer + +The HTTP status is the NHCX gateway's own. Body: + +```json +{ + "ok": true, + "path": "v1/preauth/submit", + "url": "https://apisbx.abdm.gov.in/hcx/v1/preauth/submit", + "headers": { "x-hcx-correlation_id": "...", "x-hcx-api_call_id": "...", "x-hcx-request_id": "...", "x-hcx-workflow_id": "12", "x-hcx-status": "request.initiated", "x-hcx-timestamp": "...", "x-hcx-sender_code": "...", "x-hcx-recipient_code": "..." }, + "gateway_status": 202, + "response": { "...": "the NHCX 202 body" }, + "duration_ms": 412, + "ledger_id": "7UMV0007", + "txn_id": "7UMV0007", + "correlation_id": "...", + "request_id": "..." +} +``` + +Store three things on the leg: `txn_id` (the ledger id), `correlation_id` (the thread), and `headers["x-hcx-api_call_id"]`. Store them on every send. + +Local failures come back as `{"ok": false, "error": {"code", "message", "retryable"}, "request_id", "upstream_status", "upstream_body"}` with these statuses: `400` for `INVALID_ENVELOPE`, `INVALID_PAYLOAD`, `INVALID_BODY`, `INVALID_JWE`, `NO_PATH`, `NO_RECIPIENT`, `WRONG_RECIPIENT`, `BODY_READ`; `401` for the API key; `413` `BODY_TOO_LARGE`; `422` for `DECRYPT_FAILED`, `CERT_NOT_FOUND`, `SELF_ENCRYPTION_KEY`; `502` for any code starting `CALLBACK_`, `GATEWAY_`, `CERT_FETCH_`, `TOKEN_`; `501` `LEDGER_DISABLED`. A gateway refusal is recorded in the ledger as `rejected` with `GATEWAY_HTTP_`. + +## 6. The inbound callback your HMIS receives + +The adapter POSTs to `callback.url` plus the NHCX path. Body: + +```json +{ + "meta": { + "type": "in", + "payloadType": "fhir", + "path": "v1/preauth/on_submit", + "ip": "1.2.3.4", + "time": "", + "redelivery": false, + "participant": "@hcx" + }, + "jwe_headers": { + "alg": "RSA-OAEP-256", "enc": "A256GCM", + "x-hcx-api_call_id": "...", "x-hcx-correlation_id": "...", "x-hcx-request_id": "...", + "x-hcx-sender_code": "@hcx", "x-hcx-recipient_code": "@hcx", + "x-hcx-status": "response.partial", "x-hcx-timestamp": "...", "x-hcx-workflow_id": "20" + }, + "fhir": { "resourceType": "Bundle", "...": "..." } +} +``` + +`payloadType` is `fhir` for a bundle and `protocol` for a ProtocolResponse. A ProtocolResponse is a refusal. Then `fhir` is the plain JSON body with `type: "ProtocolResponse"`, `x-hcx-status: response.error` and `x-hcx-error_details` at its top level. + +HTTP headers on the delivery: + +| Header | Value | +| --- | --- | +| `X-Nhcx-Path` | `v1/preauth/on_submit` | +| `X-Nhcx-Payload-Kind` | `fhir` or `protocol` | +| `X-Nhcx-Correlation-Id` | the thread | +| `X-Nhcx-Api-Call-Id` | this delivery's id, stable across redeliveries | +| `X-Nhcx-Redelivery` | `true` when the ledger already holds this api_call_id (absent otherwise) | +| `X-Nhcx-Participant` | the hosted identity it was addressed to | +| `X-Hcxkit-Txn-Id` | equals `x-hcx-api_call_id` (what a kit-style backend dedupes on) | +| `X-Hcxkit-Type` | entity: `coverage`, `insurance`, `preauth`, `claim`, `task`, `payment`, `communication`, `status` | +| `X-Hcxkit-Flow` | `request` for an arriving response, `on_request` for an arriving request (inverted on purpose) | +| `X-Hcxkit-Payload-Kind` | same as `X-Nhcx-Payload-Kind` | +| `Authorization` | `Bearer ` when configured | + +Contract: answer any 2xx quickly. The adapter then answers NHCX with the 202 acceptance body and an `X-Nhcx-Ledger-Id` header: + +```json +{ + "timestamp": "11/09/2026 10:00:00:123", + "api_call_id": "...", "correlation_id": "...", + "result": { "sender_code": "...", "recipient_code": "...", "entity_type": "preauth", "protocol_status": "request.queued" }, + "error": { "code": "", "message": "" } +} +``` + +A non-2xx from your HMIS becomes `CALLBACK_HTTP_` and NHCX redelivers. NHCX makes five attempts, then drops the correlation id. Your handler must therefore be idempotent on `x-hcx-api_call_id`. Do not do slow work inside the callback: store the envelope, answer 200, apply it after. Apply a delivery on a context detached from the incoming request, so a gateway that hangs up cannot roll the write back. + +The HMIS callback handler: + +- Routes `POST /callback`, `POST /callback/` and `POST /nhcx/callback`. +- Takes an optional shared secret on the query string (`?token=`). +- Reads `X-Hcxkit-Type`, `X-Hcxkit-Flow` and `X-Hcxkit-Payload-Kind`. +- Archives the envelope before applying it. +- Answers `400` for an unreadable body, because redelivery cannot help. Anything unexpected becomes a 500, so the adapter retries. +- Returns `{"status": "settled" | "unmatched" | "ignored"}`. +- Routes by correlation id, never by path. + +## 7. The ledger + +Layout: `ledger.dir//.json`, one file per message, plus `/index.jsonl` with one summary line per message. Ids are eight base32 characters (alphabet `0-9A-V`), a day prefix and a counter that restarts each day: `7UMV0001` is the first message of its day. Pruned hourly by `retentionDays`. + +Entry fields: `id, direction (out|in), created_at, path, entity, action, kind (request|response), format (fhir|protocol|json), sender, recipient, correlation_id, api_call_id, request_id, workflow_id, hcx_status, status, error{code,message}, redelivery, duration_ms, peer{url,status_code,response}, also[], headers{}, fhir{}, fhir_summary{resource_type,bundle_type,entries,resource_types,focus,identifier,patient,outcome}`. + +`status` values: outbound `accepted`, `rejected`, `failed`; inbound `delivered`, `delivery_failed`, `rejected`. + +Thread: `{correlation_id, entity, workflow_id, counterparty, role (initiator|responder), state, started, updated, messages[]}`. `state` is derived by walking the messages in order: + +- `awaiting_response`: you sent a request. +- `awaiting_our_response`: a request reached you. +- `partial`: a `response.partial` arrived. +- `completed`: a response closed it. +- `error`: a rejection, a failed send or delivery, a protocol message, or an `error` status. +- `unknown`. + +Two ledger behaviours you rely on. An outbound `on_` response with no `correlation_id` is threaded to the newest matching inbound request. An inbound whose `api_call_id` was seen before is flagged `redelivery: true`. + +CLI, same data, no server needed for `follow`: + +```sh +nhcx-adapter ledger list --since 24h --entity preauth --status rejected +nhcx-adapter ledger follow --direction in +nhcx-adapter ledger show 7UMV0007 +nhcx-adapter ledger thread +nhcx-adapter ledger stats +nhcx-adapter decrypt --file body.json +nhcx-adapter cert +nhcx-adapter send --path v1/preauth/submit --recipient --file bundle.json +``` + +## 8. hcxkit-compatible endpoints + +A client written against hcxkit polls the adapter for the other side's answer instead of only waiting for its callback. The adapter serves the sliver of hcxkit's `/internal` API that such a client needs. None of these need the API key. Keep the adapter's port off any network you do not control (`nhcx-package/docs/02-Getting Started/10-NHCX Adapter.md`, "Before you expose it"). + +| Route | Body | Answers | +| --- | --- | --- | +| `GET /internal/config/get` | none | `{participant{participantId,name,callbackUrl}, participants[], CMID, env, urls{nhcx,participant,sessions}}` | +| `POST /internal/participants/search` | `{"participant_code": ""}` | `{participants:[registry record + participant_code, participant_name, endpoint_url, status, roles]}`; an unknown code is `{participants: []}` | +| `POST /internal/txn/related` | `{"txnId": ""}` | every ledger row on the same correlation id, both directions, as `{id, direction, status, sender, recipient, correlation_id, api_call_id, type, flow, created_at}`; `404 TXN_NOT_FOUND` when the ledger no longer holds it | +| `POST /internal/txn/fhir` | `{"txnId": ""}` | `{meta{type,payloadType,path,time}, jwe_headers, fhir}`, the same envelope shape a delivery carries | +| `POST /internal/txn/dispatch` | `{"txnId": ""}` | `{txnId, status}` with `dispatch_failed` for a failed or rejected send, `dispatched` for accepted or delivered, plus `errorCode`, `errorMessage` | +| `GET /internal/txn/list?limit=200` | none | the recent ledger, newest first, same row shape | +| `POST /internal/policies/search` | `{"identifiertype": "MemberId", "MobileNo" or "AbhaNumber", "identifiervalue": "..."}` (also `mobile`, `abhaNo`) | the ABDM registry's `participant/get/policies` answer, status passed through; "No policies found" is an error the caller reads as empty | +| `POST /internal/policies/abha/link`, `.../delink` | forwarded verbatim | registry answer | +| `POST /internal/participants/list` | forwarded verbatim | registry roster | +| `POST /internal/participants/certs` | `{"participantid": ""}` | `{participant_code, encryption_cert}` | +| `GET /internal/participants/saved` | none | the configured profiles | + +The polling pattern: + +1. After a send, call `/internal/txn/related` with the stored `txn_id`. +2. Take the inbound rows on the thread that were not sent by you. Keep only rows addressed to the participant the send came from. +3. Fetch each with `/internal/txn/fhir`, newest first. +4. Take the first whose bundle carries the resource the reply is made of (ClaimResponse, CoverageEligibilityResponse, InsurancePlan, Task). +5. Apply it through the same code path the callback uses. Dedupe on `x-hcx-api_call_id`. + +A `404` from `txn/related` means the ledger was reset. Settle the leg as an error instead of spinning. + +## 9. curl examples + +Set these once. The address is the adapter's default `listen`: + +```sh +export ADAPTER=http://127.0.0.1:8090 +export KEY= +export ME=@hcx +export PAYER=@hcx +``` + +Liveness and readiness: + +```sh +curl -s $ADAPTER/healthz +curl -s $ADAPTER/readyz +``` + +Send a coverage eligibility check. Write the envelope to a file first. The bundle is the package's validation request, `nhcx-package/fhir/B1/validation.json`, with your own identifiers substituted. Run this from the project root that holds `nhcx-package/`: + +```sh +python3 - <<'EOF' +import json, os +bundle = json.load(open("nhcx-package/fhir/B1/validation.json")) +env = {"jwe_headers": {"x-hcx-sender_code": os.environ["ME"], + "x-hcx-recipient_code": os.environ["PAYER"], + "x-hcx-workflow_id": ""}, + "fhir": bundle} +json.dump(env, open("/tmp/coverage-out.json", "w")) +EOF +curl -s $ADAPTER/fhir/out/v1/coverageeligibility/check \ + -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \ + --data-binary @/tmp/coverage-out.json +``` + +Read the answer back from the ledger with the `correlation_id` from that response: + +```sh +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger/thread/" +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger?direction=in&entity=coverageeligibility&since=1h" +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger/" +``` + +Same thread through the kit endpoints (no key): + +```sh +curl -s $ADAPTER/internal/txn/related -H 'Content-Type: application/json' -d '{"txnId":""}' +curl -s $ADAPTER/internal/txn/fhir -H 'Content-Type: application/json' -d '{"txnId":""}' +``` + +A session token for the PMJAY payer service or a registry call: + +```sh +curl -s -H "Authorization: Bearer $KEY" $ADAPTER/token +``` + +Simulate a delivery to your own callback while the adapter is not involved (useful for the callback handler's unit test). This is the exact shape the adapter posts. Wrap the package's bare payer bundle, here the pre-auth approval `nhcx-package/fhir/C5/C5-approved-wf21.json`, as `{"meta":{...},"jwe_headers":{...},"fhir":}` first: + +```sh +python3 - <<'EOF' +import json +bundle = json.load(open("nhcx-package/fhir/C5/C5-approved-wf21.json")) +env = {"meta": {"type": "in", "payloadType": "fhir", "path": "v1/preauth/on_submit"}, + "jwe_headers": {"x-hcx-correlation_id": "", "x-hcx-api_call_id": "", + "x-hcx-sender_code": "@hcx", + "x-hcx-recipient_code": "@hcx", + "x-hcx-status": "response.complete", "x-hcx-workflow_id": "21"}, + "fhir": bundle} +json.dump(env, open("/tmp/delivery.json", "w")) +EOF +curl -s -X POST "http://127.0.0.1:/nhcx/callback/v1/preauth/on_submit" \ + -H 'Content-Type: application/json' -H 'X-Nhcx-Path: v1/preauth/on_submit' \ + -H 'X-Nhcx-Payload-Kind: fhir' -H 'X-Nhcx-Correlation-Id: ' -H 'X-Nhcx-Api-Call-Id: ' \ + -H 'X-Hcxkit-Txn-Id: ' -H 'X-Hcxkit-Type: preauth' -H 'X-Hcxkit-Flow: request' -H 'X-Hcxkit-Payload-Kind: fhir' \ + -H 'Authorization: Bearer ' \ + --data-binary @/tmp/delivery.json +``` + +## 10. The HMIS-side endpoints a build exposes + +Use these as the model for what your HMIS needs. `` is the claim episode id. + +| Method | Path | Purpose | Leg | +| --- | --- | --- | --- | +| GET | `/claims`, `/claims/new`, `/claims/` | list, policy search, detail | none | +| POST | `/claims` | open an episode from a chosen policy | none | +| GET | `/claims//state` | the whole episode as JSON after the page-load polls | none | +| POST | `/claims//check` | coverage eligibility (validation, benefits, discovery) | `v1/coverageeligibility/check` | +| POST | `/claims//plan` | fetch or refresh the package master | `v1/insuranceplan/request` | +| GET | `/claims//plan/forms`, `.../forms/`, `.../plan/` | questionnaires and one package | none | +| POST | `/claims//link`, `/unlink` | attach or detach the admission | none | +| POST | `/claims//preauth` | save the dossier draft | none | +| GET, POST | `/claims//lines`, `.../lines/quantities`, `.../lines//delete` | procedure, implant and tier lines | none | +| POST | `/claims//forms` | save questionnaire answers | none | +| POST | `/claims//auth` | auth-requirements ruling | `v1/coverageeligibility/check` | +| POST | `/claims//submit` | pre-auth 12, query answer 19, enhancement 13, enhancement answer 131 | `v1/preauth/submit` | +| POST | `/claims//predetermination` | a quote | `v1/preauth/submit` | +| POST | `/claims//cancel` | cancel Task PC01 | `v1/task/submit` | +| POST | `/claims//status` | status enquiry Task | `v1/task/submit` | +| POST | `/claims//reprocess`, `/release` | reprocess or balance release, 36 | `v1/task/submit` | +| POST | `/claims//queries//reply`, `.../acknowledge` | communication reply or notification acknowledgement | `v1/communication/on_request` | +| POST | `/claims//discharge` | record how the stay ended | none | +| POST | `/claims//claim` | claim 15, query answer 161 or 151, resubmit 16 | `v1/claim/submit` | +| POST | `/claims//claim/documents`, `/documents`, `/documents/required`, `.../delete` | attachments | none | +| GET | `/claims//documents/` | view an attachment | none | +| POST | `/claims//payments//ack` | resend a payment acknowledgement | `v1/paymentnotice/on_request` | +| POST | `/v1/` under the registered `endpoint_url` (own transport), or `/callback`, `/callback/`, `/nhcx/callback` (nhcx-adapter) | a delivery | inbound | + +The HMIS configuration a build needs: + +- The transport's settings: for nhcx-adapter, its base URL (it listens on `127.0.0.1:8090` by default) and API key; for your own transport, the ABDM client id and secret, the private key, and the sessions, NHCX and registry addresses (`references/transport-knowledge.md` section 3). +- The payer's participant code (`1518@hcx` for the PMJAY SHA Himachal Pradesh sandbox) and the payer's name. +- The callback shared secret. +- A workflow-id override table, JSON, that overrides the per-payer table key by key, for example `cancel=122`. +- A map from payer code to payer adapter, for example `1518=pmjay,=generic`. +- The archive folder for cases, and a switch to turn the archive off. + +The sender code is not an environment variable. It is the facility's participant code, held in the HMIS's own settings. + +## 11. What the adapter client looks like in code + +The whole client is one function, `_api(path, payload, timeout, method, claim_id, use_case)`. It builds the URL from the base, adds `Authorization: Bearer` when a key is set, POSTs JSON, raises `GatewayError(message, status)` on any non-2xx or network failure, decodes JSON, and archives the envelope beside the case when `claim_id` is given. Every send in the module goes through it, which is what lets a test replace it with a stub: + +```python +posted = {} +def _ack(path, payload=None, **kw): + posted["path"], posted["payload"] = path, payload + return {"txn_id": "01PLAN", "correlation_id": "corr-plan-1"} +claims._api = _ack +``` + +Give your HMIS the same single door. diff --git a/plugins/nhcx/skills/nhcx-claim/references/errors-and-debugging.md b/plugins/nhcx/skills/nhcx-claim/references/errors-and-debugging.md new file mode 100644 index 000000000..9be844d82 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-claim/references/errors-and-debugging.md @@ -0,0 +1,167 @@ +# Errors and debugging + +Sources: + +- `nhcx-package/nhcx-error.yaml`: every NHCX, PAYR and ERR-PYR code, with the standard and reference payer readings side by side. +- `nhcx-package/docs/06-Reference/01-Error Codes.md`: the same codes as tables. +- `nhcx-package/docs/01-Overview/04-JWE, Status and Errors.md`, "Codes met live". +- `nhcx-package/docs/03-Building a Provider/11-PMJAY Sandbox Run.md`: one full case run, refusal by refusal. +- `nhcx-package/docs/06-Reference/02-Troubleshooting.md`. +- The nhcx-adapter release README, "Troubleshooting". + +The live readings are from runs against the PMJAY SHA Himachal Pradesh sandbox payer (`1518@hcx`). + +## 1. Where an error comes from + +Three places refuse a message, and the family of the code says which (`nhcx-error.yaml`, `spaces`): + +| Family | Who refused | How you hear it | +| --- | --- | --- | +| Gateway answers to your own send (`400`, `401`) | the exchange, before the message goes further | the HTTP answer to your POST on `/v1/...`; a `401` is an expired token or a missing `Bearer` | +| A delivery your key cannot open (own transport) | your receiving end | the JWE will not decrypt: the certificate on your participant record is not the key you hold | +| Adapter codes (`INVALID_ENVELOPE`, `CERT_NOT_FOUND`, `CALLBACK_HTTP_500`), nhcx-adapter only | nhcx-adapter, before or after the wire | the HTTP answer to your `/fhir/out` call, `{"ok": false, "error": {...}}` | +| `NHCX-*` | the exchange; the message never reached the payer | the HTTP answer to your call (`gateway_status` 4xx with `upstream_body`), or a `ProtocolResponse` delivered to your callback later | +| `PAYR-*`, `ERR-PYR-*` | the payer; the message reached it | a `ProtocolResponse` on your callback with `x-hcx-status: response.error` and `x-hcx-error_details {code, message}`, on the request's correlation id | + +A `ProtocolResponse` is plain JSON, not a bundle. The exchange delivers it with `type: ProtocolResponse` and the `x-hcx-` fields in the clear; nhcx-adapter passes it on with `X-Nhcx-Payload-Kind: protocol` and `fhir` set to the body. Read `fhir.type == "ProtocolResponse"` and `fhir["x-hcx-error_details"]`. Settle the leg as refused at the door with the payer's words, and keep the thread the payer last answered on. + +PAYR numbers are not globally unique. The same number means different things on different sheets (`nhcx-error.yaml` lists them under `collisions`), and the live sandbox reuses several with a meaning the published sheet does not give. Match on the message text and log both. + +## 2. PAYR and ERR codes met live + +The published text is from `nhcx-package/nhcx-error.yaml`. Where the standard and reference payer sheets collide, both readings are given. The live text and the fix are from the sandbox runs. + +| Code | Published text | Live text | What it means | Fix | +| --- | --- | --- | --- | --- | +| PAYR-1008 | Invalid FHIR bundle received (reference payer); Eligible coverage amount is insufficient (standard) | "Invalid content type" or "Invalid input, code and reason code" or "Invalid Base64" | Three faults on one code: a document outside pdf, jpg, jpeg, png and fhir+json; a Task code paired with a reason the scheme does not accept (every `status`, `reprocess`, `release` Task on the sandbox, and a reprocess with the intimation input misspelt); an attachment it will not decode | Check the content type. For a Task, the sandbox takes only one financial task code, `cancel` (`11-PMJAY Sandbox Run.md`, "What the sandbox will not take"). Spell the reprocess input `intimationNumber` | +| PAYR-1018 | Time limit for submission expired (standard); No task reason code received (reference payer) | asks for a `Task.reasonCode` on a status enquiry | The status Task is refused as incomplete; with a reason it is refused with PAYR-1008 | Do not offer a status enquiry on PMJAY; switch it off in the PMJAY payer adapter | +| PAYR-1019 | Requested additional information was not received in time (standard); Invalid sequence received in supporting info element (reference payer) | "Invalid sequence received in supporting info element" | A `supportingInfo` entry with no `sequence` | Number the whole list once it is assembled | +| PAYR-1027 | (item error family) | "Invalid item id found for item in claim component" | `Claim.item` has no element `id` (`Item/1`). Nothing to do with the package code | Put `id` on every item, procedure and supportingInfo | +| PAYR-1083 | (practitioner family) | "No HPR details found for the practitioner ... category code as HPIN" | The Practitioner carries no identifier typed `HPIN` | Add the `HPIN` identifier under `https://hpr.abdm.gov.in` | +| PAYR-1096, PAYR-1503 | (supporting-info value-type family) | the death date is missing | A death claim without the `ONS`/`DTM` entry | Add `ONS`/`DTM` with the death instant and answer the plan's death forms | +| PAYR-1214 | No previous preauthorization approved record found for the resubmission request | same | A 121 after a rejection | Send a fresh 12 | +| PAYR-1238 | Beneficiary is having an active preauthorization request at this hospital with reference number ... | same; the reference ends in the SHA's case id | Scheme rule, not a bundle fault: one live pre-auth per beneficiary per hospital. Perversely the first sign the bundle is right, because validation runs first | Cancel the other case (PC01) or let it be rejected; sweep before a run | +| PAYR-1245 | Rule failure | "Only one conservative procedure can be booked for a case" | The master's `ProcedureType`; an enhancement on a conservative case must add a medical package | Pick a package whose `ProcedureType` is medical | +| PAYR-1254, PAYR-1365 | Response for STG Questionnaire id ... is mandatory for procedure code ... | same | A package's treatment-guideline questionnaire unanswered | Answer every `/stgquestionnaire/` form the plan attaches to the quoted packages | +| PAYR-1256, PAYR-1363 | Response for Authentication Consent Questionnaire is missing | same | The plan's consent questionnaire unanswered where no biometric token was taken; 1256 on the pre-auth, 1363 on the claim | Answer the policy-level consent form on both legs | +| PAYR-1270 | Item LM100 is not applicable for preauthorization request | same | `LM100` on a pre-auth | Only a LAMA or DAMA claim before or during surgery carries it | +| PAYR-1321 | Error occurred while processing the request due to invalid workflow id | same | 151, 19 or 16 on `v1/claim/submit` | Answer a claim query on 161; never resubmit a decided claim, reprocess it | +| PAYR-1322 | No active case found for the given case number | "Active instance found for case number" | A request is already open on that case; the scheme takes one at a time | Wait about 30 seconds after a decision, then send again; up to three tries | +| PAYR-1362 | No procedure with code LM100 received with 'Requested' status | same | A LAMA or DAMA claim before or during surgery that still carries the package | Collapse the claim to one `LM100` line | +| PAYR-1367, PAYR-1368 | No biometric records found ... / units of cycle information received | same | A cyclic package (dialysis) claimed without a biometric record per cycle and cycle information | Do not claim a cyclic package unless the HMIS can produce both | +| PAYR-1401 | policy not allowed for the hospital | same | The plan was asked for under a policy the hospital is not empanelled under | Ask under the beneficiary's own policy code from the policy search | +| PAYR-1406 | Existing request with correlation id ... is in progress | same | A second plan request while one is still being served | Wait 15 to 60 minutes; reuse the master you hold | +| ERR-PYR-CLM-007 | on none of the published sheets; `nhcx-error.yaml` lists it as observed live | "No prior preauthorization or claim record found for case number" | The claim was sent under a number of its own instead of the pre-auth's | Send the claim under the pre-auth's claim number | + +Refusals arrive in order: the SHA validates the bundle first and applies the scheme's rules only to a bundle that passed. A refusal in the `PAYR-102x` block is structural, so check ids and sequences before values. + +## 3. Gateway protocol errors + +From `nhcx-package/nhcx-error.yaml` (the gateway space) and the live notes: + +| Code | Message | When you meet it | Fix | +| --- | --- | --- | --- | +| NHCX-1006 | Duplicate request. Request with same correlation id already exist | A request sent again on a correlation id the exchange already holds | Mint a fresh correlation id for every request; only a response echoes one | +| NHCX-1010 | No Data with given Correlation id for call back request | A response sent on a thread the exchange has retired: the request was redelivered five times without a 2xx, or the id was never a request | Acknowledge inbound requests at once; a payer that decides minutes later sends `outcome queued` first | +| NHCX-1012 | No records found with the requested api caller id | The sandbox's own `v1/status` route, whatever id you pass | Ask status as a Task on `v1/task/submit` | +| NHCX-1015 | Invalid response received from receiver (published); the registry answers "You are not authorized to update/modify details" | Updating a participant's endpoint or certificate with a client id that did not create it | Use the creator's credentials or the NHCX participant portal (nhcx-adapter release README, "Troubleshooting") | +| NHCX-1016 | Invalid Api Action / no policies found (the registry, on a policy search) | A policy search that finds nothing | Read it as an empty result | +| NHCX-1018 | Invalid ABHA number received | An ABHA not in `XX-XXXX-XXXX-XXXX` form on the envelope | Format it, or omit the header | + +With nhcx-adapter as the transport, its local codes and their HTTP statuses are in `api-knowledge.md` section 5. The ones you will meet first: + +- `CERT_NOT_FOUND`: the recipient has no certificate on the registry; nothing to fix locally. +- `SELF_ENCRYPTION_KEY`: the registry handed out your own certificate for another code; run `nhcx-adapter cert --refresh`. +- `DECRYPT_FAILED` on `/in`: your registered certificate is not the key you hold; run `nhcx-adapter check`. +- `WRONG_RECIPIENT` on `/in`: a message for a participant this adapter does not hold. +- `CALLBACK_HTTP_` and `CALLBACK_UNREACHABLE`: your HMIS refused or was down; NHCX will redeliver up to five times. +- `TOKEN_HTTP_401`: wrong `clientId` or `clientSecret`, or sandbox credentials against production. + +## 4. Reading a ledger thread + +The per-case archive is the first place to look, with any transport: every message sent and received, by correlation id, in `//transactions.txt` (step 4). With nhcx-adapter as the transport, its ledger also holds what reached it but not your HMIS; the commands below read it. + +Step 1. Find the thread. From the leg row's `correlation_id`, or from the case number in a summary: + +```sh +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger/thread/" | python3 -m json.tool +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger?since=2h&direction=in&limit=100" | python3 -c 'import json,sys; [print(r["id"], r["created_at"][11:19], r["direction"], r["path"], r["workflow_id"], r["hcx_status"], r["status"], r.get("fhir_summary",{}).get("outcome")) for r in json.load(sys.stdin)["items"]]' +nhcx-adapter ledger thread # no server needed +``` + +Step 2. Read the derived `state`: + +| state | Meaning | What to do | +| --- | --- | --- | +| `awaiting_response` | You sent a request and nothing came back | Wait; on the SHA a decision needs the desk. Check `peer.status_code` on the outbound row is 202 | +| `partial` | A `response.partial` arrived (20, 25, or the SHA's 37) | The payer has it. The decision comes on the same thread | +| `completed` | A `response.complete` arrived | The leg should be settled in the HMIS. If it is not, the callback failed or the reader misread it | +| `awaiting_our_response` | A request reached you (a CommunicationRequest, a payment notice) | Your reply is due on this correlation id | +| `error` | A rejection, a failed send or delivery, or a protocol message | Open the message with `error` or `format: protocol` | + +Step 3. Read one message in full, bundle included: + +```sh +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger/" | python3 -m json.tool | less +``` + +On an inbound row, `peer.status_code` is what your callback answered and `peer.response` is its body. A `delivery_failed` row with a 500 is your handler raising. On an outbound row, `peer.status_code` is the gateway's answer and `peer.response` its body. A `rejected` row carries `GATEWAY_HTTP_` and the NHCX error in `peer.response`. + +Step 4. Compare with the HMIS's own archive for the case, `//transactions.txt`. Each line names the workflow id, correlation id, api call id, ledger id and file. + +- A message in the ledger and not in the archive is a callback that failed. +- A message in the archive marked `outcome=unmatched` is one the HMIS could not tie to a case: the correlation id is on no leg row, and the bundle names no claim number the HMIS knows. +- A message in neither is a send that never left; look at the HMIS's error on the leg row. + +Files, when the server is down: `//.json`, and `index.jsonl` in the same folder for the summaries. `ledger.dir` is `data/ledger` by default. + +## 5. Correlation mistakes + +Each of these was made once in a real build. + +- Answering on the wrong thread. A communication reply or a payment acknowledgement must carry the request's `x-hcx-correlation_id`; every other leg must not carry one. A PMJAY query answer (19, 131, 161) goes on a new correlation id; a same-thread answer is swallowed without a refusal. +- Sending a non-UUID correlation id. nhcx-adapter replaces anything that is not an 8-4-4-4-12 UUID with a fresh one, so the thread is silently lost; store what the transport returned, not what you sent. With your own transport, a request's correlation id is its own `api_call_id` and an answer echoes the request's. +- Matching by path or by header type. Route an inbound message by its correlation id first, then by the claim number inside the bundle. With nhcx-adapter, the `X-Hcxkit-Flow` header is inverted on purpose and must not be a filter. +- Closing a thread on the first reply. The acknowledgement and the decision share one correlation id; a settled-status guard throws the approval away. +- Losing the thread after a refusal at the door. A send refused with a ProtocolResponse went out under a correlation id the payer never took in. The case still lives on the thread the payer last answered; keep it as `thread_correlation_id`. +- Reusing a correlation id after an error. The exchange retires it; the next attempt needs a fresh one. +- Forgetting the workflow id on a reply. Some payers match the payment acknowledgement on the notice's own workflow id; PMJAY wants 17. + +## 6. Redelivery and deduplication + +NHCX redelivers an unacknowledged message up to five times and then drops the correlation id. The SHA redelivers a large plan answer on its own, two or three times about a minute apart, under the same `x-hcx-api_call_id`. A case archive showed it as three lines on one api call id. With `callback.also` configured, one delivery reaches every target, and a refusal by any one of them makes NHCX redeliver to all. + +So: + +- Dedupe on `x-hcx-api_call_id` (with nhcx-adapter, `X-Hcxkit-Txn-Id` carries the same value). Either store the last applied `api_call_id` on the leg row and ignore a repeat, or keep an inbound ledger keyed on it and answer `duplicate`. A payer that omits the id is deduped on identical outcome and adjudication. +- Dedupe payment notices and communication requests on their correlation id, with a unique index on each table. +- Answer 2xx before doing slow work. The exchange allows 30 seconds for the 202 receipt (nhcx-adapter gives your HMIS 20 of them, `callback.timeoutSeconds`); anything slower is a failed delivery. +- Un-record a delivery whose application failed for a passing reason (database away), so the redelivery is not waved off as a duplicate. +- With nhcx-adapter, treat `X-Nhcx-Redelivery: true` as a hint, not a rule: the ledger flag is per adapter process and is lost on a ledger reset. + +## 7. A send reported as failed can still have landed + +Seen live on the sandbox three times in one night. A pre-authorisation went out through nhcx-adapter, the connection dropped after the request had been written, and it answered the hospital `GATEWAY_UNREACHABLE` with HTTP 502. NHCX had taken the message: the SHA acknowledged it four seconds later on the correlation the adapter had minted. A hospital that treats that 502 as "not sent" sends again. The scheme refuses the duplicate (ERR-PYR-PRE-030 "Active instance found for case number", PAYR-1238 for a fresh pre-auth), and a live case stands at the payer that the hospital has no record of. + +So: + +- nhcx-adapter's failure body names the ids the message went out under: `ledger_id`, `txn_id`, `correlation_id`, `api_call_id`, `request_id` and the `headers` map. Keep them. With your own transport the ids are the ones you minted before sealing: store them before the POST, so a failed POST still has a thread to look for. +- Record the failed leg under that correlation, not as nothing. Carry the ids on the client's error and write them onto the leg row. +- When an answer arrives on a failed leg's correlation, revive it: the leg becomes a sent leg, the record moves from draft to with-the-payer, and the desk is not offered a second send. A protocol error answer revives nothing. +- Anything that creates a record before it sends must name that record in the refusal, or the record is orphaned where nobody can see it. An enhancement handler returns the child it raised alongside the gateway's words. + +## 8. Sandbox pace rules + +What the SHA Himachal Pradesh sandbox (`1518@hcx`) did across the runs. `nhcx-package/docs/03-Building a Provider/11-PMJAY Sandbox Run.md` records one such run in order. + +- One live pre-authorisation per beneficiary per hospital (PAYR-1238). Every HMIS that shares the facility's participant code shares the limit, so sweep before a run: withdraw every approved case without a claim, then wait ten seconds. +- One request at a time per case (PAYR-1322). About 30 seconds between a decision and the next leg; an enhancement refused with "Active instance" is resent up to three times. +- Decisions are taken on the NHCX Payer Service desk, not on the exchange (`nhcx-package/docs/03-Building a Provider/12-PMJAY Adjudication APIs.md`). A case has to be driven through roles: PPD-Trust decides a pre-auth; a claim walks CEX-Trust, CPD-Trust, the Medical Audit Committee, ACO-Trust, SHA-Trust and the Claim Review Committee. The desk answers "Event Meta Log not found" or "Case not found" until the exchange has delivered the request; retry every six seconds, up to 150 seconds. A decision the desk accepts is sometimes never sent; taken again a minute later it is answered in seconds, so decide up to four rounds of 90 seconds. +- An enhancement's query has to be taken a minute after the acknowledgement. +- A claim episode with a query answered and the roles walked takes about ten minutes. Run cases one at a time and allow 20 minutes per case. +- The plan answer arrives in pieces over a minute and is redelivered; expect the same api call id three times. +- The beneficiary registry behind the ABDM session refuses a search now and then while a token refreshes. Retry the search up to four times, 30 seconds apart. +- The sandbox approves a claim query answer at zero with "No query response comments received" when the `CQD` reply is missing, and sometimes even when it is present. Report it; do not assert on the amount. +- The status Task is refused on this sandbox: without a `Task.reasonCode` it answers PAYR-1018, with any reason code PAYR-1008. PMJAY decides on its own desk and answers no status enquiry, so do not offer one for it. Record the refusal on the enquiry row and move on. +- The reprocess Task is taken only under the standard's spelling, `intimationNumber`. Use that spelling on every Task (cancel included); the package's bundles carry it too. The SHA answers workflow 37, "Arbitration claim submission process completed successfully". +- A test payer you run yourself has none of these limits; six use cases ran in under four minutes against one. diff --git a/plugins/nhcx/skills/nhcx-claim/references/fhir-knowledge.md b/plugins/nhcx/skills/nhcx-claim/references/fhir-knowledge.md new file mode 100644 index 000000000..08ffbb6c6 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-claim/references/fhir-knowledge.md @@ -0,0 +1,206 @@ +# FHIR knowledge: every bundle sent and received + +Sources: the bundles under `nhcx-package/fhir` (the hospital pins in `B1` to `B9`, the payer answers in `C3` to `C11`, the live PMJAY hospital captures in `D1` to `D13`) and the chapters under `nhcx-package/docs/05-FHIR Reference`. Get the package as `references/material.md` says. + +## 1. Where the examples live + +| Set | Path | What it is | +| --- | --- | --- | +| Pinned hospital bundles | `nhcx-package/fhir/B1` to `B9`, the lower-case files (`B3/preauth-request.json`) | One bundle per message a hospital sends, written to the specification with placeholders. A build is held to these byte for byte. The pin map is in `references/material.md`. | +| Payer answers | `nhcx-package/fhir/C3` to `C11` | One file per message the payer sends: the generic answer and, where one exists, its `-pmjay` twin. Feed these into your readers. | +| Live hospital captures | `nhcx-package/fhir/D1` to `D13` (PMJAY) and the capitalised B files such as `B3/B3-request.json` (generic) | Bundles taken from the sandbox wire, with the beneficiary's identifiers replaced | +| The catalogue | `nhcx-package/fhir/index.yaml` | For each file: direction, side, scheme (`generic` or `pmjay`), workflow id, focal resource, origin. Origin `example` means placeholders, not a payload; `wire` means a capture. | +| The NRCeS IG's own example | `nhcx-package/fhir/B4/communication-request.json` | The communication TaskBundle for the payer's request comes from the IG | +| Your build's archive | `//NNN--.json` and `transactions.txt` (modules 7.1 and 7.3) | Every envelope one episode sent and received, in order | +| Chapters | `nhcx-package/docs/05-FHIR Reference/*.md` | Element by element: `08-Preauthorisation Request.md`, `12-Claim Request.md`, `13-Claim Response.md`, `17-Communication.md`, `15-Cancel, Reprocess and Shortfall.md`, `16-Payment Notice and Acknowledgement.md`, `06-Insurance Plan Response, Package-Based.md`, `19-Codes and Value Sets.md` | + +Pins, by leg. Paths are under `nhcx-package/fhir/`. + +| Leg | Provider pin | Payer answer or capture | +| --- | --- | --- | +| Coverage eligibility | `B1/discovery.json`, `B1/validation.json`, `B1/benefits.json`, `B1/auth-requirements.json` | `C3/validation-response.json`, `C3/discovery-response.json`, `C3/benefits-response.json`, `C3/C3-response-generic.json`; PMJAY `C3/coverage-eligibility.json`, `C3/C3-benefits-pmjay.json`, `C3/C3-response-pmjay.json` | +| Insurance plan | `B2/insurance-plan-request.json` | `C4/C4-response-pmjay.json` (package-based, abridged), `C4/C4-response-generic.json` (coverage-based) | +| Pre-auth 12, enhancement 13, query answer 19 or 131 | `B3/preauth-request.json`, `B3/preauth-enhancement.json`, `B3/preauth-queryupdate.json` | `C5/C5-received-wf20.json`, `C5/C5-approved-wf21.json`, `C5/preauth-queried.json`, `C5/C5-rejected-wf23.json`, `C5/C5-enhancement-approved-wf22.json`; PMJAY the `-pmjay` twins and `C5/C5-queried-wf24.json` | +| Cancel PC01 | `B3/preauth-cancel.json` | `C10/C10-cancelled-wfPC02.json`, `C10/C10-cancelled-wfPC02-pmjay.json` | +| Claim 15, query answer 161 | `B5/claim-request.json`, `B5/claim-queryupdate.json` | `C7/C7-received-wf25.json`, `C7/C7-approved-wf26.json`, `C7/claim-queried.json`, `C7/C7-rejected-wf291.json`; PMJAY the `-pmjay` twins, `C7/C7-approved-deduction-wf26-pmjay.json` and `C7/C7-queried-wf27.json` | +| Reprocess 36, release 36 | `B5/claim-reprocess.json`, `B5/claim-release.json` | `C10/C10-arbitration-wf37.json`, `C10/C10-arbitration-wf37-pmjay.json` | +| Payment acknowledgement | `B7/payment-notice-ack.json` | The notice you answer: `C9/C9-notice-wf30.json`; PMJAY `C9/payment-notice.json`, `C9/C9-notice-tds-wf30-pmjay.json` | +| Communication reply | `B4/communication-response.json` | `B4/communication-request.json` (the query you answer; the IG's example), `C6/C6-preauth-query-wf24.json` and `C6/C6-claim-query-wf27.json` (live, generic), `C6/C6-notification-wfN02.json` (PMJAY) | +| Status enquiry | None. The published call carries no bundle (`nhcx-package/docs/05-FHIR Reference/18-Predetermination, Status and Search.md`). | None captured | + +## 2. Conventions every hospital bundle follows + +From `nhcx-package/docs/05-FHIR Reference/01-Bundles and Conventions.md` and the pins: + +- `Bundle.type` is `collection`; `Bundle.meta.profile` names the NRCES bundle profile (`ClaimBundle`, `TaskBundle`, `CoverageEligibilityRequestBundle`); every resource names its own profile under `https://nrces.in/ndhm/fhir/r4/StructureDefinition/`. +- Every entry has an absolute `fullUrl` under one base, `https://nhcx.abdm.gov.in/...`, and every reference resolves to another entry. A thing that is genuinely not in the bundle is named by identifier, not by a URL. The chapter's rule 3 also accepts `urn:uuid:` references; parse both. +- `Bundle.id` is fixed per shape: `coverage-validation-request-generic`, `preauth-request-generic`, `preauth-enhancement-request-generic`, `claim-queryupdate-request-generic`, `preauth-cancel-request-generic`. +- No `meta.versionId`, no `meta.lastUpdated`, no bundle `timestamp` on a request. The communication reply and acknowledgement are the exception: the IG example carries `meta.lastUpdated` and `timestamp`, and the build writes them. +- Money carries `currency: INR`; the total equals the sum of the item nets; whole numbers are written as integers. +- Instants are IST with `+05:30`. The four coverage pins in `B1` stamp `created` at `+05:00`, so leave `created` out of the byte comparison. + +## 3. Coverage eligibility request + +Builder: `build_coverage_request`. Seven entries, in this order and at these urls: + +1. `CoverageEligibilityRequest` at `/coverage-eligibility/request`: `identifier: [{system: https://nhcx.abdm.gov.in}]`, `status active`, `priority normal`, `purpose: []`, `patient`, `created`, `enterer` (the PractitionerRole), `provider`, `insurer`, `facility` (the Location), `insurance: [{focal: true, coverage}]`, and `item[]` on `benefits` and `auth-requirements`. +2. `Patient` at `/patient`: identifiers typed `PMJAY` (NDHM identifier-type system) and `MB` (v2-0203), both the member id. Nothing else; demographics are the payer's to return. +3. `Organization` provider at `/provider`: identifier `NPI` under `https://nhcx.abdm.gov.in` = the facility's registry id (HFR id); `type prov`; `name`. +4. `Organization` payer at `/payer`: identifier `NIIP` = the participant code without `@hcx` (`1518`); `type pay`. +5. `Location` at `/location`: `name`, `managingOrganization` the provider. +6. `Coverage` at `/coverage`: identifier `NH` = the policy code, or `NONE` on a discovery; `status active`; `type HIP`; `subscriber`, `beneficiary`, `subscriberId` = member id; `relationship self`; `payor`. +7. `PractitionerRole` at `/practitioner-role`: `code` SNOMED `307988006` Medical technician. + +Items (`eligibility_item`): `category` under `https://nhcx.abdm.gov.in/category-code` (the specialty), `productOrService` under `https://nhcx.abdm.gov.in/product-code` (the package), `quantity.value` as an integer, and each ward tier quoted through the package as a `modifier` coding with code and display and no system. No money, no diagnosis, no sequence. + +The four purposes differ only in `purpose`, the Coverage identifier and whether `item` is present. + +Reader (`parse_validation_bundle`): the payer echoes the request's entries and appends its own, so take the last `CoverageEligibilityResponse`, `Patient` and `Coverage`. Read `insurance[0].inforce`, `outcome`, `disposition`, `item[].authorizationRequired`, the largest `benefit[].allowedMoney` with its `usedMoney`, the Patient's name, gender, birth date, address, `ABHA` identifier and photo, the Coverage's `class[0].name` and `period`. The SHA answers on workflow id `5` (`nhcx-package/fhir/C3/C3-response-pmjay.json`). + +Auth-requirements reader (`parse_auth_bundle`, with `supporting_entry`; examples `C3/C3-response-generic.json` and `C3/C3-response-pmjay.json`): one `insurance[0].item` per line quoted, each with `authorizationRequired`, `excluded`, `benefit[0]` and `authorizationSupporting[]`. Each supporting entry is a CodeableConcept whose `text` is free text the scheme overloads: `fullUrl: ` marks a form to answer; `Type: pre` or `Type: post` says which leg a document is due at; `Procedure Code: X` says for which line. The space after the colon is sometimes missing; match both. A form is always wanted at pre-auth; a document only when its stage is `pre`. + +## 4. Insurance plan request and the plan + +Request (`build_plan_request`): a `TaskBundle` with one entry, a `Task` at `https://nhcx.abdm.gov.in/insurance/request`: `status requested`, `intent order`, `code poll` on the HL7 financial task code system, inputs typed `policyNumber` and `providerId` under the NDHM task-input code system. No id, no timestamp, no requester. At least one input is mandatory. Bundle id `insurance-request-generic`. + +Answer: an `InsurancePlanBundle` with one `InsurancePlan`, an `Organization`, and one `Questionnaire` per form the plan names (the same form repeated once per benefit that needs it; collect by `url`). The parser (`parse_plan_bundle`) reads both published shapes and merges them on package code: + +- `plan[].specificCost[].category` (the specialty) then `benefit[].type` (the package) then `cost[]`: the cost typed `Procedure` is the package rate; `Stratification` and `Implant` costs are money paid over the rate, named by their `qualifiers[0]`. +- `coverage[].benefit[].limit[]`: the limit whose code is the package's own is the rate; the rest (STRAT codes, implants) are tiers. +- Extensions on the plan, the coverage and each benefit, matched by a squashed url family: `Claim-Condition` children name conditions (`ProcedureType`, `IsDayCare`, and so on); `Claim-SupportingInfoRequirement` children are one nested requirement per document, each with `category`, `code` (`MAND0409` and the like) and `documentationUrl` pointing at a Questionnaire. Requirements on the `InsurancePlan` resource itself are policy-wide (proof of identity, the consent forms). +- A `Questionnaire` under `/questionnaire/` is a policy form; under `/stgquestionnaire/` a treatment-guideline checklist. Questions live on `item.prefix` far more often than `item.text`; answer options are plain strings; `initialSelected` is the payer's default. + +Store it once per facility and policy and copy it onto later episodes (`reuse_plan`). The PMJAY master runs to tens of megabytes; the validator cannot check it whole. + +## 5. The Claim bundle: pre-authorisation, enhancement, query answer, claim, predetermination + +One document for every leg (`claim_bundle`). Entries, in order and at these urls: + +1. `Claim` at `https://nhcx.abdm.gov.in//`: leg `preauth`, `claim` or `predetermination`; flow `request`, `enhancement` or `queryupdate`. +2. `Patient` at `/patient`, `id 1`: identifiers `PMJAY` (member id), `ABHA` (when known), `MB` (member id); `name.text`, `telecom`, `gender`, `birthDate`. +3. `Organization` provider at `/provider`, `id 1`; `Organization` payer at `/payer`, `id 2` (as in section 3). +4. `Coverage` at `/coverage`, `id 1`: `NH` identifier = policy code, `subscriberId` = member id. +5. `Practitioner` at `/practitioner` (the second and later at `/practitioner/2` and so on), `id n`: identifiers `HPID` under `https://nhcx.abdm.gov.in`, `MD` (licence) when known, and `HPIN` under `https://hpr.abdm.gov.in`. PMJAY looks the practitioner up by the `HPIN` typed identifier and refuses a bundle without one with PAYR-1083. `qualification.code` under HL7 v2-0360 with the table's own display (`degree_coding`). +6. `Procedure` at `/procedure/n`, `id n`, one per package: `status preparation` before treatment, `completed` on the claim; `code` SNOMED `71388002` with `text` = the package display; `performedDateTime`. +7. `QuestionnaireResponse` at `/questionnaireresponse/n`, one per answered form: `questionnaire` = the plan's Questionnaire url, `status completed`, `subject` the Patient, `authored`, `item[].answer[]` typed by the question (`valueString`, `valueDateTime`, `valueBoolean`, `valueInteger`, `valueDecimal`, `valueAttachment`). + +The Claim itself: + +- `id` = the claim number; `identifier[0]` typed `CLN` under `https://nhcx.abdm.gov.in` = the claim number. Element ids on every list the payer indexes: `item[].id = Item/n`, `procedure[].id = Procedure/n`, `supportingInfo[].id = SupportingInformation/n`. PAYR-1027 is an item without one. +- `status active`, `type` SNOMED `737481003` inpatient care, `use` = `preauthorization`, `claim` or `predetermination`, `billablePeriod`, `created`, `insurer`, `provider`, `priority normal`. +- `careTeam[]`: sequence, provider reference, role `primary` for the first and `assist` after, `qualification` SNOMED specialty. +- `diagnosis[]`: ICD-10 under `http://hl7.org/fhir/sid/icd-10`, type `admitting`, `onAdmission yes`. +- `procedure[]`: sequence, `type` under `https://nhcx.abdm.gov.in/procedure-type` = the plan's `ProcedureType` condition lower-cased (`conservative`, `medical`, `surgical`), `date`, `procedureReference` with the package display. +- `insurance[0]`: `sequence 1`, `focal true`, `coverage`; on the claim `preAuthRef: [""]`. The pin carries the pre-auth's own claim number there (`B5/claim-request.json` quotes `B3/preauth-request.json`'s claim id). The build carries the payer's `ClaimResponse.preAuthRef`, which the live capture `nhcx-package/fhir/D9/D9-request.json` shows as `2026091110000810`. +- `item[]` (`claim_items`): one per procedure or implant, never per tier. `sequence`, `careTeamSequence`, `diagnosisSequence`, `procedureSequence` (its own Procedure), `informationSequence` (every supportingInfo), `category` under `ndhm-benefit-category` (the specialty), `productOrService` under `ndhm-procedure-code` (the package), `modifier[]` one coding per ward tier with code and display and no system, `programCode` `AB-PMJAY` under `ndhm-program-code` for PMJAY and none for a generic payer, `servicedPeriod` as dates, `quantity`, `unitPrice` = net divided by quantity, `factor` from the scheme's multiple-procedure rule (1, 0.5, 0.25 by cost rank; PMJAY only), `net` = the line plus its tiers. +- `total` = the sum of the nets. + +supportingInfo (`supporting_info`), every entry numbered once the list is assembled (PAYR-1019 is an entry without `sequence`): + +| When | category | code | value | +| --- | --- | --- | --- | +| every leg, one per attached document | `INV` (or the document's own category) under `ndhm-supportinginfo-category` | the plan's requirement code (`MAND0408`) under `https://nhcx.abdm.gov.in/document-code`, else `ODN` | `valueAttachment {contentType, data, title}` | +| every leg | `ONS` | `ADDD` | `valueString` admission instant | +| every leg | `OTH` | `EDT` | `valueString` admission instant | +| claim | `HDS` | the plan's summary code (`MAND0006` in the pin) else `HDS` | `valueAttachment` the discharge summary | +| claim, when a surgery time is known | `ONS` | `PSP` | `valueString` surgery instant | +| claim | `ONS` | `DSDE` | `valueString` discharge instant, or the death instant | +| claim, death only | `ONS` | `DTM` | `valueString` death instant (PAYR-1096 and PAYR-1503 without it) | +| claim | `DIS` | `DTH`, `LAMA`, `DAMA` or `DTM` | `valueString` the stage: `Before Surgery`, `During Surgery`, `After Surgery` | +| query answer (flow `queryupdate`) | `NMI` | `CQD` | `valueString` the desk's reply. The SHA reads its query response comments from here; an answer without one is decided as if none was given | +| every leg, one per answered form | `INF` (or `STG` for a treatment guideline) | `ODN` (or `STG`) | `valueReference` to the QuestionnaireResponse entry | + +Which forms ride (`required_forms`): with an auth-requirements ruling, the forms it named for the leg; without one, at pre-auth every guideline form the plan attaches to the quoted packages; and on both legs every policy-level form. The scheme refuses a pre-auth that answers neither biometrically nor with its Authentication Consent questionnaire (PAYR-1256, PAYR-1271), a claim without the consent answered again at discharge (PAYR-1363, PAYR-1364), and a package without its STG questionnaire (PAYR-1254, PAYR-1365). The live D4 capture carries two policy questionnaires; the live D9 claim carries four, including the Discharge Consent (`nhcx-package/fhir/D9/D9-request.json`). + +Which documents ride (`required_documents`, `preauth_documents`): the ruling's list for the leg, else the plan's list for the quoted packages at pre-auth and whatever was not attached there at the claim. A file attached against a requirement carries that requirement's code; a file nobody asked for carries `ODN`. Never drop one. Content types the scheme takes: pdf, jpg, jpeg, png (PAYR-1008 otherwise). + +The legs differ in these ways only: + +| Leg | flow | use | Procedure status | Extra | +| --- | --- | --- | --- | --- | +| Pre-auth 12 | `request` | `preauthorization` | `preparation` | | +| Enhancement 13 | `enhancement` | `preauthorization` | `preparation` | every line, old and new, under the same claim number; the costlier package at factor 1 and the other at 0.5 (the live capture `nhcx-package/fhir/D6/D6-enhancement.json` carries the two lines at 1 and 0.5) | +| Query answer 19 or 131 | `queryupdate` | `preauthorization` | `preparation` | the `NMI`/`CQD` reply | +| Claim 15 | `request` | `claim` | `completed` | discharge scalars, summary, `preAuthRef`, the claim under the pre-auth's number (ERR-PYR-CLM-007) | +| Claim query answer 161 | `queryupdate` | `claim` | `completed` | as the claim, plus `NMI`/`CQD` | +| Predetermination | `request` | `predetermination` | `preparation` | sent on `v1/preauth/submit` with workflow 12 | + +LAMA and DAMA before or during surgery (`claim_lines`): the claim carries one item, procedure `LM100` at the plan's rate (the sandbox prices it at zero), no tier, and the payer disqualifies every approved item (PAYR-1362 if the package is still there). After surgery the package stands and `LM100` is not used. PAYR-1270 is `LM100` on a pre-auth. + +## 6. The ClaimResponse you read + +Shape (`nhcx-package/docs/01-Overview/07-Payer Flexibility.md`, "Answer detail"): `ClaimResponse`, `Patient`, the two `Organization` entries, `Coverage`, in that order. Fields to read (`parse_claim_response`): + +- `use`: `preauthorization` or `claim`; a bundle with none is whatever you sent on that thread. +- `outcome`: `queued` (acknowledgement), `partial` (queried, or approved for less), `complete`, `error` (rejected). +- `adjudication[]` at claim level: the entry whose `category` is `status` carries `reason.coding.code`: `submitted`, `approved`, `queried`, `rejected`, `cancelled`. +- `preAuthRef`: the payer's case number; see `flow-knowledge.md` section 3 for which answers carry it. +- `identifier[0].value`: your claim number, echoed on every answer. +- `total[]`: a repeating list by `category`, never positional: `benefit` (granted this round), `eligible` (what the case stands at), `submitted`; PMJAY adds `tax` and `incentive`. +- `item[].adjudication[]` by category: `eligible` (amount), `status` (reason `Approved`, `Queried`, `Rejected`), `reason` (the desk's remark, pipe-delimited `USER~datetime~type~comment~trust`, kept verbatim), `eligpercent`, `eligquant`, `deductible` with its reason after a claim. +- `processNote[].text`. +- `type` is present only on the pre-auth acknowledgement (SNOMED `737481003`). + +The status rule (`verdict_status`): `queued` or reason `submitted` is still `submitting`; reason `cancelled` is `rejected`; reason `queried` is `queried`; outcome `error` is `rejected`; outcome `partial` is `partial` only with reason `approved`, else `queried`; outcome `complete` is `approved` with reason `approved` or none, else `queried`. Never read `outcome` alone. + +## 7. Task bundles the hospital sends + +A `TaskBundle` with the `Task` at `https://nhcx.abdm.gov.in//` followed by the provider and payer Organizations. The Task: `status requested` (`completed` on an acknowledgement), `intent order`, `code` on the HL7 financial task code system with no display, `description`, `authoredOn`, `requester` the provider, `owner` the payer. + +| Task | code | reasonCode (NDHM reason code system) | inputs | Other | +| --- | --- | --- | --- | --- | +| Cancel PC01 | `cancel` | one of `treatmentplanchanged`, `patientrequest`, `financialconstraints`, `alternativetreatment`, `duplicateclaim`, `administrativeerror`, `other` (with `other` the description is the only justification) | `claimNumber`, `intimationNumber` (both typed under `ndhm-task-input-type-code`) | anchor `/preauth/cancel` | +| Reprocess 36 | `reprocess` | `claimrejected`, `partialpayment` or `rejectiondisputed` with the reference's displays | `claimNumber`, `intimationNumber` (the standard's spelling), one `document` input per attachment as `valueAttachment` | `basedOn[0].identifier` typed `CLN`; `for.identifier` typed `PMJAY` on the scheme, `MB` elsewhere; anchor `/claim/reprocess` | +| Release 36 | `release` | `partialpayment` | `claimNumber`, `amount` as `valueMoney` under `https://nhcx.abdm.gov.in/task-input-type` | `basedOn` as above; anchor `/claim/release` | +| Status | `status` | none | `claimNumber` | anchor `//status`; not in the package, whose status call carries no bundle (`18-Predetermination, Status and Search.md`); refused by PMJAY | +| Payment acknowledgement 17 | `status`, `status completed` | none | none; `output[]`: `status` = `paymentack` under the NDHM task-output systems, and `claimNumber` | anchor `/payment/notice-ack` | + +The spelling rule: the input is `intimationNumber`, the standard's spelling, on every Task. A reprocess under any other spelling is refused with PAYR-1008 (proven live; `nhcx-package/docs/01-Overview/07-Payer Flexibility.md`, "One spelling on the Task"). The pinned cancel and reprocess Tasks carry the same spelling, so the offline comparison diffs them unchanged. + +## 8. Task answers you read + +`parse_task_response`: find the `Task`, then follow each `output[].valueReference` to the entry it names; when that is a `ClaimResponse`, read it with the same parser as a verdict. + +- PC02 (`nhcx-package/fhir/C10/C10-cancelled-wfPC02.json`): Task `completed`, code `approve`, `output[0]` an `include` reference to a `ClaimResponse` with adjudication reason `cancelled`, `use preauthorization`. Accept the cancel when the Task status is `completed` or `accepted` and the outcome is not `error`. Retire the claim number after an accepted cancel. +- 37 (`nhcx-package/fhir/C10/C10-arbitration-wf37.json`): Task `accepted`, code `approve`, a `ClaimResponse` with outcome `queued`, `use claim`. Put the claim leg back to `submitting`; the new verdict comes on the claim's own thread. +- A status answer: none captured in the package. A generic payer that answers a status Task sends a Task `completed`, code `status`, `output[]` with `claimNumber` and a `claimStatus` string; PMJAY refuses the enquiry instead. + +## 9. The communication loop + +The query, generic payer (`nhcx-package/fhir/C6/C6-preauth-query-wf24.json`; the IG's example at `nhcx-package/fhir/B4/communication-request.json`): a `TaskBundle` with a `Task` `poll`, `requested`, `intent order`, `reasonCode additionalinfo`, one `include` input pointing at the `CommunicationRequest`; the request with `identifier` (the claim number), `basedOn` the Claim, `payload[].contentString` one per ask, `reasonCode[].text` repeating them; then the Claim, Patient, the two Organizations, Practitioner and Coverage. It arrives on `v1/communication/request` on a new correlation id, with the queried leg's correlation id in `x-hcx-workflow_id` when the payer sends one. + +The notification, PMJAY (`nhcx-package/fhir/C6/C6-notification-wfN02.json`): a Task `poll`, `completed`, `intent proposal`, reason `information` under `http://terminology.hl7.org/CodeSystem/communication-category`, a `CommunicationRequest` with one `contentString`, and the two Organizations. + +Reader (`parse_communication_request`): the first `CommunicationRequest`; the claim numbers it names in `about[]`, `basedOn[]` and `identifier[]`; the asks from `payload[].contentString`, else `reasonCode[].text`, else the Task's `description`; the Task's `intent` and `reasonCode`. Match the claim by those numbers first, then by a request id already held, then by the correlation id of one of your sends, then by the workflow id as a thread. + +The reply (`build_communication_bundle`; pin `nhcx-package/fhir/B4/communication-response.json`): a `TaskBundle` with `meta.lastUpdated`, `identifier` under the payer system, `timestamp`, and entries in this order: + +1. `Task` at `urn:uuid:`: `status completed`, `intent order`, `code deliver` under `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-codes`, `authoredOn`, `requester` the provider, `owner` the payer, one `input` typed `include` (HL7 financialtaskinputtype) pointing at the Communication, `reasonCode` echoed from the request's Task when it carried one. +2. `Communication` at `urn:uuid:`: `identifier` echoed from the request, `basedOn: [{reference: }]`, `about: [{reference: }]`, `status completed`, `category notification`, `priority routine`, `recipient` the payer, `sender` the provider, `payload[]`: a `contentString` for the text, then one `contentAttachment {contentType, title, creation, data}` per document, each with an `extension` carrying the document code. The extension url is participant-defined (`17-Communication.md`): write it under your own system and keep one url. `inResponseTo` is never set: FHIR allows only a Communication there and the validator refuses a request. +3. The `CommunicationRequest` echoed as it arrived. +4. The case as the payer holds it, lifted from the queried leg's own bundle: `Claim`, `Patient`, provider `Organization`, payer `Organization`, `Practitioner`, `Coverage`. + +Envelope for the reply: `x-hcx-correlation_id` = the request's, `x-hcx-workflow_id` = the request's, else the queried leg's correlation id, else the claim number; sender and recipient swapped. + +The acknowledgement of a notification: the payer's own bundle sent back with `Task.status` set to `completed`, its intent and reason as sent, the provider Organization ahead of the payer's, a fresh `timestamp`. A request that came without a Task gets one built round it, coded `poll`, intent `proposal`, pointing at the request. The package's `B4/communication-acknowledgement.json` is a different shape: a `status` Task, `completed`, with a `status` output and the two Organizations, and no CommunicationRequest. + +## 10. The payment notice you read and the acknowledgement you send + +Notice (`nhcx-package/fhir/C9/C9-notice-wf30.json`; PMJAY `C9/payment-notice.json` and `C9/C9-notice-tds-wf30-pmjay.json`): a Task `deliver`, `requested`, with a `status` input; a `PaymentNotice` with a `CLN` identifier (the claim number), `amount`, `paymentStatus paid`; a `PaymentReconciliation` with the same identifier, `disposition`, `paymentDate`, `paymentAmount`, `paymentIdentifier` typed `UTR`, and `detail[]` lines (`RF` and `Payment` in `payment-notice.json`; `TDS` and `Payment` in the other two); the two Organizations. It arrives on `v1/paymentnotice/request` on a new thread, workflow 30, 31 or 33. + +Reader (`parse_payment_notice`): the claim number from the `CLN` identifier on the notice, the reconciliation, the Task, or the first entry's untyped identifier, never from the bundle identifier; the amount from the notice or `paymentAmount`; the UTR; the details. Dedupe on the notice's correlation id; a second notice with the same `PaymentNotice.id` updates the first (`record_payment`). Count money once per UTR (`paid_total`). + +Acknowledgement: the Task in section 7, sent on `v1/paymentnotice/on_request` to whoever sent the notice (not always the claim's payer), with `x-hcx-correlation_id` = the notice's and `x-hcx-workflow_id` = `17` for PMJAY or the notice's own id for a generic payer. + +## 11. Validating a bundle + +The package ships no validator. Use the HL7 FHIR validator (`validator_cli.jar`, from HL7) with the NRCeS IG package `ndhm.in`, version 6.5.0. A bundle refused with PAYR-1004 or PAYR-1008 goes through the validator before anything else (`nhcx-package/docs/06-Reference/02-Troubleshooting.md`). The rules it checks against are in `nhcx-package/docs/05-FHIR Reference/01-Bundles and Conventions.md`. + +```sh +java -Xmx4g -jar validator_cli.jar \ + -version 4.0.1 -ig -tx n/a -output result.json +``` + +Pass every file in one call; starting the JVM is the slow part. `-tx n/a` keeps the terminology checks offline; drop it to add them. A bundle passes when the output holds no issue of severity error or fatal. + +The provider pins carry 0 to 13 errors each and the SHA accepted every one as it stands. An error that says "a code the profile does not define" is the scheme's own vocabulary, not a fault to fix. A warning is advice. diff --git a/plugins/nhcx/skills/nhcx-claim/references/flow-knowledge.md b/plugins/nhcx/skills/nhcx-claim/references/flow-knowledge.md new file mode 100644 index 000000000..098cd9dbc --- /dev/null +++ b/plugins/nhcx/skills/nhcx-claim/references/flow-knowledge.md @@ -0,0 +1,206 @@ +# Flow knowledge: the claim episode, its workflow ids, the two payer kinds, the use cases + +Sources: the NHCX package, fetched by `scripts/fetch-package.sh` into `nhcx-package/` beside `nhcx-build/`. That means the overview chapters under `nhcx-package/docs/01-Overview`, the workflow sheet `nhcx-package/workflow.yaml`, the use-case catalogue `nhcx-package/usecases.yaml`, and the payer bundles under `nhcx-package/fhir/C3` to `nhcx-package/fhir/C11`. The published chapters live under `nhcx-package/docs/01-Overview`, `nhcx-package/docs/05-FHIR Reference` and `nhcx-package/docs/03-Building a Provider`. Everything else here was learnt live on the NHCX sandbox. + +## 1. The episode + +One hospital admission that an insurer pays for is one claim episode. Store it as one record with a claim number. Any number works if it is unique per hospital, short, sortable, and fits the payer's `CLN` identifier. The episode has these legs, each a separate exchange with its own correlation id: + +| Order | Leg | You send | Payer answers | Thread | +| --- | --- | --- | --- | --- | +| 1 | Policy lookup | The participant service's `participant/get/policies`, through the transport; the recipient of every later leg is the policy's `processingid` | synchronous JSON | none, plain REST | +| 2 | Coverage eligibility | `v1/coverageeligibility/check`, purpose `discovery`, `validation` or `benefits` | `on_check` | new per check | +| 3 | Insurance plan (package master) | `v1/insuranceplan/request` | `on_request` | new; one plan per facility and policy | +| 4 | Auth requirements | `v1/coverageeligibility/check`, purpose `auth-requirements`, with items | `on_check` (the PMJAY sandbox rarely answers; `nhcx-package/fhir/C3/C3-response-pmjay.json` is an SHA ruling, `C3/C3-response-generic.json` a generic one) | new per procedure set | +| 5 | Pre-authorisation | `v1/preauth/submit` wf 12 | `on_submit` 20 first, then 21, 23 or 24 | new; the acknowledgement comes first on the same thread | +| 5a | Pre-auth query answer | `v1/preauth/submit` wf 19 (PMJAY) or `v1/communication/on_request` (generic) | 21 or 23 | new (PMJAY) or the request's (generic) | +| 5b | Enhancement | `v1/preauth/submit` wf 13, the whole pre-auth again with the added line | 20 then 22, 231 or 241 (the SHA sandbox has also answered with 21) | new | +| 5c | Enhancement query answer | `v1/preauth/submit` wf 131 | 22 or 231 | new | +| 5d | Cancel | `v1/task/submit` wf PC01 | `task/on_submit` PC02 | new | +| 5e | Predetermination | `v1/preauth/submit`, `Claim.use = predetermination`, wf 12 | `on_submit` | new | +| 6 | Claim | `v1/claim/submit` wf 15, `Claim.use = claim`, under the pre-auth's number | 25 then 26, 27 or 291 | new | +| 6a | Claim query answer | `v1/claim/submit` wf 161 (PMJAY) or `v1/communication/on_request` (generic) | 26 or 291 | new (PMJAY) or the request's (generic) | +| 6b | Reprocess or release | `v1/task/submit` wf 36 | `task/on_submit` 37, then a fresh verdict on the claim's thread | new | +| 7 | Payment notice | the payer sends `v1/paymentnotice/request` wf 30 (31, 33) | you answer `v1/paymentnotice/on_request` wf 17 (PMJAY) or the notice's own id (generic) | the notice's | +| any | Status enquiry | `v1/task/submit`, Task code `status` | `task/on_submit` (generic); PMJAY refuses it | new | +| any | Communication | the payer sends `v1/communication/request` | you answer `v1/communication/on_request` | the request's | + +The payer's acknowledgement is `x-hcx-status: response.partial` and the decision is `response.complete`, on the same correlation id (`nhcx-package/docs/01-Overview/07-Payer Flexibility.md`, "Answer detail"). Read the acknowledgement as "the payer has it", never as a decision. Map `ClaimResponse.outcome` `queued`, or an adjudication reason `submitted`, to leg status `submitting` (`verdict_status`). + +## 2. Every workflow id + +The hospital's table. PMJAY and a generic payer differ in three rows: `claim_query_response`, `claim_resubmit` and `payment_ack`. + +| Kind | PMJAY | Generic | Path | Note | +| --- | --- | --- | --- | --- | +| `preauth` | `12` | `12` | `v1/preauth/submit` | A new pre-auth. Also a fresh request after a rejection: PMJAY refuses 121 there with PAYR-1214. | +| `preauth_resubmit` | `121` | `121` | `v1/preauth/submit` | Kept in the table. `preauth_send_kind` never picks it after a rejection. | +| `preauth_query_response` | `19` | `19` | `v1/preauth/submit` | The answer to a 24. A generic payer asks by communication instead, so this is a PMJAY leg. | +| `enhancement` | `13` | `13` | `v1/preauth/submit` | The whole pre-auth again under the parent's number, plus the added line. | +| `enhancement_resubmit` | `131` | `131` | `v1/preauth/submit` | The answer to a 241. | +| `cancel` | `PC01` | `PC01` | `v1/task/submit` | Task code `cancel`. The handbook's section 8.6 says 122 (`nhcx-package/docs/01-Overview/06-Workflow Codes.md`, "Reconciled Discrepancies and Authority Rules", takes PC01). If a payer insists on 122, override it per payer in configuration. | +| `claim` | `15` | `15` | `v1/claim/submit` | The final bill. | +| `claim_query_response` | `161` | `151` | `v1/claim/submit` | PMJAY refuses 151, 19 and 16 with PAYR-1321; 161 is taken. | +| `claim_resubmit` | none | `16` | `v1/claim/submit` | PMJAY has no claim resubmit. A decided claim goes back only as a reprocess. | +| `payment_ack` | `17` | none (echo the notice's own id) | `v1/paymentnotice/on_request` | `None` in the table means "echo". | +| `reprocess` | `36` | `36` | `v1/task/submit` | Task code `reprocess`; acknowledged on 37. | +| `release` | `36` | `36` | `v1/task/submit` | Task code `release`, reason `partialpayment`, an `amount` input. | +| status enquiry | the leg's correlation id, fallback `13` | same | `v1/task/submit` | The fallback id is `13`. The NHCX sandbox refuses `v1/status` with NHCX-1012. | +| coverage, plan, auth requirements | your case number | your case number | see section 1 | The sheet lists no code. Send the episode's case number. | + +The payer's ids you must branch on (`nhcx-package/workflow.yaml`, `nhcx-package/docs/01-Overview/06-Workflow Codes.md`), with what the sandbox actually sent: + +| Id | Meaning | Status word | +| --- | --- | --- | +| `20` | Pre-auth or enhancement received | `response.partial` | +| `21` | Pre-auth approved | `response.complete` | +| `22` | Enhancement approved. A generic payer sends 22. The SHA sandbox has answered an enhancement with 21, and `nhcx-package/fhir/C5/C5-enhancement-approved-wf22-pmjay.json` is an SHA answer on 22. Accept both. | `response.complete` | +| `23` | Pre-auth rejected | `response.complete` | +| `231` | Enhancement denied | `response.complete` | +| `24` | Pre-auth queried | the sheet says `request.initiated`; the SHA sent `response.complete` | +| `241` | Enhancement queried | as 24 | +| `25` | Claim received | `response.partial` | +| `26` | Claim approved | `response.complete` | +| `27` | Claim queried | as 24 | +| `28`, `29` | Claim in process, forwarded | `response.partial` | +| `291` | Claim rejected | `response.complete` | +| `251`, `252`, `253`, `254` | Reprocess received, approved, rejected, queried | listed; both live payers answer a 36 with 37 instead | +| `37` | Arbitration acknowledged (the reprocess taken) | `response.complete` (the SHA sent `response.partial`) | +| `PC02` | Cancellation done | `response.complete` | +| `30`, `31`, `33` | Payment initiated, processed, settled with UTR | `request.initiated`, new thread | +| `5` | The SHA's coverage eligibility and plan answers | `response.complete` (`nhcx-package/fhir/index.yaml` gives 5 for `C3/C3-response-pmjay.json` and `C4/C4-response-pmjay.json`) | +| `N02` | Notification to a provider (a PMJAY CommunicationRequest) | `request.initiated` | + +Other codes exist (10, 11, 14, 141, 18, 45 to 47, 181, 491, 34, 35, 38, 39, G11 to G13, RP1 to RP3, DC01, DC02, N01, N03, N04, the R-series). A hospital build sends none of them. See `nhcx-package/docs/01-Overview/06-Workflow Codes.md` for the full sheet and the seven codes the handbook and the sheet publish differently. + +## 3. Two kinds of payer + +Read `nhcx-package/docs/01-Overview/07-Payer Flexibility.md` in full. A generic payer is any payer on the exchange, IRDAI-regulated insurers and TPAs included (`nhcx-package/fhir/README.md`). The rule, as coded: + +| | PMJAY (`query_mode: resubmit`) | Generic (`query_mode: communication`) | +| --- | --- | --- | +| The query arrives as | a `ClaimResponse` on the case's own thread, `outcome: partial`, item status `Queried`, wf 24, 241 or 27 | a `CommunicationRequest` TaskBundle on `v1/communication/request`, on a new thread, wf 24, 241 or 27 | +| The answer | the whole bundle again on `v1/preauth/submit` or `v1/claim/submit`, wf 19, 131 or 161, a new correlation id, the reply text on the `NMI`/`CQD` supportingInfo entry | a Communication TaskBundle on `v1/communication/on_request`, the request's correlation id and workflow id echoed | +| A `CommunicationRequest` from this payer | always a notification: acknowledge and leave the case alone | classified (below) | + +Where the payer's case number arrives. The package files are under `nhcx-package/fhir/`; the rule is in `07-Payer Flexibility.md`, "When the case number arrives". + +| Answer | PMJAY | Generic | +| --- | --- | --- | +| 20 on a fresh pre-auth | The package says none, and `C5/C5-received-wf20-pmjay.json` carries none. A live SHA 20 has also carried the path form, `PMJAY/HP/S/2024/R2/`. Handle both. | present (`C5/C5-received-wf20.json`) | +| 20 on an enhancement | none; keep the parent's | present | +| 21, 23, 24 | the bare number (`C5/C5-approved-wf21-pmjay.json`, `C5/C5-rejected-wf23-pmjay.json`, `C5/C5-queried-wf24.json`) | present (`C5/C5-approved-wf21.json`, `C5/C5-rejected-wf23.json`) | +| 25 | the path form (`C7/C7-received-wf25-pmjay.json`) | present (`C7/C7-received-wf25.json`) | +| 26, 27, 291, PC02, 37 | none | none | + +So the brief's rule holds with care. A generic payer's `response.partial` acknowledgement carries the payer's case number. PMJAY's 25 carries it; its 20 may not. Read `ClaimResponse.preAuthRef` on every answer. Keep a value and never overwrite it with an empty one (`apply_preauth`). The bare number is what the payer service desk wants; the path form ends in it. + +`query_mode` lives on the payer adapter. Choose the adapter by the payer's participant code through configuration: `1518@hcx` is PMJAY, and an unmapped code is generic. + +### The classification rule + +`classify_communication(adapter, reason, intent)` applies these, in order: + +1. If the payer's `query_mode` is `resubmit`: notification. +2. Else if `Task.intent` is `proposal`: notification. If `order`: query. +3. Else look at `Task.reasonCode`: absent, `additionalinfo`, `questionnaire` or `query` is a query; anything else (`tatquery`, `grievance`, `walletupdate`, `policychange`, `claimarbitration`) is a notification. Fold `claimArbitartion` into `claimarbitration`. +4. A bare `Communication` with no `CommunicationRequest` is a note: recorded, shown, never acted on. + +Acknowledge a notification at once. Send the payer's own bundle back with `Task.status` flipped to `completed`, the reason echoed and the provider Organization first. File a query open for the desk, and answer it later with the TaskBundle reply (see `fhir-knowledge.md`). The reply names the request in `Communication.basedOn`, never `inResponseTo`. + +The live shapes. A generic payer's query (`nhcx-package/fhir/C6/C6-preauth-query-wf24.json`) carries a Task `poll`, `requested`, `intent order`, reason `additionalinfo`, and a CommunicationRequest with one `contentString` per ask and `basedOn` the Claim. PMJAY's notification (`nhcx-package/fhir/C6/C6-notification-wfN02.json`) carries a Task `poll`, `completed`, `intent proposal`, reason `information` under the HL7 communication-category system. + +## 4. Stage, sub-stage, next actions + +Stamp two words onto the episode after every leg write (`stamp_case`), and compute a next-action list from them. Copy the vocabulary; it is what a desk needs to see. + +Stages: `eligibility`, `preauth`, `enhancement`, `claim`, `payment`. + +Sub-stages: `draft`, `checking`, `eligible`, `not-eligible`, `requested`, `resubmitted`, `answered`, `queried`, `approved`, `partial`, `rejected`, `cancelling`, `cancelled`, `refused`, `noticed`, `paid`. + +How a send kind maps to a sub-stage: `preauth`, `claim`, `enhancement` set `requested`; `*_resubmit` sets `resubmitted`; `*_query_response` and `enhancement_resubmit` set `answered`. `requested`, `answered` and `resubmitted` mean "with the payer". + +Derivation (`case_stage`): a payment notice wins, then the filed claim, then the pre-auth (stage `enhancement` if the last submission kind was an enhancement), then a saved draft, then the eligibility status. An open communication query on a leg that is with the payer flips the sub-stage to `queried`, because a generic payer's query never touches the leg row. + +Next actions (`next_actions`) are `{label, tab, tone}`; the first is what the case waits for. Rules worth copying: + +- An unanswered query always leads with "Answer the payer (n)". +- The leg's own reply box is offered only for a `resubmit` payer. A `communication` payer's desk is sent to the communication tab. +- A claim refused at the door offers "send again" while `claim_send_kind` still yields a kind, else "Ask for a reprocess". +- After a rejection the pre-auth offers a fresh 12, not 121. + +## 5. Rules the exchange enforces that no document states + +Each was found live on the sandbox. + +- Acknowledge or lose the thread. NHCX redelivers an unanswered submission, then drops it and retires the correlation id; a verdict sent later is refused with NHCX-1010. Both live payers answer twice on one correlation: `outcome: queued` first, the decision after. Your reader must not close a thread on the first reply. +- One message is taken once. The SHA redelivers the same `api_call_id` two or three times, about a minute apart, and a transport can fan one delivery out to several receivers (nhcx-adapter's `callback.also`). Dedupe on `x-hcx-api_call_id`. +- One live pre-auth per beneficiary per hospital (PAYR-1238). Clear it with PC01 or a rejection (`nhcx-package/docs/03-Building a Provider/11-PMJAY Sandbox Run.md`, "PAYR-1238 An active preauthorisation exists"). Sweep live pre-auths before a test run. +- One request at a time per case (PAYR-1322, "Active instance found"). Wait about 30 seconds after a decision before the next leg. When a refusal says "Active instance", wait and resend, up to three times. +- One plan per facility and policy. Key it on policy code, provider id and payer. Copy the held master onto a new episode instead of asking again (`reuse_plan`). A PMJAY master runs to tens of megabytes; one fetched live was 56 MB. +- Never drop a document. A file nobody asked for by name goes under `ODN`, "other document". A file attached against a requirement carries that requirement's code (`attach_required_document`). Take the code list from the plan, not from a constant. +- Ask the auth-requirements check, never await it (`ensure_auth_requirements`). Fingerprint the quoted set (`procedure_set`) so an unchanged set is not asked twice. Send the quantity as a whole number. +- Tiers are modifiers, not lines. A ward or ICU tier rides on `Claim.item.modifier` under its procedure, and that item's `net` carries both. +- The claim goes under the pre-auth's number (ERR-PYR-CLM-007), and PMJAY bills the package alone at the whole amount (`11-PMJAY Sandbox Run.md`, "ERR-PYR-CLM-007" and "What the package master decides"). +- Answers to a PMJAY query go on a new correlation id (`07-Payer Flexibility.md`, "On the claim thread"). A same-thread answer is swallowed: no acknowledgement, no refusal, and the desk dies on the old id. +- Cancel retires the number. Give the episode a fresh claim number after an accepted PC01, and keep the withdrawn one on the leg. +- A send refused at the door keeps the case on the thread the payer last answered. An enhancement refused at the door leaves the pre-auth approved. + +## 6. The use-case catalogue + +Codes and titles are quoted from `nhcx-package/usecases.yaml`, rendered as `nhcx-package/docs/01-Overview/05-NHCX Use Cases.md`. "Proves" is what a test run must show for each one. "Package file" is the provider bundle the package holds for it, under `nhcx-package/fhir/`. + +### A: shared + +| Code | Title | What it proves | +| --- | --- | --- | +| A1 | Get participant list | You can find the payer's code in the registry (the participant service's `fetch/participants/list`). | +| A2 | Get policy | You can find a beneficiary's policy and the processor code that becomes `x-hcx-recipient_code` (the participant service's `participant/get/policies`). | +| A3 | Get public key | The transport fetches the recipient's certificate (`fetch/certs`) and caches it. | +| A4 | Get auth token | The transport holds an ABDM session token (the gateway's sessions call) and refreshes it. | +| A5 | Get status | A status Task on `v1/task/submit` gets a Task back (generic), or a PAYR-1018 then PAYR-1008 refusal (PMJAY). The package holds no bundle for A5 (`nhcx-package/fhir/README.md`). | +| A6 | Receive errors | Your callback accepts a `ProtocolResponse` on any path and answers 2xx. | + +### B: hospital on the generic network + +| Code | Title | Workflow | Proves | Package file | +| --- | --- | --- | --- | --- | +| B1 | Check coverage eligibility | none | The check goes out; `inforce` and the wallet come back. | `B1/B1-check.json` | +| B2 | Request insurance plan | none | The package master lands and is stored once per policy. | `B2/B2-request.json` | +| B3 | Submit pre-authorisation | 12, 13 | Sent, acknowledged on 20, decided on 21 or 23; an enhancement on 13 decided on 22. | `B3/B3-request.json`, `B3/B3-enhancement.json` | +| B4 | Respond to a communication | 24, 27 echoed | A CommunicationRequest is classified and the TaskBundle reply goes on the request's thread. | `B4/B4-preauth-query-answer.json`, `B4/B4-claim-query-answer.json` | +| B5 | Submit claim | 15 | The claim under the pre-auth's number, acknowledged 25, decided 26 or 291. | `B5/B5-request.json` | +| B6 | Search claims | none | Not built by these skills. | `B6/claim-search.json` (example) | +| B7 | Acknowledge payment notice | 30 echoed | The notice is filed by claim number, deduped by correlation id, acknowledged on `on_request`. | `B7/B7-acknowledgement.json` | +| B8 | Reprocess or cancel | 36, PC01 | A decided claim is reopened (37 then a new verdict); a live pre-auth is withdrawn (PC02). | `B8/B8-reprocess.json`, `B8/B8-cancel.json` | +| B9 | Submit predetermination | 12 | A quote comes back as a ClaimResponse; nothing else changes. | `B9/predetermination-request.json` (example); the answer is `C11/predetermination-response.json` | + +### C: payer answering (for reference; you build the reader, not the sender) + +C3 coverage answer, C4 plan answer, C5 pre-auth answers (20, 21, 22, 23, 24, 231, 241), C6 communication (24, 241, 27, N02), C7 claim answers (25, 26, 27, 28, 29, 291), C9 payment notice (30, 31, 33), C10 Task answers (PC02, 37, 251 to 254), C11 predetermination. Reader inputs: `nhcx-package/fhir/C3` to `nhcx-package/fhir/C11`. The files ending `-pmjay` are the SHA's own; the rest are the generic payer's. `nhcx-package/fhir/index.yaml` gives each file's scheme, workflow id and origin. The PMJAY captures have the beneficiary's identifiers replaced. + +### D: hospital on PMJAY + +| Code | Title | Workflow | Proves | Package file | +| --- | --- | --- | --- | --- | +| D1 | Fetch the insurance plan | none | The scheme's master, both `coverage[]` and `specificCost[]`, nested document requirements, questionnaires. | `D1/D1-request.json` | +| D2 | Authenticate the beneficiary | not NHCX | Biometric token or the consent questionnaire fallback. | none | +| D3 | Check coverage eligibility | none | The wallet answer on wf 5. | `D3/D3-check.json` | +| D4 | Submit pre-authorisation | 12 | Element ids, HPIN, consent QuestionnaireResponse, documents from the master; acknowledged 20, decided 21 or 23 with `preAuthRef`. | `D4/D4-request.json` | +| D5 | Resubmit pre-authorisation | 121 | Not reachable on the sandbox after a rejection (PAYR-1214); send a fresh 12. | none | +| D6 | Raise an enhancement | 13, 131 | A second package (medical, not conservative: PAYR-1245) under the parent's number; a 241 answered on 131. | `D6/D6-enhancement.json`, `D6/D6-enhancement-query-answer.json` | +| D7 | Answer a pre-authorisation query | 19 | The 24 answered as a fresh submit with `CQD` reply text, new correlation id, then 21. | `D7/D7-query-answer.json` | +| D8 | Cancel pre-authorisation | PC01 | Task `cancel` with `claimNumber` and `intimationNumber`; PC02 back. | `D8/D8-cancel.json` | +| D9 | Submit claim | 15 | Under the pre-auth's number, the package alone, discharge scalars, Discharge Consent answered, PDF documents; 25 then 26. | `D9/D9-request.json` | +| D10 | Answer a claim query | 161 | The 27 answered on 161 with a written reply; the sandbox approves at zero. | `D10/D10-query-answer.json` | +| D11 | Reprocess a rejected claim | 36 | Task `reprocess`, reason `claimrejected`, second input spelled `intimationNumber` on every Task (a reprocess under any other spelling is refused PAYR-1008). The SHA answers 37, "Arbitration claim submission process completed successfully", and reopens the case; a generic payer answers 37 too. | `D11/D11-reprocess.json` | +| D12 | Claim a shortfall | 36 | Task `reprocess` with `partialpayment` after a settled payment. Out of reach on the sandbox: its finance side issues the notice on its own schedule, and the combination is refused before notice 33 is acknowledged (`11-PMJAY Sandbox Run.md`, "What the sandbox will not take"). | none | +| D13 | Acknowledge the payment notice | 17 | Notice 30 filed and acknowledged on `on_request` with 17. | `D13/D13-acknowledgement.json` | + +Discharge variants the D9 claim must cover, each proven on the sandbox: normal after surgery; LAMA and DAMA before, during and after surgery; death before, during and after surgery. Before or during surgery, LAMA and DAMA collapse the claim to one `LM100` line; a death carries `ONS`/`DTM`. `nhcx-package/docs/03-Building a Provider/08-PMJAY Provider.md` states the LAMA and DAMA rule. + +## 7. What each payer sends back, in order + +A pre-authorisation on the SHA sandbox: 20 (`queued`, `response.partial`, `ClaimResponse.type` present only here, as in `nhcx-package/fhir/C5/C5-received-wf20-pmjay.json`), then 24 (query) or 21 or 23. A claim: 25, then 27 or 26 or 291. A cancel: PC02 as a Task `completed`, code `approve`, `output[0]` an `include` reference to a ClaimResponse whose adjudication reason is `cancelled` (`C10/C10-cancelled-wfPC02-pmjay.json`). A reprocess: 37 as a Task `accepted` with a `queued` ClaimResponse (`C10/C10-arbitration-wf37-pmjay.json`), then 26 or 291 on the claim's thread. A payment: 30 on a new thread with a Task `deliver`, a `PaymentNotice` and a `PaymentReconciliation` (`C9/payment-notice.json`). + +A generic payer sends the same ids with the generic differences: 22 for an enhancement, `preAuthRef` on every acknowledgement and every pre-auth decision, queries as CommunicationRequests, `response.complete` on 37. Its files are the ones without `-pmjay` under `nhcx-package/fhir/C5`, `C6`, `C7`, `C9` and `C10`. diff --git a/plugins/nhcx/skills/nhcx-claim/references/material.md b/plugins/nhcx/skills/nhcx-claim/references/material.md new file mode 100644 index 000000000..d8882931d --- /dev/null +++ b/plugins/nhcx/skills/nhcx-claim/references/material.md @@ -0,0 +1,120 @@ +# Material: where the pins, fixtures and docs live + +The stage and module files cite pins, payer fixtures and chapters. All of them come from one source, the NHCX package. This file says how to get it, what it holds, and which package file each citation means. + +## The package + +| Source | Has | Get it | +| --- | --- | --- | +| The NHCX package (`nhcx-package/`) | The docs, every API as a request, the FHIR bundles (the fifteen hospital pins, the payer answers, the live PMJAY captures with identifiers replaced), the field mappings per use case, `workflow.yaml`, `usecases.yaml`, `nhcx-error.yaml`, `baseurl.yaml`, a `MANIFEST` with a sha256 per file | `scripts/fetch-package.sh`, or by hand (below) | +| nhcx-adapter (optional: only when the user asks for it) | The binary, `config.sample.json`, `serve.sh`, `README.md` | The latest release of https://github.com/nha-in/nhcx-adapter, downloaded only when the user chose it (`references/transport-knowledge.md` section 5). Its contract is in `references/api-knowledge.md`. | + +By default `scripts/fetch-package.sh` takes the build attached to the latest GitHub release of `nha-in/nhcx-package`. It checks the download against the sha256 the release records. To use a different build, pass a link or a local path: `scripts/fetch-package.sh `. + +By hand: download the `nhcx-package-v.zip` asset from https://github.com/nha-in/nhcx-package/releases/latest. Unzip it beside `nhcx-build/`. It unpacks to `nhcx-package/`. + +Where the web is off, copy the package in. Do not try to fetch it. + +After unpacking, check it. `nhcx-package/MANIFEST` names the version and lists every file with its size and sha256. Verify at least the pins you will be held to. + +What the package holds: + +| Path | What it is | +| --- | --- | +| `nhcx-package/fhir/B1` to `B9` | Hospital bundles. Lower-case files (`preauth-request.json`) are the pins, written to the specification with placeholders. Capitalised files (`B3-request.json`) are live captures. | +| `nhcx-package/fhir/C3` to `C11` | Payer answers. A generic file and, where one exists, its `-pmjay` twin. | +| `nhcx-package/fhir/D1` to `D13` | Live PMJAY hospital captures, identifiers replaced | +| `nhcx-package/fhir/index.yaml` | The catalogue: for each file its direction, side, scheme (`generic` or `pmjay`), workflow id, focal resource, origin (`wire` or `example`) | +| `nhcx-package/docs/` | The chapters, `01-Overview` to `07-Go Live` | +| `nhcx-package/mappings/.yaml` | Field mappings per bundle; `A1.yaml` is the master dictionary | +| `nhcx-package/apis/` | Every API as a request (a Bruno collection) | +| `nhcx-package/workflow.yaml`, `usecases.yaml`, `nhcx-error.yaml`, `baseurl.yaml` | Workflow ids, use cases, error codes, base URLs | +| `nhcx-package/MANIFEST` | Version, and a size and sha256 per file | + +## The pin map + +Every hospital-side pin, and its file in the package. The fifteen hospital-built pins are the bytes a build is held to (canonical JSON). The last row is a payer's message, the reader's input. + +| Pin | Package | Module | +| --- | --- | --- | +| `coverage/discovery` | `nhcx-package/fhir/B1/discovery.json` | 7.4 | +| `coverage/validation` | `nhcx-package/fhir/B1/validation.json` | 7.4 | +| `coverage/benefits` | `nhcx-package/fhir/B1/benefits.json` | 7.4 | +| `coverage/authrequirements` | `nhcx-package/fhir/B1/auth-requirements.json` | 7.6 | +| `insurance` | `nhcx-package/fhir/B2/insurance-plan-request.json` | 7.5 | +| `preauth/request` | `nhcx-package/fhir/B3/preauth-request.json` | 7.7 | +| `preauth/enhancement` | `nhcx-package/fhir/B3/preauth-enhancement.json` | 7.7 | +| `preauth/queryupdate` | `nhcx-package/fhir/B3/preauth-queryupdate.json` | 7.7 | +| `preauth/cancel` | `nhcx-package/fhir/B3/preauth-cancel.json` | 7.9 | +| `claim/request` | `nhcx-package/fhir/B5/claim-request.json` | 7.7 | +| `claim/queryupdate` | `nhcx-package/fhir/B5/claim-queryupdate.json` | 7.7 | +| `claim/reprocess` | `nhcx-package/fhir/B5/claim-reprocess.json` | 7.9 | +| `claim/release` | `nhcx-package/fhir/B5/claim-release.json` | 7.9 | +| `communication/response` | `nhcx-package/fhir/B4/communication-response.json` | 7.10 | +| `payment/notice-ack` | `nhcx-package/fhir/B7/payment-notice-ack.json` | 7.10 | +| `communication/request` (a payer's message, the reader's input) | `nhcx-package/fhir/B4/communication-request.json`. It is the NRCeS IG's own example, with the Patient's name, identifier, birth date and phone replaced. | 7.10 | + +## The payer fixtures + +What the readers are fed. `generic` is what any payer on the exchange sends, IRDAI-regulated insurers and TPAs included. `pmjay` is the SHA's own message, a live capture with the beneficiary's identifiers replaced. Some identifiers are absent from the PMJAY files: `C5-received-wf20-pmjay.json` carries no `preAuthRef`. Read a value from the file before you assert it. Paths are under `nhcx-package/fhir/`. + +| Answer | Generic | PMJAY | Reader | +| --- | --- | --- | --- | +| Coverage, validation | `C3/validation-response.json` | `C3/coverage-eligibility.json` | 7.4 | +| Coverage, discovery | `C3/discovery-response.json` | none | 7.4 | +| Coverage, benefits | `C3/benefits-response.json` | `C3/C3-benefits-pmjay.json` | 7.4 | +| Coverage, auth-requirements | `C3/C3-response-generic.json` | `C3/C3-response-pmjay.json` (workflow 5) | 7.6 | +| Insurance plan | `C4/C4-response-generic.json` (coverage-based) | `C4/C4-response-pmjay.json` (package-based) | 7.5 | +| Pre-auth received 20 | `C5/C5-received-wf20.json` | `C5/C5-received-wf20-pmjay.json` | 7.8 | +| Pre-auth approved 21 | `C5/C5-approved-wf21.json` | `C5/C5-approved-wf21-pmjay.json` | 7.8 | +| Enhancement approved 22 | `C5/C5-enhancement-approved-wf22.json` | `C5/C5-enhancement-approved-wf22-pmjay.json` | 7.8 | +| Pre-auth rejected 23 | `C5/C5-rejected-wf23.json` | `C5/C5-rejected-wf23-pmjay.json` | 7.8 | +| Pre-auth queried 24 | `C5/preauth-queried.json` | `C5/C5-queried-wf24.json` | 7.8 | +| Claim received 25 | `C7/C7-received-wf25.json` | `C7/C7-received-wf25-pmjay.json` | 7.8 | +| Claim approved 26 | `C7/C7-approved-wf26.json` | `C7/C7-approved-wf26-pmjay.json`, `C7/C7-approved-deduction-wf26-pmjay.json` | 7.8 | +| Claim queried 27 | `C7/claim-queried.json` | `C7/C7-queried-wf27.json` | 7.8 | +| Claim rejected 291 | `C7/C7-rejected-wf291.json` | `C7/C7-rejected-wf291-pmjay.json` | 7.8 | +| Cancellation done PC02 | `C10/C10-cancelled-wfPC02.json` | `C10/C10-cancelled-wfPC02-pmjay.json` | 7.9 | +| Arbitration acknowledged 37 | `C10/C10-arbitration-wf37.json` | `C10/C10-arbitration-wf37-pmjay.json` | 7.9 | +| Query on the communication API, 24 and 27 | `C6/C6-preauth-query-wf24.json`, `C6/C6-claim-query-wf27.json` | none | 7.10 | +| Notification N02 | none | `C6/C6-notification-wfN02.json` | 7.10 | +| The query the reply answers | `B4/communication-request.json` (the IG's example) | none | 7.10 | +| Payment notice 30 | `C9/C9-notice-wf30.json` | `C9/payment-notice.json`, `C9/C9-notice-tds-wf30-pmjay.json` | 7.10 | +| Predetermination | `B9/predetermination-request.json` (the request), `C11/predetermination-response.json` | none | 7.7, 7.8 | + +`nhcx-package/fhir/index.yaml` catalogues every file: direction, side, scheme, workflow id, focal resource, origin (`wire` or `example`). An `example` file is placeholders written to the specification, not a payload. + +## The live hospital captures + +What a hospital actually sent, as the payer accepted it. The module files quote these shapes. Paths are under `nhcx-package/fhir/`. + +| Scheme | Files | +| --- | --- | +| PMJAY | `D1/D1-request.json` (plan), `D3/D3-check.json` (auth-requirements), `D4/D4-request.json` (pre-auth 12), `D6/D6-enhancement.json` (13), `D6/D6-enhancement-query-answer.json` (131), `D7/D7-query-answer.json` (19), `D8/D8-cancel.json` (PC01), `D9/D9-request.json` (claim 15), `D10/D10-query-answer.json` (161), `D11/D11-reprocess.json` (36), `D13/D13-acknowledgement.json` (17) | +| Generic | `B1/B1-check.json`, `B2/B2-request.json`, `B3/B3-request.json`, `B3/B3-enhancement.json`, `B4/B4-preauth-query-answer.json`, `B4/B4-claim-query-answer.json`, `B5/B5-request.json`, `B7/B7-acknowledgement.json`, `B8/B8-cancel.json`, `B8/B8-reprocess.json` | + +## The docs and the data files + +| Cited | Package | +| --- | --- | +| a chapter | `nhcx-package/docs/`, from `01-Overview` to `07-Go Live` | +| workflow ids (`references/flow-knowledge.md` section 2) | `nhcx-package/workflow.yaml`, the maintained source; rendered as `nhcx-package/docs/01-Overview/06-Workflow Codes.md` | +| use cases (`flow-knowledge.md` section 6) | `nhcx-package/usecases.yaml`; rendered as `nhcx-package/docs/01-Overview/05-NHCX Use Cases.md` | +| PAYR and ERR codes (`references/errors-and-debugging.md`) | `nhcx-package/nhcx-error.yaml` | +| field mappings per bundle (stage 4) | `nhcx-package/mappings/.yaml`; `A1.yaml` is the master dictionary | +| base URLs, sandbox and production | `nhcx-package/baseurl.yaml` | +| every API as a request | `nhcx-package/apis/` (a Bruno collection) | +| the bundle catalogue | `nhcx-package/fhir/index.yaml` | + +## What the package does not hold + +| Missing | Without it | +| --- | --- | +| A status-enquiry answer | None captured. The published status call carries no bundle either way (`nhcx-package/docs/05-FHIR Reference/18-Predetermination, Status and Search.md`). | +| A validator wrapper | Run the HL7 FHIR validator directly, as `references/fhir-knowledge.md` section 11 describes | +| Reference application source | The decisions are written into the module files and the references. Build from them. Record in `NOTES.md` where you would have wanted more. | +| End-to-end drivers and checkers | Write the stage 10 driver against your own build's state address | + +## Which is newer + +Where the references and the package disagree, the package is newer for the published facts (workflow ids, error text, base URLs). The references are newer for what was seen live (which ids a payer actually sent, which refusals mean what). Say which you followed in `NOTES.md`. diff --git a/plugins/nhcx/skills/nhcx-claim/references/testing-knowledge.md b/plugins/nhcx/skills/nhcx-claim/references/testing-knowledge.md new file mode 100644 index 000000000..4a24d7946 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-claim/references/testing-knowledge.md @@ -0,0 +1,405 @@ +# Testing knowledge + +Sources: the NHCX package, fetched by `scripts/fetch-package.sh` into `nhcx-package/` beside `nhcx-build/`. That means the pins and payer fixtures under `nhcx-package/fhir` (catalogued in `nhcx-package/fhir/index.yaml`), the use-case catalogue `nhcx-package/usecases.yaml`, and the chapters named below. Also what live runs on the NHCX sandbox taught. + +## 1. The pyramid + +| Rung | What it proves | Needs | How | +| --- | --- | --- | --- | +| 1. Offline | Every builder equals its pin (`created` excepted); every reader settles the right state from a payer fixture; the state machine refuses what it should | nothing running; a throwaway database; the transport's send stubbed; `nhcx-package/` | one suite in one process (sections 2 to 4) | +| 2. Validator | Every built bundle validates against the NRCeS profiles with no error you cannot explain | Java, the HL7 FHIR validator, the bundles your tests wrote | section 5 | +| 3. A generic payer on the sandbox | Every leg over the real exchange with a payer whose desk you can drive; queries as CommunicationRequests; payment released | the transport on the sandbox (your app's own, or nhcx-adapter when the user chose it), a generic payer you can drive, the sandbox reaching your callback | section 6 | +| 4. Live PMJAY sandbox | `1518@hcx`: the scheme's own refusals and rules, decisions taken on the payer service desk | the sandbox, a real beneficiary, patience | section 6 | + +Climb in order. Rungs 1 and 2 need no service and no consent. Rungs 3 and 4 put traffic on the live NHCX sandbox, and only the user starts them. + +## 2. Writing rung 1 for a new HMIS + +Build one suite with this shape, whatever the language: + +- One process, one seeded database under a temporary path, sections in the order the episode runs. `section(name)` starts a group; `check(label, condition, detail)` records one assertion and never raises. The run exits non-zero at the end if anything failed. +- The transport's `send` is one function, and the test replaces it. Every send goes through it; the test assigns a stub that records the path, recipient, workflow id, correlation id and bundle, and returns `{"txn_id": ..., "correlation_id": ..., "api_call_id": ...}`. Restore the real one in `finally`. The receiving end is tested apart from the door: for your own transport, seal a payer bundle with a test key pair, POST it, and check the 202 receipt and the envelope the door receives. +- Call the callback handler directly with an envelope, not over HTTP: `receive({"jwe_headers": {...}, "fhir": bundle}, "", "", "fhir")`. The return value is one of `settled`, `unmatched`, `ignored`. Feed it the payer bundles under `nhcx-package/fhir/C3` to `nhcx-package/fhir/C11`, both the generic files and the `-pmjay` ones. The auth-requirements rulings are `C3/C3-response-generic.json` (one line, 10 supporting entries) and `C3/C3-response-pmjay.json` (two lines, 22 entries). +- The pin comparison builds each bundle from the pin's own data and compares canonical JSON (`json.dumps(bundle, sort_keys=True)`) against the pin. The data is all in `nhcx-package/fhir/B3/preauth-request.json`: member `MD5SLS4X5`, policy `PMJAY/HP/S/G`, provider `IN1910000151`, payer `1518@hcx`, package `MG0111A` with tier `STRAT006b`, the four `MAND` documents. Drop from both sides only `created`. The bundle id and every entry's `fullUrl` are fixed strings in the pins (`preauth-request-generic`, `https://nhcx.abdm.gov.in/preauth/request`), and the build produces them as they are. +- The single-item pins carry `factor 0.5`. That contradicts the rule their own enhancement follows (`nhcx-package/fhir/B3/preauth-enhancement.json`: the costlier line 1, the next 0.5), so compare those with `factor` removed. Compare the cancel and reprocess pins as they are; they carry `intimationNumber`, the spelling the build sends. +- Read every expected value in a reader check from the fixture you feed: `preAuthRef`, amounts, claim numbers, the UTR. The PMJAY captures have the beneficiary's identifiers replaced, and some fields are absent (`C5/C5-received-wf20-pmjay.json` carries no `preAuthRef`). A typed literal tests your memory, not the reader. +- Negative checks are half the value. A code the plan does not carry is refused. A send while the leg is with the payer is refused. A redelivered api call id is ignored. A claim refused at the door goes back to `queried` with the question restored. A cancel while the payer holds the case is accepted, and a cancel of a rejected one is refused. +- Put the regression sections near the bottom. Each is a defect that reached working code, named after what went wrong. Add one each time the sandbox teaches you something. + +In a language whose JSON encoder does not sort keys, decode into a map and encode again before comparing, so key order cannot fail a check. Where a byte comparison is too strict, as with the wire captures, compare element by element. + +## 3. The test-case matrix + +One row per hospital-side use case. Preconditions are the state the HMIS must be in. The action is what the desk or the test does. The expected wire is what must go out and come back; the per-case archive shows it (and the adapter's ledger, when it is the transport). The expected state is what the HMIS must hold afterwards. Codes are those of `nhcx-package/usecases.yaml`. Workflow ids are the PMJAY table unless the row says generic. + +| Use case | Preconditions | Action | Expected wire | Expected state | +| --- | --- | --- | --- | --- | +| A5 Get status (generic) | A pre-auth or claim leg with the payer; a generic payer | Ask status for the leg | `v1/task/submit`, Task `status` with `claimNumber`, workflow = the leg's correlation id; a Task back with `claimStatus` | An enquiry row `answered` with the status word; the leg unchanged | +| A5 Get status (PMJAY) | as above; PMJAY | Ask status | the same Task; a ProtocolResponse PAYR-1018 (no reason) or PAYR-1008 (with one) | The enquiry row `error` with the payer's words; nothing else changes | +| B1 Check coverage eligibility | A patient with a member id and policy from the policy search; facility HFR id and participant code set | Validate, then discover | `v1/coverageeligibility/check` twice, new correlation each, workflow = the case number; `on_check` with the request echoed and a `CoverageEligibilityResponse` | `claim.status eligible`, `inforce 1`, allowed and used amounts, the payer's Patient demographics | +| B2 Request insurance plan | Eligible; no master held for this facility and policy | Fetch the plan | `v1/insuranceplan/request`, a Task `poll` with `policyNumber` and `providerId`; `on_request` with the InsurancePlan and Questionnaires | `claim_plan.status ready`, benefits with rates, tiers, requirements, forms by url; a second episode on the same policy copies it without a send | +| B3 Submit pre-authorisation | Plan ready; lines quoted from it; dossier saved; admission linked; documents and forms for the pre-auth stage attached | Submit | `v1/coverageeligibility/check` purpose `auth-requirements` first (sent, not awaited), then `v1/preauth/submit` workflow 12 equal to the pin but for identifiers; `on_submit` 20 (`queued`, `response.partial`) then 21 | `claim_preauth.status submitting` after the 20 with `preauth_ref` kept, `approved` after the 21 with `approved_amount`; stage `preauth`, sub-stage `approved` | +| B3 Auth-requirements ruling | The check sent with the pre-auth; the payer answers it | Nothing; read on arrival | inbound `on_check`, a CoverageEligibilityResponse with purpose `auth-requirements`, one `insurance[0].item` per quoted line with `authorizationRequired`, `excluded` and `authorizationSupporting[]` (`C3/C3-response-generic.json`, `C3/C3-response-pmjay.json`) | each quoted line holds its ruling and what is due at pre-auth (a form always, a document only when its `Type` is `pre`); the pre-auth leg unchanged | +| B3 Enhancement | Approved; a line added since (`enhancement_lines` non-empty) | Submit again | `v1/preauth/submit` workflow 13, every line old and new, factors 1 and 0.5; 20 then 22 (generic); the SHA has answered 21 or 22 | `submission_kind enhancement`, `enhancement_no 1`, `preauth_ref` kept, then `approved`; stage `enhancement` | +| B4 Respond to a communication (generic) | A pre-auth or claim with the payer; the payer sends a CommunicationRequest on a new thread | The desk replies with text and a document | inbound `v1/communication/request` with Task `poll`, reason `additionalinfo`; outbound `v1/communication/on_request` with the request's correlation id and workflow id, a TaskBundle: Task `deliver`, Communication `basedOn` the request, the request echoed, the case entries | `claim_query` row `kind query`, `status open` then `answered` with `reply_json`; the leg row untouched; sub-stage `queried` while open | +| B4 Notification | Any leg; the payer sends a CommunicationRequest with intent `proposal` or reason `tatquery` | Nothing; it is acknowledged on arrival | outbound `v1/communication/on_request` at once, the payer's bundle with `Task.status completed`, provider Organization first | `claim_query` row `kind notification`, `status acknowledged`; the case's stage unchanged | +| B5 Submit claim | Approved pre-auth; discharge recorded with mode and stage; claim-stage documents and forms attached | Submit the claim | `v1/claim/submit` workflow 15, `use claim`, `preAuthRef`, the discharge scalars, the summary; 25 (`queued`) then 26 | `claim_submission.status submitting` then `approved` with amounts and item verdicts; stage `claim` | +| B7 Acknowledge payment notice (generic) | An approved claim; the payer's desk releases payment | Nothing; acknowledged on arrival | inbound `v1/paymentnotice/request` workflow 30 on a new thread; outbound `v1/paymentnotice/on_request` with the notice's correlation id and its own workflow id echoed, Task `status completed` with `paymentack` | `claim_payment` row with amount, UTR, `ack_status sent`; stage `payment`, sub-stage `paid`; a redelivery of the notice is `ignored` | +| B8 Cancel | A pre-auth `submitting`, `approved`, `partial` or `queried` | Cancel with a reason | `v1/task/submit` workflow PC01, Task `cancel`, inputs `claimNumber` and `intimationNumber`; `task/on_submit` PC02 with a ClaimResponse adjudicated `cancelled` | `claim_preauth.status cancelling` then `cancelled`; the episode gets a fresh claim number, the old one stays on `claim_ref`; a cancel of a `rejected` pre-auth is refused before sending | +| B8 Reprocess (generic) | A claim `rejected` or `partial` | Reprocess with reason `claimrejected` and a document | `v1/task/submit` workflow 36, Task `reprocess`, `intimationNumber`, `basedOn` CLN, `document` inputs, `for` the member; 37 (Task `accepted`, ClaimResponse `queued`); then 26 on the claim's thread | The enquiry row `answered` with `reopened`; `claim_submission` back to `submitting`, then `approved` | +| B9 Submit predetermination | Eligible; dossier saved | Ask for a quote | `v1/preauth/submit` workflow 12 with `use predetermination`; a ClaimResponse back | A `claim_predetermination` row `answered` with `allowed_amount`; the pre-auth row untouched | +| D1 Fetch the insurance plan | Eligible on PMJAY | Fetch | as B2; the answer on workflow 5, both `specificCost[]` and `coverage[]`, nested document requirements, `/questionnaire/` and `/stgquestionnaire/` forms | as B2, with `ProcedureType` conditions and the consent forms among the policy documents | +| D2 Authenticate the beneficiary | A policy from the BIS | Not NHCX; take the consent questionnaire path | none | The consent form answered for the pre-auth stage | +| D3 Check coverage eligibility | as B1 with member `MD5SLS4X5` style ids | Validate | as B1; the answer on workflow 5 with the wallet | as B1 | +| D4 Submit pre-authorisation | as B3, plus: HPIN on the doctor, `Item/n` ids, consent and STG forms answered, documents under the plan's `MAND` codes | Submit | `v1/preauth/submit` workflow 12; 20 with the path-form `preAuthRef` or none (flow-knowledge.md section 3), then 21 with the bare number | as B3; `preauth_ref` = the bare case number after the 21 | +| D5 Resubmit pre-authorisation | A pre-auth `rejected` | Submit again | a fresh 12, never 121 | a new `submitting` round; 121 would be PAYR-1214 | +| D6 Raise an enhancement | Approved; a medical package added (not conservative) | Submit | workflow 13; 20 without `preAuthRef` (keep the parent's); 241 arrives as a ClaimResponse `partial` on the case thread; the desk answers on 131 with a `CQD` reply; then approved | `enhancement_no 1`; `queried` then `answered` then `approved`; a second conservative package would be PAYR-1245 | +| D7 Answer a pre-authorisation query | The 24 arrived as a ClaimResponse `partial`, item status `Queried` | The desk writes a reply and submits again | `v1/preauth/submit` workflow 19, flow `queryupdate`, `NMI`/`CQD` carrying the words, a new correlation id; 20 then 21 | `submission_kind preauth_query_response`, `query_note` holding the payer's question, then `approved`; an empty reply is refused before sending | +| D8 Cancel pre-authorisation | as B8 on PMJAY | Cancel | as B8 | as B8 | +| D9 Submit claim | as B5, plus: the claim under the pre-auth's claim number, the package alone at the whole amount, Discharge Consent answered, PDF documents | Submit | `v1/claim/submit` workflow 15; 25 with `preAuthRef` as a path; then 26 | as B5; item verdicts with `eligible`, `status Approved` | +| D9 LAMA or DAMA before or during surgery | Discharge mode `lama` or `dama`, stage `Before Surgery` or `During Surgery` | Submit the claim | one item `LM100`, no tier, `DIS` = `LAMA` or `DAMA` with the stage | approved; the package would be PAYR-1362 | +| D9 Death | Discharge mode `death` with a date and time | Submit the claim | `ONS`/`DTM` and `DSDE` with the death instant, `DIS`/`DTM`, the death forms | approved; without `DTM` PAYR-1096 | +| D10 Answer a claim query | The 27 arrived as a ClaimResponse `partial` | The desk writes a reply and submits again | `v1/claim/submit` workflow 161, `NMI`/`CQD`, a new correlation id; 25 then 26 | `submission_kind claim_query_response`, then `approved`, possibly at zero | +| D11 Reprocess a rejected claim | A claim `rejected` | Reprocess | as B8 reprocess; on the sandbox a ProtocolResponse PAYR-1008 | the enquiry row `error` with the refusal; on a generic payer as B8 | +| D12 Claim a shortfall | A settled payment short of the approved amount | Release with `partialpayment` and the amount | `v1/task/submit` workflow 36, Task `release`, `valueMoney` | an enquiry row; out of reach on the sandbox | +| D13 Acknowledge the payment notice | An approved claim; the SHA's finance side sends 30 | Nothing; acknowledged on arrival | outbound `v1/paymentnotice/on_request` with workflow 17, the notice's correlation id, to the notice's sender | as B7 | + +Cross-cutting rows every matrix needs: + +| Case | Action | Expected | +| --- | --- | --- | +| Redelivery | Deliver the same envelope twice | the second returns `ignored`; state unchanged | +| Unmatched | Deliver an answer on an unknown correlation id | `unmatched`; archived under `unmatched`; nothing changes | +| Refusal at the door | Deliver a ProtocolResponse on a leg's thread | the leg `error` (or `queried` restored for a query answer, `approved` restored for an enhancement) with the payer's words; `correlation_id` restored to `thread_correlation_id` | +| Ledger reset (nhcx-adapter only) | The adapter answers 404 on `txn/related` | the leg `error` with "send again"; no spinning | +| Stage after every write | Any of the above | `stage` and `sub_stage` on the episode agree with `case_stage` recomputed from the legs | + +## 4. A skeleton offline test + +Replace the placeholders marked `` with your HMIS's own. Every pin and payer answer is loaded from the package. + +```python +#!/usr/bin/env python3 +"""Offline NHCX checks for : builders against the package pins, readers against the payer fixtures. + + NHCX_PACKAGE=nhcx-package python3 nhcx_offline_test.py # exit 0 when every check passes +""" +from __future__ import annotations + +import copy +import json +import os +import tempfile + +PKG = os.environ.get("NHCX_PACKAGE", "nhcx-package") +GENERIC_PAYER = "" + +os.environ[""] = os.path.join(tempfile.mkdtemp(prefix="nhcx-test-"), "t.db") + +import as nhcx # noqa: E402 the module that owns transport, build_*, receive + +failures = 0 +current = "general" +tally: dict[str, list[int]] = {} + + +def section(name: str) -> None: + global current + current = name + tally.setdefault(name, [0, 0]) + print(f"\n-- {name} " + "-" * max(3, 60 - len(name))) + + +def check(label: str, condition: bool, detail: str = "") -> None: + global failures + tally.setdefault(current, [0, 0]) + tally[current][0 if condition else 1] += 1 + if not condition: + failures += 1 + print(f"[{' ok ' if condition else ' FAIL '}] {label}" + (f" ({detail})" if detail else "")) + + +def pin(rel: str) -> dict: + """A bundle from the package by its path under fhir/, e.g. pin("B3/preauth-request.json").""" + with open(os.path.join(PKG, "fhir", rel), encoding="utf-8") as fh: + return json.load(fh) + + +def resource(bundle: dict, kind: str) -> dict: + return next(e["resource"] for e in bundle["entry"] if e["resource"]["resourceType"] == kind) + + +def task_input(task: dict, code: str): + return next(i.get("valueString") for i in task.get("input", []) if i["type"]["coding"][0]["code"] == code) + + +def total(claim_response: dict, category: str): + return next((t["amount"].get("value") for t in claim_response.get("total", []) + if t["category"]["coding"][0]["code"] == category), None) + + +def normalised(bundle: dict, factor: bool = True) -> dict: + """Drop only `created`, which a builder stamps when it sends; with factor=False, the Claim items' factor too.""" + out = copy.deepcopy(bundle) + + def walk(node): + if isinstance(node, dict): + node.pop("created", None) + for value in node.values(): + walk(value) + elif isinstance(node, list): + for value in node: + walk(value) + + walk(out) + if not factor: + for entry in out["entry"]: + if entry["resource"]["resourceType"] == "Claim": + for item in entry["resource"].get("item", []): + item.pop("factor", None) + return out + + +def canonical(bundle: dict, factor: bool = True) -> str: + return json.dumps(normalised(bundle, factor), sort_keys=True, ensure_ascii=False) + + +def same(label: str, ours: dict, want: dict, factor: bool = True) -> None: + a, b = canonical(ours, factor), canonical(want, factor) + check(label, a == b, "" if a == b else a[:300]) + + +# The package pins' own data: nhcx-package/fhir/B3/preauth-request.json and B1/*.json. +# Every builder is fed this and must produce the pin. +REF = { + "claim_no": "VB26AA2600001", "member_id": "MD5SLS4X5", "policy": "PMJAY/HP/S/G", + "provider": {"id": "IN1910000151", "name": "Facility Name"}, + "payer": {"code": "1518@hcx", "id": "1518", "name": "Insurance Company"}, + "patient": {"name": "Patient Name", "gender": "male", "dob": "2004-09-18", + "phone": "9999999999", "abha": "91718280654077", "member_id": "MD5SLS4X5"}, + "practitioner": {"name": "Practitioner Name", "hpr_id": "982374978-2343", "license_no": "MCI-12345", + "qualification": "Doctor of Medicine", "qualification_code": "MD", + "specialty": "General medicine", "specialty_code": "394802001"}, + "diagnosis": {"code": "A97", "display": "Dengue"}, + "item": {"code": "MG0111A", "display": "Pleural Effusion", "category_code": "MG", + "category_display": "General Medicine", "quantity": 1, "unit_price": 3300, "net": 3300, + "kind": "Procedure", "procedure_type": "conservative"}, + "tier": {"code": "STRAT006b", "display": "HDU", "kind": "Stratification", "parent_code": "MG0111A"}, + # The benefits and auth-requirements pins quote a different package. + "coverage_item": {"code": "MG004C", "display": "Dengue shock syndrome (Dengue fever)", + "category_code": "MG", "category_display": "General Medicine", "quantity": 1, + "tier": {"code": "STRAT006c", "display": "ICU - Without Ventilator"}}, +} + + +def main() -> int: + section("coverage eligibility: ours is the pin") + for purpose, rel in (("discovery", "B1/discovery.json"), ("validation", "B1/validation.json"), + ("benefits", "B1/benefits.json"), ("auth-requirements", "B1/auth-requirements.json")): + want = pin(rel) + ours = nhcx.build_coverage_request((purpose, want)) + same(f"coverage {purpose}", ours, want) + + section("insurance plan request: ours is the pin") + same("plan request", nhcx.build_plan_request(REF["policy"], REF["provider"]["id"]), + pin("B2/insurance-plan-request.json")) + + section("claim bundles: ours is the pin") + ref_pa = pin("B3/preauth-request.json") + ref_pdf = next(si["valueAttachment"]["data"] for si in resource(ref_pa, "Claim")["supportingInfo"] + if "valueAttachment" in si) + dossier = (REF, ref_pdf, ref_pa) + same("preauth request", nhcx.build_preauth_bundle(dossier, flow="request"), ref_pa, factor=False) + ref_qu = pin("B3/preauth-queryupdate.json") + reply = next(si["valueString"] for si in resource(ref_qu, "Claim")["supportingInfo"] + if si["category"]["coding"][0]["code"] == "NMI") + same("preauth query update", + nhcx.build_preauth_bundle(dossier, flow="queryupdate", query_response=reply), + ref_qu, factor=False) + ref_cancel = pin("B3/preauth-cancel.json") + cancel = resource(ref_cancel, "Task") + reason = cancel["reasonCode"]["coding"][0] + same("preauth cancel", + nhcx.build_cancel_task(task_input(cancel, "claimNumber"), (reason["code"], reason["display"]), + cancel["authoredOn"], REF["provider"], REF["payer"]), + ref_cancel) + ref_ack = pin("B7/payment-notice-ack.json") + ack = resource(ref_ack, "Task") + acked_claim = next(o["valueString"] for o in ack["output"] if "valueString" in o) + same("payment acknowledgement", + nhcx.build_payment_ack(acked_claim, ack["authoredOn"], REF["provider"], REF["payer"]), + ref_ack) + + section("the transport is the one door, and it can be stubbed") + posted: list[dict] = [] + real_send = nhcx.transport.send + + def submitted(payer: str, corr: str): + def _send(path, bundle, recipient, workflow_id, correlation_id=None, **kw): + posted.append({"path": path, "recipient": recipient, "workflow_id": workflow_id, + "correlation_id": correlation_id, "bundle": bundle}) + return {"txn_id": "01TEST", "correlation_id": corr, "api_call_id": "acid-" + corr} + + seeded = (payer) # eligible, plan ready, lines quoted, dossier saved + nhcx.transport.send = _send + try: + nhcx.submit_preauth(seeded) + finally: + nhcx.transport.send = real_send + return seeded + + episode = submitted(REF["payer"]["code"], "corr-preauth-1") + sent = posted[-1] + leg = nhcx.preauth(episode) + check("the pre-auth goes out on the preauth route under workflow 12", + sent["path"] == "v1/preauth/submit" and str(sent["workflow_id"]) == "12") + check("no correlation id is passed on a request", sent["correlation_id"] is None) + check("the leg waits with the transport's ids", + leg["status"] == "submitting" and leg["txn_id"] == "01TEST" and leg["correlation_id"] == "corr-preauth-1") + + section("readers: the payer answers settle the right state") + + def deliver(bundle: dict, acid: str, workflow: str, status: str = "response.complete", + corr: str = "corr-preauth-1", sender: str = "1518@hcx") -> str: + return nhcx.receive({"jwe_headers": {"x-hcx-correlation_id": corr, + "x-hcx-api_call_id": acid, + "x-hcx-sender_code": sender, + "x-hcx-status": status, "x-hcx-workflow_id": workflow}, + "fhir": bundle}, "preauth", "request", "fhir") + + received = pin("C5/C5-received-wf20-pmjay.json") + before = nhcx.preauth(episode)["preauth_ref"] + check("the PMJAY acknowledgement leaves the leg waiting", + deliver(received, "acid-20", "20", "response.partial") == "settled" + and nhcx.preauth(episode)["status"] == "submitting") + check("an acknowledgement without preAuthRef overwrites nothing", + not resource(received, "ClaimResponse").get("preAuthRef") + and nhcx.preauth(episode)["preauth_ref"] == before) + check("the same api call id delivered again is ignored", + deliver(received, "acid-20", "20", "response.partial") == "ignored") + approval = pin("C5/C5-approved-wf21-pmjay.json") + approved = resource(approval, "ClaimResponse") + check("the approval settles the leg on the same thread with the payer's case number", + deliver(approval, "acid-21", "21") == "settled" + and nhcx.preauth(episode)["status"] == "approved" + and nhcx.preauth(episode)["approved_amount"] == total(approved, "benefit") + and nhcx.preauth(episode)["preauth_ref"] == approved["preAuthRef"]) + stage, sub_stage = nhcx.case_stage(episode) + check("the episode is stamped preauth / approved", (stage, sub_stage) == ("preauth", "approved")) + + other = submitted(GENERIC_PAYER, "corr-preauth-2") + generic = pin("C5/C5-received-wf20.json") + check("a generic payer's acknowledgement carries the case number, and it is kept", + deliver(generic, "acid-20g", "20", "response.partial", corr="corr-preauth-2", + sender=GENERIC_PAYER) == "settled" + and nhcx.preauth(other)["status"] == "submitting" + and nhcx.preauth(other)["preauth_ref"] == resource(generic, "ClaimResponse")["preAuthRef"]) + + section("auth requirements: the payer's ruling is read line by line") + for rel in ("C3/C3-response-generic.json", "C3/C3-response-pmjay.json"): + ruling = pin(rel) + answer = [e["resource"] for e in ruling["entry"] + if e["resource"]["resourceType"] == "CoverageEligibilityResponse"][-1] + want = {i["productOrService"]["coding"][0]["code"]: i.get("authorizationRequired") + for i in answer["insurance"][0]["item"]} + got = nhcx.parse_auth_bundle(ruling) # {procedure code: {"required": bool, "supporting": [...]}} + check(f"{rel}: one ruling per quoted line, required as the payer says", + {code: line["required"] for code, line in got.items()} == want) + + section("the query loop") + queried = pin("C5/C5-queried-wf24.json") + check("a PMJAY query is the leg queried, with the payer's words and case number kept", + deliver(queried, "acid-24", "24") == "settled" + and nhcx.preauth(episode)["status"] == "queried" + and bool(nhcx.preauth(episode)["query_note"]) + and nhcx.preauth(episode)["preauth_ref"] == resource(queried, "ClaimResponse")["preAuthRef"]) + try: + nhcx.submit_preauth(episode, reply="") + check("an empty reply is refused before sending", False) + except ValueError: + check("an empty reply is refused before sending", True) + check("a generic payer's CommunicationRequest is classified a query", + nhcx.classify_communication(nhcx.GENERIC_ADAPTER, "additionalinfo", "order") == "query" + and nhcx.classify_communication(nhcx.PMJAY_ADAPTER, "additionalinfo", "order") == "notification" + and nhcx.classify_communication(nhcx.GENERIC_ADAPTER, "tatquery", None) == "notification") + + section("refusal at the door") + refusal = {"type": "ProtocolResponse", "x-hcx-status": "response.error", + "x-hcx-correlation_id": "corr-preauth-1", + "x-hcx-error_details": {"code": "PAYR-1238", "message": "Beneficiary is having an active preauthorization request"}} + (episode) + check("a ProtocolResponse settles the leg as refused with the payer's words", + nhcx.receive({"jwe_headers": {"x-hcx-correlation_id": "corr-preauth-1"}, "fhir": refusal}, + "preauth", "request", "protocol") == "settled" + and nhcx.preauth(episode)["status"] == "error" + and "PAYR-1238" in (nhcx.preauth(episode)["error_message"] or "")) + + section("tasks and payment") + cancelled = pin("C10/C10-cancelled-wfPC02-pmjay.json") + verdict = resource(cancelled, "ClaimResponse")["adjudication"][0]["reason"]["coding"][0]["code"] + check("PC02 is read as an accepted cancellation", + nhcx.parse_task_response(cancelled)["adjudication"] == verdict == "cancelled") + arbitration = pin("C10/C10-arbitration-wf37-pmjay.json") + check("37 is read as the reprocess taken", + nhcx.parse_task_response(arbitration)["task_status"] == resource(arbitration, "Task")["status"]) + paid = pin("C9/payment-notice.json") + pn, pr = resource(paid, "PaymentNotice"), resource(paid, "PaymentReconciliation") + notice = nhcx.parse_payment_notice(paid) + check("the payment notice names the claim, the amount and the UTR", + notice["claim_ref"] == pn["identifier"][0]["value"] + and notice["amount"] == pn["amount"]["value"] + and notice["utr"] == pr["paymentIdentifier"]["value"]) + + print("\n" + "=" * 64) + total_checks = sum(ok + bad for ok, bad in tally.values()) + for name, (ok, bad) in tally.items(): + print(f" {name:44s} {ok:3d} passed {bad:2d} failed [{'FAIL' if bad else 'ok'}]") + print("=" * 64) + if failures: + print(f"{failures} of {total_checks} check(s) FAILED") + return 1 + print(f"all {total_checks} checks passed") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) +``` + +What each placeholder must do: + +- `` names the variable your HMIS reads its database path from, so the suite runs on a throwaway file. +- `` is the module that owns `transport`, the builders and `receive`. +- `` is the participant code of a generic payer (``) that your configuration maps to `query_mode: communication`. +- `` returns the dict your coverage builder takes, filled from `REF`. The discovery pin carries policy `NONE`. The benefits and auth-requirements pins quote `REF["coverage_item"]`. Copy the Location and PractitionerRole from the pin it is given. +- `` returns whatever your claim builder takes. That is the claim number, the item, the tier, the program `AB-PMJAY` and factors `(1, 0.5, 0.25)`. Add the four `MAND` documents (`MAND0408`, `MAND0455`, `MAND0409`, `MAND0570`, each with the pin's PDF), and copy the stay and procedure dates from the pin it is given. +- `` takes a payer code and inserts an eligible episode for that payer, with the plan and lines seeded straight into the database. +- `` puts the pre-auth row back to `submitting` on `corr-preauth-1`. + +Run the suite from the folder that holds `nhcx-package/`, or set `NHCX_PACKAGE` to its path. + +## 5. Running rung 2 + +Have your tests and live runs write every bundle they build into one archive folder. The package ships no validator. Run the HL7 FHIR validator with the NRCeS IG `ndhm.in` on the whole folder in one call, with the command and flags in `references/fhir-knowledge.md` section 11. + +Read the results in three piles. "A code the profile does not define" is the scheme's vocabulary, and it is expected. "A required element is missing" and "an id or value the base rules refuse" are yours to fix. Warnings are advice; the sandbox accepted every pin as it stands. Skip the package master; it exhausts the validator's memory. A live PAYR-1004 or PAYR-1008 is the first reason to run this rung again (`nhcx-package/docs/06-Reference/02-Troubleshooting.md`). + +## 6. Running rungs 3 and 4 + +Only the user runs these. Prepare what they start and the driver, then stop and ask. + +What the user starts: + +1. The transport. Your own or the app's existing one needs a participant record carrying its certificate and a public HTTPS `endpoint_url` the exchange can reach (`references/transport-knowledge.md` section 3). nhcx-adapter, only when the user chose it, comes from its release: `config.sample.json` filled in, started with `serve.sh`. +2. Your HMIS, reachable by the exchange through that transport. +3. For rung 3, a generic payer on the sandbox whose desk you can drive (``), mapped to `query_mode: communication`. For rung 4, nothing more: the PMJAY payer is `1518@hcx`, and its decisions are taken on the payer service desk. + +The driver is a script or a browser spec. It walks the matrix rows through the app's JSON state address or its own screens, one episode per test, in series, with a 20 minute timeout per episode. + +- Before a PMJAY run, sweep every live pre-auth for the beneficiaries the tests use. Cancel it on PC01, or have the desk reject it. Otherwise the first pre-auth is refused with PAYR-1238. +- One request at a time per case. Wait about 30 seconds after a decision before the next leg. On "Active instance found" (PAYR-1322), wait and resend, up to three times. +- Wait on the case's own state, never on a fixed sleep or a checklist. +- Log every verdict the sandbox gives, with its workflow id and words, so a refusal is a finding, not a mystery. +- Expect about four minutes for the rung 3 matrix and about ten minutes per episode on PMJAY. + +After the run, package its bundles by correlation id from the per-case archive: every message sent and received, filed under its case. With nhcx-adapter as the transport, `nhcx-adapter ledger thread ` gives the same conversation, with bodies only while `ledger.storeBodies` is true (`nhcx-package/docs/02-Getting Started/10-NHCX Adapter.md`). File each thread under its use case. diff --git a/plugins/nhcx/skills/nhcx-claim/references/transport-knowledge.md b/plugins/nhcx/skills/nhcx-claim/references/transport-knowledge.md new file mode 100644 index 000000000..a0838b9cd --- /dev/null +++ b/plugins/nhcx/skills/nhcx-claim/references/transport-knowledge.md @@ -0,0 +1,283 @@ +# Transport knowledge: how the build reaches NHCX + +Every NHCX message is a FHIR bundle sealed in a JWE, sent with an ABDM session token, and answered later on the sender's own callback. Something has to do that work. This file says which of three things does it for a build, what the rest of the build expects from it, and how to build it yourself. + +Section 3 is drawn from NHA's published chapters: `nhcx-package/docs/02-Getting Started` (01 to 09, and 11), `nhcx-package/docs/01-Overview/04-JWE, Status and Errors.md` and `nhcx-package/docs/06-Reference/03-Envelope Fields.md`. Open them when a detail matters. Where they and this summary differ, they win. + +## 1. Three transports + +| Transport | Choose it when | The build | +| --- | --- | --- | +| `existing` | Stage 0 found the app already speaks NHCX: its own client that seals and posts JWEs, a vendor gateway or middleware, an HCX SDK, callbacks under `/v1/...` | Keeps it. Wraps it behind the contract in section 2 and closes the gaps section 4 lists. Never replaces a working one. | +| `own` | The app has no NHCX integration, and the user has not asked for nhcx-adapter. This is the default. | Builds the protocol into the app (section 3): the session token, the key and certificate, the participant record, the recipient's certificate, sealing and sending, the callback and its receipt. | +| `adapter` | Only when the user asks for nhcx-adapter, by name or by asking for "the adapter" | Downloads it (section 5) and talks plain FHIR to it. `references/api-knowledge.md` is its contract. | + +The rules: + +- Never propose nhcx-adapter, and never choose it because it is easier. Use it only when the user has asked for it, and write their words into `nhcx-build/1-idea.md`. +- An app with an NHCX integration of its own keeps it, even when it is partial. Extend it; never put a second transport beside it. +- The choice is made once per app, at stage 1, from stage 0's verdict on `foundation.transport`. Every skill after the first reads it from `1-idea.md`. + +## 2. The contract every transport meets + +The rest of the build (modules 7.2 to 7.13) never sees the transport, only these functions: + +| Function | Takes | Gives | Notes | +| --- | --- | --- | --- | +| `send(path, bundle, recipient, workflow_id, correlation_id = null, ben_abha_id = null, claim_no, usecase)` | The NHCX path (`v1/preauth/submit`), the bundle, the recipient's participant code, the workflow id; a correlation id only when answering (the communication reply, the payment acknowledgement); the beneficiary's ABHA, else the episode's by `claim_no` | `{txn_id, correlation_id, api_call_id, raw}` | Raises `TransportError(code, message, protocol_response, retryable)` on a refusal. Archives the outbound message. Every leg stores the three ids. | +| The receiving end | A delivery from the exchange (`own`, `existing`) or from nhcx-adapter | Calls 7.3's `receive(envelope)` with `{meta: {path, payloadType, redelivery}, jwe_headers: {every x-hcx- field}, fhir: }`; `payloadType` is `fhir`, `protocol` or `error` | Answers the sender as its transport requires (section 3.9 for `own`). The door does the rest. | +| `policies(id_type, value)` | `AbhaNumber`, `MemberId` or `MobileNo`, and the value | The participant service's answer, raw | Module 7.4 normalises it (section 3.6). | +| `participants(role)` | `PAYER`, `PROVIDER` or `TPA` | The registry's list | Cached for the day. | +| `token()` | nothing | The ABDM session token | For calls the transport does not make itself, such as the PMJAY payer service. | +| `thread(correlation_id)`, `fetch_missed(txn_id)` | | The messages on one thread; a missed answer | Only nhcx-adapter keeps a ledger to answer these. With `own` and `existing`, `thread` reads the per-case archive and `fetch_missed` answers `unavailable`; a lost answer surfaces through `/v1/error` and the status exchange instead (section 3.10). | + +Two values every transport needs from the build, both from the policy lookup (section 3.6). The recipient is the policy's `processingid`, kept on the episode as `recipient_code`. The insurer is its `payerid`, kept as `payer_code`: it goes inside the bundle and chooses the payer adapter (module 7.11). And every message carries the beneficiary's ABHA number in `x-hcx-ben-abha-id`. + +A test replaces `send` with a stub of the same signature (stage 9). Nothing else in the build changes for a test. + +## 3. Building it yourself (`own`) + +Seven things, in this order (`01-The Base Framework.md`): a token, a key and certificate, a participant record, the payer and policy lookups, the recipient's certificate, sealing and sending, and the callback. The last two are the ones every message uses. + +### 3.1 Before you start + +| Need | Why | +| --- | --- | +| The facility's HFR id | The registry that vouches for a hospital | +| ABDM sandbox client id and secret, Milestone 1 completed | NHCX uses the same credentials; there is no separate login | +| A public HTTPS server in India with a domain name | The exchange calls your callback; it will not call an IP address or a port number | +| `openssl` where the private key will live | The key pair | +| A JOSE library | RSA-OAEP-256 with A256GCM: `jose` on Node, `jwcrypto` on Python, Nimbus on Java, `jose-jwt` on .NET | + +Ask the user for the credentials. Never write them, the token or the private key into code, a log or `nhcx-build/`. + +### 3.2 Addresses and headers + +From `nhcx-package/baseurl.yaml`: + +| Service | Sandbox | Production | +| --- | --- | --- | +| ABDM session token | `https://dev.abdm.gov.in/api/hiecm/gateway/v3/sessions` | `https://apis.abdm.gov.in` plus the same path; confirm it in the onboarding letter | +| NHCX exchange, every use-case call under `/v1` | `https://apisbx.abdm.gov.in/hcx` | Shared by NHA after sandbox exit | +| Participant service | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice` | `https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice` | + +Keep every address in configuration. Every call to the participant service and the use-case endpoints carries `Accept: application/json`, `Content-Type: application/json` and `bearer_auth: Bearer `. The header is `bearer_auth`, not `Authorization`; some NHA pages write `Authorization`, so send both with the same value. + +### 3.3 The session token + +`POST` to the sessions address with three headers, none optional: `REQUEST-ID` (a fresh UUID on every call), `TIMESTAMP` (UTC with milliseconds and a trailing `Z`, from the system clock) and `X-CM-ID` (`sbx` on the sandbox, `abdm` in production). The body is `{"clientId", "clientSecret", "grantType": "client_credentials"}`. The answer carries `accessToken` and `expiresIn`. + +- NHA's documents give its life as 300, 1200 and 6000 seconds. Rely on none: keep the token and when you got it, and fetch a new one when it is a few minutes old. +- On any `401`, get a new token and retry that call once. Never retry with the same token. +- Put `Bearer` and a space before the token. Without it, `401`. + +`03-Session Token.md` also shows the two timestamp shapes in ten languages: the gateway's UTC `...975Z`, the exchange's `+05:30`. + +### 3.4 Your key and certificate + +```bash +openssl genpkey -algorithm RSA -out private.key -pkeyopt rsa_keygen_bits:2048 +openssl req -new -key private.key -out request.csr +openssl x509 -req -in request.csr -signkey private.key -out certificate.crt -days 365 +base64 -w 0 certificate.crt > certificate.b64 # macOS: base64 -i certificate.crt -o certificate.b64 +``` + +`private.key` never leaves the server that receives callbacks. `certificate.b64` goes on the participant record as `encryption_cert`. Note the expiry: a lapsed certificate stops every sender. Replace it yearly (`04-Your Certificate.md`). + +### 3.5 The participant record + +On the sandbox, `POST /participant/create` with: + +| Field | Value | +| --- | --- | +| `linked_registry_codes` | `["10001"]` (HFR) | +| `registryid` | Your ABDM client id on the sandbox; the HFR id in production | +| `roles` | `["10001"]` (provider) | +| `participant_name`, `scheme_code`, `state`, `district`, `primaryEmail`, `phone`, `primaryMobile` | The facility's | +| `encryption_cert` | The base64 certificate | +| `endpoint_url` | The base of your callback server | + +The answer is your `participant_code`: the `x-hcx-sender_code` on everything you send. `participant/update` changes the certificate or the address. Production takes four steps with a passcode to the mobile on the HFR record (`v2/participant/create`, `validate`, `v2/participant/update`, `update/validate`), and `v2/update/cert` rotates only the certificate (`05-Creating and Updating a Participant.md`). + +The exchange appends the use-case path to `endpoint_url`: a pre-auth decision arrives at `/v1/preauth/on_submit`. Only the client id that created the record may change it; any other gets NHCX-1015. + +This is the user's onboarding, not the build's. The build writes the script or the settings screen; the user runs it with their credentials. Check it worked by fetching your own certificate back (section 3.7). + +### 3.6 The payer and the policy + +- Payers: `POST /fetch/participants/list` with `role` (`PAYER`, `PROVIDER`, `TPA`), `fromdate` and `todate` (`dd/MM/yyyy`), and optionally `entitytype` (`Gov`). There is no server-side search by name: fetch, filter locally, and cache for the day. +- Policies: `POST /participant/get/policies` with `identifiertype` and `identifiervalue`. Try `AbhaNumber` (no hyphens), then `MemberId`, then `MobileNo`, and stop at the first that returns a policy. Each policy carries `payerid`, `processingid`, `memberid`, `productid` and `productname`. The published answer is a sketch: read a real one before writing the parser, and keep it raw on the episode. +- Send to the processor. `processingid` is the envelope's recipient and whose certificate seals the message; `payerid` is the insurer named inside the bundle. They are the same when the insurer processes its own claims and differ when a TPA does. Addressing the `payerid` is the portal's seventh most common mistake. A policy with no `processingid` cannot be addressed: stop and say so (`06-Finding Participants and Policies.md`). + +### 3.7 The recipient's certificate + +`POST /fetch/certs` with `{"participantid": ""}`. The answer is PEM text: usually an X.509 certificate, sometimes a bare SPKI public key (anything under about 400 bytes). Load it as a certificate and take its key; if that fails, load it as a key. NHA does not publish the JSON envelope around it, so read one real answer first. Cache by participant code for 24 hours, and refresh early when the other side stops being able to open your messages (`07-Fetching a Recipient Certificate.md`). + +### 3.8 Sealing and sending + +The protected header (`08-Building and Sending a JWE.md`, `06-Reference/03-Envelope Fields.md`): + +| Field | Value | +| --- | --- | +| `alg`, `enc` | `RSA-OAEP-256`, `A256GCM`; not `RSA-OAEP` | +| `x-hcx-sender_code` | Your participant code | +| `x-hcx-recipient_code` | The policy's `processingid` on a request; the request's sender on an answer | +| `x-hcx-api_call_id` | A fresh UUID on every message, answers included | +| `x-hcx-request_id` | A UUID per request; optional, send it | +| `x-hcx-correlation_id` | On a request, this message's own `api_call_id`. On an answer, the request's `correlation_id`, so the two ids differ on an answer | +| `x-hcx-workflow_id` | The step code (`references/flow-knowledge.md` section 2). Optional in the specification, but payers key on it: send it wherever the sheet gives one | +| `x-hcx-timestamp` | ISO 8601 with `+05:30`, no milliseconds, from the system clock | +| `x-hcx-status` | `request.initiated` on a request; `response.complete` on an answer (an `on_` path) | +| `x-hcx-ben-abha-id` | The beneficiary's ABHA number without hyphens. Mandatory on every exchange | +| `x-hcx-use_case` | Optional: `New`, `Enhancement` or `Resubmit` on a pre-auth; `New` or `Resubmit` on a claim | + +Seal with the JOSE library: the bundle as plaintext, the recipient's public key, the header above as the protected header, compact serialisation (five parts, four dots). POST `{"payload": ""}` to `/v1/` with the headers of section 3.2. The sandbox collection also repeats the `x-hcx-` fields as HTTP headers; send them both ways. + +What comes back: + +| Answer | Means | The build | +| --- | --- | --- | +| `202` with a receipt (`protocol_status: request.queued`) | The envelope was valid and is queued. It is not the decision | Store `api_call_id` and `correlation_id`, and the archive id as `txn_id`; the leg waits | +| `400` | The envelope failed validation | Raise with the gateway's body; nothing went to the payer | +| `401` | The token expired, or `Bearer` is missing | New token, retry once | +| A connection dropped after the request was written | Unknown: it may have landed | Do not resend at once (`references/errors-and-debugging.md` section 7) | + +A correlation id that failed at the gateway is retired. The next attempt needs a fresh `api_call_id` and a fresh `correlation_id` (`01-Overview/04-JWE, Status and Errors.md`). + +### 3.9 Receiving + +Host these under `endpoint_url` (`09-Receiving a Callback.md`): `/v1/coverageeligibility/on_check`, `/v1/insuranceplan/on_request`, `/v1/preauth/on_submit`, `/v1/claim/on_submit`, `/v1/predetermination/on_submit`, `/v1/search/on_submit`, `/v1/communication/request`, `/v1/paymentnotice/request`, `/v1/task/on_submit`, `/v1/on_status` and `/v1/error`. Build one handler. The path gives the receipt's `entity_type`; the correlation id routes everything else (module 7.3). + +- The address: a domain over HTTPS with TLS 1.2 or newer, hosted in India, reachable from the exchange's outbound addresses `3.109.99.210`, `13.126.152.0` and `13.200.129.223`. +- The body: `{"type": "JWEPayload", "payload": ""}`; or, when the recipient refused your message, `{"type": "ProtocolResponse", "x-hcx-...": ..., "x-hcx-status": "response.error", "x-hcx-error_details": {code, message, trace}}` with the fields in the clear. `/v1/error` carries neither: it is a plain report of a request the exchange gave up on after five attempts. Store it whole and do not parse it against a fixed schema. +- Open a `JWEPayload` with your private key: the protected header comes out in the clear and the bundle is the plaintext. A failure to decrypt means the message was sealed for a certificate that is not the one on your participant record. +- Answer every delivery with `202` and the receipt within 30 seconds, `/v1/error` and unrecognised messages included. Not `200`, and not an empty body: + + ```json + {"timestamp": "dd/MM/yyyy HH:mm:ss:SSS", "api_call_id": "", "correlation_id": "", + "result": {"sender_code": "", "recipient_code": "", "entity_type": "preauth", "protocol_status": "request.queued"}, + "error": {"code": "", "message": ""}} + ``` + + `entity_type` is the path's second-to-last segment, or the last where that is `v1`, with `on_` stripped. +- Hand the door `{meta: {path, payloadType, redelivery}, jwe_headers, fhir}`: `payloadType` `fhir` with the bundle, `protocol` with the ProtocolResponse body as `fhir`, `error` with the `/v1/error` report. The door dedupes on `x-hcx-api_call_id`, archives, matches and applies, fast and with no outbound calls, so the receipt still goes inside the 30 seconds. +- The exchange signs its calls to you with a JWT (RS256; claims `jti`, `iss`, `sub`, `iat`, `exp`). No published source gives the NHCX public key or the header the token arrives in. Build the check with the key in configuration. While no key is configured, log that at every start, accept calls only from the three addresses above, and ask NHA for the key at onboarding. Never leave the check off silently. + +### 3.10 Status and the error endpoint + +- `/v1/status` asks the exchange what became of a message you sent. The payload is empty; `x-hcx-correlation_id` is that message's `api_call_id`. The answer arrives on `/v1/on_status` with `request.queued`, `request.dispatched` or `request.stopped` (redelivery exhausted; the correlation is retired). Call it when a case has been quiet longer than the payer's turnaround, never on a timer (`11-Status and Search.md`). `references/flow-knowledge.md` section 2 records what the sandbox did with it; keep the path configurable. This is not the claim's status Task of module 7.9. +- `/v1/error` is how you learn a request died. Without it a lost message is silent. + +With no ledger to poll, these two, the per-case archive and the receipts are what an `own` transport has. A leg with no answer stays waiting; it never turns into an error on a timer. + +### 3.11 Proving it + +The sandbox's dummy payer answers when you trigger it. Send it a bundle, then `POST https://apisbx.abdm.gov.in/pmjay/sbxhcx/dummyhcxpayer/process/request` with `{"action": "Approve" | "Reject" | "Query", "method": "Preauth" | "Claim", "correlationId": ""}`. Its answer reaching your `/v1/preauth/on_submit`, sealed or as a ProtocolResponse, proves the token, the participant record, the address, the sealing and the opening together (`09-Receiving a Callback.md`, "Closing the loop"). This is live traffic: stage 10, rung 3, started by the user. + +### 3.12 Pseudo code + +``` +settings.nhcx = {sessions, base, registry, cm_id, client_id, client_secret, # from configuration, never from code + private_key, signing_key} # signing_key empty until onboarding gives it + +function token(): + if cache.token and age(cache.at) < 240s: return cache.token + r = http_post(settings.nhcx.sessions, json = {clientId: settings.nhcx.client_id, clientSecret: settings.nhcx.client_secret, + grantType: "client_credentials"}, + headers = {"REQUEST-ID": uuid4(), "TIMESTAMP": utc_millis_z(), "X-CM-ID": settings.nhcx.cm_id}) + cache = {token: r.json().accessToken, at: now()} + return cache.token + +function authed_post(url, body, extra_headers = {}): + for attempt in (1, 2): + t = token() + r = http_post(url, json = body, timeout = 90, + headers = {"Accept": "application/json", "Content-Type": "application/json", + "bearer_auth": "Bearer " + t, "Authorization": "Bearer " + t} + extra_headers) + if r.status != 401: return r + cache.token = null # one retry, with a fresh token + return r + +function registry(path, body): return authed_post(settings.nhcx.registry + "/" + path, body) + +function recipient_key(code): # cached for 24 hours + if certs[code] and age(certs[code].at) < 24h: return certs[code].key + pem = pem_in(registry("fetch/certs", {participantid: code}).json()) # read one real answer first + key = try_certificate(pem).public_key() or load_public_key(pem) # X.509 first, bare SPKI second + certs[code] = {key, at: now()} + return key + +function send(path, bundle, recipient, workflow_id, correlation_id = null, ben_abha_id = null, claim_no = null, usecase = ""): + abha = digits(ben_abha_id or ben_abha(claim_no)) + if not recipient or not workflow_id or not abha: raise ValueError("recipient, workflow id and beneficiary ABHA are required") + answer = path.split("/")[-1].startswith("on_") + api_call_id = uuid4() + header = {"alg": "RSA-OAEP-256", "enc": "A256GCM", + "x-hcx-sender_code": with_hcx(settings.participant_code), "x-hcx-recipient_code": with_hcx(recipient), + "x-hcx-api_call_id": api_call_id, "x-hcx-request_id": uuid4(), + "x-hcx-correlation_id": correlation_id if answer else api_call_id, + "x-hcx-workflow_id": str(workflow_id), "x-hcx-timestamp": now_ist_seconds(), + "x-hcx-status": "response.complete" if answer else "request.initiated", + "x-hcx-ben-abha-id": abha} + jwe = jose_encrypt_compact(to_json(bundle), recipient_key(with_hcx(recipient)), protected = header) + r = authed_post(settings.nhcx.base + "/" + path, {"payload": jwe}, extra_headers = without(header, "alg", "enc")) + txn = archive.record(claim_no, usecase, "out", {path, header, bundle, status: r.status, response: r.text}) + if r.status >= 300: + raise TransportError(code = "GATEWAY_HTTP_" + r.status, message = r.text, retryable = r.status >= 500) + return {txn_id: txn, correlation_id: header["x-hcx-correlation_id"], api_call_id: api_call_id, raw: r.json()} + +route POST /v1/ # under endpoint_url; exempt from session auth and CSRF; the exchange's addresses only +function inbound(request, path): + verify_nhcx_jwt(request, settings.nhcx.signing_key) # when the key is configured; else logged at start, never silent + body = parse_json_or_null(request.body) + if path == "error": + env = {meta: {path: "v1/error", payloadType: "error"}, jwe_headers: {}, fhir: body} + elif body and body.type == "ProtocolResponse": + env = {meta: {path: "v1/" + path, payloadType: "protocol"}, jwe_headers: x_hcx_fields(body), fhir: body} + else: + try: header, plaintext = jose_decrypt_compact(body.payload, settings.nhcx.private_key) + except: archive.record(null, "undecryptable", "in", request.body); return 202, receipt({}, path, error = "DECRYPT_FAILED") + env = {meta: {path: "v1/" + path, payloadType: "fhir"}, jwe_headers: header, fhir: parse_json(plaintext)} + receive(env) # module 7.3: dedupe, archive, match, apply; fast, no sends + return 202, receipt(env.jwe_headers, path) # within 30 seconds + +function receipt(h, path, error = ""): + return {"timestamp": now_ist("dd/MM/yyyy HH:mm:ss:SSS"), + "api_call_id": h["x-hcx-api_call_id"], "correlation_id": h["x-hcx-correlation_id"], + "result": {"sender_code": h["x-hcx-sender_code"], "recipient_code": h["x-hcx-recipient_code"], + "entity_type": entity_type(path), "protocol_status": "request.queued"}, + "error": {"code": error, "message": ""}} + +function entity_type(path): # "v1/preauth/on_submit" -> "preauth"; "v1/on_status" -> "status" + parts = ("v1/" + path).split("/"); seg = parts[-2] if parts[-2] != "v1" else parts[-1] + return seg.removeprefix("on_") +``` + +## 4. Using an existing integration (`existing`) + +How stage 0 recognises one: `x-hcx-`, `JWEPayload`, `RSA-OAEP-256`, `A256GCM`, a JOSE library among the dependencies, `bearer_auth`, a sessions URL on the ABDM gateway, `participanthcxservice`, `fetch/certs`, `participant/get/policies`, routes ending in `on_submit`, `on_check` or `on_request`, a vendor's NHCX or HCX client library, a separate gateway service the app calls. + +What it must do, checked by running it offline with the network stubbed and a test key pair for the seal: + +| Contract item (section 2) | Look at | Common gap | +| --- | --- | --- | +| `send` emits the protected header of section 3.8 | What it seals or posts | No `x-hcx-ben-abha-id`; a request correlation id that is not its own `api_call_id`; UTC timestamps; `RSA-OAEP` | +| The recipient | Who it addresses | The `payerid` instead of the `processingid` | +| The three ids back to the caller | Its return value | Only a success flag; the ids stay inside it | +| Receiving: a `202` receipt within 30 seconds on every path, `/v1/error` included | Its callback handler | `200` or an empty body; no `/v1/error`; slow work before answering | +| Handing on the header and the bundle | What it gives the app | The bundle without the header; no ProtocolResponse path | +| Dedupe on `x-hcx-api_call_id` | Its store | None | +| A record of every message | Its logs | Bodies not kept | + +The build wraps it. 7.1's `send` calls the existing client and returns the three ids. The existing callback handler, after its receipt, calls 7.3's `receive` with the envelope of section 2. Each gap is closed in the existing code, in its style (stage 7, action `extend`). The existing transport is not rewritten, and no second one is added beside it. If it cannot be made to hand on the ids or the header, record `partial` and ask the user whether to extend it further or, with their agreement, build `own` in its place. + +## 5. nhcx-adapter, only when asked + +nhcx-adapter is NHA's optional single binary that does section 3 for you (`nhcx-package/docs/02-Getting Started/10-NHCX Adapter.md`, titled "Optional"). Use it only when the user has asked for it. Then: + +1. Get it, with the user's go-ahead, from https://github.com/nha-in/nhcx-adapter/releases (the latest). Each release carries one archive per platform, `nhcx-adapter___.tar.gz` (darwin, linux, windows, freebsd; amd64, arm64, 386), holding the binary, `config.sample.json`, `serve.sh`, `stop.sh`, `update.sh` and `README.md`. Put it in a folder of the user's, not in the skill. +2. Its contract is `references/api-knowledge.md`: configuration (section 2), routes (3), the outbound envelope and answer (4, 5), the delivery your HMIS receives (6), the ledger (7), the kit endpoints (8). +3. Onboarding is sections 3.1 to 3.5 again: credentials, a key, a participant record, a public address. The adapter can generate and register the key itself (`config init`, `cert generate`, its startup checks). +4. It does not queue or retry, does not build or validate bundles, and does not verify who sent an inbound message beyond decrypting it. Its `/internal/*` routes have no authentication: bind it to loopback. + +How it maps onto section 2: `send` POSTs `{jwe_headers, fhir}` to `/fhir/out/`; the receiving end is the HMIS route the adapter posts to (`api-knowledge.md` section 6); `policies` is `/internal/policies/search`; `thread` and `fetch_missed` are its ledger and `/internal/txn/*`. diff --git a/plugins/nhcx/skills/nhcx-claim/scripts/fetch-package.sh b/plugins/nhcx/skills/nhcx-claim/scripts/fetch-package.sh new file mode 100755 index 000000000..efbafa50b --- /dev/null +++ b/plugins/nhcx/skills/nhcx-claim/scripts/fetch-package.sh @@ -0,0 +1,122 @@ +#!/usr/bin/env bash +# Fetch the NHCX package and unpack it beside nhcx-build/ as nhcx-package/. +# +# scripts/fetch-package.sh [url-or-path] [target-dir] +# +# With no [url-or-path] (or "latest"), the zip is the build attached to the latest +# release of https://github.com/nha-in/nhcx-package (the nhcx-package-v.zip +# asset); its sha256 is checked against the digest GitHub records for the asset. +# Otherwise [url-or-path] is a link to the zip or a local path to it. +# [target-dir] defaults to the current directory. The zip unpacks to /nhcx-package/. +# +# Afterwards MANIFEST is checked: every file it lists must exist with the sha256 +# it records. Nothing is deleted; an existing nhcx-package/ is replaced. +set -euo pipefail + +repo="nha-in/nhcx-package" +src="${1:-latest}" +target="${2:-.}" +if [[ "$src" == "-h" || "$src" == "--help" ]]; then + echo "usage: $0 [latest|url-or-path-to-package.zip] [target-dir]" >&2 + exit 2 +fi + +download() { # + if command -v curl >/dev/null 2>&1; then + curl -fsSL -o "$2" "$1" + elif command -v wget >/dev/null 2>&1; then + wget -qO "$2" "$1" + else + echo "neither curl nor wget is available" >&2 + exit 1 + fi +} + +mkdir -p "$target" +tmp="$(mktemp -d)" +zip="$tmp/package.zip" +want_sha="" + +if [[ "$src" == "latest" ]]; then + # Ask the releases API for the latest release's zip asset and its digest. + api="https://api.github.com/repos/$repo/releases/latest" + if download "$api" "$tmp/release.json" 2>/dev/null; then + read -r tag url want_sha < <(python3 - "$tmp/release.json" <<'PY' +import json, sys +rel = json.load(open(sys.argv[1], encoding="utf-8")) +assets = [a for a in rel.get("assets", []) + if a["name"].startswith("nhcx-package") and a["name"].endswith(".zip")] +if not assets: + sys.exit(f"release {rel.get('tag_name')} has no nhcx-package*.zip asset") +a = assets[0] +digest = a.get("digest") or "" +print(rel["tag_name"], a["browser_download_url"], + digest.split(":", 1)[1] if digest.startswith("sha256:") else "") +PY + ) + else + # API unreachable or rate limited: read the tag off the releases/latest redirect + # and build the asset name from it. No digest to check in this case. + tag="$(curl -fsSIL -o /dev/null -w '%{url_effective}' "https://github.com/$repo/releases/latest")" + tag="${tag##*/}" + if [[ -z "$tag" || "$tag" == "latest" ]]; then + echo "could not resolve the latest release of $repo" >&2 + exit 1 + fi + url="https://github.com/$repo/releases/download/$tag/nhcx-package-v$tag.zip" + fi + echo "fetching $repo release $tag: $url" + download "$url" "$zip" + if [[ -n "$want_sha" ]]; then + got_sha="$(python3 -c 'import hashlib,sys; print(hashlib.sha256(open(sys.argv[1],"rb").read()).hexdigest())' "$zip")" + if [[ "$got_sha" != "$want_sha" ]]; then + echo "sha256 mismatch for $url: got $got_sha, release says $want_sha" >&2 + exit 1 + fi + fi +elif [[ -f "$src" ]]; then + cp "$src" "$zip" +else + download "$src" "$zip" +fi + +rm -rf "$target/nhcx-package" +unzip -q "$zip" -d "$target" +if [[ ! -f "$target/nhcx-package/MANIFEST" ]]; then + echo "unpacked, but $target/nhcx-package/MANIFEST is missing; is this the NHCX package?" >&2 + exit 1 +fi + +# Verify every file the MANIFEST lists. The MANIFEST is YAML; its file entries +# carry path, bytes and sha256 on separate lines. +python3 - "$target/nhcx-package" <<'PY' +import hashlib, os, re, sys +root = sys.argv[1] +text = open(os.path.join(root, "MANIFEST"), encoding="utf-8").read() +# Only the `files:` section lists a sha256 per path; the `contents:` summary above it +# lists directories. Parse entry by entry so a directory entry never borrows the next +# file's hash. +files_section = text.split("\nfiles:\n", 1)[1] if "\nfiles:\n" in text else "" +entries = [] +for chunk in re.split(r"\n\s*-\s+path:\s*", "\n" + files_section)[1:]: + path = chunk.split("\n", 1)[0].strip() + m = re.search(r"^\s+sha256:\s*([0-9a-f]{64})", chunk, re.M) + if path and m: + entries.append((path, m.group(1))) +bad = [] +for path, want in entries: + p = os.path.join(root, path) + if not os.path.isfile(p): + bad.append(f"missing {path}") + continue + got = hashlib.sha256(open(p, "rb").read()).hexdigest() + if got != want: + bad.append(f"sha256 mismatch {path}") +print(f"nhcx-package: {len(entries)} file(s) listed, {len(bad)} problem(s)") +for b in bad[:20]: + print(" " + b) +sys.exit(1 if bad else 0) +PY + +rm -rf "$tmp" +echo "ready: $target/nhcx-package (see references/material.md for the path map)" diff --git a/plugins/nhcx/skills/nhcx-claim/stages/0-capability-check.md b/plugins/nhcx/skills/nhcx-claim/stages/0-capability-check.md new file mode 100644 index 000000000..8186c3288 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-claim/stages/0-capability-check.md @@ -0,0 +1,92 @@ +# Stage 0: capability check + +Purpose: before anything is planned, find out what the app already does. For this skill's own capabilities, for the foundation it stands on, and for what it needs from the use cases before it, write one verdict each with the evidence that decides it. The verdicts decide what the later stages reuse, extend, build or wait for. Nothing is built twice, and nothing is reused on faith. + +## Inputs + +- This skill's `SKILL.md`, section "Capability check": its own capabilities (what to look for, what makes each present), and its prerequisites with the check that proves each present. The skills that own the prerequisites do not need to be installed; their checks are in this skill's `SKILL.md`. +- `core/FOUNDATION.md`: the six foundation capabilities. +- `nhcx-build/capabilities.json` and `nhcx-build/0-capability.md`, if another NHCX skill already ran on this app. +- The target: the codebase (integrate), or the folder where the standalone app lives or will live. +- The pins and payer fixtures each check names, in `nhcx-package/`. If it is not beside `nhcx-build/`, fetch it now (`scripts/fetch-package.sh`); `references/material.md` names each pin's file. + +## The verdicts + +| Verdict | Means | What happens next | +| --- | --- | --- | +| `present` | Located, and its check was run and observed passing | Reuse. Stage 7 builds nothing for it. Stage 8 still runs its Validate rows; stage 9 still tests it. | +| `partial` | Located, but its check fails; or it covers some legs or branches and not others; or it was located and could not be run | Extend. Stage 7 builds the difference, in the existing code. | +| `absent` | Searched for as the skill says and not found | Build. Stage 7 builds it. | +| `unknown` | Could not be searched: no code is reachable | Planned as absent; stage 0 runs again when the code is reachable. | +| `not applicable` | The mode or the scope excludes it: 7.13 in integrate mode, a leg the user marked out | Nothing. | + +For a prerequisite, a verdict of `absent` or `unknown` is a stop: see step 5. + +Present is a claim about behaviour. Code that looks right is `partial` until its check has run. + +## Do + +### 1. Find the target + +Integrate: the codebase root, its language and framework, enough to search and to run code offline (stage 3 does the full survey). Standalone: the app folder. If it is empty and no other NHCX skill has built anything there, every capability is `absent` and this stage is short. Write which in one line. + +If `nhcx-build/capabilities.json` exists, read it. A verdict another skill recorded is a lead, not a result. If the code changed since its date (the version control log says), run its check again; otherwise carry it forward with its evidence and date. + +### 2. Locate + +For each capability in the three lists (own, foundation, prerequisites), search for the markers: NHCX paths such as `v1/preauth/submit`, resource names such as `CoverageEligibilityRequest`, workflow ids as strings, table and column names. `SKILL.md` lists them for its own capabilities; for a prerequisite, the marker is what its check names. Record every hit as `path:line`. A hit in a comment, a dead branch or a test fixture is not the capability; say so. + +Look also for the same job done another way: a pre-auth sent to a TPA portal, an eligibility check recorded from a phone call, a payment keyed in from a bank statement. That is a host capability that stages 3 and 4 may link to. The NHCX capability is still `absent`. + +### 3. Check + +For every capability located, run the check `SKILL.md` names, offline: + +- a builder: feed it the pin's own data and compare its output with the pin (canonical JSON, `created` excluded, and only the exclusions the module names); +- a reader: feed it the payer fixture and read the state it settles; +- a sender: call it with the 7.1 stub, or a stub of the app's own client, and read what it posted; +- the door: call the handler with an envelope; +- a screen: render it on a seeded state and read the text. + +Use the app's own test runner where it can host the check, else a one-off script under `nhcx-build/0-capability/`. Nothing leaves the machine. + +Where the existing code cannot be called without the network or a running service, record `partial` with `not run: `. Never `present`. + +### 4. Decide + +One verdict per capability, with where (the paths), how (the command), observed (the output, or the first lines of the diff), and the action: reuse, extend, build or wait. For `partial`, name the difference: which pin fails and at which element, which branch is missing (a PMJAY query answer on 19 but none on 131), which column is missing. + +### 5. When a prerequisite is missing + +A prerequisite is a capability another skill owns that this skill's legs cannot run without. `SKILL.md` lists them with their checks. If one is `absent` or `unknown`: + +1. Stop and tell the user which capability is missing, which skill owns it, and what this skill cannot do without it. +2. Offer the two ways on: run the owning skill first (installing it if it is not beside this one; it is the default); or continue with this skill's offline work only (builders, readers and tests against seeded rows), with the live legs marked `later` in stage 1 and the dependency written in `NOTES.md`. +3. Never build another skill's capability inside this one. It would be built without that skill's checks. + +A `partial` prerequisite does not stop the skill. Its gap goes into stage 2's risk table. + +## Write + +- `nhcx-build/capabilities.json` from `templates/capabilities.json`: one entry per capability, keyed by id, with `skill`, `module`, `verdict`, `located`, `how`, `observed`, `action`, `checked_by` and `date`. Update the entries this skill checked; leave the others. +- `nhcx-build/0-capability.md` from `templates/0-capability.md`: a section headed with this skill's name, holding the three tables (own, foundation, prerequisites) and the summary line. +- The scratch checks under `nhcx-build/0-capability/`, kept: stage 8 runs them again. +- This skill's block in `nhcx-build/STATE.md` (create the file from `templates/STATE.md` if it does not exist), with stage 0's row closed and its evidence. + +## Gate + +- [ ] Every capability in this skill's list, every foundation capability, and every prerequisite has a verdict. +- [ ] Every `present` names the command run and its observed output. None rests on reading alone. +- [ ] Every `partial` names the difference. +- [ ] Every `absent` names what was searched for, so a reader can repeat the search. +- [ ] A missing prerequisite was put to the user, and the answer is recorded. +- [ ] `capabilities.json` parses and holds this skill's entries. + +## Common mistakes + +- Marking a capability present because its endpoint name appears in the code. The pin decides. +- Rebuilding a working NHCX transport or callback door because this skill did not write it. An app that already seals, sends and receives NHCX messages keeps its own; the verdict says reuse. +- Proposing nhcx-adapter for an app that lacks a transport. The transport is then `own`; the adapter is used only when the user asks for it. +- Treating a legacy TPA workflow as the NHCX capability. It is a host capability; the NHCX one is absent. +- Checking against the live sandbox. Stage 0 is offline; the live rungs are stage 10's, and the user's. +- Carrying another skill's verdict forward after the code changed. diff --git a/plugins/nhcx/skills/nhcx-claim/stages/1-idea.md b/plugins/nhcx/skills/nhcx-claim/stages/1-idea.md new file mode 100644 index 000000000..b9f391316 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-claim/stages/1-idea.md @@ -0,0 +1,80 @@ +# Stage 1: the idea + +Purpose: agree with the user what is being built before anything is designed. One page, shared by the seven skills. Wrong answers here cost the most later, so this is the one stage that always ends with a question to the user when it is first written. + +The first skill to reach this stage writes `1-idea.md` whole: the mode, the payers, the constraints, and a scope row for every step of the flow, each naming the skill that owns it. A later skill reads the page, confirms that the mode and the payers still hold, and marks its own rows. It asks the user only when it would change a row or an answer. + +## Inputs + +- This skill's section of `nhcx-build/0-capability.md`: what the app already does. A leg found present is still in scope: it is validated and tested, not rebuilt. Say so in the scope table's reason column. A prerequisite the user chose to wait for makes this skill's live legs `later`. +- `flow/FLOW.md`, whole. The build walks this path; the scope table below marks its steps in, later or out, and nothing else. `flow/flow.json` names the skills of each step in `skills`. +- What the user said. If they pasted a brief, quote it in the artefact. +- `references/flow-knowledge.md` sections 1, 3 and 6: the legs, the two payer kinds, the use-case catalogue. Read them so the scope table below uses the catalogue's codes. + +## Do + +Decide five things, in this order. A later skill confirms the first two and the fourth, and does the third for its own rows. + +### 1. Mode + +| Signal | Mode | +| --- | --- | +| A codebase, a database, a running system is named | `integrate` | +| "from scratch", "standalone", "a claims app", no existing system | `standalone` | +| Unclear | Ask. Do not guess; the two modes diverge at stage 3. | + +### 2. Payers + +Which participant codes the software will talk to, and which kind each is: + +| Payer | Participant code | Kind | Query mode | +| --- | --- | --- | --- | +| PMJAY (SHA Himachal Pradesh, sandbox) | `1518@hcx` | scheme | `resubmit` | +| A generic sandbox payer you can drive, for testing | from the participant registry | generic | `communication` | +| Any other insurer | from the registry | generic unless told otherwise | `communication` | + +Both kinds are in scope by default. A build that targets only one still keeps the payer adapter switch (module 7.11), because the second is one config line away. + +### 3. Scope of legs + +Copy the steps of `flow/flow.json` (F1 to F13 with their branches) into a scope table, with the skill that owns each (`skills`), and mark each `in`, `later` or `out`, with a reason; add the catalogue code from `flow-knowledge.md` section 6 beside each. The default scope for a first release is every hospital-side leg in `flow-knowledge.md` section 1. Cutting a leg is the user's call; propose it, do not decide it. Legs that are commonly `later`: predetermination, status enquiry (PMJAY refuses it), release of a shortfall (out of reach on the sandbox). + +A later skill changes only its own rows. + +### 4. Constraints + +Ask the codebase, not the user, where you can: + +- Language and framework (integrate: whatever the HMIS uses; standalone: Python standard library unless the user names another, because the module files' pseudo code maps onto it directly). +- The transport (`references/transport-knowledge.md` section 1): `existing` when stage 0 found the app already speaks NHCX; else `own`, built into the app from NHA's protocol; `adapter` (nhcx-adapter) only when the user has asked for it, their words quoted. Never propose the adapter. +- The inbound path. For `own`: a public HTTPS domain in India, registered as the participant's `endpoint_url` and reachable from the exchange. For `existing`: the app's own callback. For `adapter`: whether the app can receive the adapter's POST; if not, polling the adapter's ledger is the only inbound path. Write it down now. +- What onboarding needs from the user: the ABDM sandbox client id and secret (Milestone 1), the facility's HFR id, and a participant record carrying the build's certificate and callback address. +- Document storage: blob, filesystem, object store. +- Whether a background worker exists. Without one, polls happen on the request path. +- Anything the user forbids: new dependencies, schema changes to existing tables, a build step. + +### 5. Definition of done + +Write the compliance points from `core/LADDER.md` as they apply to this build, and the highest rung of the test pyramid the user wants climbed before handover (`references/testing-knowledge.md` section 1). The offline rung is never optional. + +## Write + +`nhcx-build/1-idea.md` from `templates/1-idea.md`. Keep the headings. Under two pages. A later skill edits only its scope rows and adds a line under "Agreed". + +## Gate + +- [ ] Mode is `integrate` or `standalone`, and the reason is one sentence. +- [ ] Every payer has a participant code and a query mode. +- [ ] The scope table has every step of the flow and every catalogue row, each with its skill, marked in, later or out. +- [ ] Constraints name the language, the transport (existing, own, or nhcx-adapter because the user asked for it), the inbound path and the document store. +- [ ] Definition of done names the target rung. +- [ ] The user has read the page and agreed, or a written brief stands in for the user. A later skill that changed nothing records that it confirmed the page. + +Record the gate in the Shared block of `nhcx-build/STATE.md`. + +## Common mistakes + +- Choosing `standalone` because the HMIS is unfamiliar. Unfamiliar is what stage 3 is for. +- Leaving PMJAY out because the user only named an insurer. PMJAY is the payer that refuses most; a build that handles it handles the rest. +- Dropping a leg from scope because stage 0 found it present. It stays in: present capabilities are validated and tested. +- Writing design here. Tables, screens and modules belong to stages 4 to 6. diff --git a/plugins/nhcx/skills/nhcx-claim/stages/10-run-tests.md b/plugins/nhcx/skills/nhcx-claim/stages/10-run-tests.md new file mode 100644 index 000000000..e7e5d8d32 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-claim/stages/10-run-tests.md @@ -0,0 +1,59 @@ +# Stage 10: run the tests + +Purpose: climb the pyramid as far as the user asked in stage 1, for this skill's rows, and record every rung honestly. Rung 1 you run yourself. Rungs 2 to 4 need services or live payers, and only the user starts those. + +## Inputs + +- `nhcx-build/1-idea.md` (the target rung), `nhcx-build/9-tests.md` (the run command, this skill's rows) +- This skill's `SKILL.md`: its stage 10 row (which matrix rows each rung walks) +- `references/testing-knowledge.md` sections 1, 5 and 6 +- `references/errors-and-debugging.md` sections 4 to 8 (reading the ledger, sandbox pace) + +## The rungs + +| Rung | What | Who starts it | Record | +| --- | --- | --- | --- | +| 1 Offline | The suite from stage 9, against the pins and fixtures, no network | you | the full output | +| 2 Validator | The HL7 FHIR validator on every bundle this skill builds, run as `references/fhir-knowledge.md` section 11 says | you, if Java and the validator are installed | one table: bundle, errors, warnings | +| 3 Generic payer | The transport on the sandbox (the app's own, or nhcx-adapter when the user chose it) and a generic sandbox payer whose desk you can drive; this skill's legs, every query as a CommunicationRequest, payment from its desk | the user | the ledger thread per leg, the state address after each | +| 4 PMJAY sandbox | SHA Himachal Pradesh, `1518@hcx`; sweep live pre-auths first; one request at a time per case, 30 seconds between; decisions on the payer service desk | the user | the ledger, the archive folder, every refusal verbatim | + +## Do + +### Rung 1 + +Run the command from `nhcx-build/9-tests.md`: the whole suite, not only this skill's tests, because a skill that extended a shared module can break another skill's test. Save the whole output to `nhcx-build/10-test-run/-rung1.log`. In `integrate` mode also run the HMIS's own suite and save it. A failure goes back to stage 7 (the module) or stage 9 (the test); record the fix and the re-run. Do not edit a test to make it pass unless the test was wrong, and say so. + +### Rung 2 + +If the validator runs, validate every bundle this skill's tests built (write them to a folder from the tests). Warnings are advice; the sandbox accepted every pin as it stands. Errors are findings. If it does not run, write `not run` and why. + +### Rungs 3 and 4 + +Prepare, do not run: + +1. The commands the user runs: the HMIS with its public callback (`own` or `existing`), nhcx-adapter with its filled config only when the user chose it, and the payer (rung 3). For `own`, the sandbox's dummy payer proves the loop first (`references/transport-knowledge.md` section 3.11). Write them into this skill's section of `nhcx-build/10-test-run.md` under "Runbook". +2. The driver: a script or a spec that walks this skill's matrix rows through the JSON state address, waiting on the case's own state and never on a fixed sleep, logging every verdict the payer gives. The earlier legs a row needs (an eligible case, an approved pre-auth) are reached by the earlier skills' drivers or through the app's own screens. +3. The sweep for rung 4: cancel or let expire every live pre-auth for the beneficiaries the tests use (PAYR-1238 otherwise). +4. Then stop and ask the user to start the services. When they have, run the driver, save its log, and package the run's bundles by correlation id from the per-case archive (or the adapter's ledger, when it is the transport). + +While a live run is going: one request at a time per case; wait about 30 seconds after a decision; on "Active instance found" wait and resend up to three times; on a refusal read the ledger thread before touching the code. + +## Write + +This skill's section of `nhcx-build/10-test-run.md` from `templates/10-test-run.md`: per rung, `passed`, `failed`, `not run` with the reason, the log path, and the findings (each a line: what, where, the PAYR or rule, the fix or the open question). The raw logs under `nhcx-build/10-test-run/`, named for the skill. + +## Gate + +- [ ] This skill's rung 1 log exists and shows every test in the suite passing, or the failures are listed as findings with a stage to return to. +- [ ] In `integrate` mode the HMIS's own suite log exists and passes. +- [ ] Rung 2 has a table or `not run` with a reason. +- [ ] Rungs 3 and 4 have a runbook and a driver for this skill's rows, and either a log or `not run: user has not started the services`. +- [ ] No rung is marked passed without a log. + +## Common mistakes + +- Starting a service yourself: the app's public callback, or nhcx-adapter. Only the user does. +- Running only this skill's tests at rung 1. A shared module may have broken another skill's. +- Sleeping a fixed time in a driver. Wait on the state address. +- Reading a refusal as a code bug before reading the ledger thread. Half of them are scheme rules (flow-knowledge section 5). diff --git a/plugins/nhcx/skills/nhcx-claim/stages/11-build-report.md b/plugins/nhcx/skills/nhcx-claim/stages/11-build-report.md new file mode 100644 index 000000000..4ea8a0806 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-claim/stages/11-build-report.md @@ -0,0 +1,64 @@ +# Stage 11: the report + +Purpose: one document a stranger can pick up to know what was built, what was found already there, what was proven, what was not, and what to do next. Written from the artefacts in `nhcx-build/`, not from memory. Its value is its honesty. + +`11-report.md` has a summary across the skills at the top and one section per skill below it. This skill writes its section and updates its row of the summary. + +## Inputs + +- Everything in `nhcx-build/`, `STATE.md` first, `NOTES.md` last +- This skill's sections of `0-capability.md`, `8-validation.md` and `10-test-run.md` + +## Do + +### 1. Read STATE.md + +Every gate row in this skill's block, and the foundation rows it built, with their evidence. A gate without evidence is reported as open, whatever you remember. + +### 2. Write this skill's section + +From `templates/11-report.md`, in this order: + +| Section | Holds | +| --- | --- | +| Capabilities | Every capability in this skill's section of `0-capability.md`: its verdict at stage 0, what was done (reused, extended, built), and its evidence after stage 8 | +| What was built | Each module part this skill built or extended, with its files and its record (`7-modules/7.N.md`) | +| Compliance | The seven points from `core/LADDER.md` for this skill's legs, each with the evidence path (the pin comparisons, the door tests, the screen tests, the rung logs) | +| The test pyramid | Per rung: passed, failed, not run, the log | +| Findings | Every failure from stages 8 and 10 with its resolution or its open state | +| Gaps | This skill's entries in `NOTES.md` folded in: what the skills did not say, what the docs did not say, what the sandbox did that no document states | +| Exceptions | Every accepted exception from stage 8 and the user's agreement | +| Runbook | How to start it, how to run the suite, how to run rungs 3 and 4, what to sweep first, where the archive and the ledger are | +| Next | The `later` legs from stage 1, the open gates, the rungs not climbed, and the skill to run next in the order `core/LADDER.md` gives | + +Then update this skill's row in the summary table: stages closed, rung reached, what it reused, extended and built, what is open. Mode, payers and "today a user can" are for the whole build; bring them up to date. + +### 3. Check the report against the rules + +- Every claim of "passes" has a log or a record path beside it. +- Every rung not run says so. +- Every capability reported as reused has its stage 8 evidence, not only stage 0's. +- No em dashes, short sentences, tables for facts. +- A stranger with this report and the target project could resume at the first open gate. + +## Write + +This skill's section of `nhcx-build/11-report.md`, and its summary row. Update `STATE.md` with the final gate. + +## Gate + +- [ ] Every section in the template is present in this skill's section. +- [ ] Every capability in this skill's section of `0-capability.md` appears under Capabilities. +- [ ] Every module part this skill touched appears in "What was built" or, if reused, under Capabilities. +- [ ] Every compliance point names evidence. +- [ ] The pyramid table matches this skill's section of `10-test-run.md`. +- [ ] This skill's entries in `NOTES.md` are folded into "Gaps" in full. +- [ ] The runbook has the start commands, the test command and the sweep. +- [ ] The summary table has this skill's row. + +## Common mistakes + +- Reporting the rung the user asked for as reached because the offline rung passed. +- Reporting a reused capability as working on the strength of stage 0 alone. +- Dropping a finding that was fixed. Fixed findings are the most useful part of the report for the next build. +- Writing the report before stage 10's logs exist. diff --git a/plugins/nhcx/skills/nhcx-claim/stages/2-planning.md b/plugins/nhcx/skills/nhcx-claim/stages/2-planning.md new file mode 100644 index 000000000..06c405cdc --- /dev/null +++ b/plugins/nhcx/skills/nhcx-claim/stages/2-planning.md @@ -0,0 +1,67 @@ +# Stage 2: planning + +Purpose: turn the idea and the capability check into this skill's schedule of gates, and add its block to the ledger every later stage writes to. This is bookkeeping, and it is short. + +## Inputs + +- `nhcx-build/1-idea.md` +- This skill's section of `nhcx-build/0-capability.md`: the verdict of every capability it owns or stands on +- `core/LADDER.md`, "The ladder"; this skill's `SKILL.md`, "The ladder, for this skill" +- `references/testing-knowledge.md` section 1 (the pyramid) and section 3 (the matrix), so the acceptance tests below are the matrix's rows and not invented ones + +## Do + +### 1. Size each stage + +For every stage 3 to 11, write one row for this skill: what it produces for this build, how big it is (small, medium, large), and what proves it done. "What proves it done" is the stage's gate, restated for this skill. + +For stage 7, list the modules this skill's `SKILL.md` names and the foundation modules, each with its verdict from stage 0 turned into an action: + +| Verdict | Action in stage 7 | +| --- | --- | +| `present` | reuse: nothing built; validated in stage 8, tested in stage 9 | +| `partial` | extend: the difference, in the existing code | +| `absent`, `unknown` | build | +| `not applicable` | nothing | + +Module 7.13 depends on the mode: + +| Module | integrate | standalone | +| --- | --- | --- | +| 7.1 to 7.12 | yes | yes | +| 7.13 standalone shell | no | yes | + +Module 7.12 (screens) is smaller in `integrate` mode when the HMIS already has patients, admissions and documents; the plan says which existing screens gain a panel and which are new. + +### 2. Order and dependencies + +The ladder is sequential by stage. Inside stage 7, foundation modules come first, then this skill's modules in the order of `stages/7-write-code/README.md`; the plan may not reorder them, because each module's validation assumes the ones before it exist. + +### 3. Risks + +Copy into a risk table the rules from `references/flow-knowledge.md` section 5 that touch this skill's legs; its `SKILL.md` names them in its stage 2 row. Each rule is a way the build fails live even when the offline tests pass. When this skill builds or extends a foundation module, add the foundation's rules too: acknowledge or lose the thread; one message is taken once (dedupe on `x-hcx-api_call_id`). Add every `partial` prerequisite from stage 0, and the build's own risks: a missing HPIN on the practitioner table, no inbound route to the HMIS, a plan master too large for the database column, a callback behind auth middleware. + +### 4. What the user must do + +List every point where the ladder stops for the user: agreeing stage 1, running an owning skill first when a prerequisite is missing, supplying participant credentials (the ABDM client id and secret), registering the participant's certificate and callback address, starting the services for stage 10 rungs 3 and 4 (the app's public callback, or nhcx-adapter when the user chose it), sweeping live pre-auths before a PMJAY run. + +## Write + +- This skill's section of `nhcx-build/2-planning.md`, from `templates/2-planning.md`. +- This skill's block in `nhcx-build/STATE.md` (created at stage 0 from `templates/STATE.md`), with a row per stage and a row per module part, each module row carrying its action. +- `nhcx-build/NOTES.md`, empty but for its heading, if it does not exist. + +## Gate + +- [ ] Every stage 3 to 11 has a row with a size and a proof, for this skill. +- [ ] Every module this skill touches, and every foundation module, has its verdict and its action; 7.13 is marked by mode. +- [ ] The risk table holds every rule this skill's `SKILL.md` names for stage 2, and the foundation's rules when this skill builds or extends a foundation module. +- [ ] The user-action list names the credentials and the service starts. +- [ ] STATE.md has this skill's block with a row per stage and per module part. + +## Common mistakes + +- Estimating in days. Estimate in size; the user turns size into time. +- Planning to skip stage 8 or 9 "for the first pass". They are what makes the report true. +- Planning to rebuild a capability stage 0 found present. +- Reordering modules so screens come first. Screens derive from messages; without readers there is nothing to derive from. diff --git a/plugins/nhcx/skills/nhcx-claim/stages/3-discovery.md b/plugins/nhcx/skills/nhcx-claim/stages/3-discovery.md new file mode 100644 index 000000000..9feb26eca --- /dev/null +++ b/plugins/nhcx/skills/nhcx-claim/stages/3-discovery.md @@ -0,0 +1,97 @@ +# Stage 3: discovery + +Purpose: find the surface you will build on. In `integrate` mode that is the HMIS; in `standalone` mode it is the runtime, the storage and the deployment target the user has chosen. Every answer names the file, table or endpoint that proves it. An answer without proof is a gap. + +`3-discovery.md` is shared by the seven skills: one row per concern, each naming the skill that answered it. This skill answers the rows its `SKILL.md` lists under "Host facts", and the framework and runtime rows if no skill has. A row an earlier skill answered with proof is reused; check it again only if the code changed since. + +Stage 0 looked for NHCX capabilities. This stage looks at the host: where patients, admissions, doctors, documents and bills live. + +## Inputs + +- `nhcx-build/1-idea.md`, `nhcx-build/2-planning.md`, this skill's section of `nhcx-build/0-capability.md` +- This skill's `SKILL.md`, "Host facts" +- The target codebase (integrate) or the chosen runtime (standalone) +- `stages/7-write-code/7.2-storage.md` (the claim tables) and `stages/7-write-code/7.13-standalone-shell.md` (patient, encounter, practitioner, document), as the shape to compare against + +## Do + +Answer in writing every question below that this skill's host facts name, plus the framework and runtime questions when they are not yet answered. Reading only; change nothing. + +### Framework and runtime + +| Question | Why it matters | +| --- | --- | +| Language, web framework, ORM, database engine, migration tool | Where a new table goes and how it is created | +| How configuration is read (env, file, database) | Where the transport's settings live: the participant code, and the client id and secret and the private key (`own`), or the adapter URL and key (`adapter`) | +| How the app exposes an HTTP endpoint an outside process can POST to; which auth middleware must be exempted | The callback door, module 7.3 | +| Background worker or scheduler, or none | Whether polls run on the request path or in a worker | +| How the app serves a page and what the screen conventions are | Module 7.12 must match them | +| How tests are run and where they live | Stage 9 must match them | + +### Patients + +| Question | Why it matters | +| --- | --- | +| The patient table, its primary key, the unique identifier (MRN) | `claim.patient_id` | +| Where name, gender, date of birth, phone, ABHA number live | The Patient resource in every bundle | +| Where a scheme member id (PMJAY id) and a policy code can be stored, per patient or per visit | The Coverage resource; the policy search result | + +### Admissions and encounters + +| Question | Why it matters | +| --- | --- | +| The inpatient encounter table: admission time, discharge time, ward or bed, admitting doctor, status | `billablePeriod`, `ONS/ADDD`, the care team | +| How discharge is recorded, and whether it can carry a mode (normal, LAMA, DAMA, death) and a stage (before, during, after surgery) | `DIS` and `DSDE` on the claim; the LM100 collapse | +| Diagnoses: SNOMED, ICD-10 or free text | The payer needs ICD-10 with a display | +| Procedures or surgeries, and whether a surgery time is recorded | `ONS/PSP` | + +### Billing + +| Question | Why it matters | +| --- | --- | +| Billing lines: code, quantity, unit price, net; which charge master | Lines are quoted from the payer's plan, not the HMIS master, but the two must be reconcilable | +| Whether a line can be tagged with a payer package code and a category | `claim_line` | +| Invoices and receipts: where a settlement amount and a UTR go | Payment notices, module 7.10 | + +### Documents + +| Question | Why it matters | +| --- | --- | +| Where PDFs and images live (blob column, filesystem, object store) | `valueAttachment` needs the bytes and the content type | +| Whether a file can be tagged with a payer document code and a stage (pre-auth or claim) | The plan's requirement codes; never `ODN` for a file that was asked for by name | +| Accepted content types | The scheme takes pdf, jpg, jpeg, png only (PAYR-1008) | + +### Doctors + +| Question | Why it matters | +| --- | --- | +| The practitioner table; an HPR id (HPIN); a licence number; a qualification string | PMJAY refuses a pre-auth without an HPIN typed identifier (PAYR-1083) | + +### Facility + +| Question | Why it matters | +| --- | --- | +| The facility's HFR id, name, phone; its NHCX participant code | The provider Organization; the sender code | + +### Standalone mode + +The same questions, answered for the runtime the user chose. Where the answer is "nothing exists yet", write what module 7.13 will create: `patient`, `encounter`, `practitioner`, `document`, `settings`. A standalone app still has to hold every fact the questions ask for; it simply has to capture it itself. + +## Write + +`nhcx-build/3-discovery.md` from `templates/3-discovery.md`: one table, concern by concern, columns `Concern | Where it lives (proof) | Gap | Answered by`. A gap is what stage 4 fills. Add rows; do not rewrite another skill's rows. + +## Gate + +- [ ] Every host fact this skill's `SKILL.md` names has a row, and so does every framework and runtime question. +- [ ] Every row that is not a gap names a file path, a table, or an endpoint. +- [ ] When this skill builds or extends the callback door, the callback route is answered: which URL, which middleware to exempt, or "no inbound route, poll only". +- [ ] When this skill's bundles carry a Practitioner, the HPIN question is answered; if the practitioner table has no HPR id, the gap says so. +- [ ] When this skill attaches documents, the document store is answered with content-type handling. + +## Common mistakes + +- Answering from the framework's documentation instead of the codebase. The proof column is the codebase. +- Skipping the discharge-mode question. A death claim without `DTM` is refused (PAYR-1096); the HMIS must be able to say the patient died and when. +- Treating "no background worker" as a blocker. Without one, polls run on the request path; it is a design input, not a stop. +- Answering every concern for every skill. Answer the ones this skill needs; the next skill adds its own. diff --git a/plugins/nhcx/skills/nhcx-claim/stages/4-flow-and-data-mapping.md b/plugins/nhcx/skills/nhcx-claim/stages/4-flow-and-data-mapping.md new file mode 100644 index 000000000..bf51c7991 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-claim/stages/4-flow-and-data-mapping.md @@ -0,0 +1,92 @@ +# Stage 4: flow and data mapping + +Purpose: decide where every fact the exchange needs comes from and where every fact the exchange returns goes, leg by leg. This is the design stage with the most rows; get it right and stages 6 and 7 are transcription. + +Two parts of this stage belong to the episode, not to one skill: the flow table (section 1) and the home of every table (section 2), with the matching order (section 4). The first skill to run this stage writes them whole, so every later skill builds on one design; a later skill checks them and adds only what its gaps need. The field mapping (section 3) is this skill's own bundles only. + +## Inputs + +- `nhcx-build/1-idea.md` (scope), `nhcx-build/3-discovery.md` (the surface and its gaps), this skill's section of `nhcx-build/0-capability.md` (what exists already) +- This skill's `SKILL.md`: its steps, legs, bundles and tables +- `flow/FLOW.md` and `flow/flow.json`: the steps this build implements. They are copied, not redesigned. +- `references/flow-knowledge.md` sections 1, 2, 4 and 5 +- `references/transport-knowledge.md` section 2 (what a send returns, what arrives at the door) +- `references/fhir-knowledge.md` sections 3 to 10 (what each bundle needs); `fhir/FHIR.md` for the exact elements, as the builders' data dictionaries name them +- `stages/7-write-code/7.2-storage.md`: the claim tables and the columns each must hold + +## Do + +### 1. The flow, for this build + +The first skill copies every step of `flow/flow.json` into the flow table, in order, with its id and its skills, and adds two columns for this build: the HMIS event it hangs off (admission, discharge, a desk action) and the mark from stage 1 (`in`, `later`, `out`). The steps, their order, their tabs, their guards and their action labels are the flow's; this build adds where each fact comes from, nothing else. Then note the payer branches as the flow has them (F9b, F11, F12: `19`/`131`/`161` resubmits against a Communication reply; `17` against an echoed id). The stage and sub-stage vocabulary is copied as is; do not rename it. + +Write the step ids into `mapping.json` under `flow.steps` and the eight tabs, in order and with their labels, under `flow.tabs`. + +A later skill checks its own steps' rows and fills their HMIS event where the first skill left it open. + +### 2. The episode tables + +The first skill gives every table below a home, not only its own. The home is one decision for the episode (sidecar tables, or columns on the HMIS's tables), and a skill that chose differently later would split the design. It writes the columns each table must hold, and the legs' columns under `legs`. Later skills read the homes and add only the columns their gaps need. + +For each table below, decide one of three homes and write it down: + +| Home | When | +| --- | --- | +| A new sidecar table keyed on the HMIS's own ids | Default. Keeps the HMIS schema untouched and the integration removable. | +| Columns added to an existing HMIS table | Only for a scalar the HMIS already half-holds (a member id on the visit, an HPIN on the doctor) | +| An existing table used as is (`existing`) | Only when it already holds every column named below. This is the home of a capability stage 0 found present: record its real name and its columns, and a gap for each column it lacks | + +| Table | Why it exists | Must hold | +| --- | --- | --- | +| `claim` | The episode: beneficiary, policy, payer, eligibility verdict, link to the admission, pre-auth draft, stage and sub-stage | claim number, member id, policy code, payer participant code, patient and encounter keys, `txn_id`, `correlation_id`, `stage`, `sub_stage` | +| `claim_plan`, `claim_plan_benefit`, `claim_plan_form` | The payer's package master, flattened; one per facility and policy, copied onto later episodes | packages with rate, kind, conditions, extras (tiers, implants), document requirements; questionnaires by url | +| `claim_auth`, `claim_auth_item`, `claim_auth_requirement` | The auth-requirements ruling on the quoted set | per line: authorised, excluded; per requirement: kind (document or form), code, url, stage | +| `claim_line` | What is quoted: procedures, implants, ward tiers with a parent procedure | code, kind, quantity, unit price, amount, parent code | +| `claim_form_answer` | Answers to the plan's questionnaires | url, linkId, answer, stage | +| `claim_preauth` | The pre-auth leg, one row rewritten each round (12, 19, 13, 131) | status, `txn_id`, `correlation_id`, `thread_correlation_id`, `api_call_id`, `preauth_ref`, `submission_kind`, `workflow_id`, request and response json, cancel fields | +| `claim_submission` | The claim leg plus the discharge | discharge mode, stage, dates; the same exchange columns as the pre-auth | +| `claim_query` | Every CommunicationRequest or Communication from the payer, classified | `correlation_id` (unique), request id, kind, reason code, status, reply fields | +| `claim_payment`, `claim_payment_detail` | Payment notices, matched by claim number, deduped by correlation id | amount, UTR, payment status, ack fields | +| `claim_enquiry` | Status, reprocess and release Tasks, one row per ask | kind, `correlation_id`, answer | +| `claim_predetermination` | A quote, one row per ask | as a pre-auth, without state effects | +| `claim_document` | Attachments with the payer's code, category and stage | bytes or a pointer, content type, code, stage | +| `claim_diagnosis`, `claim_care_team`, `claim_item` | ICD-10 codes, doctors, non-package items | as named | + +The rule that never bends: every leg row holds `txn_id`, `correlation_id` and `api_call_id` from the transport's answer, and `thread_correlation_id` separately, because a send refused at the door must not lose the thread the payer last answered on. + +### 3. Field mapping, per bundle + +For each bundle this skill sends (its `SKILL.md` lists them; `fhir-knowledge.md` sections 3, 4, 5, 7, 9, 10), one table: `FHIR element | Source (table.column or constant or payer answer) | Transform | Gap`. Do not fill values; name sources. The elements that are always mapped from a payer answer and never from the HMIS: package codes and rates (the plan), document codes and questionnaire urls (the plan or the ruling), `preAuthRef` (the ClaimResponse), the payer's own case number. + +For each bundle this skill reads (sections 6, 8, 9, 10 and the coverage answer in section 3), one table: `FHIR element | Destination | Rule`. The status rule for a ClaimResponse is `verdict_status`, copied verbatim; never read `outcome` alone. + +Where stage 0 found a builder or reader present, map what it does today, and name each element where it differs from the pin as a gap. + +### 4. Inbound matching + +Written once, by the first skill. Write the matching order as a numbered list: `x-hcx-correlation_id` against every leg table; then the claim number inside the bundle; then unmatched, archived, 2xx returned. Write the dedupe key: `x-hcx-api_call_id`. Write the archive path: `//NNN--.json` plus `transactions.txt`. A later skill adds its leg tables to the correlation order. + +## Write + +- `nhcx-build/4-flow-data-mapping.md` from `templates/4-flow-data-mapping.md`. The first skill writes the flow table, the table homes and the matching order at the top; each skill writes a section headed with its name holding its field mappings. +- `nhcx-build/mapping.json` in the shape of `templates/mapping.json`. The first skill writes `flow`, `episode`, `tables`, `legs` and `inbound` whole; every skill adds its bundles under `bundles`, each entry with `"skill"`. Stage 6 reads it. + +## Gate + +- [ ] The flow table has every step of `flow/flow.json`, in its order, with its id, its skills and an in/later/out mark; `mapping.json` `flow.steps` lists every id and `flow.tabs` the eight tabs verbatim. +- [ ] Every table above has a home in `mapping.json` under `tables`. +- [ ] Every leg table's columns in `mapping.json` include `txn_id`, `correlation_id`, `api_call_id` and `thread_correlation_id`. +- [ ] `mapping.json` `episode.columns` includes `stage` and `sub_stage`. +- [ ] Every bundle this skill sends has a source table; every element with no source is listed as a gap, not omitted. +- [ ] Where this skill's bundles carry a Practitioner, the HPIN element's source is named (or its gap is). +- [ ] Every capability stage 0 found present is mapped to what exists, with its differences from the pin as gaps. +- [ ] The matching order, the dedupe key and the archive path are written. + +## Common mistakes + +- Redesigning the flow: merging tabs, adding a "status" step, moving the discharge out of the claim tab. The flow is the reference flow; copy it. +- Giving homes only to this skill's tables when it is the first to run the stage. The next skill would choose differently. +- Mapping package rates to the HMIS charge master. Prices come from the plan; the master is for reconciliation. +- One `correlation_id` column on the episode instead of one per leg. Each leg is its own thread. +- Forgetting `thread_correlation_id`. It is the difference between a recoverable door refusal and a dead case. +- Mapping `Patient` demographics on the coverage request. Only the member id goes out; the payer returns the rest. diff --git a/plugins/nhcx/skills/nhcx-claim/stages/5-screen-plan.md b/plugins/nhcx/skills/nhcx-claim/stages/5-screen-plan.md new file mode 100644 index 000000000..9ec0d8bc2 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-claim/stages/5-screen-plan.md @@ -0,0 +1,74 @@ +# Stage 5: screen plan + +Purpose: decide the screens, and for every value on every screen, the received message it is derived from. The two honesty rules are the whole point of this stage, and a reviewer tests them before anything else. + +The case screen is the episode's (`foundation.screens`): its eight tabs, the status line and actions, the JSON state address and the cases list. The first skill to run this stage lays them out whole, every tab present with its opening condition. Each skill then plans the values and actions of its own tabs and screens, which its `SKILL.md` lists. + +## Inputs + +- `nhcx-build/1-idea.md`, `nhcx-build/3-discovery.md` (screen conventions), `nhcx-build/4-flow-data-mapping.md` +- This skill's `SKILL.md`: its tabs, its screens, its next actions +- `flow/FLOW.md` ("The shape", "The status line and the actions", every step's Screen line) and `flow/flow.json`: the screens are put on these steps, not invented. +- `references/flow-knowledge.md` section 4 (stage, sub-stage, next actions) +- `ui/UI-GUIDE.md`: the screens, a layout per screen, where every value comes from, the state words. Read it whole before planning. +- `nhcx-package/docs/03-Building a Provider/09-UI Guide.md` (the published source of the guide) + +## The two rules + +1. No screen shows a decision the exchange has not sent. Every state on every screen is derived from a stored message. A case with a request sent and no answer back reads as waiting, never approved, never rejected. That case exists only because module 7.3 kept a record of what was sent, so the screen must be able to render a leg with a request and no response. +2. Nothing the exchange already knows is typed. Payer names, policies, balances, package rates, the payer's own wording, `preAuthRef`, the approved amount, the UTR are rendered from the message that carried them. A package rate is never an editable field. + +## Do + +### 1. The screen list + +The case screen carries the eight tabs of `flow.json` `tabs`, in that order, with those labels, opening under those conditions. The status line and the action list above the tabs use the labels of `flow.json` `next_actions` verbatim. Then, minimum, once every skill has run: + +| Screen | Who | Shows | Derived from | Planned by | +| --- | --- | --- | --- | --- | +| Cases list | billing clerk | every episode, its stage and sub-stage, what it waits for | `claim.stage`, `sub_stage`, `next_actions` | the first skill | +| Case | everyone | the timeline of legs, the payer's answer verbatim, the actions open now | every leg row and its archived messages | the first skill; each skill its tabs | +| Inbox | desk | payer messages routed by kind: query, notification, note | `claim_query` | `nhcx-communication` | +| Payments | accounts | notices, deductions, UTR, reconciliation | `claim_payment`, `claim_payment_detail` | `nhcx-payment` | +| Find and cover | registration clerk | policy search, eligibility verdict, register or link | the policy search answer and the `on_check` bundle | `nhcx-coverage` | +| Plan | doctor | specialty, package, add-ons, tiers, the documents and forms the plan wants | `claim_plan_*`, `claim_auth_*` | `nhcx-insurance`, with the ruling from `nhcx-preauth` | + +`integrate` mode adds a panel to the HMIS's own admission screen linking the admission to its episode. `standalone` mode adds the capture screens module 7.13 describes (patient, admission, discharge, documents, settings). + +Where stage 0 found a screen present, plan what it shows today against the rules, and list every value that breaks one as a gap. + +### 2. Per screen, per value + +For every value on this skill's screens, one row: `Value | Message and element | Empty state`. The empty state is what the screen shows before the message arrives (for a decision: "waiting"; for a rate: nothing, the field does not exist yet). A value whose source is "the user types it" is allowed only for things the exchange cannot know: the discharge mode and dates, the desk's reply to a query, the documents, the questionnaire answers, the chosen lines. + +### 3. Actions + +Every action is one step of `flow.json` and carries its id in `step`. For every action this skill's screens offer, the leg it sends, the sub-stage that must hold for it to be offered, and the sub-stage it moves to. Take the offered-when rules from `next_actions` in flow-knowledge section 4: an unanswered query always leads; the reply box is offered only to a `resubmit` payer; after a rejection the pre-auth offers a fresh 12, not 121. + +### 4. Addresses and conventions + +Write the route for each screen in the HMIS's own style (from stage 3). The state of a case must also be readable as JSON at one address, because stage 10 drives the screens through it (for example `GET /claims//state`). Each skill adds its legs to what the address returns. + +## Write + +- `nhcx-build/5-screen-plan.md` from `templates/5-screen-plan.md`: the shell at the top (first skill), then a section per skill. +- `nhcx-build/screens.json` in the shape of `templates/screens.json`: the first skill writes `rules`, `tabs`, `state_address`, the cases list and the case screen; each skill adds its screens and actions. + +## Gate + +- [ ] `screens.json` `tabs` lists the eight tabs of `flow.json` in order with the same keys and labels. +- [ ] Every user-driven step this skill owns (its steps among F1 to F13, except F9a, F12 and F12b, which the payer starts) appears as an action with its `step` id, and every action's `label` is one of `flow.json` `next_actions` or the step's own button. +- [ ] `screens.json` holds the cases list, the case screen, and every screen this skill plans, each with a route (plus 7.13's in standalone mode). +- [ ] Every screen this skill plans has a `values` list and every value names a message element or is marked `typed` with a reason from the allowed list. +- [ ] Every decision-bearing value has an empty state of waiting. +- [ ] No `values` entry marks a rate, a payer name, a `preAuthRef` or a UTR as typed. +- [ ] Every action names its leg, its offered-when sub-stage and its resulting sub-stage. +- [ ] A JSON state address exists for a case. + +## Common mistakes + +- A status dropdown on the case. Status is derived; there is no dropdown. +- Showing `preAuthRef` from the pre-auth's own claim number. It comes from the ClaimResponse. +- Designing the desk's reply box for a `communication` payer on the leg. It belongs on the inbox item. +- Laying out only this skill's tab when it is the first to run the stage. The shell has all eight. +- Screens that need JavaScript. Forms post and the page re-renders; that is enough. diff --git a/plugins/nhcx/skills/nhcx-claim/stages/6-code-plan.md b/plugins/nhcx/skills/nhcx-claim/stages/6-code-plan.md new file mode 100644 index 000000000..2167000f1 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-claim/stages/6-code-plan.md @@ -0,0 +1,68 @@ +# Stage 6: code plan + +Purpose: turn the mapping, the screen plan and the capability verdicts into a list of modules with files, dependencies, the pin each is held to, and what this skill does to each. Stage 7 builds this list in order; stage 8 validates it in order. + +The transport's shape, the configuration, the archive and the test placement (sections 2 to 5) are the episode's: the first skill to run this stage writes them, and later skills use them. + +## Inputs + +- `nhcx-build/3-discovery.md`, `nhcx-build/4-flow-data-mapping.md`, `mapping.json`, `nhcx-build/5-screen-plan.md`, `screens.json` +- This skill's section of `nhcx-build/0-capability.md` and `nhcx-build/2-planning.md` (the action per module) +- `stages/7-write-code/README.md` and every `7.N-*.md` this skill touches: the module ladder is fixed; the plan decides the files +- `references/fhir-knowledge.md` section 1: where the pins live +- `fhir/FHIR.md`: the builders and readers the modules 7.4 to 7.10 implement, so the plan names them + +## Do + +### 1. Place each module + +For each module this skill touches (its `SKILL.md` lists them) and each foundation module it builds or extends, write: + +| Field | Meaning | +| --- | --- | +| `skills` | A map from skill to action: `build`, `extend` or `reuse`. A module another skill already placed keeps its entry; add this skill and its action | +| `files` | The files it creates or changes, in the target's layout and naming (from stage 3). For a reused or extended module, the files that exist | +| `depends_on` | The modules that must exist first; the ladder's order is the floor, the plan may add more | +| `held_to` | The pin in `nhcx-package/fhir` (its file, from `references/material.md`), the payer fixture, or the rule (for modules with no bundle) | +| `copy_from` | What the module follows: its own Pseudo code section and the `fhir/FHIR.md` section it names | +| `tables` | The tables from `mapping.json` it reads and writes | +| `screens` | The screens from `screens.json` it serves (7.12 and 7.13 only) | + +`modules.json` holds one entry per module, in ladder order (7.1 to 7.13), whichever skill adds it. + +### 2. The transport's shape + +Decide once, and every module uses it: the transport kind from stage 1, and the functions of the contract in `references/transport-knowledge.md` section 2: `send`, the receiving end that hands the door a normalised envelope, `policies`, `participants`, `token`, and `thread` and `fetch_missed` where the kind has them. Name them here so 7.4 to 7.10 call the same thing. A stub of `send`, recording the path, recipient, workflow id, correlation id and bundle and returning `{"txn_id", "correlation_id", "api_call_id"}`, is what stage 9 injects. When stage 0 found an existing transport, name its functions and what wraps them. + +### 3. Configuration + +List every setting and where it lives (from stage 3): the transport kind, participant code, facility HFR id and name, cases directory, per-payer overrides for workflow ids, and the transport's own. For `own`: the ABDM client id and secret, the private key, the sessions, NHCX and registry addresses, and the NHCX signing key once onboarding gives it. For `adapter`: its URL, API key and callback secret. For `existing`: whatever its client reads. Name the environment variables or config keys in the target's convention. + +### 4. The archive + +The per-case archive path from stage 4, and which module writes it (7.3 for inbound, 7.1 for outbound). + +### 5. Test placement + +Where the offline test lives (from stage 3's "how tests are run"), and how the pin comparison is wired: canonical JSON, `created` excluded, one comparison per pin. + +## Write + +- `nhcx-build/6-code-plan.md` from `templates/6-code-plan.md`: the episode sections once, the modules table, and this skill's section. +- `nhcx-build/modules.json` in the shape of `templates/modules.json`. + +## Gate + +- [ ] `modules.json` has an entry, in ladder order, for every module this skill touches and every foundation module (7.13 in standalone mode). +- [ ] Every entry this skill touches has non-empty `files`, `depends_on` (7.1 may be empty), `held_to` and `copy_from`, and this skill in `skills` with its action. +- [ ] Every pin this skill owns appears in some module's `held_to`. +- [ ] The transport kind and its functions are named. +- [ ] The configuration list includes the transport kind, the participant code, the cases directory, and every setting the chosen transport needs. +- [ ] The test file's location and the pin comparison rule are written. + +## Common mistakes + +- Splitting the claim bundle builder across modules by leg, or by skill. One builder, one `leg` and `flow` argument, is what the pins expect; `nhcx-claim` extends what `nhcx-preauth` built. +- Planning a second transport for the reply legs. Same function; the reply legs add `x-hcx-correlation_id` to the headers. +- Planning new files for a module stage 0 found present. +- Planning the screens before the readers exist in the dependency list. diff --git a/plugins/nhcx/skills/nhcx-claim/stages/7-write-code/7.1-config-and-transport.md b/plugins/nhcx/skills/nhcx-claim/stages/7-write-code/7.1-config-and-transport.md new file mode 100644 index 000000000..2ad046569 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-claim/stages/7-write-code/7.1-config-and-transport.md @@ -0,0 +1,131 @@ +# Module 7.1: configuration and the NHCX transport + +Purpose: the one path every message leaves by, whichever transport carries it. The settings, the transport chosen at stage 1 behind one `send`, the policy lookup, and the outbound half of the per-case archive. + +Skills: the foundation (`core/FOUNDATION.md`). Built whole by the first skill whose stage 0 finds it absent; every skill sends through it. + +## Depends on + +Nothing. First module. + +## Inputs + +- `nhcx-build/1-idea.md`: the transport, `existing`, `own`, or `adapter` because the user asked for it +- `nhcx-build/6-code-plan.md` sections 2 to 4 (the transport's functions, the configuration keys, the archive path) +- `references/transport-knowledge.md` section 2 (the contract), and section 3 (`own`), 4 (`existing`) or 5 (`adapter`) for the kind chosen +- With `adapter` only: `references/api-knowledge.md` sections 2 to 5, 7, 8 and 11 + +## Build + +### Settings + +Read from the target's configuration mechanism (stage 3). + +| Setting | Transport | Meaning | +| --- | --- | --- | +| transport kind | all | `existing`, `own` or `adapter` | +| participant code | all | The hospital's, with `@hcx`: `x-hcx-sender_code` | +| facility HFR id, name, phone | all | The provider Organization | +| cases directory | all | The per-case archive root | +| per-payer workflow id overrides | all | Optional, for a payer that insists on a code the table does not carry (`cancel` as 122) | +| ABDM client id and secret | own | The session token (`transport-knowledge.md` section 3.3) | +| private key | own | The PEM behind the certificate on the participant record, read from a file or a secret store | +| sessions, NHCX and registry addresses, `X-CM-ID` | own | From `nhcx-package/baseurl.yaml`; the sandbox by default | +| NHCX signing key | own | For the exchange's JWT on inbound calls. Empty until onboarding gives it, and logged while empty | +| adapter URL, adapter API key, callback secret | adapter | `references/api-knowledge.md` section 2. Also fill the adapter's `config.sample.json` into `nhcx-build/adapter.config.json`, secrets as `${ENV}` placeholders | +| whatever the existing client reads | existing | Named here, not duplicated | + +Secrets are read from configuration: never in code, never in `nhcx-build/`. + +### The transport + +One `send` with the signature in `transport-knowledge.md` section 2, and beside it `policies`, `participants`, `token`, `thread` and `fetch_missed`. What sits under them depends on the kind: + +| Kind | `send` | `policies`, `participants`, `token` | `thread`, `fetch_missed` | +| --- | --- | --- | --- | +| `own` | Seal and post (`transport-knowledge.md` sections 3.3 to 3.8): the token, the recipient's certificate, the protected header, a compact JWE, `{"payload"}` to `/v1/`, a `401` retried once | The participant service directly (sections 3.6 and 3.7) | `thread` reads the per-case archive; `fetch_missed` answers `unavailable` | +| `existing` | Calls the app's own client and maps its answer onto `{txn_id, correlation_id, api_call_id}` (section 4) | The app's own calls, or the participant service directly | What the app keeps; else as `own` | +| `adapter` | POSTs `{jwe_headers, fhir}` to `/fhir/out/` with the bearer key (`api-knowledge.md` sections 4 and 5) | `/internal/policies/search`, `/internal/participants/list`, `/token` | The adapter's ledger and `/internal/txn/*` (`api-knowledge.md` sections 7 and 8) | + +Common to every kind: + +1. A send without a recipient, a workflow id or the beneficiary's ABHA is refused before anything goes on the wire. +2. The recipient is the policy's processor: `recipient_of(row)` is `claim.recipient_code`, else `claim.payer_code` for an episode opened before the processor was kept. +3. A correlation id is passed only on the two answer legs, the communication reply and the payment acknowledgement. On a request the transport mints it (`own`: the message's own `api_call_id`). +4. A refusal raises `TransportError(code, message, protocol_response, retryable)`: the gateway's status and body (`own`), the adapter's `error.code` and `upstream_body` (`adapter`), or the existing client's error. A ProtocolResponse inside it is a refusal at the door; the caller records the payer's words. +5. The outbound message is archived before `send` returns: `//NNN--out.json` with what was sent and what came back, and a `transactions.txt` line (sequence, time, direction, path, workflow id, correlation id, api call id, txn id, outcome). With `own`, the archive entry is the `txn_id`. +6. The caller stores `txn_id`, `correlation_id` and `api_call_id` on the leg. + +## Rules + +- Use nhcx-adapter only when the user asked for it; `1-idea.md` records their words. Never propose it. +- Keep an existing NHCX integration and wrap it. Never put a second transport beside it. +- Seal and open JWEs only for `own`, and only with a JOSE library: `RSA-OAEP-256`, `A256GCM`, compact serialisation. Never hand-roll the cryptography. +- The workflow id goes out on every leg that has one; `x-hcx-ben-abha-id` goes out on every message. +- The sandbox refuses sends faster than one per 30 seconds per case (PAYR-1322). The transport does not throttle; the caller does. Say so in the docstring. +- The private key never leaves the server that receives callbacks, and never enters a log. + +## Validate + +- [ ] A send with no recipient, no workflow id or no beneficiary ABHA is refused before anything goes on the wire. +- [ ] The protected header of a send carries every mandatory field under the protocol's rules: sender and recipient with `@hcx`, a fresh `api_call_id`, a `correlation_id` equal to the `api_call_id` on a request and to the request's on an answer, the workflow id, `x-hcx-timestamp` in ISO 8601 with `+05:30`, `x-hcx-status` `request.initiated` or `response.complete`, and `x-hcx-ben-abha-id`. Observed on what the transport emits: the JWE header opened with a test key pair (`own`), the posted `jwe_headers` with the adapter's completion rules (`adapter`), the existing client's output (`existing`). +- [ ] The recipient is the episode's `recipient_code`, the policy's `processingid`, whenever the episode has one. +- [ ] A refusal raises `TransportError` carrying the code and the words the exchange or the adapter gave. With `own`, a `401` is retried once with a fresh token, and a second `401` raises. +- [ ] The archive file and the `transactions.txt` line exist after a send, with the sequence number zero-padded to three digits. +- [ ] Secrets are read from configuration, not present in code or in `nhcx-build/`. +- [ ] With `own`: a bundle sealed for a test certificate opens with its private key to the same bytes and the same protected header; the token is reused while fresh and fetched again when stale; a recipient's certificate is fetched once and then read from the cache. + +## Tests + +- Stub the HTTP layer and assert the URL, the headers and the body of one send with and one without a correlation id: `bearer_auth` and `{"payload"}` for `own`; the bearer key and `{jwe_headers, fhir}` for `adapter`. +- `own`: seal with a test key pair and open it again; check the header fields above; a `401` then a `202` sends twice with two tokens; a certificate in SPKI form loads as well as an X.509 one. +- `adapter`: a `502` with a ProtocolResponse `upstream_body` raises an error whose text carries the payer's `x-hcx-error_details` message; a `404` from `txn/related` is terminal, not retried. +- The archive sequence increments across two sends on one case. + +## Pseudo code + +The `own` transport's token, certificate cache, sealing and receiving end: `references/transport-knowledge.md` section 3.12. The adapter client: `references/api-knowledge.md` section 11. What every kind shares: + +``` +settings = { + transport: env("NHCX_TRANSPORT", "own"), # own | existing | adapter; adapter only when the user asked for it + participant_code: env("NHCX_PARTICIPANT_CODE"), # "@hcx" + facility: {hfr_id: env("NHCX_HFR_ID"), name: env("NHCX_FACILITY_NAME"), phone: ...}, + cases_dir: env("NHCX_CASES_DIR", "data/cases"), + workflow_overrides: parse_json(env("NHCX_WORKFLOW_IDS", "{}")), # {"1518@hcx": {"cancel": "122"}} + nhcx: {sessions: env("NHCX_SESSIONS_URL", "https://dev.abdm.gov.in/api/hiecm/gateway/v3/sessions"), # own + base: env("NHCX_BASE_URL", "https://apisbx.abdm.gov.in/hcx"), + registry: env("NHCX_REGISTRY_URL", "https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice"), + cm_id: env("NHCX_CM_ID", "sbx"), + client_id: env("NHCX_CLIENT_ID"), client_secret: env("NHCX_CLIENT_SECRET"), + private_key: read_secret(env("NHCX_PRIVATE_KEY_FILE")), signing_key: env("NHCX_SIGNING_KEY", "")}, + adapter: {url: env("NHCX_ADAPTER_URL"), api_key: env("NHCX_ADAPTER_API_KEY"), # adapter only + callback_secret: env("NHCX_CALLBACK_SECRET")}, +} + +transport = {"own": OwnTransport, "existing": ExistingTransport, "adapter": AdapterTransport}[settings.transport]() +# each offers send, policies, participants, token, thread, fetch_missed (transport-knowledge.md section 2) + +function recipient_of(row): return row.recipient_code or row.payer_code + +function ben_abha(claim_no): # the payer's Patient from the coverage answer, else the HMIS patient + row = claim_by_no(claim_no) + return digits(abha_in(row.patient_json) or patient(row.patient_id).abha) + +function with_hcx(code): return code if code.endswith("@hcx") else code + "@hcx" + +# the archive, outbound half; 7.3 writes the inbound half through the same function +function archive.record(claim_no, usecase, direction, payload): + folder = settings.cases_dir + "/" + (claim_no or "unmatched"); mkdir(folder) + n = next_sequence(folder) # 001, 002, ... + write(folder + f"/{n:03d}-{usecase}-{direction}.json", pretty(payload)) + append(folder + "/transactions.txt", f"{n:03d} {now()} {direction} {payload.path} wf={payload.workflow_id} " + f"cid={payload.correlation_id} acid={payload.api_call_id} txn={payload.txn_id} {payload.outcome}") + return f"{claim_no or 'unmatched'}/{n:03d}" +``` + +## Done when + +- Validate passes for the transport chosen. +- `own`: the onboarding the user must do is written into `nhcx-build/7-modules/7.1.md`: the credentials, the key and certificate, the participant record, the `endpoint_url`, and the NHCX signing key to ask NHA for. `adapter`: `nhcx-build/adapter.config.json` exists with placeholders. `existing`: the wrapper and every gap it closed are listed. +- `nhcx-build/7-modules/7.1.md` is written. diff --git a/plugins/nhcx/skills/nhcx-claim/stages/7-write-code/7.10-communication-and-payment.md b/plugins/nhcx/skills/nhcx-claim/stages/7-write-code/7.10-communication-and-payment.md new file mode 100644 index 000000000..271d56732 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-claim/stages/7-write-code/7.10-communication-and-payment.md @@ -0,0 +1,124 @@ +# Module 7.10: communication and payment + +Purpose: the two legs the payer starts. A CommunicationRequest is classified as a query, a notification or a note and answered accordingly; a PaymentNotice is recorded, matched to its claim, and acknowledged. + +Skills: `nhcx-communication` (classification, the notification acknowledgement, the reply) and `nhcx-payment` (the payment notice and its acknowledgement). Validate rows 1, 3, 4 and 5 are the communication half's; rows 2, 6 and 7 the payment half's; row 8 is both. + +## Depends on + +7.1 to 7.3, 7.7, 7.11 (for the payer's query mode; build 7.11's adapter table first if not yet). + +## Inputs + +- `references/flow-knowledge.md` section 3 (the two payer kinds, the classification rule) and section 1 rows "Payment notice" and "Communication" +- `references/fhir-knowledge.md` sections 9 and 10 +- Pins: `nhcx-package/fhir/B4/communication-request.json` (the payer's message), `B4/communication-response.json` (the reply), `nhcx-package/fhir/B7/payment-notice-ack.json` +- Payer messages: `nhcx-package/fhir/C6/C6-preauth-query-wf24.json` and `C6/C6-claim-query-wf27.json` (generic queries), `C6/C6-notification-wfN02.json` (PMJAY notification), `nhcx-package/fhir/C9/*.json` (payment notices) + +## Build + +### Classification + +`classify_communication(adapter, reason_code, intent) -> kind`, in order: a `resubmit` payer's request is a notification; `intent proposal` is a notification, `order` a query; then `reasonCode`: absent, `additionalinfo`, `questionnaire`, `query` is a query, anything else (`tatquery`, `grievance`, `walletupdate`, `policychange`, `claimarbitration`, with `claimArbitartion` folded in) a notification. A bare `Communication` with no request is a note: recorded, shown, never acted on. + +### Receiving + +`parse_communication_request(bundle)`: the Task's status, intent, reason; the CommunicationRequest's id, `basedOn` (the Claim), one question per `payload[].contentString`; the leg asked about (from the Claim's `use` or the `basedOn` identifier). Store a `claim_query` row keyed on the message's correlation id with `kind`, `stage`, `questions_json`, status `open`. + +### Acknowledging a notification + +`build_acknowledgement_bundle(query_id)`: the payer's own bundle sent back with `Task.status` flipped to `completed`, the reason echoed and the provider Organization first, on `v1/communication/on_request` with the request's correlation id and workflow id echoed in `jwe_headers`. Sent by `acknowledge_notification` from outside the callback (the desk's next request, or a worker). Status `acknowledged`. + +### Answering a query (communication payer) + +`build_communication_bundle(query_id, text, document_ids)`: a TaskBundle with a Task `deliver`, `completed`, including the Communication; the Communication `basedOn` the request (never `inResponseTo`) and `about` the Claim, its text a `contentString`, each document a `contentAttachment` under the document-type extension (its url is participant-defined: read it from configuration; the pin comparison takes the pin's own url); the CommunicationRequest echoed; then the Claim, Patient, provider Organization, payer Organization, Practitioner and Coverage lifted from the queried leg's bundle as sent. This bundle carries `meta.lastUpdated` and `timestamp` (the IG example does). Sent on `v1/communication/on_request` with the request's correlation id and workflow id. Status `answered`. + +For a `resubmit` payer the answer is not here: it is 7.7's query answer on a fresh thread. The inbox item for a PMJAY query is the leg's `query_note`, and its reply box calls `submit_preauth` or `submit_claim` with the reply. + +### Payment notice + +`parse_payment_notice(bundle)`: `PaymentNotice.amount`, `paymentStatus`, `paymentDate`, the `request` reference's identifier (the claim number), `payment` identifier (the UTR when settled), the `PaymentReconciliation` details when present. `record_payment` matches the claim number, dedupes on the correlation id, stores `claim_payment` and `claim_payment_detail`, and stamps the episode `payment`/`noticed` or `paid`. + +### Payment acknowledgement + +`build_payment_ack(payment_id)`: a TaskBundle in the shape of `B7/payment-notice-ack.json`, sent on `v1/paymentnotice/on_request` with the notice's correlation id and, for PMJAY, workflow `17`; for a generic payer the notice's own workflow id echoed (`None` in the adapter table means echo). Sent by `acknowledge_payment` from outside the callback. `ack_status` `sent` or `error`. + +## Rules + +- The reply names the request in `Communication.basedOn`, never `inResponseTo`. +- A `resubmit` payer's CommunicationRequest is always a notification, whatever it says. +- A notification is acknowledged at once and the case is left alone. +- The acknowledgement and the reply are the only two sends that carry `x-hcx-correlation_id` (with the payment acknowledgement). + +## Validate + +- [ ] `B4/communication-response.json` pin: the builder fed the request pin (`B4/communication-request.json`) and the pre-auth pin (`B3/preauth-request.json`) produces the response pin byte for byte (`meta.lastUpdated`, `timestamp` and `authoredOn` excluded). +- [ ] `B7/payment-notice-ack.json` pin comparison passes. +- [ ] Classification: the generic query (`C6/C6-preauth-query-wf24.json`: `intent order`, `additionalinfo`) is a query; the PMJAY notification (`C6/C6-notification-wfN02.json`: `intent proposal`, `information`) is a notification; the same PMJAY bundle under a `communication` adapter with `intent order` is a query; a bare Communication is a note. +- [ ] The reply's `Communication.basedOn` names the request and `inResponseTo` is absent. +- [ ] The acknowledgement and the reply carry `x-hcx-correlation_id` equal to the request's; the workflow id is echoed. +- [ ] Two deliveries of one notice create one `claim_payment` row. +- [ ] The PMJAY acknowledgement carries workflow `17`; the generic one echoes the notice's. +- [ ] No send happens inside the callback (7.1 stub sees zero sends during receipt). + +## Tests + +- The two pin comparisons. +- Classification table as a parametrised test. +- B6, B7, C6, D8, D13 and the notification rows from the matrix. + +## Pseudo code + +Classification, the acknowledgement, the reply and the payment reader: `fhir/FHIR.md` sections 7 and 8. Wiring: + +``` +APPLY["inbound_request"] = function (row, env): + kind = resource_types(env.fhir) + if "PaymentNotice" in kind: record_payment(row, env) + elif "CommunicationRequest" in kind: receive_communication(row, env) + elif "Communication" in kind: record_note(row, env) # a bare Communication: shown, never acted on + +function receive_communication(row, env): + p = fhir.parse_communication_request(env.fhir); adapter = payers.for_claim(row) + kind = fhir.classify_communication(adapter, p.reason, p.intent) + q = insert("claim_query", {claim_id: row.id, correlation_id: env.jwe_headers["x-hcx-correlation_id"], request_id: p.request_id, + workflow_id: env.jwe_headers["x-hcx-workflow_id"], sender_code: env.jwe_headers["x-hcx-sender_code"], + kind, stage: leg_asked_about(row, p), reason_code: p.reason, intent: p.intent, questions_json: p.questions, + request_json: env.fhir, status: "open", received_at: now()}) + if kind == "notification": enqueue(acknowledge_notification, q.id) # sent outside the callback + +function acknowledge_notification(query_id): + q = query(query_id); row = claim(q.claim_id) + bundle = fhir.build_acknowledgement_bundle(q.request_json, settings.facility) + r = transport.send("v1/communication/on_request", bundle, q.sender_code, workflow_id = q.workflow_id, correlation_id = q.correlation_id, claim_no = row.claim_no, usecase = "communication-ack") + update(q, {status: "acknowledged", reply_txn_id: r.txn_id, reply_api_call_id: r.api_call_id, replied_at: now()}) + +function answer_query(query_id, text, document_ids): # communication payer + q = query(query_id); row = claim(q.claim_id) + if payers.for_claim(row).query_mode == "resubmit": return submit_preauth(row.id, reply = text) if q.stage == "preauth" else submit_claim(row.id, reply = text) + sent = (preauth(row.id) if q.stage == "preauth" else submission(row.id)).request_json + bundle = fhir.build_communication_bundle(q, text, [doc_with_bytes(i) for i in document_ids], sent, settings.facility, payer_of(row), now_ist()) + r = transport.send("v1/communication/on_request", bundle, q.sender_code, workflow_id = q.workflow_id, correlation_id = q.correlation_id, claim_no = row.claim_no, usecase = "communication-reply") + update(q, {status: "answered", reply_text: text, reply_document_ids: document_ids, reply_txn_id: r.txn_id, replied_at: now()}); stamp_case(row.id) + +function record_payment(row, env): + p = fhir.parse_payment_notice(env.fhir) + pay = insert_or_ignore("claim_payment", {claim_id: row.id, correlation_id: env.jwe_headers["x-hcx-correlation_id"], workflow_id: env.jwe_headers["x-hcx-workflow_id"], + sender_code: env.jwe_headers["x-hcx-sender_code"], amount: p.amount, payment_status: p.payment_status, payment_date: p.payment_date, + utr: p.utr, notice_json: env.fhir, ack_status: "pending", received_at: now()}) + if not pay: return # the unique constraint caught a redelivery + for d in p.details: insert("claim_payment_detail", {payment_id: pay.id, type: d.type, amount: d.amount}) + enqueue(acknowledge_payment, pay.id) + +function acknowledge_payment(payment_id): + pay = payment(payment_id); row = claim(pay.claim_id); adapter = payers.for_claim(row) + bundle = fhir.payment_ack(submission(row.id).claim_ref or row.claim_no, now_ist(), settings.facility, payer_of(row)) + wf = adapter.workflow_ids.payment_ack or pay.workflow_id # 17 for PMJAY; echo for a generic payer + r = transport.send("v1/paymentnotice/on_request", bundle, pay.sender_code, workflow_id = wf, correlation_id = pay.correlation_id, claim_no = row.claim_no, usecase = "payment-ack") + update(pay, {ack_status: "sent", ack_txn_id: r.txn_id, ack_api_call_id: r.api_call_id, acked_at: now()}); stamp_case(row.id) +``` + +## Done when + +- Validate passes. +- `nhcx-build/7-modules/7.10.md` is written. diff --git a/plugins/nhcx/skills/nhcx-claim/stages/7-write-code/7.11-state-and-payer-adapters.md b/plugins/nhcx/skills/nhcx-claim/stages/7-write-code/7.11-state-and-payer-adapters.md new file mode 100644 index 000000000..94fbfc313 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-claim/stages/7-write-code/7.11-state-and-payer-adapters.md @@ -0,0 +1,145 @@ +# Module 7.11: state and payer adapters + +Purpose: two small tables of truth the whole build reads. The payer adapter says how a payer behaves; the stage machine says where an episode stands and what it waits for. + +Skills: the foundation (`core/FOUNDATION.md`). The first skill builds the payer adapter table whole; each skill adds the `case_stage` branches and the `next_actions` rows for its own legs. + +## Depends on + +7.2. (7.7 to 7.10 call it; build the adapter table as early as 7.4 needs the participant codes.) + +## Inputs + +- `references/flow-knowledge.md` sections 2, 3 and 4, whole +- `nhcx-build/1-idea.md` (the payers in scope) + +## Build + +### The payer adapter + +A table keyed by participant code (normalised: `1518` and `1518@hcx` are one key), each entry holding: + +| Field | PMJAY | Generic | +| --- | --- | --- | +| `query_mode` | `resubmit` | `communication` | +| `workflow_ids` | the PMJAY column of flow-knowledge section 2 | the generic column; `payment_ack` is `None` (echo) | +| `program_code` | `AB-PMJAY` | none | +| `auth_requirements` | asked | asked | +| `status_enquiry` | refused; do not offer | offered | +| `claim_resubmit` | none; reprocess only | `16` | +| `payer_system` | the identifier system for the payer Organization | same | + +`adapter_for(participant_code)` returns the entry or the generic default. `for_claim(row)` reads the episode's payer code. Overrides from configuration (7.1) merge on top, per payer, so a payer that insists on `cancel` as 122 is one config line. + +### Stage and sub-stage + +Stages: `eligibility`, `preauth`, `enhancement`, `claim`, `payment`. Sub-stages: `draft`, `checking`, `eligible`, `not-eligible`, `requested`, `resubmitted`, `answered`, `queried`, `approved`, `partial`, `rejected`, `cancelling`, `cancelled`, `refused`, `noticed`, `paid`. Send kind to sub-stage: `preauth`, `claim`, `enhancement` set `requested`; `*_resubmit` sets `resubmitted`; `*_query_response` and `enhancement_resubmit` set `answered`. `requested`, `answered`, `resubmitted` mean "with the payer". + +`case_stage(row, ...) -> (stage, sub_stage)`: a payment notice wins, then the filed claim, then the pre-auth (stage `enhancement` if the last submission kind was one), then a saved draft, then the eligibility status. An open communication query on a leg that is with the payer flips the sub-stage to `queried`. + +`stamp_case(claim_id)`: recompute and write both onto the episode. Called after every leg write by 7.3, 7.4 to 7.10. + +### Next actions + +The table in `flow/FLOW.md` ("The status line and the actions") and `flow/flow.json` `next_actions` is the specification; the labels are used verbatim. + +`next_actions(claim_id) -> [{label, tab, tone}]`, first is what the case waits for: an unanswered query always leads with "Answer the payer (n)"; the leg's own reply box only for a `resubmit` payer, a `communication` payer is sent to the inbox; a claim refused at the door offers "send again" while `claim_send_kind` still yields a kind, else "Ask for a reprocess"; after a rejection the pre-auth offers a fresh 12; a payer whose adapter refuses status enquiry never gets a "Ask status" action. + +## Rules + +- An unmapped payer is generic. +- The two words are derived, never set by a screen. +- Stamp after every write. A test that checks state after every step is what makes stage 8 possible. + +## Validate + +- [ ] `adapter_for("1518@hcx")` and `adapter_for("1518")` return the PMJAY entry; an unknown code returns generic. +- [ ] The PMJAY `workflow_ids` table equals flow-knowledge section 2's PMJAY column for every kind listed; the generic table has `payment_ack` as echo and `claim_query_response` as `151`. +- [ ] A configuration override for one kind changes only that kind. +- [ ] `case_stage` on each seeded state (draft; checking; eligible; pre-auth submitting; approved; queried by communication; enhancement requested; claim submitting; payment noticed; paid) returns the expected pair (write the table in the test). +- [ ] `next_actions` leads with the query when one is open; offers no status enquiry for PMJAY; offers a fresh 12 after a rejection. +- [ ] For every row of `flow.json` `next_actions`, the seeded state yields that label, character for character. +- [ ] After every leg write in 7.4 to 7.10, `claim.stage` and `sub_stage` equal `case_stage` recomputed. + +## Tests + +- A parametrised table for `case_stage`. +- A parametrised table for `next_actions`. +- The adapter lookups and the override. + +## Pseudo code + +``` +QUERY_MODE_RESUBMIT = "resubmit"; QUERY_MODE_COMMUNICATION = "communication" + +PMJAY = {"name": "PMJAY", "query_mode": QUERY_MODE_RESUBMIT, "program_code": "AB-PMJAY", "auth_requirements": true, + "status_enquiry": false, "payer_system": "https://nhcx.abdm.gov.in", + "workflow_ids": {"preauth": "12", "preauth_resubmit": "121", "preauth_query_response": "19", "enhancement": "13", "enhancement_resubmit": "131", + "cancel": "PC01", "claim": "15", "claim_query_response": "161", "claim_resubmit": null, "payment_ack": "17", "reprocess": "36", "release": "36"}} +GENERIC = {"name": "generic", "query_mode": QUERY_MODE_COMMUNICATION, "program_code": null, "auth_requirements": true, "status_enquiry": true, + "payer_system": "https://nhcx.abdm.gov.in", + "workflow_ids": {... as PMJAY except "claim_query_response": "151", "claim_resubmit": "16", "payment_ack": null}} # null = echo the notice's id +ADAPTERS = {"1518": PMJAY} # keyed without @hcx + +function adapter_for(participant_code): + key = (participant_code or "").split("@")[0] + base = deepcopy(ADAPTERS.get(key, GENERIC)) + for (k, v) in settings.workflow_overrides.get(with_hcx(key), {}): base.workflow_ids[k] = v + return base + +function for_claim(row): return adapter_for(row.payer_code) + +STAGES = ["eligibility", "preauth", "enhancement", "claim", "payment"] +KIND_TO_SUB = {"preauth": "requested", "claim": "requested", "enhancement": "requested", "preauth_resubmit": "resubmitted", "claim_resubmit": "resubmitted", + "preauth_query_response": "answered", "claim_query_response": "answered", "enhancement_resubmit": "answered"} +WITH_PAYER = {"requested", "answered", "resubmitted"} + +function leg_sub_stage(leg): + if leg.status == "submitting": return KIND_TO_SUB.get(leg.submission_kind, "requested") + return {"approved": "approved", "partial": "partial", "queried": "queried", "rejected": "rejected", "error": "refused", + "cancelling": "cancelling", "cancelled": "cancelled", "draft": "draft"}.get(leg.status, leg.status) + +function case_stage(row): + paid = sum(p.amount for p in payments(row.id) if p.payment_status in ("paid", "cleared")) + if payments(row.id): return ("payment", "paid" if paid > 0 else "noticed") + cs = submission(row.id) + if cs and cs.status != "draft": + sub = leg_sub_stage(cs) + if sub in WITH_PAYER and "claim" in open_query_stages(row): sub = "queried" + return ("claim", sub) + pa = preauth(row.id) + if pa and pa.status != "draft": + stage = "enhancement" if pa.submission_kind in ("enhancement", "enhancement_resubmit") else "preauth" + sub = leg_sub_stage(pa) + if sub in WITH_PAYER and "preauth" in open_query_stages(row): sub = "queried" + return (stage, sub) + if pa: return ("preauth", "draft") + return ("eligibility", {"checking": "checking", "eligible": "eligible", "not-eligible": "not-eligible"}.get(row.status, "draft")) + +function stamp_case(claim_id): (s, sub) = case_stage(claim(claim_id)); update(claim(claim_id), {stage: s, sub_stage: sub}) + +function next_actions(claim_id): + row = claim(claim_id); adapter = for_claim(row); out = []; pa = preauth(claim_id); cs = submission(claim_id) + open_q = open_queries(claim_id) + if open_q: out.append({label: f"Answer the payer ({len(open_q)})", tab: "communication" if adapter.query_mode == "communication" else ("claim" if open_q[0].stage == "claim" else "preauth"), tone: "primary"}) + if row.status in ("draft", "not-eligible", "error"): out.append({label: "Check cover", tab: "cover", tone: "primary"}) + elif not row.plan_id: out.append({label: "Fetch the plan", tab: "plan", tone: "primary"}) + elif not pa or pa.status == "draft": out.append({label: "Submit the pre-authorisation", tab: "preauth", tone: "primary"}) + elif pa.status == "queried" and adapter.query_mode == "resubmit": out.append({label: "Answer the query", tab: "preauth", tone: "primary"}) + elif pa.status == "rejected": out.append({label: "Send a fresh pre-authorisation", tab: "preauth", tone: "primary"}) # 12, never 121 + elif pa.status == "error": out.append({label: "Send again", tab: "preauth", tone: "warn"}) + elif pa.status in ("approved", "partial") and (not cs or cs.status == "draft"): + out.append({label: "Discharge and claim", tab: "claim", tone: "primary"}) + if enhancement_lines(claim_id): out.append({label: "Send the enhancement", tab: "lines", tone: "default"}) + out.append({label: "Cancel the pre-authorisation", tab: "preauth", tone: "danger"}) + elif cs and cs.status == "error": out.append({label: "Send again" if claim_send_kind(claim_id) else "Ask for a reprocess", tab: "claim", tone: "warn"}) + elif cs and cs.status == "rejected": out.append({label: "Ask for a reprocess", tab: "claim", tone: "warn"}) + for p in payments(claim_id): if p.ack_status != "sent": out.append({label: "Acknowledge the payment", tab: "payments", tone: "default"}) + if adapter.status_enquiry and (pa or cs): out.append({label: "Ask status", tab: "enquiries", tone: "default"}) + return out +``` + +## Done when + +- Validate passes. +- `nhcx-build/7-modules/7.11.md` is written. diff --git a/plugins/nhcx/skills/nhcx-claim/stages/7-write-code/7.12-screens.md b/plugins/nhcx/skills/nhcx-claim/stages/7-write-code/7.12-screens.md new file mode 100644 index 000000000..130115d38 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-claim/stages/7-write-code/7.12-screens.md @@ -0,0 +1,124 @@ +# Module 7.12: screens + +Purpose: the screens in `screens.json`, built the way the target builds screens, every value derived from a stored message, plus the JSON state address a driver reads. + +Skills: the foundation (`core/FOUNDATION.md`) builds the case screen shell: all eight tabs, the status line, the state address, the page-load polls, the cases list. Each skill fills its own tabs and screens, and adds its legs to the state address. + +## Depends on + +7.1 to 7.11. Screens come last because they render what the readers stored. + +## Inputs + +- `nhcx-build/5-screen-plan.md`, `nhcx-build/screens.json` +- `nhcx-build/3-discovery.md` (screen conventions, helpers, styling) +- `nhcx-package/docs/03-Building a Provider/09-UI Guide.md` +- `ui/UI-GUIDE.md` for the route shape, the state address and the helper vocabulary; two or three route modules of the target for its conventions + +## Build + +### The case screen walks the flow + +Tabs in the order and with the labels of `flow.json` `tabs`; the Pre-authorisation tab appears once the verdict is `eligible`. Above the tabs the status line and the actions from 7.11. Each step F1 to F13 has its control on the tab the flow names, offered only when the step's `holds` hold. The page-load polls run in the order `flow.json` `page_load_polls` gives, bounded, before rendering. + +### Every screen in `screens.json` + +For each screen: the route, the handler, the render. Each value in the screen's `values` list is rendered from the element it names; the empty state is what shows before the message arrived. A decision-bearing value with no message renders as waiting. There is no status control anywhere. + +### The case screen + +The timeline: one row per leg row and per archived message, in time order, with direction, path, workflow id label (7.8's labels), status word, and the payer's words verbatim (`disposition`, item remarks, process notes, `x-hcx-error_details` on a refusal). The actions open now are `next_actions` from 7.11, rendered as buttons that post to the senders; the first action is highlighted. Each pane (cover, plan, lines, forms, documents, pre-auth, communication, claim, payments) shows only when its leg exists. + +### The JSON state address + +`GET /state` returns everything the case screen shows, as JSON, after the same polls the screen runs: stage, sub-stage, next actions, each leg's status and ids, the inbox items, the payments. Stage 10's drivers read this. + +### Polling on the request path + +Where there is no worker, the case screen and the state address run 7.3's poll fallback for any leg that is `submitting` or `checking` before rendering. Bound it: one poll per leg per request, a short timeout, and never a send. + +### Standalone mode + +Also the capture screens from 7.13, in the same style. + +## Rules + +- No screen shows a decision the exchange has not sent. +- Nothing the exchange already knows is typed. Rates, payer names, `preAuthRef`, the approved amount, the UTR and the payer's wording are rendered, never fields. +- An unknown case is a 404, never an invented page. +- Screens answer within two seconds; the poll is bounded. +- Forms post and the page re-renders; no client-side rendering is needed. + +## Validate + +- [ ] The case page's tabs are the eight of `flow.json`, in order, with those labels (string test on the HTML). +- [ ] Every step of `flow.json` with a `routes` entry answers on that route (or the plan's equivalent recorded in `screens.json`). +- [ ] Every route in `screens.json` answers 200 for a seeded case and 404 for an unknown one. +- [ ] A case with a pre-auth `submitting` and no answer renders "waiting" (or the plan's word) and neither "approved" nor "rejected" appears on the page. +- [ ] After a 21 is applied (`nhcx-package/fhir/C5/C5-approved-wf21.json`), the page shows its `preAuthRef` and approved amount verbatim. +- [ ] After a payment notice is applied (`nhcx-package/fhir/C9/C9-notice-wf30.json`), the payments screen shows its UTR verbatim. +- [ ] After a query is applied, the inbox shows the request's `contentString` text verbatim. +- [ ] No `` or `, unless spec.typed +``` + +### Which actions to offer + +``` +function actions(case): + out = [] + q = open_queries(case) + if q: out.append(action("Answer the payer (n)", tab = inbox if payer.query_mode == communication else leg_tab)) + leg = current_leg(case) + if leg.status == "rejected" and leg.kind == "preauth": out.append(action("Send a fresh pre-authorisation", sends = 12)) + if leg.status == "approved" and no_request_in_flight(case) and leg.kind == "preauth": + out.append(action("Enhance", sends = 13)); out.append(action("Cancel", sends = PC01)); out.append(action("Discharge and claim", tab = claim)) + if leg.kind == "claim" and leg.status == "rejected": out.append(action("Ask for a reprocess", sends = 36)) + if payer.status_enquiry: out.append(action("Ask status", sends = task status)) + for notice in unacknowledged_notices(case): out.append(action("Acknowledge payment", sends = 17 or echo)) + return out +``` + +## Component vocabulary (suggested, for a standalone build) + +A suggested set of helpers. Server-rendered HTML from Python functions returning strings, styled by the 0build kit 0.5.4 from jsDelivr. Components: `z-card`, `z-button`, `z-input`, `z-select`, `z-table`, `z-nav`, `z-tab` with `data-z-switcher`, `z-alert`, `z-badge`, `z-breadcrumb`. Utilities take values through custom properties (`class="display-grid gap" style="--gap: 4"`). Helpers a screen needs: `page`, `card`, `stack`, `table`, `grid`, `field`, `text_input`, `select`, `button`, `post_button`, `confirm_form`, `badge`, `when`, `muted`, `dl`, `tabs`, `stat`, `empty_state`. Tables cap at about eight columns; merge facts into a main line with a muted sub-line. Every state-changing action that is not a full form is a `post_button`; destructive ones confirm. + +In `integrate` mode use the HMIS's own components and conventions; the layouts above are the content, not the markup. diff --git a/plugins/nhcx/skills/nhcx-communication/SKILL.md b/plugins/nhcx/skills/nhcx-communication/SKILL.md new file mode 100644 index 000000000..ae9950fb9 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-communication/SKILL.md @@ -0,0 +1,96 @@ +--- +name: nhcx-communication +description: Add NHCX communication to a hospital information system or a standalone claims desk. Receive the payer's CommunicationRequest, classify it as a query, a notification or a note, acknowledge notifications at once, and answer queries with the TaskBundle reply on the request's own thread, held to the pinned bundle. Starts by checking whether the app already receives payer messages or answers queries, and whether it keeps the pre-auth or claim a query is about, then builds, extends or reuses only what is missing. Self-contained; needs no other skill installed. Use for payer queries, notifications, the inbox, the communication reply, NHCX use case B4, flow steps F9b (communication payer) and F12b. +--- + +# NHCX communication: the payer's questions and notices + +This skill handles the messages a payer starts on a case: it files each CommunicationRequest, decides whether it is a query, a notification or a note, acknowledges notifications at once, and sends the desk's answer to a query as a Communication on the request's own thread. + +Read `core/LADDER.md` first. It holds the ladder every NHCX skill walks: the definition of compliant, the stages, the workspace, how to run a stage, and the rules. This folder carries everything it needs and runs on its own; the other six NHCX skills are separate folders, and none of them has to be installed. Paths starting `core/`, `stages/`, `references/`, `fhir/`, `flow/`, `ui/`, `templates/` or `scripts/` are relative to this folder. Paths starting `nhcx-package/` are in the NHCX package, which `scripts/fetch-package.sh` fetches into the target project beside `nhcx-build/`; `references/material.md` names the package file of every pin by its label. + +## What this skill covers + +| | | +| --- | --- | +| Flow steps | F9b Answer a query, and the claim query of F11, for a `communication` payer; F12b The inbox | +| Tabs | Communication (tab 6); the inbox view across cases | +| Wire | In: `v1/communication/request` on a new thread. Out: `v1/communication/on_request` with the request's correlation id and workflow id echoed, carrying either the TaskBundle reply to a query or, for a notification, the payer's own bundle back with `Task.status completed` | +| Next actions | "Answer the payer (n)", which leads every list while a query is open; "Answer the payer's query" | +| Use cases | B4, its query and notification rows; C6 as readers | +| Module | 7.10, the communication half | +| Pins | `communication/response` (`nhcx-package/fhir/B4/communication-response.json`, the reply), and `communication/request` (`nhcx-package/fhir/B4/communication-request.json`) read as the payer's message | +| Payer fixtures | `nhcx-package/fhir/C6/C6-preauth-query-wf24.json` and `C6-claim-query-wf27.json` (queries), `nhcx-package/fhir/C6/C6-notification-wfN02.json` (a PMJAY notification); the replies in `nhcx-package/fhir/B4/*` | +| Tables | `claim_query`, its correlation id unique | +| FHIR | `fhir/FHIR.md` section 7; `references/fhir-knowledge.md` section 9; `references/flow-knowledge.md` section 3 | + +Not here: a `resubmit` payer's query (PMJAY). It arrives inside the ClaimResponse on the case's own thread and is answered as a fresh submit by the pre-auth use case (19, 131) or the claim use case (161). A PMJAY CommunicationRequest is always a notification. + +## Needs and hands on + +Needs: at least one leg a payer can ask about, a pre-auth or a claim, with its bundle as sent kept on the leg (`request_json`). The reply lifts the Claim, Patient, Organizations, Practitioner and Coverage from it. Stage 0 checks for it below, whichever way the app got it. + +Hands on: `claim_query` rows by kind and status. An open query flips its leg's sub-stage to `queried` and leads every action list; an answered query leaves the leg to wait for the decision on its own thread. + +## Capability check + +Stage 0 (`stages/0-capability-check.md`) gives every capability below a verdict: search for the markers, run the check, record what was observed. + +### Own + +| Id | What | Look for | Present when (observed) | +| --- | --- | --- | --- | +| `communication.receive` | Receive and file a CommunicationRequest | a handler for `v1/communication/request`; `CommunicationRequest`, `contentString`, `basedOn`; a table keyed on the request's correlation id | Delivered through the door, `C6-preauth-query-wf24.json` matches its case by the claim number inside and creates one `claim_query` row with the questions verbatim; a second delivery creates none; the `communication/request` pin reads into its questions and the leg asked about | +| `communication.classify` | Query, notification or note | `intent`, `reasonCode`, `additionalinfo`, `tatquery`, `claimArbitartion` | The classification table (7.10 Validate, row 3): `C6-preauth-query-wf24.json` is a query; `C6-notification-wfN02.json` is a notification; the same notification under a `communication` adapter with `intent order` is a query; a bare Communication is a note | +| `communication.acknowledge` | Acknowledge a notification at once | a send on `v1/communication/on_request` with `Task.status` `completed` | The payer's bundle goes back with `Task.status completed`, the reason echoed and the provider Organization first, with the request's correlation id and workflow id in `jwe_headers`; sent outside the callback (the 7.1 stub sees no send during receipt) | +| `communication.reply` | F9b: the TaskBundle reply | `Communication`, `basedOn`, `inResponseTo`, `contentAttachment` | Fed the request pin and the pre-auth pin, the builder produces `communication/response` byte for byte with `meta.lastUpdated`, `timestamp` and `authoredOn` excluded; `basedOn` names the request and `inResponseTo` is absent; the correlation id and workflow id are the request's; an empty reply is refused before any HTTP call (7.10 Validate, rows 1, 4 and 5) | +| `communication.screens` | The Communication tab and the inbox | an inbox route; a reply form | The questions render verbatim from the stored request; the reply box sits on the inbox item for a `communication` payer; a notification shows as acknowledged and changes nothing; "Answer the payer (n)" leads the actions while a query is open | + +### Foundation + +All six capabilities in `core/FOUNDATION.md`. `foundation.callback` is partial until the door matches an inbound request by the claim number inside it; `foundation.state` until an open query flips the leg's sub-stage to `queried`; `foundation.storage` until `claim_query` exists with its unique correlation id. + +### Prerequisites + +The pre-auth use case (`nhcx-preauth`) or the claim use case (`nhcx-claim`) owns this. The check is here, so neither skill need be installed. + +| Capability | Why | Look for | Present when (observed) | +| --- | --- | --- | --- | +| `preauth.send` or `claim.send` (at least one), with the bundle as sent | A query names a Claim the hospital sent, and the reply lifts its entries from that bundle | a pre-auth or claim leg with `correlation_id` and the bundle it posted (`request_json` or the archive) | A leg sent with a stubbed client stores its correlation id and the bundle as posted, with the Claim, Patient, both Organizations, the Practitioner and the Coverage in it | + +### Host facts + +The document store, since a reply can attach documents; the accepted content types. + +## The ladder, for this skill + +| Stage | What is specific here | +| --- | --- | +| 0 | The tables above. | +| 1 | Confirm the shared page, or write it if this skill runs first on the app. Own row: B4. If every payer in scope is a `resubmit` payer, the reply is `later` and only receipt and acknowledgement are in. | +| 2 | Risks: acknowledge or lose the thread; the reply keyed on the wrong correlation id (it carries the request's); `basedOn`, never `inResponseTo`; nothing is sent inside the callback. | +| 3 | The host facts above. | +| 4 | The `claim_query` home; the reply's source map (the queried leg's bundle as sent, the desk's text and documents); the classification inputs. If this skill maps first, every table's home too. | +| 5 | The Communication tab and the inbox; action F9b for a `communication` payer. | +| 6 | The communication half of 7.10; the foundation modules stage 0 found absent or partial. | +| 7 | The communication half of 7.10, as far as its verdicts say. | +| 8 | 7.10 Validate rows 1, 3, 4, 5 and 8. | +| 9 | The reply pin; the request reader; the classification table as a parametrised test; matrix rows B4 query and B4 notification; the C6 captures as readers; the cross-cutting rows for an inbound request (redelivery, unmatched). | +| 10 | Rung 1. Rung 3 walks B4, since a generic payer asks by communication. Rung 4 sees N02 notifications only. | +| 11 | This skill's section. | + +## Rules for these legs + +- A `resubmit` payer's CommunicationRequest is always a notification, whatever it says. +- A notification is acknowledged at once and the case left alone. +- A query is filed `open` and leads every action list until answered. The leg row is untouched; its sub-stage reads `queried` while the query is open. +- The reply names the request in `Communication.basedOn`, never `inResponseTo`, and echoes the request's correlation id and workflow id. +- Documents in a reply go under the payer's code, else `ODN`. +- Nothing is sent inside the callback. +- A bare `Communication` with no request is a note: recorded, shown, never acted on. + +## Done when + +- Every gate in this skill's block of `nhcx-build/STATE.md` is closed with evidence. +- The reply pin passes, and the request pin reads. +- The compliance points in `core/LADDER.md` hold for F9b (communication payer) and F12b. diff --git a/plugins/nhcx/skills/nhcx-communication/core/FOUNDATION.md b/plugins/nhcx/skills/nhcx-communication/core/FOUNDATION.md new file mode 100644 index 000000000..2037811b9 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-communication/core/FOUNDATION.md @@ -0,0 +1,65 @@ +# The foundation: what every skill stands on + +Six modules carry every leg, and no one skill owns them. Every skill's stage 0 checks them. The first skill that finds one absent or partial builds or extends it in its own stage 7, and records itself as `Built by` in the Foundation block of `nhcx-build/STATE.md`. Later skills find it present and reuse it. An HMIS that already has one (an NHCX integration, a webhook door, a claims table) has it `existing`. + +| Id | Module | What | Every skill adds | +| --- | --- | --- | --- | +| `foundation.transport` | 7.1 | Settings; the one transport behind `send` (the app's existing NHCX integration, the build's own, or nhcx-adapter when the user asked for it); the policy lookup; the outbound archive | Nothing; it sends through it | +| `foundation.storage` | 7.2 | The episode table with its claim number, payer and recipient codes, stage and sub-stage; the leg tables | The leg tables its `SKILL.md` lists, in its own migration | +| `foundation.callback` | 7.3 | The transport's receiving end and the door: dedupe, archive before apply, match by correlation id then claim number, the door refusal, the poll fallback where there is a ledger | Its readers, wired into the door's dispatch | +| `foundation.state` | 7.11 | The payer adapter table; `case_stage`, `stamp_case`, `next_actions` | The stage branches and next-action rows for its legs, labels verbatim from `flow/flow.json` | +| `foundation.screens` | 7.12 | The case screen shell: the eight tabs in the flow's order, the status line and actions, the JSON state address, the page-load polls, the cases list | Its own tabs and screens | +| `foundation.shell` | 7.13 | Standalone only: patients, admissions, practitioners, diagnoses, documents, settings, the run script | Nothing; `not applicable` in integrate mode | + +## Recognising each one + +For each capability: what to search for, what must be observed for it to be present, and what makes it partial. Search code, dependencies, migrations, configuration and tests. Run every check offline, with the network stubbed. + +### `foundation.transport` (7.1) + +- Look for an NHCX integration of the app's own: `x-hcx-`, `JWEPayload`, `RSA-OAEP-256`, `A256GCM`, a JOSE library among the dependencies, `bearer_auth`, a sessions URL on the ABDM gateway, `participanthcxservice`, `fetch/certs`, `participant/get/policies`, routes ending in `on_submit`, `on_check` or `on_request`, a vendor's NHCX or HCX client, a gateway service the app calls. Look also for nhcx-adapter already in use: `/fhir/out/`, `/out/v1/`, `jwe_headers`, an adapter URL setting, `/ledger/thread/`, `/internal/txn/related`. +- Present when: what was found meets the contract in `references/transport-knowledge.md` section 2, observed through 7.1's Validate rows 1 to 6 (and row 7 for an app that seals its own messages), with the network stubbed and a test key pair for the seal; and `send` is one function a test can replace. +- Partial when: it sends but misses a contract item (no `x-hcx-ben-abha-id`, the `payerid` as the recipient, no ids back to the caller, no archive) or cannot be stubbed. Extend it in place (`references/transport-knowledge.md` section 4). Never add a second transport beside it. +- Absent when: the app has no NHCX integration. The transport is then `own`, built from `references/transport-knowledge.md` section 3, unless the user has asked for nhcx-adapter. +- nhcx-adapter is never the answer to a partial or absent transport unless the user asked for it. Do not suggest it. + +### `foundation.storage` (7.2) + +- Look for: tables or models with `claim_no`, `correlation_id`, `txn_id`, `sub_stage`; migrations that mention claim, preauth or nhcx. +- Present when: observed on a migrated scratch database, or read from the schema file and confirmed by a migration run: the episode table has a unique claim number, member id, policy code, payer code, recipient code, patient and encounter keys, `stage` and `sub_stage`; every leg table this skill needs exists with `txn_id`, `correlation_id`, `api_call_id` and `thread_correlation_id`; the migration runs twice without error; deleting an episode removes its children (7.2 Validate, rows 2, 3, 5 and 6). For `nhcx-communication` and `nhcx-payment`, also row 4: the correlation id on their tables is unique by constraint. +- Partial when: the episode exists but a leg table this skill needs does not, a leg table lacks `thread_correlation_id` or `api_call_id`, or the episode keeps no `recipient_code`. The skill adds its tables and columns in a new migration. + +### `foundation.callback` (7.3) + +- Look for: routes under `/v1/` ending in `on_submit`, `on_check`, `on_request`, `/v1/error`, or a route with `callback` in it; `JWEPayload`, `ProtocolResponse`, `x-hcx-correlation_id`, `x-hcx-api_call_id`, a receipt with `protocol_status`. +- Present when: 7.3 Validate rows 1 to 5, 7 and 8 are observed by calling the receiving end with deliveries of the transport's kind (every inbound path reaches it; an unreadable body is archived and changes nothing; one api call id delivered twice changes state once and is `ignored`; an unknown correlation id is answered and archived under `unmatched`; a delivery is archived even when the apply raises; no outbound call during a delivery; the inbound authentication of the kind). Row 6, the door refusal, is checked by each skill on its own thread. +- Partial when: it receives but routes by path instead of by correlation id, lacks the dedupe, archives after applying, answers the exchange with anything but the 202 receipt (`own`, `existing`), hosts no `/v1/error`, or, with `adapter`, has no poll fallback. Extend it; there is one door. +- A skill whose reader is not wired into the door is partial for its own capability, not for the door. + +### `foundation.state` (7.11) + +- Look for: `query_mode`, `resubmit`, `1518`, a workflow id table (`"12"`, `"PC01"`, `"161"`), `sub_stage`, `next_actions`, a stamp after each write. +- Present when: 7.11 Validate rows 1 to 3 are observed (`adapter_for` with `1518@hcx` and `1518` gives PMJAY and an unknown code gives generic; the PMJAY workflow table equals `references/flow-knowledge.md` section 2; an override changes one kind only), and rows 4 to 7 hold on the seeded states the legs built so far can reach. +- Partial when: the payer table exists and the stage machine does not, or the stage machine lacks this skill's stage branches or labels. Each skill adds its own. + +### `foundation.screens` (7.12) + +- Look for: routes like `/claims`, `/claims/`, `/claims//state`; the tab keys `eligibility`, `plan`, `lines`, `validate`, `preauth`, `communication`, `claim`, `payments`. +- Present when: 7.12 Validate rows 1, 3, 8 and 9 are observed on the shell (the eight tabs in the flow's order with the flow's labels; routes answer 200 for a seeded case and 404 for an unknown one; no input or select named for a rate, a payer name, a `preAuthRef`, a UTR or a status; the state address returns `stage`, `sub_stage`, `next_actions` and `legs`). Rows 4 to 7 belong to the skills whose tabs they test. +- Partial when: the case screen exists without some tabs, without the status line, or without the state address. +- An HMIS with its own screens: the shell may live inside them, for example a panel on the admission screen that opens the case. Present is judged on the eight tabs and the state address, not on the look. + +### `foundation.shell` (7.13, standalone only) + +- Present when: every row of 7.13's Validate section is observed. +- In integrate mode: `not applicable`. The HMIS is the shell; stage 3 finds its patients, admissions, practitioners and documents. + +## Who builds what + +| Verdict at stage 0 | What the running skill does | +| --- | --- | +| `absent` | Builds it in stage 7, before its own modules. 7.1 and 7.3 whole, for the transport chosen at stage 1. 7.2: the episode table and this skill's leg tables. 7.11: the payer adapter table whole, and this skill's stage branches and labels. 7.12: the shell with all eight tabs present in order, its own tabs filled, the others showing their empty state. 7.13 whole, in standalone mode. | +| `partial` | Extends it in the existing code, for the difference stage 0 named, and runs the module's whole Validate section after. | +| `present` | Reuses it. Stage 8 still runs the rows this skill depends on. | + +Record: the Foundation row in `STATE.md` with `Built by` (the skill, or `existing`), and the module record `nhcx-build/7-modules/7.N.md` with a part for each skill that touched it. diff --git a/plugins/nhcx/skills/nhcx-communication/core/LADDER.md b/plugins/nhcx/skills/nhcx-communication/core/LADDER.md new file mode 100644 index 000000000..7a6f3f12b --- /dev/null +++ b/plugins/nhcx/skills/nhcx-communication/core/LADDER.md @@ -0,0 +1,185 @@ +# The NHCX build ladder + +This skill is one of seven NHCX skills, one per use case: `nhcx-coverage`, `nhcx-insurance`, `nhcx-preauth`, `nhcx-claim`, `nhcx-communication`, `nhcx-payment` and `nhcx-reprocess`. Each is a folder of its own and runs on its own: it carries this ladder, the stages, the module files, the references, the flow, the templates and the fetch script. The seven copies of these are the same; only `SKILL.md` differs. This file holds what they share. `SKILL.md` says which flow steps, legs, capabilities, modules, pins and test rows are this skill's own, and what it needs from the use cases before it. + +## Paths + +Paths that start with `core/`, `stages/`, `references/`, `fhir/`, `flow/`, `ui/`, `templates/` or `scripts/` are relative to this skill's folder, the one that holds `SKILL.md`. Paths that start with `nhcx-package/` are in the NHCX package, fetched into the target project beside `nhcx-build/` (below). Paths that start with `nhcx-build/` are the workspace in the target project. + +## Getting the material + +Pins, payer fixtures and docs come from the NHCX package, published at https://github.com/nha-in/nhcx-package. `scripts/fetch-package.sh` downloads the latest release, unpacks it to `nhcx-package/` beside `nhcx-build/` and verifies its MANIFEST (pass a link or a local path to use a different build). `references/material.md` says what the package holds, gives the file of every pin by its label (`preauth/request` is `nhcx-package/fhir/B3/preauth-request.json`), and lists what it does not hold. Read it once, at stage 0. + +## What the skills produce + +Software that raises cashless claims on the National Health Claims Exchange (NHCX) with a private insurer and with PMJAY, in one of two shapes: + +| Mode | You start with | You end with | +| --- | --- | --- | +| `integrate` | A working hospital information system (HMIS, EMR, HIS, billing system) in any language | The same system, with a claims module that speaks NHCX through its transport, kept in sidecar tables and removable | +| `standalone` | Nothing | A self-contained claims desk: its own patients, admissions, documents and screens, speaking NHCX through a transport of its own | + +Every message goes through one transport, chosen at stage 1 from three (`references/transport-knowledge.md` section 1): + +| Transport | When | What the build does | +| --- | --- | --- | +| `existing` | Stage 0 found the app already speaks NHCX: its own client, a vendor gateway, an SDK | Wraps it behind 7.1's `send` and 7.3's door, and closes its gaps; never replaces it | +| `own` | The app has no NHCX integration, and the user has not asked for nhcx-adapter | Builds the protocol into the app from NHA's published chapters: the ABDM session token, the key and certificate, the participant record, the recipient's certificate, the JWE, the callback and its receipt | +| `adapter` | Only when the user asks for nhcx-adapter | Downloads it from https://github.com/nha-in/nhcx-adapter/releases and talks plain FHIR to it (`references/api-knowledge.md`) | + +Never propose nhcx-adapter; use it only when the user asks for it. Whichever the transport, the rest of the build sees the same two things: `send`, and a door that receives `{meta, jwe_headers, fhir}`. + +## The seven skills + +One skill per use case. Together they walk the whole flow in `flow/FLOW.md`; each one alone builds its slice. This folder builds only its own row. The others are named so that a verdict can say which skill owns a missing piece. + +| Skill | Flow steps | Legs | Use cases | Pins | +| --- | --- | --- | --- | --- | +| `nhcx-coverage` | F1, F2, F3 | policy search; `v1/coverageeligibility/check` purpose `discovery`, `validation`, `benefits` | A2, B1, D3 | `coverage/{discovery,validation,benefits}` | +| `nhcx-insurance` | F4, F7 | `v1/insuranceplan/request`; lines quoted from the plan | B2, D1 | `insurance` | +| `nhcx-preauth` | F5, F6, F8, F9, F9a, F9b for a `resubmit` payer, F9c, F9d, F9e | auth requirements; `v1/preauth/submit` 12, 19, 13, 131 and predetermination; cancel PC01 | B3, B8 cancel, B9, D2, D4 to D8 | `coverage/authrequirements`, `preauth/{request,enhancement,queryupdate,cancel}` | +| `nhcx-claim` | F10, F11 | `v1/claim/submit` 15; 161 (PMJAY) or 151 (generic); 16 (generic) | B5, D9, D10 | `claim/{request,queryupdate}` | +| `nhcx-communication` | F9b and the claim query for a `communication` payer, F12b | `v1/communication/request` in; `v1/communication/on_request` out | B4 | `communication/response`, and the `communication/request` reader | +| `nhcx-payment` | F12 | `v1/paymentnotice/request` in; `v1/paymentnotice/on_request` out on 17 or the notice's own id | B7, D13 | `payment/notice-ack` | +| `nhcx-reprocess` | F13 | `v1/task/submit`: reprocess and release on 36, status; 37 and the status Task read | A5, B8 reprocess, D11, D12 | `claim/{reprocess,release}` | + +`flow/flow.json` names the skills of every step in `skills`. Fifteen pins, each owned by exactly one skill, plus the communication request read as the sixteenth comparison. + +### The order they depend on + +The use cases depend on one another in the order the episode happens. A full build runs the seven skills top to bottom. Any one can run alone on an app that already has what it needs; stage 0 establishes whether it does, with the checks in this skill's `SKILL.md` under "Prerequisites". The other skills do not have to be installed for that check. + +| Skill | Needs | Because | +| --- | --- | --- | +| `nhcx-coverage` | nothing | It opens the episode | +| `nhcx-insurance` | coverage: an episode with an `eligible` verdict | The plan is fetched for an eligible episode's policy | +| `nhcx-preauth` | coverage (eligible, and its builder for auth requirements); insurance (plan ready, lines quoted) | Items, prices, documents and forms come from the plan; F9 holds `eligible` | +| `nhcx-claim` | preauth: an approved or partial pre-auth with its `preAuthRef`, the dossier, the Claim builder | The claim goes under the pre-auth's number, built by the same builder | +| `nhcx-communication` | preauth or claim: a leg the payer can ask about, with its bundle as sent | A query names a Claim; the reply lifts entries from the bundle sent | +| `nhcx-payment` | claim: a filed claim | A notice is matched by the claim number | +| `nhcx-reprocess` | claim: a decided claim; payment for a release; preauth for status on a pre-auth | A reprocess reopens a decided claim; a release follows a short payment | + +## The foundation + +Six modules carry every leg and belong to no one skill: 7.1 (the transport), 7.2 (storage), 7.3 (the callback door), 7.11 (state and payer adapters), 7.12 (the case screen shell) and 7.13 (the standalone shell). Every skill's stage 0 checks them. The first skill that finds one absent builds it; a skill that runs later on the same app finds it present and reuses it. `core/FOUNDATION.md` says how to recognise each and what makes it present. + +## What compliant means + +Every skill is held to the same points, for its own legs: + +1. Every hospital-side leg the skill owns (`references/flow-knowledge.md` section 1) is sent with its workflow id, and every payer answer on it is read. +2. Every bundle the skill sends matches its pin in `nhcx-package/fhir` byte for byte, `created` excepted. +3. The callback door answers 2xx fast, dedupes on `x-hcx-api_call_id`, archives before it applies, and matches by correlation id first. +4. No screen shows a decision the exchange has not sent, and nothing the exchange already said is retyped. +5. The offline tests pass, and the report says honestly which rungs of the test pyramid were climbed. +6. The software walks the flow in `flow/FLOW.md`, step for step: the same steps in the same order, the same tabs with the same names, the same guards, the same action labels. The flow is copied, never redesigned. +7. Nothing the app already did is built a second time. Every capability stage 0 found present is reused, and validated and tested like new code. + +## The flow + +An NHCX provider desk walks one path from policy search to settlement, and a build from these skills walks it. `flow/FLOW.md` is that path: thirteen steps with their branches, the case screen's eight tabs in order, the status line, the action labels the desk sees, the guards before every send, and what runs on every page load. `flow/flow.json` is the same, machine-readable, with step ids `F1` to `F13`. Read FLOW.md whole at stage 1; stage 4 copies the steps, stage 5 puts the screens on them, stage 7 implements them by id, stage 8 checks every step has a route. An agent that reorders, merges or renames these steps has left the skill. + +## The ladder + +Twelve stages, 0 to 11. Each has one file under `stages/`, reads the artefacts of the stages before it, writes into `nhcx-build/` in the target project, and ends at a gate. A gate is a list of conditions a reader can check without trusting you. Do not start a stage until the gate before it is closed, and never close a gate by asserting it; close it by pointing at the evidence. + +This skill runs every stage over its own slice. Stage 1 is shared with any other NHCX skill that runs on the same app: the first writes it and later ones confirm it. Parts of stages 3 to 6 are the episode's, not the skill's: the first skill to reach them writes those parts whole, and later skills build on them. + +| Stage | File | Scope | Writes | Gate closes when | +| --- | --- | --- | --- | --- | +| 0 | `stages/0-capability-check.md` | this skill | `nhcx-build/0-capability.md` section, `nhcx-build/capabilities.json` entries | Every own, foundation and prerequisite capability has a verdict with observed evidence | +| 1 | `stages/1-idea.md` | shared | `nhcx-build/1-idea.md` | The mode, the payers, the scope of every step with its skill, and the constraints are written and the user has agreed | +| 2 | `stages/2-planning.md` | this skill | `nhcx-build/2-planning.md` section, this skill's block in `nhcx-build/STATE.md` | Every later stage has a size and a proof; every module has its action from stage 0 | +| 3 | `stages/3-discovery.md` | shared rows; this skill's host facts | `nhcx-build/3-discovery.md` | Every host fact this skill needs is answered with proof, or marked as a gap | +| 4 | `stages/4-flow-and-data-mapping.md` | the flow and table homes episode-wide; this skill's bundles | `nhcx-build/4-flow-data-mapping.md`, `nhcx-build/mapping.json` | Every table has a home, every leg the four ids, every bundle of this skill a source map | +| 5 | `stages/5-screen-plan.md` | the case screen shell episode-wide; this skill's tabs | `nhcx-build/5-screen-plan.md`, `nhcx-build/screens.json` | Every value on this skill's screens names its message; the honesty rules hold | +| 6 | `stages/6-code-plan.md` | this skill's modules; the client and configuration episode-wide | `nhcx-build/6-code-plan.md`, `nhcx-build/modules.json` | Every module this skill touches has files, dependencies, a pin and an action | +| 7 | `stages/7-write-code/README.md` and `7.N-*.md` | what stage 0 found absent or partial | Code, plus `nhcx-build/7-modules/7.N.md` | Each module's "Done when" list is met, in order | +| 8 | `stages/8-validate-modules.md` | every module part this skill owns, reused ones included | `nhcx-build/8-validation.md`, `nhcx-build/8-validation/7.N.json` | Every row passes, or carries a named, accepted exception | +| 9 | `stages/9-write-tests.md` | this skill's pins, readers and matrix rows | Test code, plus `nhcx-build/9-tests.md` | Every row this skill owns has a test, or a written reason it cannot | +| 10 | `stages/10-run-tests.md` | this skill's tests | `nhcx-build/10-test-run.md` and the raw outputs | The offline rung passes; the higher rungs are run only when the user starts the services | +| 11 | `stages/11-build-report.md` | this skill | `nhcx-build/11-report.md` section | The report is written from the artefacts, names every gap, and a stranger could resume from it | + +Stage 7 is a module ladder of its own, 7.1 to 7.13. Each module file carries its own Build, Pseudo code, Validate and Tests sections, and names the skills that build it; stage 8 runs the Validate sections and stage 9 writes the Tests sections, so a module is never validated against a checklist written somewhere else. + +## The workspace + +Everything this skill writes lives in one folder in the target project, so the work can be resumed, reviewed and deleted as a unit. When several NHCX skills work on one app they share that folder, whichever skill folder each runs from: each adds its own section or entries and leaves the others alone. + +``` +nhcx-build/ + STATE.md the gate ledger: the shared rows, the foundation, one block per skill + capabilities.json every capability checked, its verdict and its evidence; read and written by every skill + 0-capability.md one section per skill; scratch checks under 0-capability/ + 1-idea.md shared + 2-planning.md one section per skill + 3-discovery.md shared; each row says which skill answered it + 4-flow-data-mapping.md the flow and table homes, then one section per skill; plus mapping.json + 5-screen-plan.md the case screen shell, then one section per skill; plus screens.json + 6-code-plan.md the client and configuration, then one section per skill; plus modules.json + 7-modules/7.1.md .. 7.13.md one record per module; a shared module has a part per skill + 8-validation.md one section per skill; plus 8-validation/7.N.json, each row tagged with its skill + 9-tests.md one section per skill + 10-test-run.md one section per skill; plus 10-test-run/-*.log + 11-report.md a summary across skills, then one section per skill + NOTES.md every place a skill was silent, ambiguous or wrong +``` + +`templates/` holds the skeleton of each artefact. Copy the skeleton, fill it, keep its headings: later stages find things by heading. + +## How to run a stage + +1. Read `nhcx-build/STATE.md`. If stage 1 in the Shared block is open, and this skill's stage 0 is closed, run stage 1. Otherwise find the first open gate in this skill's block. That is the stage to run; do not skip ahead and do not redo a closed stage unless the user asks. +2. Read the stage file. Read the artefacts it lists under Inputs, and this skill's `SKILL.md` row for the stage. Read the references it names, in the sections it names. +3. Do the work. Write the artefact from its template, in this skill's section. +4. Walk the gate. For each condition, write the evidence into STATE.md: a file path, a line, a command and its output. A condition with no evidence stays open. Every artefact that names a step, a tab or an action uses the ids and words from `flow/flow.json`. +5. If a gate needs the user (stage 0 when a prerequisite is missing; stage 1 always when it is first written; stage 10 rungs 3 and 4 always), stop and ask. Otherwise continue to the next stage. + +Resuming later is step 1 again. Nothing lives in your memory; everything lives in `nhcx-build/`. + +You may be asked to run one stage alone with the earlier artefacts already written. Treat those as closed; do not rewrite them. + +## Rules that hold throughout + +- Reading and offline commands only until stage 10 says otherwise. Never start a service or send live traffic unless the user asks. +- Never edit the files in `nhcx-package/`. They are the truth you are held to. +- Build only what stage 0 found absent or partial. A capability found present is reused through its existing code, never built a second time: two transports or two callback doors break the rule that one module sends and one receives. +- Present means a check was observed passing. Code that looks right is partial until its check has run. +- Never build another skill's capability inside this one. When a prerequisite is missing, stop and say which skill owns it. +- When this skill extends a module another skill built, it re-runs that skill's Validate rows for the module. The rows are in the module file, which every skill folder carries. +- This skill writes its own section of a shared artefact and leaves the other skills' sections alone. +- Never hard-code a document code, a package code or a questionnaire url. Take them from the payer's plan or auth-requirements answer. +- Every outbound leg stores three things from the transport's answer: `txn_id`, `correlation_id` and `api_call_id`. Every message is addressed to the policy's processor (`recipient_code`) and carries the beneficiary's ABHA. Every inbound message is matched by `x-hcx-correlation_id` first and by the claim number inside the bundle second. +- Take the decisions from the module files (Build, Rules, Pseudo code) and `fhir/FHIR.md`, and write them in the target's language and conventions. Never invent a shape the pins do not show. +- Write `nhcx-build/NOTES.md` as you go. A fact the skill does not give you is a gap to record, never a guess to bury in code. +- No em dashes anywhere you write. Short sentences. Tables for anything with more than three columns of fact. +- Do not claim a rung of the test pyramid was climbed when it was not. The report's value is its honesty. + +## Reference map + +| File | Holds | Read at | +| --- | --- | --- | +| `core/FOUNDATION.md` | The six foundation capabilities: how to recognise each, what makes it present, who builds it | Stage 0, stage 7 when building one | +| `references/flow-knowledge.md` | The episode and its legs, every workflow id, the two payer kinds, the classification rule, stage vocabulary, the use-case catalogue, rules no document states | Stages 1, 2, 4, 7.4 to 7.11 | +| `references/transport-knowledge.md` | The three transports and when each applies; the contract `send` and the door rely on; building the protocol yourself from NHA's chapters (token, key and certificate, participant record, policy lookup, recipient certificate, JWE, callback and receipt, status and `/v1/error`); wrapping an existing integration; getting nhcx-adapter when asked | Stages 0, 1, 4, 6, 7.1, 7.3 | +| `references/api-knowledge.md` | The nhcx-adapter contract, read only when the user chose the adapter: config, routes, envelope and answer, delivery, ledger, kit endpoints, curl | 7.1 and 7.3, adapter only | +| `references/fhir-knowledge.md` | Every bundle sent and received, element ids, HPIN, consent questionnaires, supportingInfo, LM100, ONS and DTM, the TaskBundle reply, where the pins live, the validator | Stages 4, 6, 7.4 to 7.10, 8 | +| `references/errors-and-debugging.md` | PAYR and ERR codes with meaning and fix, gateway errors, reading a ledger thread, correlation mistakes, redelivery, sandbox pace | Stages 8, 10, 11 | +| `references/testing-knowledge.md` | The test pyramid, the test-case matrix per use case, a skeleton offline test | Stages 2, 9, 10 | +| `fhir/FHIR.md` | The FHIR guide: every bundle sent and read, entries in pinned order, the code systems, pseudo code for each builder and reader, the refusal each rule guards against | Stages 0, 4, 6, 7.4 to 7.10, 8 | +| `ui/UI-GUIDE.md` | The screens: the two honesty rules, where every value comes from, a layout per screen, the state words, pseudo code for the status line, the timeline and the actions | Stages 5, 7.12, 7.13 | +| `flow/FLOW.md`, `flow/flow.json` | The one path an episode walks: steps F1 to F13 and their skills, the tab order, the action labels, the guards, the page-load polls | Stage 1 whole; stages 4, 5, 7, 8 by step id | +| `references/material.md` | Where the pins, fixtures and docs live: the NHCX package, the pin map, what the package lacks | Stage 0, and whenever a cited file is needed | + +## Keeping the seven copies in step + +Everything in this folder except `SKILL.md` is the same in all seven skill folders. A change to one of these files is made in all seven. `diff -r --exclude=SKILL.md` between any two skill folders prints nothing when they agree. + +## Deliverables + +- This skill's sections of `nhcx-build/`, every gate in its STATE.md block closed with evidence or open with a reason. +- Its verdicts in `capabilities.json`, each with the check that decided it. +- Schema additions for its legs (integrate) or its tables in the whole schema (standalone), under the target's conventions. +- Builders and readers for every leg it owns, each compared with its pin in the offline test. +- Its tabs and screens, deriving every state from received messages. +- Tests covering its rows of the matrix, a run record, and a report section a stranger could act on. diff --git a/plugins/nhcx/skills/nhcx-communication/fhir/FHIR.md b/plugins/nhcx/skills/nhcx-communication/fhir/FHIR.md new file mode 100644 index 000000000..90b85cbae --- /dev/null +++ b/plugins/nhcx/skills/nhcx-communication/fhir/FHIR.md @@ -0,0 +1,658 @@ +# NHCX FHIR: the bundles a hospital sends and reads + +Every bundle here is held to a pin in the NHCX package, under `nhcx-package/fhir/B*`. Read `../references/fhir-knowledge.md` for the why; this file is the how. The pseudo code is language-neutral: a `dict` is a JSON object, a `list` is a JSON array, and `ref(url)` is `{"reference": url}`. + +## 1. Conventions every bundle follows + +"Validator" below is the HL7 FHIR validator with the NRCeS `ndhm.in` IG, run as `../references/fhir-knowledge.md` section 11 describes. + +| Rule | Detail | Refusal if broken | +| --- | --- | --- | +| Bundle | `resourceType Bundle`, `type collection`, `id` fixed per shape, `meta.profile` = the NRCES bundle profile | validator error | +| Entries | Every entry has an absolute `fullUrl` under `https://nhcx.abdm.gov.in/...`; every `reference` resolves to a `fullUrl` in the same bundle | validator error, PAYR-10xx | +| Profiles | Every resource carries `meta.profile` = `https://nrces.in/ndhm/fhir/r4/StructureDefinition/` | validator warning | +| No timestamps on requests | No `meta.versionId`, `meta.lastUpdated`, bundle `timestamp` (the communication reply is the exception) | none, but the pin differs | +| Money | `{"value": n, "currency": "INR"}`; whole numbers as integers, never `3300.0` | pin differs | +| Instants | IST with `+05:30`, seconds precision | PAYR on dates | +| Identifiers | Typed with a `type.coding` from the NDHM identifier-type system or HL7 v2-0203, `system` where the pin has one | PAYR-1083 and kin | + +### Code systems, named once + +``` +NDHM = "https://nrces.in/ndhm/fhir/r4/CodeSystem/" +PROFILE = "https://nrces.in/ndhm/fhir/r4/StructureDefinition/" +BASE = "https://nhcx.abdm.gov.in" +HL7 = "http://terminology.hl7.org/CodeSystem/" +SNOMED = "http://snomed.info/sct" +ICD10 = "http://hl7.org/fhir/sid/icd-10" +HPR = "https://hpr.abdm.gov.in" + +ID_TYPE = NDHM + "ndhm-identifier-type-code" # PMJAY, ABHA, HPID, HPIN, CLN +V2_0203 = HL7 + "v2-0203" # MB, MD, NH, NPI, NIIP +V2_0360 = HL7 + "v2-0360" # qualification degrees +ORG_TYPE = HL7 + "organization-type" # prov, pay +ACT_CODE = HL7 + "v3-ActCode" # HIP +REL = HL7 + "subscriber-relationship" # self +PRIORITY = HL7 + "processpriority" # normal +CARE_ROLE = HL7 + "claimcareteamrole" # primary, assist +DX_TYPE = HL7 + "ex-diagnosistype" # admitting +DX_ONADM = HL7 + "ex-diagnosis-on-admission" # yes +FIN_TASK = HL7 + "financialtaskcode" # poll, cancel, reprocess, release, status +FIN_INPUT = HL7 + "financialtaskinputtype" # include +COMM_CAT = HL7 + "communication-category" # notification + +BENEFIT_CAT = NDHM + "ndhm-benefit-category" # Claim.item.category (specialty) +PROC_CODE = NDHM + "ndhm-procedure-code" # Claim.item.productOrService (package) +PROGRAM = NDHM + "ndhm-program-code" # AB-PMJAY +SI_CATEGORY = NDHM + "ndhm-supportinginfo-category" # INV, ONS, OTH, HDS, DIS, NMI, INF, STG +SI_CODE = NDHM + "ndhm-supportinginfo-code" # ADDD, EDT, PSP, DSDE, DTM, DTH, LAMA, DAMA, CQD, ODN +DOC_CODE = BASE + "/document-code" # the plan's MANDxxxx codes, else ODN +TASK_INPUT = NDHM + "ndhm-task-input-type-code" # policyNumber, providerId, claimNumber, intimationNumber, document +TASK_INPUT_X = BASE + "/task-input-type" # amount +TASK_OUTPUT = NDHM + "ndhm-task-output-type" # status +TASK_OUTVAL = NDHM + "ndhm-task-output-value" # paymentack +TASK_CODES = NDHM + "ndhm-task-codes" # deliver +REASON = NDHM + "ndhm-reason-code" # treatmentplanchanged, claimrejected, partialpayment, rejectiondisputed +CAT_CODE = BASE + "/category-code" # CoverageEligibilityRequest.item.category +PRODUCT_CODE = BASE + "/product-code" # CoverageEligibilityRequest.item.productOrService +PROC_TYPE = BASE + "/procedure-type" # conservative, medical, surgical +DOC_TYPE_EXT = settings.document_type_extension_url # on a Communication attachment; participant-defined (nhcx-package/docs/05-FHIR Reference/17-Communication.md). + # The communication/response pin carries its author's own url: the pin comparison sets this from the pin. +``` + +### Shared helpers + +``` +function cc(system, code, display=null): # CodeableConcept + coding = {"code": code}; if system: coding.system = system; if display: coding.display = display + return {"coding": [coding]} + +function typed_id(type_system, type_code, type_display, value, system=null): + out = {"type": cc(type_system, type_code, type_display), "value": value} + if system: out.system = system # put "system" before "value" as the pins do; canonical JSON sorts anyway + return out + +function entry(url, resource): return {"fullUrl": url, "resource": resource} + +function profile(name): return {"profile": [PROFILE + name]} + +function bundle(id, profile_name, entries): # profile_name: "ClaimBundle", "TaskBundle", "CoverageEligibilityRequestBundle" + return {"resourceType": "Bundle", "id": id, "meta": profile(profile_name), "type": "collection", "entry": entries} + +function organization(role, identifier_code, identifier_display, id_value, name, res_id=null): + o = {"resourceType": "Organization", "meta": profile("Organization"), + "identifier": [typed_id(V2_0203, identifier_code, identifier_display, id_value, BASE)], + "type": [cc(ORG_TYPE, role, "Healthcare Provider" if role == "prov" else "Payer")], "name": name} + if res_id: o.id = res_id + return o + +function provider_org(facility, res_id=null): return organization("prov", "NPI", "National provider identifier", facility.hfr_id, facility.name, res_id) +function payer_org(payer, res_id=null): return organization("pay", "NIIP", "National Insurance Payor Identifier (Payor)", strip_hcx(payer.participant_code), payer.name, res_id) +function strip_hcx(code): return code.split("@")[0] + +function money(v): return {"value": int(v) if v == int(v) else round(v, 2), "currency": "INR"} +``` + +## 2. Coverage eligibility request + +Pins: `coverage/{discovery,validation,benefits,authrequirements}`. Sent on `v1/coverageeligibility/check`, workflow id = the case number. Purposes: `discovery` (who covers this person), `validation` (is the policy in force), `benefits` (balances), `auth-requirements` (rule on the quoted items). + +Entries, in order: CoverageEligibilityRequest, Patient, provider Organization, payer Organization, Location, Coverage, PractitionerRole. + +``` +function build_coverage_request(d): + # d: purpose, member_id, policy_code (null on discovery), facility{hfr_id,name}, payer{participant_code,name}, created, items[] (benefits, auth-requirements only) + U = BASE + cer = {"resourceType": "CoverageEligibilityRequest", "meta": profile("CoverageEligibilityRequest"), + "identifier": [{"system": BASE}], "status": "active", + "priority": cc(PRIORITY, "normal", "Normal"), "purpose": [d.purpose], + "patient": ref(U + "/patient"), "created": d.created, + "enterer": ref(U + "/practitioner-role"), "provider": ref(U + "/provider"), + "insurer": ref(U + "/payer"), "facility": ref(U + "/location"), + "insurance": [{"focal": true, "coverage": ref(U + "/coverage")}]} + if d.purpose in ("benefits", "auth-requirements"): + cer.item = [eligibility_item(i) for i in d.items] + patient = {"resourceType": "Patient", "meta": profile("Patient"), + "identifier": [typed_id(ID_TYPE, "PMJAY", "Pradhan Mantri Jan Aarogya Yojana (PMJAY) ID", d.member_id), + typed_id(V2_0203, "MB", "Member Number", d.member_id)]} # no name, no demographics + coverage = {"resourceType": "Coverage", "meta": profile("Coverage"), + "identifier": [typed_id(V2_0203, "NH", "National Health Plan Identifier", d.policy_code or "NONE")], + "status": "active", "type": cc(ACT_CODE, "HIP", "health insurance plan policy"), + "subscriber": ref(U + "/patient"), "subscriberId": d.member_id, "beneficiary": ref(U + "/patient"), + "relationship": cc(REL, "self"), "payor": [ref(U + "/payer")]} + location = {"resourceType": "Location", "name": d.facility.name, "managingOrganization": ref(U + "/provider")} + role = {"resourceType": "PractitionerRole", "meta": profile("PractitionerRole"), + "code": [cc(SNOMED, "307988006", "Medical technician")]} + return bundle("coverage-" + d.purpose.replace("-", "") + "-request-generic", "CoverageEligibilityRequestBundle", [ + entry(U + "/coverage-eligibility/request", cer), entry(U + "/patient", patient), + entry(U + "/provider", provider_org(d.facility)), entry(U + "/payer", payer_org(d.payer)), + entry(U + "/location", location), entry(U + "/coverage", coverage), entry(U + "/practitioner-role", role)]) + +function eligibility_item(i): + # i: category{code,display}, code, display, quantity (integer), tiers[] {code, display} + out = {"category": cc(CAT_CODE, i.category.code, i.category.display), + "productOrService": cc(PRODUCT_CODE, i.code, i.display), + "quantity": {"value": int(i.quantity)}} + if i.tiers: out.modifier = [cc(null, t.code, t.display) for t in i.tiers] # no system on a tier + return out +``` + +Bundle ids: `coverage-discovery-request-generic`, `coverage-validation-request-generic`, `coverage-benefits-request-generic`, `coverage-authrequirements-request-generic`. + +### Reader: CoverageEligibilityResponse + +The payer echoes the request's entries and appends its own; take the last of each type. + +``` +function parse_validation_bundle(b): + resp = last(b, "CoverageEligibilityResponse"); pat = last(b, "Patient"); cov = last(b, "Coverage") + out = {"outcome": resp.outcome, "disposition": resp.disposition, "inforce": resp.insurance[0].inforce, + "auth_required": any(item.authorizationRequired for item in resp.insurance[0].item or []), + "allowed": null, "used": null} + for item in resp.insurance[0].item or []: + for ben in item.benefit or []: + if ben.allowedMoney and (out.allowed is null or ben.allowedMoney.value > out.allowed): + out.allowed = ben.allowedMoney.value; out.used = (ben.usedMoney or {}).value or 0 + out.patient = {"name": pat.name[0].text, "gender": pat.gender, "birthDate": pat.birthDate, + "abha": first_identifier(pat, "ABHA"), "photo": pat.photo[0].data if pat.photo else null} + out.coverage = {"class": cov.class[0].name if cov.class else null, "period": cov.period} + return out +# status: eligible if inforce else not-eligible; balance shown = allowed - used +``` + +### Reader: the auth-requirements ruling + +``` +function parse_auth_bundle(b): + resp = last(b, "CoverageEligibilityResponse"); items = []; requirements = [] + for item in resp.insurance[0].item or []: + items.append({"code": item.productOrService.coding[0].code, "authorised": item.authorizationRequired, + "excluded": item.excluded, "benefit": item.benefit[0] if item.benefit else null}) + for sup in item.authorizationSupporting or []: + text = sup.text or "" # the scheme overloads free text + r = {"line": item.productOrService.coding[0].code, "code": sup.coding[0].code if sup.coding else null, + "display": sup.coding[0].display if sup.coding else text} + if "fullUrl:" in text: r.kind = "form"; r.url = after("fullUrl:", text).strip(); r.stage = "pre" + else: r.kind = "document"; r.stage = "post" if "Type: post" in text else "pre" + r.at_preauth = (r.kind == "form") or (r.stage == "pre") + requirements.append(r) + return {"items": items, "requirements": requirements} +``` + +## 3. Insurance plan request + +Pin: `insurance`. Sent on `v1/insuranceplan/request`, workflow id = the case number. One entry. + +``` +function build_plan_request(policy_code, provider_id): + task = {"resourceType": "Task", "meta": profile("Task"), "status": "requested", "intent": "order", + "code": cc(FIN_TASK, "poll"), + "input": [{"type": cc(TASK_INPUT, "policyNumber"), "valueString": policy_code}, + {"type": cc(TASK_INPUT, "providerId"), "valueString": provider_id}]} + return bundle("insurance-request-generic", "TaskBundle", [entry(BASE + "/insurance/request", task)]) +# no id, no authoredOn, no requester; at least one input is mandatory +``` + +### Reader: the plan + +``` +function parse_plan_bundle(b): + plan = first(b, "InsurancePlan"); forms = {q.url: q for q in all(b, "Questionnaire")} + benefits = {} # keyed by package code + for p in plan.plan or []: # shape 1: package-based + for sc in p.specificCost or []: + specialty = sc.category.coding[0] + for ben in sc.benefit or []: + code = ben.type.coding[0].code; row = benefits.setdefault(code, new_benefit(code, ben.type.coding[0].display, specialty)) + for cost in ben.cost or []: + kind = cost.type.coding[0].code # Procedure | Implant | Stratification + if kind == "Procedure": row.rate = cost.value.value; row.kind = "Procedure" + else: row.extras.append({"kind": kind, "code": cost.qualifiers[0].coding[0].code, "display": cost.qualifiers[0].coding[0].display, "amount": cost.value.value}) + row.conditions.update(read_conditions(ben.extension)); row.requirements += read_requirements(ben.extension) + for cov in plan.coverage or []: # shape 2: coverage-based + for ben in cov.benefit or []: + code = ben.type.coding[0].code; row = benefits.setdefault(code, new_benefit(code, ben.type.coding[0].display, cov.type.coding[0])) + for lim in ben.limit or []: + if lim.code.coding[0].code == code: row.rate = lim.value.value + else: row.extras.append({"kind": "Stratification", "code": lim.code.coding[0].code, "display": lim.code.coding[0].display, "amount": lim.value.value}) + row.conditions.update(read_conditions(ben.extension)); row.requirements += read_requirements(ben.extension) + policy_requirements = read_requirements(plan.extension) # policy-wide: identity proof, consent forms + return {"plan": {"id": plan.id, "name": plan.name}, "benefits": list(benefits.values()), + "policy_requirements": policy_requirements, + "forms": [{"url": u, "title": q.title, "kind": "stg" if "/stgquestionnaire/" in u else "policy", + "questions": [{"linkId": it.linkId, "text": it.prefix or it.text, "type": it.type, + "options": [o.valueString or o.valueCoding.display for o in it.answerOption or []], + "default": first_selected(it)} for it in q.item]} for u, q in forms.items()]} + +function read_conditions(exts): # extension url family "...Claim-Condition": children named by their url tail + out = {} + for e in exts or []: + if "Claim-Condition" in e.url: + for child in e.extension or []: out[tail(child.url)] = child.valueString or child.valueBoolean or child.valueCodeableConcept.coding[0].code + return out + +function read_requirements(exts): # "...Claim-SupportingInfoRequirement": one nested requirement per document + out = [] + for e in exts or []: + if "Claim-SupportingInfoRequirement" in e.url: + for req in e.extension or []: + r = {} + for f in req.extension or []: + if tail(f.url) == "category": r.category = f.valueCodeableConcept.coding[0].code + if tail(f.url) == "code": r.code = f.valueCodeableConcept.coding[0].code; r.display = f.valueCodeableConcept.coding[0].display + if tail(f.url) == "documentationUrl": r.url = f.valueUri or f.valueString + out.append(r) + return out +``` + +## 4. The Claim bundle + +Pins: `preauth/request`, `preauth/enhancement`, `preauth/queryupdate`, `claim/request`, `claim/queryupdate`. One builder, three switches: `leg` (`preauth`, `claim`, `predetermination`), `flow` (`request`, `enhancement`, `queryupdate`), `use` (`preauthorization`, `claim`, `predetermination`). + +Entries, in order: Claim, Patient, provider Organization (id 1), payer Organization (id 2), Coverage (id 1), Practitioner (one per care team member), Procedure (one per package line), QuestionnaireResponse (one per answered form). + +``` +function claim_bundle(leg, use, d): + # d: flow, claim_no, created, admission{admitted_at, discharged_at, surgery_at, death_at, mode, stage}, + # patient{member_id, abha, name, phone, gender, birthDate}, facility, payer, policy_code, + # care_team[] {hpid, licence, hpin, name, qualification_code, qualification_display, specialty_snomed, specialty_display}, + # diagnoses[] {code, display}, lines[] (procedures and implants, each with tiers[]), documents[] {code, category, content_type, bytes, title}, + # forms[] {url, answers[] {linkId, type, value}}, program_code (AB-PMJAY or null), factor_rule (pmjay or null), + # preauth_ref (claim leg), summary{code, content_type, bytes, title} (claim leg), query_reply (queryupdate) + U = BASE; anchor = U + "/" + leg + "/" + d.flow + practitioners = [practitioner_resource(m, n + 1) for n, m in enumerate(d.care_team)] + procedures = [procedure_resource(line, n + 1, completed = (leg == "claim"), when = d.admission.surgery_at or d.admission.admitted_at) for n, line in enumerate(package_lines(d.lines))] + (qrs, form_refs) = questionnaire_responses(d.forms, d.created) + (si, si_refs) = supporting_info(d, leg, form_refs) + claim = {"resourceType": "Claim", "id": d.claim_no, "meta": profile("Claim"), + "identifier": [typed_id(ID_TYPE, "CLN", "Claim number", d.claim_no, BASE)], + "status": "active", "type": cc(SNOMED, "737481003", "Inpatient care management (procedure)"), "use": use, + "patient": ref(U + "/patient"), + "billablePeriod": {"start": d.admission.admitted_at, "end": d.admission.discharged_at or planned_end(d)}, + "created": d.created, "insurer": ref(U + "/payer"), "provider": ref(U + "/provider"), + "priority": cc(PRIORITY, "normal", "Normal"), + "careTeam": [{"sequence": n + 1, "provider": ref(practitioner_url(n)), + "role": cc(CARE_ROLE, "primary" if n == 0 else "assist", "Primary provider" if n == 0 else "Assisting Provider"), + "qualification": cc(SNOMED, m.specialty_snomed, m.specialty_display)} for n, m in enumerate(d.care_team)], + "supportingInfo": si, + "diagnosis": [{"sequence": n + 1, "diagnosisCodeableConcept": cc(ICD10, dx.code, dx.display), + "type": [cc(DX_TYPE, "admitting", "Admitting Diagnosis")], "onAdmission": cc(DX_ONADM, "yes", "Yes")} for n, dx in enumerate(d.diagnoses)], + "procedure": [{"id": "Procedure/" + str(n + 1), "sequence": n + 1, + "type": [cc(PROC_TYPE, line.procedure_type.lower(), line.procedure_type)], # from the plan's ProcedureType condition + "date": d.admission.surgery_at or d.admission.admitted_at, + "procedureReference": {"reference": U + "/procedure/" + str(n + 1), "display": line.display}} for n, line in enumerate(package_lines(d.lines))], + "insurance": [{"sequence": 1, "focal": true, "coverage": ref(U + "/coverage")}], + "item": claim_items(d, si_refs), + "total": money(sum(item.net.value for item in items))} + if leg == "claim": claim.insurance[0].preAuthRef = [d.preauth_ref] # the payer's ClaimResponse.preAuthRef + entries = [entry(anchor, claim), entry(U + "/patient", patient_resource(d.patient)), + entry(U + "/provider", provider_org(d.facility, "1")), entry(U + "/payer", payer_org(d.payer, "2")), + entry(U + "/coverage", coverage_resource(d.policy_code, d.patient.member_id))] + entries += [entry(practitioner_url(n), p) for n, p in enumerate(practitioners)] + entries += [entry(U + "/procedure/" + str(n + 1), p) for n, p in enumerate(procedures)] + entries += [entry(U + "/questionnaireresponse/" + str(n + 1), q) for n, q in enumerate(qrs)] + return bundle(leg + "-" + d.flow + "-request-generic", "ClaimBundle", entries) + # preauth-request-generic, preauth-enhancement-request-generic, preauth-queryupdate-request-generic, claim-request-generic, claim-queryupdate-request-generic + +function practitioner_url(n): return BASE + "/practitioner" + ("" if n == 0 else "/" + str(n + 1)) + +function patient_resource(p): + ids = [typed_id(ID_TYPE, "PMJAY", "Pradhan Mantri Jan Aarogya Yojana (PMJAY) ID", p.member_id)] + if p.abha: ids.append(typed_id(ID_TYPE, "ABHA", "Ayushman Bharat Health Account (ABHA) ID", p.abha)) + ids.append(typed_id(V2_0203, "MB", "Member Number", p.member_id)) + return {"resourceType": "Patient", "id": "1", "meta": profile("Patient"), "identifier": ids, + "name": [{"text": p.name}], "telecom": [{"system": "phone", "value": p.phone}], "gender": p.gender, "birthDate": p.birthDate} + +function practitioner_resource(m, n): + ids = [typed_id(ID_TYPE, "HPID", "Healthcare Professional ID (HPID)", m.hpid or m.hpin, BASE)] + if m.licence: ids.append(typed_id(V2_0203, "MD", "Medical License number", m.licence, BASE)) + ids.append(typed_id(ID_TYPE, "HPIN", "Health Practitioner ID issued by NDHM", m.hpin, HPR)) # PAYR-1083 without it + return {"resourceType": "Practitioner", "id": str(n), "meta": profile("Practitioner"), "identifier": ids, + "name": [{"text": m.name}], "qualification": [{"code": cc(V2_0360, m.qualification_code, m.qualification_display)}]} + +function coverage_resource(policy_code, member_id): + return {"resourceType": "Coverage", "id": "1", "meta": profile("Coverage"), + "identifier": [typed_id(V2_0203, "NH", "National Health Plan Identifier", policy_code)], + "status": "active", "type": cc(ACT_CODE, "HIP", "health insurance plan policy"), + "subscriber": ref(BASE + "/patient"), "subscriberId": member_id, "beneficiary": ref(BASE + "/patient"), + "relationship": cc(REL, "self"), "payor": [ref(BASE + "/payer")]} + +function procedure_resource(line, n, completed, when): + return {"resourceType": "Procedure", "id": str(n), "meta": profile("Procedure"), + "status": "completed" if completed else "preparation", + "code": {"coding": [{"system": SNOMED, "code": "71388002", "display": "Procedure"}], "text": line.display}, + "subject": ref(BASE + "/patient"), "performedDateTime": when} +``` + +### Items: one per procedure or implant, never per tier + +``` +function package_lines(lines): return [l for l in lines if l.kind in ("procedure", "implant")] # tiers ride on their parent + +function claim_items(d, si_refs): + groups = package_lines(d.lines); factors = procedure_factors(groups, d.factor_rule) + items = [] + for n, line in enumerate(groups): + tiers = [t for t in d.lines if t.kind == "tier" and t.parent_code == line.code] + net = line.amount + sum(t.amount for t in tiers) + item = {"id": "Item/" + str(n + 1), "sequence": n + 1, "careTeamSequence": [1], "diagnosisSequence": [1], + "procedureSequence": [n + 1], "informationSequence": si_refs, # every supportingInfo sequence + "category": cc(BENEFIT_CAT, line.category.code, line.category.display), + "productOrService": cc(PROC_CODE, line.code, line.display)} + if tiers: item.modifier = [cc(null, t.code, t.display) for t in tiers] + if d.program_code: item.programCode = [cc(PROGRAM, d.program_code, "Ayushman Bharat Pradhan Mantri Jan Arogya Yojana (AB-PMJAY)")] + item.servicedPeriod = {"start": day(d.admission.admitted_at), "end": day(d.admission.discharged_at or planned_end(d))} + item.quantity = {"value": int(line.quantity)} + item.unitPrice = money(net / line.quantity) + if factors: item.factor = factors[n] + item.net = money(net) + items.append(item) + return items + +function procedure_factors(groups, rule): + # PMJAY multiple-procedure rule: by cost rank, 1, 0.5, 0.25; a generic payer sends no factor + if rule != "pmjay" or len(groups) < 2: return null # the single-item pins carry factor 0.5 (their own contradiction); compare without it + ranked = sorted(range(len(groups)), key = lambda i: -groups[i].amount) + return {i: [1, 0.5, 0.25][min(rank, 2)] for rank, i in enumerate(ranked)} +``` + +### supportingInfo: the table, then the numbering + +``` +function supporting_info(d, leg, form_refs): + si = [] + for doc in d.documents: # one per attached file; never drop one + si.append({"category": cc(SI_CATEGORY, doc.category or "INV", display_for(doc.category or "INV")), + "code": cc(DOC_CODE, doc.code or "ODN", doc.title), # the plan's code, else ODN + "valueAttachment": {"contentType": doc.content_type, "data": base64(doc.bytes), "title": doc.title}}) + if leg == "claim": + si.append({"category": cc(SI_CATEGORY, "HDS", "Discharge summary"), "code": cc(DOC_CODE, d.summary.code or "HDS", d.summary.title), + "valueAttachment": {"contentType": d.summary.content_type, "data": base64(d.summary.bytes), "title": d.summary.title}}) + si.append(scalar("ONS", "ADDD", "Admission date -Discharge date", d.admission.admitted_at)) + si.append(scalar("OTH", "EDT", "EncounterDateTime", d.admission.admitted_at)) + if leg == "claim": + if d.admission.surgery_at: si.append(scalar("ONS", "PSP", "Procedure start", d.admission.surgery_at)) + si.append(scalar("ONS", "DSDE", "Discharge date", d.admission.death_at or d.admission.discharged_at)) + if d.admission.mode == "death": si.append(scalar("ONS", "DTM", "Date and time of death", d.admission.death_at)) # PAYR-1096 without it + code = {"normal": "DTH", "lama": "LAMA", "dama": "DAMA", "death": "DTM"}[d.admission.mode] + si.append(scalar("DIS", code, display_for(code), stage_words(d.admission.stage))) # "Before Surgery" | "During Surgery" | "After Surgery" + if d.flow == "queryupdate": + si.append(scalar("NMI", "CQD", "Claim query detail", d.query_reply)) # the desk's words; PMJAY reads its answer from here + for (form, url) in form_refs: # one per answered form + cat = "STG" if form.kind == "stg" else "INF"; code = "STG" if form.kind == "stg" else "ODN" + si.append({"category": cc(SI_CATEGORY, cat, display_for(cat)), "code": cc(SI_CODE, code, display_for(code)), "valueReference": ref(url)}) + for n, s in enumerate(si): # number once, after assembly: PAYR-1019 without sequence + s.id = "SupportingInformation/" + str(n + 1); s.sequence = n + 1 + reorder(s, ["id", "sequence", "category", "code", "value*"]) + return (si, [s.sequence for s in si]) + +function scalar(cat, code, display, value): + return {"category": cc(SI_CATEGORY, cat, display_for(cat)), "code": cc(SI_CODE, code, display), "valueString": value} +``` + +### Questionnaire responses + +``` +function questionnaire_responses(forms, authored): + qrs = []; refs = [] + for n, form in enumerate(forms): + url = BASE + "/questionnaireresponse/" + str(n + 1) + qr = {"resourceType": "QuestionnaireResponse", "id": str(n + 1), "meta": profile("QuestionnaireResponse"), + "questionnaire": form.url, "status": "completed", "subject": ref(BASE + "/patient"), "authored": authored, + "item": [{"linkId": a.linkId, "answer": [typed_answer(a)]} for a in form.answers]} + qrs.append(qr); refs.append((form, url)) + return (qrs, refs) + +function typed_answer(a): + switch a.type: + "string", "text", "choice": return {"valueString": a.value} + "date", "dateTime": return {"valueDateTime": a.value} + "boolean": return {"valueBoolean": a.value} + "integer": return {"valueInteger": int(a.value)} + "decimal": return {"valueDecimal": a.value} + "attachment": return {"valueAttachment": {"contentType": a.content_type, "data": base64(a.bytes), "title": a.title}} +``` + +### Which forms and documents ride + +``` +function required_forms(case, stage): # stage: preauth | claim + if case.ruling: forms = [r for r in case.ruling.requirements if r.kind == "form" and (stage == "preauth" or r.stage != "pre")] + else: forms = plan_stg_forms(case.plan, case.lines) if stage == "preauth" else [] + return forms + policy_forms(case.plan) # consent every leg: PAYR-1256 / PAYR-1363; STG: PAYR-1254 / PAYR-1365 + +function required_documents(case, stage): + if case.ruling: return [r for r in case.ruling.requirements if r.kind == "document" and (r.stage == "pre") == (stage == "preauth")] + wanted = plan_documents(case.plan, case.lines) + return wanted if stage == "preauth" else [w for w in wanted if not attached_at_preauth(case, w.code)] +``` + +### The legs, and the LAMA collapse + +``` +function lines_for(case, leg): + if leg == "claim" and case.admission.mode in ("lama", "dama") and case.admission.stage in ("before", "during"): + return [{"kind": "procedure", "code": "LM100", "display": "Left against medical advice", "quantity": 1, + "amount": plan_rate(case.plan, "LM100") or 0, "category": lm100_category(case.plan)}] # PAYR-1362 if the package stays + return case.lines # LM100 never on a pre-auth: PAYR-1270 +``` + +| Leg | flow | use | Procedure status | Workflow | Extra | +| --- | --- | --- | --- | --- | --- | +| Pre-auth | `request` | `preauthorization` | `preparation` | 12 | fresh 12 after a rejection too (PAYR-1214 on 121) | +| Enhancement | `enhancement` | `preauthorization` | `preparation` | 13 | every line, old and new, same claim number; factors 1 and 0.5 | +| Query answer | `queryupdate` | `preauthorization` | `preparation` | 19 (131 after an enhancement query) | `NMI/CQD`; new correlation id | +| Claim | `request` | `claim` | `completed` | 15 | discharge scalars, `HDS`, `preAuthRef`, under the pre-auth's number (ERR-PYR-CLM-007) | +| Claim query answer | `queryupdate` | `claim` | `completed` | 161 (PMJAY), 151 (generic) | as the claim plus `NMI/CQD` | +| Predetermination | `request` | `predetermination` | `preparation` | 12 on `v1/preauth/submit` | no state effects | + +## 5. Reader: ClaimResponse + +Fed by every answer on a pre-auth, enhancement, claim or predetermination thread. Entries: ClaimResponse, Patient, two Organizations, Coverage. + +``` +function parse_claim_response(b): + r = first(b, "ClaimResponse") + status_adj = first(a for a in r.adjudication or [] if a.category.coding[0].code == "status") + out = {"use": r.use, "outcome": r.outcome, "disposition": r.disposition, + "status_reason": status_adj.reason.coding[0].code.lower() if status_adj else null, # submitted|approved|queried|rejected|cancelled + "preauth_ref": r.preAuthRef if is_string(r.preAuthRef) else (r.preAuthRef[0] if r.preAuthRef else null), + "claim_no": r.identifier[0].value if r.identifier else null, + "totals": {t.category.coding[0].code: t.amount.value for t in r.total or []}, # by category, never by position + "items": [], "notes": [n.text for n in r.processNote or []]} + for it in r.item or []: + adj = {a.category.coding[0].code: a for a in it.adjudication or []} + out.items.append({"sequence": it.itemSequence, + "status": adj.status.reason.coding[0].code.lower() if adj.status else null, + "eligible": adj.eligible.amount.value if adj.eligible else null, + "submitted": adj.submitted.amount.value if adj.submitted else null, + "reason": adj.reason.reason.coding[0].display if adj.reason else "", # verbatim, pipe-delimited USER~datetime~type~comment~trust + "eligpercent": adj.eligpercent.value if adj.eligpercent else null, + "deductible": adj.deductible.amount.value if adj.deductible else null}) + return out + +function verdict_status(p): # copy exactly; never read outcome alone + if p.outcome == "queued" or p.status_reason == "submitted": return "submitting" + if p.status_reason == "cancelled": return "rejected" + if p.status_reason == "queried": return "queried" + if p.outcome == "error": return "rejected" + if p.outcome == "partial": return "partial" if p.status_reason == "approved" else "queried" + if p.outcome == "complete": return "approved" if p.status_reason in ("approved", null) else "queried" + return "queried" + +function apply_claim_response(leg, p, envelope): + leg.status = verdict_status(p) + if p.preauth_ref: leg.preauth_ref = p.preauth_ref # never overwrite a value with an empty one + leg.eligible_amount = p.totals.get("eligible") or p.totals.get("benefit") + leg.submitted_amount = p.totals.get("submitted") + leg.approved_amount = p.totals.get("benefit") # what the screen shows as the decision + leg.items_json = p.items; leg.query_note = join(p.notes + [i.reason for i in p.items if i.reason]) + leg.thread_correlation_id = envelope.jwe_headers["x-hcx-correlation_id"] + leg.answered_at = now() if leg.status != "submitting" else leg.answered_at +``` + +Payer workflow ids are labels for the timeline only: 20 received, 21 approved, 22 enhancement approved, 23 rejected, 24 queried, 25 claim received, 26 approved, 27 queried, 291 rejected. The bundle decides the state. + +## 6. Task bundles the hospital sends + +Pins: `preauth/cancel`, `claim/reprocess`, `claim/release`, `payment/notice-ack`. Sent on `v1/task/submit` (the payment acknowledgement on `v1/paymentnotice/on_request`). Entries: Task, provider Organization, payer Organization. + +``` +function task_bundle(id, anchor, task, facility, payer): + return bundle(id, "TaskBundle", [entry(BASE + anchor, task), entry(BASE + "/provider", provider_org(facility)), entry(BASE + "/payer", payer_org(payer))]) + +function base_task(code, status, authored_on, description): + return {"resourceType": "Task", "meta": profile("Task"), "status": status, "intent": "order", + "code": cc(FIN_TASK, code), "description": description, "authoredOn": authored_on, + "requester": ref(BASE + "/provider"), "owner": ref(BASE + "/payer")} + +function task_input(code, display, value): return {"type": cc(TASK_INPUT, code, display), "valueString": value} +function based_on(claim_no): return [{"identifier": typed_id(ID_TYPE, "CLN", "Claim number", claim_no, BASE), "display": "Claim " + claim_no}] + +function cancel_task(claim_no, reason, authored_on, facility, payer): # workflow PC01 + t = base_task("cancel", "requested", authored_on, "Cancel the preauthorization " + claim_no) + t.reasonCode = cc(REASON, reason.code, reason.display) # treatmentplanchanged, ... + t.input = [task_input("claimNumber", "ClaimNumber", claim_no), task_input("intimationNumber", "IntimationNumber", claim_no)] + return task_bundle("preauth-cancel-request-generic", "/preauth/cancel", t, facility, payer) + +function reprocess_task(claim_no, member_id, reason, description, documents, authored_on, facility, payer): # workflow 36 + t = base_task("reprocess", "requested", authored_on, description) + t.reasonCode = cc(REASON, reason.code, reason.display) # claimrejected | partialpayment | rejectiondisputed + t.basedOn = based_on(claim_no) + t.input = [task_input("claimNumber", "ClaimNumber", claim_no), task_input("intimationNumber", "IntimationNumber", claim_no)] + t.input += [{"type": cc(TASK_INPUT, "document", "Document"), "valueAttachment": {"contentType": d.content_type, "data": base64(d.bytes), "title": d.title}} for d in documents] + t.for = {"identifier": typed_id(ID_TYPE, "PMJAY", "Pradhan Mantri Jan Aarogya Yojana (PMJAY) ID", member_id)} # MB on a generic payer + return task_bundle("claim-reprocess-request-generic", "/claim/reprocess", t, facility, payer) + +function release_task(claim_no, amount, authored_on, facility, payer): # workflow 36 + t = base_task("release", "requested", authored_on, "Release the balance amount for claim " + claim_no) + t.reasonCode = cc(REASON, "partialpayment", "Reprocess request due to partial payment by payer") + t.basedOn = based_on(claim_no) + t.input = [task_input("claimNumber", "ClaimNumber", claim_no), {"type": cc(TASK_INPUT_X, "amount", "Amount"), "valueMoney": money(amount)}] + return task_bundle("claim-release-request-generic", "/claim/release", t, facility, payer) + +function status_task(claim_no, authored_on, facility, payer): # workflow = the leg's correlation id; PMJAY refuses (PAYR-1018) + t = base_task("status", "requested", authored_on, "Status of " + claim_no) + t.input = [task_input("claimNumber", "ClaimNumber", claim_no)] + return task_bundle("claim-status-request-generic", "/claim/status", t, facility, payer) + +function payment_ack(claim_no, authored_on, facility, payer): # workflow 17 (PMJAY) or the notice's own id; x-hcx-correlation_id = the notice's + t = base_task("status", "completed", authored_on, "Received the payment for claim " + claim_no) + t.output = [{"type": cc(TASK_OUTPUT, "status", "Status"), "valueCodeableConcept": cc(TASK_OUTVAL, "paymentack", "Payment is acknowledged")}, + {"type": cc(TASK_INPUT, "claimNumber", "ClaimNumber"), "valueString": claim_no}] + return task_bundle("payment-notice-ack-generic", "/payment/notice-ack", t, facility, payer) +``` + +The pins and the build both carry `intimationNumber`, so the offline comparison diffs the pins unchanged. + +### Readers: PC02, 37, status + +``` +function parse_task_answer(b): + t = first(b, "Task"); cr = first(b, "ClaimResponse") # a 37 may carry a ClaimResponse queued + outputs = {o.type.coding[0].code: o for o in t.output or []} + return {"status": t.status, "code": t.code.coding[0].code, + "claim_status": (outputs.get("claimStatus") or outputs.get("status") or {}).valueCodeableConcept.coding[0].code if outputs else null, + "description": t.description, "queued": cr is not null and cr.outcome == "queued"} +# PC02: pre-auth -> cancelled, episode gets a fresh claim number, the withdrawn one stays on the leg +# 37: enquiry row -> answered; a fresh verdict follows on the claim's own thread +``` + +## 7. Communication + +Pins: `communication/request` (the payer's TaskBundle, the reader's input) and `communication/response` (the hospital's reply). On `v1/communication/request` in, `v1/communication/on_request` out, with the request's correlation id and workflow id echoed. + +``` +function parse_communication_request(b): + t = first(b, "Task"); cr = first(b, "CommunicationRequest") + return {"task_status": t.status, "intent": t.intent, "reason": t.reasonCode.coding[0].code.lower() if t.reasonCode else null, + "request_id": cr.id, "request_url": fullurl_of(b, cr), + "questions": [p.contentString for p in cr.payload or [] if p.contentString], + "about_claim": (cr.basedOn or [{}])[0].display, "claim_no": claim_no_in(b)} + +function classify_communication(adapter, reason, intent): + if adapter.query_mode == "resubmit": return "notification" + if intent == "proposal": return "notification" + if intent == "order": return "query" + if reason in (null, "additionalinfo", "questionnaire", "query"): return "query" + return "notification" # tatquery, grievance, walletupdate, policychange, claimarbitration + +function build_acknowledgement_bundle(request_bundle, facility): # a notification, sent back at once + b = deepcopy(request_bundle); t = first(b, "Task"); t.status = "completed" + move_first(b, "Organization", where = provider) # provider Organization first + return b + +function build_communication_bundle(q, text, documents, sent_leg_bundle, facility, payer, now): + # q: the parsed request; sent_leg_bundle: the pre-auth or claim bundle as sent (its Claim, Patient, Organizations, Practitioner, Coverage are lifted) + task_id = uuid(); comm_id = uuid() + comm = {"resourceType": "Communication", "id": comm_id, "meta": profile("Communication"), + "identifier": [{"value": q.request_identifier}], "basedOn": [{"reference": q.request_url, "display": "CommunicationRequest"}], # never inResponseTo + "status": "completed", "category": [cc(COMM_CAT, "notification")], "priority": "routine", + "about": [{"reference": claim_anchor(sent_leg_bundle), "display": "Claim " + claim_no}], + "sender": {"reference": BASE + "/provider", "display": "Organization"}, "recipient": [{"reference": BASE + "/payer", "display": "Organization"}], + "payload": [{"contentString": text}] + [{"contentAttachment": {"contentType": d.content_type, "data": base64(d.bytes), "title": d.title}, + "extension": [{"url": DOC_TYPE_EXT, "valueString": d.code}]} for d in documents]} + task = {"resourceType": "Task", "id": task_id, "meta": profile("Task"), "status": "completed", "intent": "order", + "code": cc(TASK_CODES, "deliver"), "reasonCode": cc(null, q.reason or "additionalinfo", "Additional information requested"), + "authoredOn": now, "requester": {"reference": BASE + "/provider", "display": "Organization"}, "owner": {"reference": BASE + "/payer", "display": "Organization"}, + "input": [{"type": cc(FIN_INPUT, "include"), "valueReference": {"reference": "urn:uuid:" + comm_id, "display": "Communication"}}]} + entries = [entry("urn:uuid:" + task_id, task), entry("urn:uuid:" + comm_id, comm), entry(q.request_url, q.request_resource)] + entries += [entry(e.fullUrl, e.resource) for e in sent_leg_bundle.entry if e.resource.resourceType in ("Claim", "Patient", "Organization", "Practitioner", "Coverage")] + b = bundle("communication-response-generic", "TaskBundle", entries) + b.meta.lastUpdated = now; b.timestamp = now # the IG example carries both; the only request that does + return b +``` + +Excluded from the byte comparison of the reply: `meta.lastUpdated`, `timestamp`, `authoredOn`, the two generated uuids. + +## 8. Payment notice + +Read on `v1/paymentnotice/request`. Entries: Task, PaymentNotice, PaymentReconciliation, two Organizations. + +``` +function parse_payment_notice(b): + pn = first(b, "PaymentNotice"); pr = first(b, "PaymentReconciliation"); t = first(b, "Task") + out = {"claim_no": pn.identifier[0].value if pn.identifier else claim_no_in(b), + "amount": pn.amount.value, "payment_status": pn.paymentStatus.coding[0].code, # paid | cleared | ... + "payment_date": pn.paymentDate, "utr": null, "details": []} + if pr: + out.utr = pr.paymentIdentifier.value if pr.paymentIdentifier else null + out.gross = pr.paymentAmount.value if pr.paymentAmount else null + out.details = [{"type": d.type.coding[0].code, "amount": d.amount.value if d.amount else null} for d in pr.detail or []] # deductions, TDS + if not out.utr and pn.payment and pn.payment.identifier: out.utr = pn.payment.identifier.value + return out +# record: one claim_payment row keyed on the message's correlation id (unique), matched by claim_no; then acknowledge with payment_ack() +``` + +## 9. Validate before you send + +``` +function validate_bundle(b, pin): # the offline gate, module 7.7 Validate + assert canonical(strip(b, ["created"])) == canonical(strip(pin, ["created"])) # plus the per-shape exclusions above + urls = {e.fullUrl for e in b.entry} + for r in all_references(b): assert r in urls or r.startswith("urn:uuid:") + c = first(b, "Claim") + if c: + for it in c.item: assert it.id and it.sequence + for p in c.procedure: assert p.id and p.sequence + for n, s in enumerate(c.supportingInfo): assert s.id and s.sequence == n + 1 + for pr in all(b, "Practitioner"): assert any(i.type.coding[0].code == "HPIN" and i.system == HPR for i in pr.identifier) + assert c.total.value == sum(it.net.value for it in c.item) + assert not any(it.productOrService.coding[0].code == "LM100" for it in c.item) or c.use == "claim" + assert no literal in the builder matches r"MAND\d+|MG\d+|/questionnaire/" +``` + +| Symptom | Refusal | +| --- | --- | +| an item without `id` | PAYR-1027 | +| a supportingInfo without `sequence` | PAYR-1019 | +| a Practitioner without `HPIN` | PAYR-1083 | +| a death claim without `ONS/DTM` | PAYR-1096, PAYR-1503 | +| a LAMA claim before surgery still carrying the package | PAYR-1362 | +| `LM100` on a pre-auth | PAYR-1270 | +| the consent form unanswered | PAYR-1256 (pre-auth), PAYR-1363 (claim) | +| a package's STG form unanswered | PAYR-1254, PAYR-1365 | +| a claim under its own number | ERR-PYR-CLM-007 | +| 121 after a rejection | PAYR-1214 | +| 151, 19 or 16 on `v1/claim/submit` to PMJAY | PAYR-1321 | +| a document outside pdf, jpg, jpeg, png; a Task the sandbox does not take; a misspelt intimation input on a reprocess | PAYR-1008 | diff --git a/plugins/nhcx/skills/nhcx-communication/flow/FLOW.md b/plugins/nhcx/skills/nhcx-communication/flow/FLOW.md new file mode 100644 index 000000000..312668e67 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-communication/flow/FLOW.md @@ -0,0 +1,228 @@ +# The flow: the one path a claim episode walks + +This is the reference flow for an NHCX provider desk: these steps, in this order, with these guards and these words. A build from this skill walks the same path. It does not redesign it, reorder it, merge steps, or invent screens the path does not have. Stage 4 copies it, stage 5 puts screens on it, stage 7 implements it step by step, stage 8 checks every step exists, and test drivers check the same through `flow.json`. + +## The shape + +One episode is one case (`claim` row). It has one list screen, one "new case" screen and one case screen. The case screen has tabs in the order the episode happens, and above the tabs one status line and the actions the case is waiting for. Everything else (inbox, payments across cases) is a view over the same rows. + +Tabs on the case screen, in this order and with these names: + +| # | Tab key | Tab label | Opens when | +| --- | --- | --- | --- | +| 1 | `eligibility` | Eligibility | always | +| 2 | `plan` | Insurance plan | always (empty until the plan is fetched) | +| 3 | `lines` | Line items | always (quoting refused until the plan is `ready`) | +| 4 | `validate` | Validate | always (the ruling on the quoted set) | +| 5 | `preauth` | Pre-authorisation | once the coverage verdict is `eligible` | +| 6 | `communication` | Communication | always (the payer's questions on both legs) | +| 7 | `claim` | Claim | always; its submit opens once a pre-auth is approved or partial | +| 8 | `payments` | Payments | always | + +The episode may also render on one page, with the same sections in the same order. Either shape is fine; the order and the gating are not negotiable. + +## Which skill builds which step + +Seven skills build this flow, one slice each (`core/LADDER.md`). `flow.json` names them per step in `skills`, the first named being the one that owns the step. + +| Steps | Skill | +| --- | --- | +| F1, F2, F3 | `nhcx-coverage` | +| F4, F7 | `nhcx-insurance` | +| F5, F6, F8, F9, F9a, F9c, F9d, F9e; F9b for a `resubmit` payer (19, 131) | `nhcx-preauth` | +| F10, F11; the claim query answer for a `resubmit` payer (161) | `nhcx-claim` | +| F9b and the claim query for a `communication` payer; F12b | `nhcx-communication` | +| F12 | `nhcx-payment` | +| F13 | `nhcx-reprocess` | + +The case screen, its tabs, the status line and actions, and the page-load polls are the foundation's (`core/FOUNDATION.md`): the first skill lays them out whole, and each skill fills its own tabs. + +## The status line and the actions + +Above the tabs: `stage / sub-stage` from `case_stage` (module 7.11) and the list from `next_actions`, first item highlighted. The labels are these, verbatim: + +| Stage | Sub-stage | Action offered (label, tab) | +| --- | --- | --- | +| any | an open query exists | "Answer the payer (n)", `communication` (leads every list) | +| `eligibility` | `draft`, `error`, `not-eligible` | "Check the cover", `eligibility` | +| `eligibility` | `eligible`, no plan `ready` | "Fetch the package master", `plan` | +| `eligibility` | plan ready, no lines | "Quote the treatment", `lines` | +| `eligibility` | lines quoted | "Send the pre-authorisation", `preauth` | +| `preauth` or `enhancement` | `queried` | "Answer the query", `preauth` (resubmit payer) or "Answer the payer's query", `communication` (communication payer) | +| `preauth` | `draft`, `refused` | "Send the pre-authorisation", `preauth` | +| `preauth` | `rejected` | "Send a fresh pre-authorisation", `preauth` | +| `preauth` | `approved`, `partial`, lines added since | "Send the enhancement (n added)", `preauth` | +| `preauth` | `approved`, `partial`, not discharged | "Record the discharge", `claim` | +| `preauth` | `approved`, `partial`, discharged | "File the claim", `claim` | +| `preauth` | `requested`, `answered`, `resubmitted` | "With the payer; ask where it stands", `preauth` | +| `claim` | `queried` | "Answer the claim query", `claim` or "Answer the payer's query", `communication` | +| `claim` | `rejected`, `partial` | "Ask for a reprocess", `claim` | +| `claim` | `requested`, `answered`, `resubmitted` | "With the payer; ask where it stands", `claim` | +| `claim` | `refused` | "Send the claim again", `claim` (while a send kind remains) else "Ask for a reprocess" | +| `claim` | `approved` | "Await the payment notice", `payments` | +| `payment` | a notice unacknowledged | "Acknowledge the payment notice", `payments` | +| `payment` | all acknowledged | "Settled", `payments` | + +## The steps + +Each step: where it happens, what must hold, what the user does, what the system does (module in brackets), what goes on the wire, what is stored, where the case stands afterwards, and what the screen shows next. Ids are `F1` to `F13` with letters for branches; `flow.json` carries the same ids. + +### F1. Policy search + +- Screen: Cases list, "New case", `GET /claims/new`. +- Holds: nothing. +- User: picks an identifier type (`MemberId`, `AbhaNumber`, `MobileNo`) and a value, presses "Search policies". +- System [7.4]: `search_policies` through the transport: the participant service's `participant/get/policies`; normalises each row (`member_id`, `policy_code` from `productid`, `payer_code` from `payerid`, `recipient_code` from `processingid`, `product_name`). NHCX-1016 (nothing linked) is an empty list, not an error. +- Screen: a table, one row per policy: beneficiary, product and policy, payer, ABHA, mobile, a "Select" button. No name and no photo yet; the payer returns those at F3. + +### F2. Open the case + +- Screen: the same, "Select" on a row; `POST /claims`. +- System [7.4, 7.2]: `create_claim` snapshots the policy (`member_id`, `policy_code`, `payer_code`, `recipient_code`, `policy_json`), mints the claim number, stamps `eligibility / draft`. +- Redirect: the case screen, Eligibility tab, "Claim opened." +- Next action: "Check the cover". + +### F3. Check the cover (coverage eligibility) + +- Screen: Eligibility tab, card "Coverage eligibility check": purpose select (`validation` default, `benefits`, `discovery`), policy code and member id shown from the snapshot, "Send to payer". +- Holds: member id; policy code for `validation` and `benefits`. +- System [7.4]: `run_check(purpose)`, workflow id = the claim number, status `checking`; the page shows "Awaiting payer" and refreshes; the answer arrives by callback [7.3] or poll. +- Wire: `v1/coverageeligibility/check`; `on_check` back. +- Stored: `txn_id`, `correlation_id`, `api_call_id`; on the answer `inforce`, `outcome`, `disposition`, allowed and used amounts, the payer's `Patient` (name, gender, DOB, address, ABHA, photo), `Coverage` class and period. +- After: `eligibility / eligible` or `not-eligible` (or `error` with the payer's words). A `ProtocolResponse` or a 404 on `txn/related` settles as `error`, never spins. +- Screen: card "Payer verdict": Sum insured, Utilised, Wallet balance (allowed less used), Disposition verbatim, In force, Pre-authorisation required, Checked at, Correlation. Beneficiary card fills with the payer's demographics. "Check again" allowed from any settled state. +- Next action: "Fetch the package master". + +### F4. Fetch the package master (insurance plan) + +- Screen: Insurance plan tab, "Fetch the plan" (or "Refresh"). +- Holds: `eligible`. +- System [7.5]: `reuse_plan` first (same policy, provider, payer, status `ready`: zero sends); else `request_plan`, status `fetching`, workflow id = the claim number. +- Wire: `v1/insuranceplan/request`; `on_request` back with the InsurancePlan and Questionnaires. +- Stored: `claim_plan` (`ready`, `empty` or `error`), `claim_plan_benefit` per package, `claim_plan_form` per url. Both published shapes merged on package code. +- Screen: a search over the master (name or code, specialty filter, procedure or implant), one row per package with rate, kind, "View"; a package view with rate, implants approved, tiers, conditions, documents wanted, the forms those point at as questions; an "All forms" page. Policy-wide requirements shown above the table. +- Next action: "Quote the treatment". + +### F5. Link the admission (integrate) or capture it (standalone) + +- Screen: Pre-authorisation tab, card "Link the admission" (opens once `eligible`). +- Holds: `eligible`. +- Integrate: list every current inpatient stay of the patient whose ABHA matches the payer's (digits only); "Link" stores `patient_id` and `encounter_id`, defaults the admission date from the encounter. Linking before `eligible` and to a stay that is not a current IPD admission is refused. "Unlink" keeps the draft. +- Standalone [7.13]: register the patient (from the payer's demographics) and admit them here; the same two keys are stored. +- Screen after: card "Linked admission" with ward, bed, admitted at, consultant. + +### F6. The dossier (pre-auth capture) + +- Screen: Pre-authorisation tab, once linked: the form, saved in one transaction by `save_preauth` [7.7 inputs]. +- Captured: admission date (required) and provisional discharge date (not before admission); ICD-10 diagnoses (at least one; read off the admission when it recorded them, else a picker); the treating doctor (the admission's consultant, else a picker; must have an HPIN); package case or non-package case toggle; documents (pdf, jpg, jpeg, png, each recorded against the payer requirement code it answers, else `ODN`). +- Estimated amount: always recomputed server-side from the lines (F7), never from the form. +- Guards: saving a package case with no line quoted is refused. + +### F7. Quote the treatment (lines from the plan) + +- Screen: Line items tab, "Choose line items", `GET /claims//lines`. Three parts: what is quoted (editable quantities, running total, "remove"); what the payer says goes with it (implants approved for the quoted procedures, the tiers each offers; anything already quoted drops out); the whole master to search. +- Holds: plan `ready`. Quoting anything before that is refused. +- System [7.5]: `add_line(kind, code, parent_code)`; price read from the plan at add time; `amount = rate x quantity` server-side; a tier is added through the procedure that offers it and carries `parent_code`. Refused: a code the plan lacks, a tier the procedure does not offer, a duplicate, a zero quantity. +- Forms: the chosen lines pull in the questionnaires the plan attaches (STG per package, policy forms always); they render on the Pre-authorisation tab and are answered there (`save_answers`, one row per question, file answers upload a document). +- Next action: "Send the pre-authorisation". + +### F8. Validate the set (auth requirements) + +- Screen: Validate tab, "Ask the payer" (also run silently before F9). +- Holds: at least one line. +- System [7.6]: `ensure_auth_requirements`: fingerprint the quoted set; send only when the fingerprint is new; never wait for the answer. +- Wire: `v1/coverageeligibility/check` with purpose `auth-requirements` and the items; `on_check` back (the PMJAY sandbox rarely answers). +- Stored: `claim_auth` (`checking` then `ready`), items authorised or excluded, requirements (document or form, code, url, stage `pre` or `post`, `at_preauth`). +- Screen: the ruling per line, the documents and forms it wants for each leg; the pre-auth and claim tabs read it to build their document and form cards. Without a ruling they fall back to the plan's list. + +### F9. Send the pre-authorisation + +- Screen: Pre-authorisation tab, card "Submit": what will be sent (lines, forms answered, documents attached, the total), "Send to payer". +- Holds (all before any HTTP call): `eligible`; an admission linked; an admission date; at least one diagnosis; at least one care team member with an HPIN; at least one line; every required form answered; every document the ruling or plan asks for at pre-auth attached. +- System [7.7]: `submit_preauth`: `preauth_send_kind` picks `preauth` (12); builds the Claim bundle (`preauth`, `request`); status `submitting`, `submission_kind`, `workflow_id`; stores the three ids; `thread_correlation_id` untouched until the payer answers. +- Wire: `v1/preauth/submit`, workflow 12. +- After: `preauth / requested`. +- Screen: "Awaiting payer", the timeline row for the send, Refresh. Next action: "With the payer; ask where it stands". + +#### F9a. The payer answers + +- Callback [7.3] or poll: first the acknowledgement (workflow 20, `outcome queued`, reason `submitted`): recorded, `preauth_ref` kept, the leg stays `submitting`. Then the decision on the same correlation id: `verdict_status` [7.8]. +- After: `approved` (21), `partial` (approved for less), `queried` (24), `rejected` (23). Never read `outcome` alone. +- Screen: Decision, Payer reference (`preAuthRef`), Approved amount (`total[benefit]`), Eligible amount, the item verdicts table (eligible, status, reason verbatim, eligible %, quantity), process notes verbatim. A door refusal shows as a flag with the payer's code and text, the thread restored. +- Next action per the table above. + +#### F9b. Answer a query + +- Resubmit payer (PMJAY): the query is inside the ClaimResponse (`query_note`). Screen: Pre-authorisation tab, the payer's words, a reply box, "Submit again". System: `submit_preauth(reply)` with kind `preauth_query_response` (19; 131 after an enhancement query), flow `queryupdate`, `NMI/CQD` = the reply, a new correlation id. After: `answered`, then the decision. +- Communication payer (generic): the query is a CommunicationRequest on a new thread, filed in `claim_query` (F12 inbox). Screen: Communication tab, the questions verbatim, a reply box, documents to attach (existing or new, each under the payer's code else `ODN`), "Send the reply". System [7.10]: `answer_query`: the TaskBundle reply on `v1/communication/on_request` with the request's correlation id and workflow id. The leg stays `queried` until the decision arrives on its own thread. An empty reply is refused before any HTTP call. + +#### F9c. Enhancement + +- Screen: Line items tab, add a line after a decision; the Pre-authorisation card shows "enhancement pending (n added)"; "Submit enhancement". +- Holds: `approved` or `partial`; no request in flight. +- System: `submit_preauth` with kind `enhancement` (13; `enhancement_resubmit` 131 on a query): the whole bundle again, every line old and new, same claim number, factors 1 and 0.5. After: `enhancement / requested`, then 22 (or 21 from the SHA), 231, 241. + +#### F9d. Cancel + +- Screen: Pre-authorisation tab, "Withdraw": a reason picker (the seven documented reasons) and a note, required for Other. Hidden once a claim has been raised; refused on a `rejected` pre-auth and twice. +- System [7.9]: `cancel_preauth`: Task `cancel`, workflow PC01, on its own thread (`cancel_correlation_id`), `cancelling`. +- After PC02: `cancelled`; the episode gets a fresh claim number, the withdrawn one stays on the leg. + +#### F9e. Predetermination (a quote) + +- Screen: Pre-authorisation tab, "Ask for a quote". +- System [7.7]: the very bundle F9 would send with `use predetermination`, on `v1/preauth/submit`, workflow 12, its own row (`asking` then `answered`). Nothing on the pre-auth changes. + +### F10. Record the discharge + +- Screen: Claim tab, card "Discharge": mode (Normal, LAMA, DAMA, Death), stage (Before, During, After surgery), discharge date and time, surgery date and time, death date and time (death only). +- Holds: a pre-auth `approved` or `partial`. +- Stored: on `claim_submission` (`draft`) or the encounter. +- Screen after: the claim card opens; for LAMA or DAMA before or during surgery it says the approved packages are voided and the claim will carry `LM100` only. +- Next action: "File the claim". + +### F11. File the claim + +- Screen: Claim tab, cards "Documents for the claim" (what the ruling deferred to this stage, plus the discharge summary, always), "Forms for the claim" (the consent again, and what the ruling deferred), "Everything attached for the claim" (any further pdf or image), "Submit the claim". +- Holds: discharge recorded; the discharge summary attached; every claim-stage form answered; amount not above the approved amount. +- System [7.7]: `submit_claim`: `claim_send_kind` (`claim` 15; `claim_query_response` 161 PMJAY or 151 generic; `claim_resubmit` 16 generic only); the Claim bundle (`claim`, `request`) under the pre-auth's claim number with `preAuthRef`, procedures `completed`, discharge scalars, `HDS`, `DIS`; `LM100` collapse when it applies. +- Wire: `v1/claim/submit`. +- After: `claim / requested`; then 25 (ack), 26 `approved`, 27 `queried`, 291 `rejected`, read as F9a. +- Screen: as the pre-auth card: decision, amounts, item verdicts with `deductible`, notes verbatim. + +#### F11, continued: claim query and reprocess + +- Query: as F9b, on the claim (161 or the Communication reply). +- Rejected or partial: "Ask for a reprocess" (F13). There is no claim resubmit on PMJAY. + +### F12. Payments + +- The payer starts it: `v1/paymentnotice/request` arrives on a new thread, matched by the claim number inside (a `CLN` identifier, then any untyped identifier on the notice, the reconciliation, the Task; never the bundle id), looked up against `claim_no` and every leg's `claim_ref`. +- System [7.10]: `record_payment`: one `claim_payment` row per notice, deduped on the notice's correlation id; details from the PaymentReconciliation; a payer that reuses the notice id updates the row. Then, at once and automatically, `acknowledge_payment`: Task `status` `completed`, output `paymentack`, to the notice's own sender, its correlation id echoed, workflow 17 (PMJAY) or the notice's own (generic). A failed acknowledgement is kept on the row; the notice is still recorded and the callback still answered 2xx. +- After: `payment / noticed` or `paid`. Paid is counted once per UTR, newest notice winning; an initiated notice without a UTR shows "Initiated, UTR awaited" and is not money received. +- Screen: Payments tab, one card per notice: status, amount, UTR as text, the breakdown, "Acknowledged at" or "Send the acknowledgement again". Across cases: the payments view. +- Next action: "Acknowledge the payment notice" while one is pending, else "Settled". + +### F12b. The inbox + +- Every CommunicationRequest is classified [7.10]: query, notification or note. Notifications are acknowledged at once (the payer's bundle back, Task `completed`) and the case left alone. Queries are filed `open` and lead every action list until answered (F9b). Notes are shown, never acted on. +- Screen: Communication tab on the case; the inbox view across cases, by kind and reason. + +### F13. The small exchanges + +- Status: "Ask where it stands" on the pre-auth and claim cards, while awaiting and after a decision; Task `status`, workflow = the leg's correlation id (fallback 13); not offered to a payer whose adapter refuses it (PMJAY, PAYR-1018). The answer fills the enquiry row; the leg is unchanged. +- Reprocess: on a decided claim not paid in full, "Send reprocess request" with a coded reason (`claimrejected`, `partialpayment`, `rejectiondisputed`), words, and documents; Task `reprocess`, workflow 36. The payer's `completed` Task (37) reopens the claim: the submission goes back to `requested` and the new verdict lands on the claim's own thread. +- Release: once part of an approved claim is paid, "Ask for the balance" with the amount owed; Task `release`, reason `partialpayment`, `valueMoney`, workflow 36. +- Each ask is its own `claim_enquiry` row on its own thread, shown on the card it belongs to, newest first. + +## What runs on every page load of the case + +In this order, before rendering, each bounded to one poll and a short timeout, never a send: coverage (`checking`), plan (`fetching`), ruling (`checking`), claim (`submitting`), predeterminations (`asking`), pre-auth (`submitting` or `cancelling`), enquiries (`asking`). Then the beneficiary card, the policy card, the verdict card, the status line and actions, the tabs. A "Refresh" button reloads the same tab. + +## What is not in the flow + +- No status control anywhere. Stage and sub-stage are derived. +- No manual acknowledgement of a payment notice as the only path; it goes automatically and the screen shows that it went. +- No "chase" button without the status exchange behind it. +- No separate discharge submission on PMJAY; the discharge rides on the claim. +- No claim resubmit on PMJAY; a decided claim is reprocessed. diff --git a/plugins/nhcx/skills/nhcx-communication/flow/flow.json b/plugins/nhcx/skills/nhcx-communication/flow/flow.json new file mode 100644 index 000000000..315d1a4b8 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-communication/flow/flow.json @@ -0,0 +1,818 @@ +{ + "source": "flow/FLOW.md", + "tabs": [ + { + "key": "eligibility", + "label": "Eligibility", + "opens": "always" + }, + { + "key": "plan", + "label": "Insurance plan", + "opens": "always" + }, + { + "key": "lines", + "label": "Line items", + "opens": "always; quoting refused until the plan is ready" + }, + { + "key": "validate", + "label": "Validate", + "opens": "always" + }, + { + "key": "preauth", + "label": "Pre-authorisation", + "opens": "coverage verdict eligible" + }, + { + "key": "communication", + "label": "Communication", + "opens": "always" + }, + { + "key": "claim", + "label": "Claim", + "opens": "always; submit once the pre-auth is approved or partial" + }, + { + "key": "payments", + "label": "Payments", + "opens": "always" + } + ], + "stages": [ + "eligibility", + "preauth", + "enhancement", + "claim", + "payment" + ], + "sub_stages": [ + "draft", + "checking", + "eligible", + "not-eligible", + "requested", + "resubmitted", + "answered", + "queried", + "approved", + "partial", + "rejected", + "cancelling", + "cancelled", + "refused", + "noticed", + "paid" + ], + "next_actions": [ + { + "when": "an open query exists", + "label": "Answer the payer (n)", + "tab": "communication", + "leads": true + }, + { + "stage": "eligibility", + "sub_stage": [ + "draft", + "error", + "not-eligible" + ], + "label": "Check the cover", + "tab": "eligibility" + }, + { + "stage": "eligibility", + "when": "no plan ready", + "label": "Fetch the package master", + "tab": "plan" + }, + { + "stage": "eligibility", + "when": "no lines", + "label": "Quote the treatment", + "tab": "lines" + }, + { + "stage": "eligibility", + "when": "lines quoted", + "label": "Send the pre-authorisation", + "tab": "preauth" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "queried" + ], + "label": "Answer the query", + "tab": "preauth", + "payer": "resubmit" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "queried" + ], + "label": "Answer the payer's query", + "tab": "communication", + "payer": "communication" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "draft", + "refused" + ], + "label": "Send the pre-authorisation", + "tab": "preauth" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "rejected" + ], + "label": "Send a fresh pre-authorisation", + "tab": "preauth" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "approved", + "partial" + ], + "when": "lines added since", + "label": "Send the enhancement (n added)", + "tab": "preauth" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "approved", + "partial" + ], + "when": "not discharged", + "label": "Record the discharge", + "tab": "claim" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "approved", + "partial" + ], + "when": "discharged", + "label": "File the claim", + "tab": "claim" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "requested", + "answered", + "resubmitted" + ], + "label": "With the payer; ask where it stands", + "tab": "preauth" + }, + { + "stage": "claim", + "sub_stage": [ + "queried" + ], + "label": "Answer the claim query", + "tab": "claim", + "payer": "resubmit" + }, + { + "stage": "claim", + "sub_stage": [ + "queried" + ], + "label": "Answer the payer's query", + "tab": "communication", + "payer": "communication" + }, + { + "stage": "claim", + "sub_stage": [ + "rejected", + "partial" + ], + "label": "Ask for a reprocess", + "tab": "claim" + }, + { + "stage": "claim", + "sub_stage": [ + "requested", + "answered", + "resubmitted" + ], + "label": "With the payer; ask where it stands", + "tab": "claim" + }, + { + "stage": "claim", + "sub_stage": [ + "refused" + ], + "label": "Send the claim again", + "tab": "claim", + "when": "a send kind remains, else Ask for a reprocess" + }, + { + "stage": "claim", + "sub_stage": [ + "approved" + ], + "label": "Await the payment notice", + "tab": "payments" + }, + { + "stage": "payment", + "when": "a notice unacknowledged", + "label": "Acknowledge the payment notice", + "tab": "payments" + }, + { + "stage": "payment", + "when": "all acknowledged", + "label": "Settled", + "tab": "payments" + } + ], + "steps": [ + { + "id": "F1", + "name": "Policy search", + "screen": "new case", + "tab": null, + "routes": [ + "GET /claims/new" + ], + "module": "7.4", + "skills": ["nhcx-coverage"], + "holds": [], + "user": "Search policies", + "sends": { + "path": "participant/get/policies", + "kind": "registry REST" + }, + "stores": [], + "after": null, + "shows": "one row per policy with Select" + }, + { + "id": "F2", + "name": "Open the case", + "screen": "new case", + "tab": null, + "routes": [ + "POST /claims" + ], + "module": "7.4", + "skills": ["nhcx-coverage"], + "holds": [], + "user": "Select", + "sends": null, + "stores": [ + "claim: member_id, policy_code, payer_code, recipient_code, policy_json, claim_no" + ], + "after": { + "stage": "eligibility", + "sub_stage": "draft" + }, + "next_action": "Check the cover" + }, + { + "id": "F3", + "name": "Check the cover", + "screen": "case", + "tab": "eligibility", + "routes": [ + "POST /claims//check" + ], + "module": "7.4", + "skills": ["nhcx-coverage"], + "holds": [ + "member id", + "policy code for validation and benefits" + ], + "user": "purpose, Send to payer", + "sends": { + "path": "v1/coverageeligibility/check", + "workflow": "", + "reply": "on_check" + }, + "stores": [ + "txn_id", + "correlation_id", + "api_call_id", + "inforce", + "outcome", + "disposition", + "allowed_amount", + "used_amount", + "patient demographics", + "coverage class and period" + ], + "after": { + "stage": "eligibility", + "sub_stage": "eligible|not-eligible|error" + }, + "shows": "Payer verdict: sum insured, utilised, wallet balance, disposition verbatim", + "next_action": "Fetch the package master" + }, + { + "id": "F4", + "name": "Fetch the package master", + "screen": "case", + "tab": "plan", + "routes": [ + "POST /claims//plan", + "GET /claims//plan/", + "GET /claims//plan/forms" + ], + "module": "7.5", + "skills": ["nhcx-insurance"], + "holds": [ + "eligible" + ], + "user": "Fetch the plan (reuse first)", + "sends": { + "path": "v1/insuranceplan/request", + "workflow": "", + "reply": "on_request" + }, + "stores": [ + "claim_plan", + "claim_plan_benefit", + "claim_plan_form" + ], + "after": { + "plan": "ready|empty|error" + }, + "shows": "searchable master, package view, all forms", + "next_action": "Quote the treatment" + }, + { + "id": "F5", + "name": "Link or capture the admission", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//link", + "POST /claims//unlink" + ], + "module": "7.13 or the HMIS", + "skills": ["nhcx-preauth"], + "holds": [ + "eligible" + ], + "user": "Link the admission", + "sends": null, + "stores": [ + "claim.patient_id", + "claim.encounter_id", + "admission date default" + ], + "after": null + }, + { + "id": "F6", + "name": "The dossier", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//preauth", + "POST /claims//documents", + "POST /claims//documents/required" + ], + "module": "7.7 inputs", + "skills": ["nhcx-preauth"], + "holds": [ + "linked" + ], + "user": "Save the dossier", + "sends": null, + "stores": [ + "claim_diagnosis", + "claim_care_team", + "claim_document (code, stage)", + "claim_item" + ], + "guards": [ + "admission date required", + "at least one diagnosis", + "doctor with HPIN", + "package case needs a line" + ] + }, + { + "id": "F7", + "name": "Quote the treatment", + "screen": "lines", + "tab": "lines", + "routes": [ + "GET /claims//lines", + "POST /claims//lines", + "POST /claims//lines/quantities", + "POST /claims//lines//delete", + "POST /claims//forms" + ], + "module": "7.5", + "skills": ["nhcx-insurance"], + "holds": [ + "plan ready" + ], + "user": "add procedure, implant or tier; quantities; answer the forms the lines pull in", + "sends": null, + "stores": [ + "claim_line (rate from the plan, parent_code on a tier)", + "claim_form_answer" + ], + "guards": [ + "code not in plan", + "tier not offered by the procedure", + "duplicate", + "zero quantity" + ], + "next_action": "Send the pre-authorisation" + }, + { + "id": "F8", + "name": "Validate the set", + "screen": "case", + "tab": "validate", + "routes": [ + "POST /claims//auth" + ], + "module": "7.6", + "skills": ["nhcx-preauth"], + "holds": [ + "at least one line" + ], + "user": "Ask the payer (validate)", + "sends": { + "path": "v1/coverageeligibility/check", + "purpose": "auth-requirements", + "workflow": "", + "reply": "on_check", + "awaited": false + }, + "stores": [ + "claim_auth (fingerprint)", + "claim_auth_item", + "claim_auth_requirement" + ], + "after": { + "auth": "checking|ready" + } + }, + { + "id": "F9", + "name": "Send the pre-authorisation", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//submit" + ], + "module": "7.7", + "skills": ["nhcx-preauth"], + "holds": [ + "eligible", + "linked", + "admission date", + "diagnosis", + "care team with HPIN", + "a line", + "required forms answered", + "required documents attached" + ], + "user": "Send to payer", + "sends": { + "path": "v1/preauth/submit", + "workflow": "12", + "kind": "preauth", + "reply": "on_submit 20 then 21|23|24" + }, + "stores": [ + "claim_preauth: submitting, submission_kind, workflow_id, txn_id, correlation_id, api_call_id, request_json" + ], + "after": { + "stage": "preauth", + "sub_stage": "requested" + }, + "next_action": "With the payer; ask where it stands" + }, + { + "id": "F9a", + "name": "The payer answers", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /nhcx/callback/v1/preauth/on_submit" + ], + "module": "7.8", + "skills": ["nhcx-preauth"], + "holds": [], + "user": null, + "reads": "20 queued (stay submitting, keep preauth_ref) then the decision via verdict_status", + "stores": [ + "status", + "preauth_ref", + "approved_amount", + "eligible_amount", + "items_json", + "query_note", + "thread_correlation_id" + ], + "after": { + "stage": "preauth", + "sub_stage": "approved|partial|queried|rejected" + }, + "shows": "decision, payer reference, approved amount, item verdicts, notes verbatim; door refusal as a flag" + }, + { + "id": "F9b", + "name": "Answer a query", + "screen": "case", + "tab": "preauth or communication", + "routes": [ + "POST /claims//submit (reply)", + "POST /claims//queries//reply" + ], + "module": "7.7 or 7.10", + "skills": ["nhcx-preauth", "nhcx-communication"], + "holds": [ + "queried" + ], + "user": "reply text and documents", + "sends": { + "resubmit": { + "path": "v1/preauth/submit", + "workflow": "19 or 131", + "flow": "queryupdate", + "new_thread": true + }, + "communication": { + "path": "v1/communication/on_request", + "workflow": "", + "correlation_id": "" + } + }, + "after": { + "stage": "preauth", + "sub_stage": "answered (resubmit) or queried until the decision (communication)" + } + }, + { + "id": "F9c", + "name": "Enhancement", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//submit" + ], + "module": "7.7", + "skills": ["nhcx-preauth"], + "holds": [ + "approved or partial", + "lines added", + "no request in flight" + ], + "user": "Submit enhancement", + "sends": { + "path": "v1/preauth/submit", + "workflow": "13 or 131", + "flow": "enhancement", + "whole_bundle": true + }, + "after": { + "stage": "enhancement", + "sub_stage": "requested" + } + }, + { + "id": "F9d", + "name": "Cancel", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//cancel" + ], + "module": "7.9", + "skills": ["nhcx-preauth"], + "holds": [ + "not rejected", + "not cancelled", + "no claim raised" + ], + "user": "Withdraw the pre-authorisation", + "sends": { + "path": "v1/task/submit", + "workflow": "PC01", + "task": "cancel", + "own_thread": true + }, + "after": { + "stage": "preauth", + "sub_stage": "cancelling then cancelled; fresh claim number" + } + }, + { + "id": "F9e", + "name": "Predetermination", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//predetermination" + ], + "module": "7.7", + "skills": ["nhcx-preauth"], + "holds": [ + "as F9" + ], + "user": "Ask for a quote", + "sends": { + "path": "v1/preauth/submit", + "workflow": "12", + "use": "predetermination" + }, + "after": { + "predetermination": "asking then answered; the pre-auth unchanged" + } + }, + { + "id": "F10", + "name": "Record the discharge", + "screen": "case", + "tab": "claim", + "routes": [ + "POST /claims//discharge" + ], + "module": "7.7 inputs", + "skills": ["nhcx-claim"], + "holds": [ + "approved or partial" + ], + "user": "mode (normal, lama, dama, death), stage, discharge, surgery and death times", + "sends": null, + "stores": [ + "claim_submission draft: discharge_mode, discharge_stage, dates" + ], + "next_action": "File the claim" + }, + { + "id": "F11", + "name": "File the claim", + "screen": "case", + "tab": "claim", + "routes": [ + "POST /claims//claim", + "POST /claims//claim/documents" + ], + "module": "7.7", + "skills": ["nhcx-claim", "nhcx-communication"], + "holds": [ + "discharge recorded", + "discharge summary attached", + "claim-stage forms answered", + "amount not above approved" + ], + "user": "Submit the claim", + "sends": { + "path": "v1/claim/submit", + "workflow": "15 (161 or 151 query answer; 16 generic resubmit)", + "kind": "claim", + "under": "the pre-auth's claim number", + "reply": "on_submit 25 then 26|27|291" + }, + "after": { + "stage": "claim", + "sub_stage": "requested then approved|queried|rejected|partial" + } + }, + { + "id": "F12", + "name": "Payments", + "screen": "case", + "tab": "payments", + "routes": [ + "POST /nhcx/callback/v1/paymentnotice/request", + "POST /claims//payments//ack", + "GET /claims/payments" + ], + "module": "7.10", + "skills": ["nhcx-payment"], + "holds": [], + "user": null, + "reads": "PaymentNotice matched by claim number; deduped on its correlation id", + "sends": { + "path": "v1/paymentnotice/on_request", + "workflow": "17 (PMJAY) or the notice's own", + "correlation_id": "", + "to": "the notice's sender", + "automatic": true + }, + "after": { + "stage": "payment", + "sub_stage": "noticed|paid" + }, + "next_action": "Acknowledge the payment notice, then Settled" + }, + { + "id": "F12b", + "name": "The inbox", + "screen": "inbox", + "tab": "communication", + "routes": [ + "POST /nhcx/callback/v1/communication/request", + "GET /claims/inbox", + "POST /claims//queries//acknowledge" + ], + "module": "7.10", + "skills": ["nhcx-communication"], + "holds": [], + "reads": "classify: query | notification | note", + "sends": { + "notification": { + "path": "v1/communication/on_request", + "automatic": true + } + }, + "after": { + "query": "open, leads every action list" + } + }, + { + "id": "F13", + "name": "Status, reprocess, release", + "screen": "case", + "tab": "preauth or claim", + "routes": [ + "POST /claims//status", + "POST /claims//reprocess", + "POST /claims//release" + ], + "module": "7.9", + "skills": ["nhcx-reprocess"], + "holds": [ + "status: payer allows it", + "reprocess: claim decided and not paid in full", + "release: part paid" + ], + "sends": { + "path": "v1/task/submit", + "workflow": "leg correlation id (status) or 36", + "own_thread": true + }, + "after": { + "enquiry": "asking then answered|error; a reprocess reopens the claim to requested" + } + } + ], + "page_load_polls": [ + "coverage checking", + "plan fetching", + "ruling checking", + "claim submitting", + "predeterminations asking", + "preauth submitting or cancelling", + "enquiries asking" + ], + "not_in_the_flow": [ + "a status control", + "a manual-only payment acknowledgement", + "a chase button without the status exchange", + "a separate discharge submission on PMJAY", + "a claim resubmit on PMJAY" + ] +} \ No newline at end of file diff --git a/plugins/nhcx/skills/nhcx-communication/references/api-knowledge.md b/plugins/nhcx/skills/nhcx-communication/references/api-knowledge.md new file mode 100644 index 000000000..3b07e901d --- /dev/null +++ b/plugins/nhcx/skills/nhcx-communication/references/api-knowledge.md @@ -0,0 +1,400 @@ +# API knowledge: the nhcx-adapter contract (optional transport) and the HMIS endpoints that face it + +Read this file only when the transport is nhcx-adapter, and use nhcx-adapter only when the user has asked for it (`references/transport-knowledge.md` section 1). Otherwise the build reaches NHCX through the app's existing integration or its own transport, and `references/transport-knowledge.md` sections 3 and 4 replace everything here. + +This file describes nhcx-adapter (https://github.com/nha-in/nhcx-adapter) as its release ships it, and the HMIS side a build needs to face it. A release carries the binary, `config.sample.json`, `serve.sh`, `stop.sh`, `update.sh` and `README.md`. `nhcx-package/docs/02-Getting Started/10-NHCX Adapter.md` covers the same adapter. When a detail matters, check the release README and `config.sample.json` for the version you run. + +## 1. What the adapter is + +One binary, one `config.json`, no database. You POST plain FHIR to it. It mints the protocol ids, fetches the recipient's certificate, encrypts a compact JWE, posts to the NHCX gateway, and records the exchange in a file ledger. NHCX callbacks reach it encrypted; it decrypts them and POSTs plain FHIR to your HMIS. Both directions are synchronous; there is no queue (release README, "How it works"). + +The same binary can front several participants at once. Inbound, `x-hcx-recipient_code` picks the profile whose key decrypts and whose callback receives. Outbound, `x-hcx-sender_code` picks who sends (release README, "Hosting several participants"). Encrypting for a code the same adapter holds is allowed. So one adapter can host a hospital and a test payer together, and a test between them needs no second gateway. + +## 2. Configuration + +File: `config.sample.json` in the release. `${NAME}` reads an environment variable; `@file` reads a file next to the config. Unknown keys are rejected. + +| Key | Default | What it does | +| --- | --- | --- | +| `env` | `sandbox` | `sandbox` or `production`. Picks the gateway (`https://apisbx.abdm.gov.in/hcx/v1` or `https://apis.abdm.gov.in/hcx/v1`), registry, session endpoint and `X-CM-ID` (`sbx` or `abdm`). | +| `listen` | `127.0.0.1:8090` | The HTTP listener. | +| `publicUrl` | empty | How NHCX reaches the adapter. Register `/in` as the participant's `endpoint_url`. | +| `apiKey` | `${NHCX_ADAPTER_API_KEY}` | The key your HMIS presents on `/out`, `/fhir/out`, `/ledger*`, `/token`. Demanded in production, honoured but not demanded in sandbox. `requireApiKey: true` closes a sandbox adapter. | +| `participant.participantId` | none; the sample carries an example code | Your registry code. `@hcx` is added if missing. | +| `participant.clientId`, `clientSecret` | `${NHCX_CLIENT_ID}`, `${NHCX_CLIENT_SECRET}` | ABDM credentials that mint the session token. | +| `participant.privateKey` | `@private_key.pem` | The RSA key of your registered certificate. | +| `participants[]` | `[]` | Further hosted identities. Each needs only `participantId` and `callback`; the rest is inherited. | +| `callback.url` | `http://127.0.0.1:8765/nhcx/callback` in the sample | Where decrypted messages are POSTed. | +| `callback.appendPath` | `true` | Appends the NHCX path: `.../callback` receives `v1/preauth/on_submit` at `.../callback/v1/preauth/on_submit`. | +| `callback.timeoutSeconds` | `20` | One delivery. NHCX wants its 202 within 30 seconds. | +| `callback.apiKey` | empty | Sent to your HMIS as `Authorization: Bearer `. | +| `callback.routes` | `{}` | Per-path overrides, used exactly as written: `{"v1/preauth/on_submit": "http://preauth-svc/hook"}`. | +| `callback.also` | absent | Extra targets for the same delivery (two systems behind one participant code). Every target must accept or NHCX redelivers to all. | +| `ledger.enabled`, `ledger.dir`, `ledger.retentionDays`, `ledger.storeBodies` | `true`, `data/ledger`, `30`, `true` | The traffic ledger. A hand-written config that leaves out `retentionDays` keeps every day. | +| `maxBodyBytes` | 8 MiB in the v1.0.1 README | Caps request bodies on both surfaces. A PMJAY package master is far larger: set 100 MiB (`104857600`) explicitly. | +| `panel.password`, `panel.path` | empty, `/panel` | The browser console; off until a password is set. | +| `auth.mode`, `auth.tokenTtlSeconds` | `sessions`, `1200` | How the ABDM token is obtained. | + +Minimal working config for one hospital: + +```json +{ + "env": "sandbox", + "listen": "127.0.0.1:8090", + "publicUrl": "https:///in", + "apiKey": "${NHCX_ADAPTER_API_KEY}", + "participant": { + "participantId": "@hcx", + "clientId": "${NHCX_CLIENT_ID}", + "clientSecret": "${NHCX_CLIENT_SECRET}", + "privateKey": "@private_key.pem" + }, + "callback": { "url": "http://127.0.0.1:/nhcx/callback", "appendPath": true, "apiKey": "" } +} +``` + +Start it with `./nhcx-adapter serve`, or `./serve.sh` from the release archive; `./stop.sh` stops a background server. It checks token, participant record, certificate and registered endpoint first and offers to fix each in a terminal (release README, "Startup checks"). `./nhcx-adapter check --no-tui` is the same as a health gate. `serve --no-tui --skip-checks` starts it with no prompts and no checks, for a script that has already checked. + +## 3. Routes + +| Route | Auth | Does | +| --- | --- | --- | +| `POST /out/{path...}` | API key | Send. `path` is the NHCX API path, `v1/preauth/submit`. | +| `POST /fhir/out/{path...}` | API key | Same handler, hcxkit's prefix. The client in section 11 sends here. | +| `POST /in/{path...}` | none | NHCX delivers here. Register `/in`. | +| `POST /v1/{path...}` | none | Alias of `/in` for a registry `endpoint_url` of `/`. | +| `GET /ledger` | API key | Newest first. Filters: `direction, entity, kind, status, sender, recipient, participant, correlation_id, workflow_id, since, until, before, limit` (1 to 500). `since` and `until` take RFC 3339, a date, or a duration such as `24h`. | +| `GET /ledger/stats` | API key | Counts by direction, status, entity. | +| `GET /ledger/thread/{cid}` | API key | Every message on one correlation id plus the derived state. | +| `GET /ledger/{id}` | API key | One message in full, bundle included. | +| `GET /token`, `POST /token/refresh` | API key | The ABDM session token, for calls the adapter does not make (registry, PMJAY payer service). `?participant=` for a hosted identity. | +| `GET /healthz`, `GET /readyz` | none | Liveness; readiness is 503 until a token is held. | +| `GET /panel` | its own password | Operator console: Live, Ledger, Send, Lookup, Setup. | +| `/internal/*` | none | hcxkit-compatible console API, section 8. | + +API key check: `Authorization: Bearer ` first, then `X-Api-Key: `. Constant-time compare. A miss answers `401 {"ok":false,"error":{"code":"UNAUTHORIZED","message":"missing or invalid API key"}}`. + +## 4. The outbound envelope + +The body must be a JSON object. Header precedence, lowest to highest: + +1. HTTP request headers named `x-hcx-*`. +2. The `jwe_headers` object (hcxkit spelling). +3. Top-level `x-hcx-*` keys. +4. Top-level short aliases: `sender`, `recipient`, `correlation_id`, `request_id`, `api_call_id`, `workflow_id`, `status`. + +The payload is `fhir`, else `payload`, else the body itself when it carries `resourceType`. Otherwise `400 INVALID_ENVELOPE`. + +The protected header names: + +``` +x-hcx-api_call_id x-hcx-request_id x-hcx-correlation_id x-hcx-timestamp +x-hcx-status x-hcx-sender_code x-hcx-recipient_code x-hcx-workflow_id +``` + +Completion rules: + +- Sender and recipient codes get `@hcx` appended if missing. +- `api_call_id`, `request_id`, `correlation_id` are kept only when they are plain 8-4-4-4-12 UUIDs; anything else is replaced with a fresh UUID. So a response must carry the request's `correlation_id` as a UUID or the thread is lost. +- `x-hcx-status` defaults to `request.initiated`, or `response.complete` when the last path segment starts with `on_`. +- `x-hcx-timestamp` defaults to now as `YYYY-MM-DDThh:mm:ss±hhmm`. The zone has no colon: `+0530`, not `+05:30`. +- An empty `x-hcx-workflow_id` is dropped, not sent. +- On an `on_` path with no usable correlation id, the adapter threads the message to the newest inbound request of that entity from that recipient. Do not rely on it; send the id. + +What a hospital sends on a normal leg: + +```json +{ + "jwe_headers": { + "x-hcx-sender_code": "@hcx", + "x-hcx-recipient_code": "@hcx", + "x-hcx-workflow_id": "12" + }, + "fhir": { "resourceType": "Bundle", "type": "collection", "...": "..." } +} +``` + +Add `"x-hcx-correlation_id": ""` only on the two reply legs: the communication reply on `v1/communication/on_request` and the payment acknowledgement on `v1/paymentnotice/on_request`. + +## 5. The outbound answer + +The HTTP status is the NHCX gateway's own. Body: + +```json +{ + "ok": true, + "path": "v1/preauth/submit", + "url": "https://apisbx.abdm.gov.in/hcx/v1/preauth/submit", + "headers": { "x-hcx-correlation_id": "...", "x-hcx-api_call_id": "...", "x-hcx-request_id": "...", "x-hcx-workflow_id": "12", "x-hcx-status": "request.initiated", "x-hcx-timestamp": "...", "x-hcx-sender_code": "...", "x-hcx-recipient_code": "..." }, + "gateway_status": 202, + "response": { "...": "the NHCX 202 body" }, + "duration_ms": 412, + "ledger_id": "7UMV0007", + "txn_id": "7UMV0007", + "correlation_id": "...", + "request_id": "..." +} +``` + +Store three things on the leg: `txn_id` (the ledger id), `correlation_id` (the thread), and `headers["x-hcx-api_call_id"]`. Store them on every send. + +Local failures come back as `{"ok": false, "error": {"code", "message", "retryable"}, "request_id", "upstream_status", "upstream_body"}` with these statuses: `400` for `INVALID_ENVELOPE`, `INVALID_PAYLOAD`, `INVALID_BODY`, `INVALID_JWE`, `NO_PATH`, `NO_RECIPIENT`, `WRONG_RECIPIENT`, `BODY_READ`; `401` for the API key; `413` `BODY_TOO_LARGE`; `422` for `DECRYPT_FAILED`, `CERT_NOT_FOUND`, `SELF_ENCRYPTION_KEY`; `502` for any code starting `CALLBACK_`, `GATEWAY_`, `CERT_FETCH_`, `TOKEN_`; `501` `LEDGER_DISABLED`. A gateway refusal is recorded in the ledger as `rejected` with `GATEWAY_HTTP_`. + +## 6. The inbound callback your HMIS receives + +The adapter POSTs to `callback.url` plus the NHCX path. Body: + +```json +{ + "meta": { + "type": "in", + "payloadType": "fhir", + "path": "v1/preauth/on_submit", + "ip": "1.2.3.4", + "time": "", + "redelivery": false, + "participant": "@hcx" + }, + "jwe_headers": { + "alg": "RSA-OAEP-256", "enc": "A256GCM", + "x-hcx-api_call_id": "...", "x-hcx-correlation_id": "...", "x-hcx-request_id": "...", + "x-hcx-sender_code": "@hcx", "x-hcx-recipient_code": "@hcx", + "x-hcx-status": "response.partial", "x-hcx-timestamp": "...", "x-hcx-workflow_id": "20" + }, + "fhir": { "resourceType": "Bundle", "...": "..." } +} +``` + +`payloadType` is `fhir` for a bundle and `protocol` for a ProtocolResponse. A ProtocolResponse is a refusal. Then `fhir` is the plain JSON body with `type: "ProtocolResponse"`, `x-hcx-status: response.error` and `x-hcx-error_details` at its top level. + +HTTP headers on the delivery: + +| Header | Value | +| --- | --- | +| `X-Nhcx-Path` | `v1/preauth/on_submit` | +| `X-Nhcx-Payload-Kind` | `fhir` or `protocol` | +| `X-Nhcx-Correlation-Id` | the thread | +| `X-Nhcx-Api-Call-Id` | this delivery's id, stable across redeliveries | +| `X-Nhcx-Redelivery` | `true` when the ledger already holds this api_call_id (absent otherwise) | +| `X-Nhcx-Participant` | the hosted identity it was addressed to | +| `X-Hcxkit-Txn-Id` | equals `x-hcx-api_call_id` (what a kit-style backend dedupes on) | +| `X-Hcxkit-Type` | entity: `coverage`, `insurance`, `preauth`, `claim`, `task`, `payment`, `communication`, `status` | +| `X-Hcxkit-Flow` | `request` for an arriving response, `on_request` for an arriving request (inverted on purpose) | +| `X-Hcxkit-Payload-Kind` | same as `X-Nhcx-Payload-Kind` | +| `Authorization` | `Bearer ` when configured | + +Contract: answer any 2xx quickly. The adapter then answers NHCX with the 202 acceptance body and an `X-Nhcx-Ledger-Id` header: + +```json +{ + "timestamp": "11/09/2026 10:00:00:123", + "api_call_id": "...", "correlation_id": "...", + "result": { "sender_code": "...", "recipient_code": "...", "entity_type": "preauth", "protocol_status": "request.queued" }, + "error": { "code": "", "message": "" } +} +``` + +A non-2xx from your HMIS becomes `CALLBACK_HTTP_` and NHCX redelivers. NHCX makes five attempts, then drops the correlation id. Your handler must therefore be idempotent on `x-hcx-api_call_id`. Do not do slow work inside the callback: store the envelope, answer 200, apply it after. Apply a delivery on a context detached from the incoming request, so a gateway that hangs up cannot roll the write back. + +The HMIS callback handler: + +- Routes `POST /callback`, `POST /callback/` and `POST /nhcx/callback`. +- Takes an optional shared secret on the query string (`?token=`). +- Reads `X-Hcxkit-Type`, `X-Hcxkit-Flow` and `X-Hcxkit-Payload-Kind`. +- Archives the envelope before applying it. +- Answers `400` for an unreadable body, because redelivery cannot help. Anything unexpected becomes a 500, so the adapter retries. +- Returns `{"status": "settled" | "unmatched" | "ignored"}`. +- Routes by correlation id, never by path. + +## 7. The ledger + +Layout: `ledger.dir//.json`, one file per message, plus `/index.jsonl` with one summary line per message. Ids are eight base32 characters (alphabet `0-9A-V`), a day prefix and a counter that restarts each day: `7UMV0001` is the first message of its day. Pruned hourly by `retentionDays`. + +Entry fields: `id, direction (out|in), created_at, path, entity, action, kind (request|response), format (fhir|protocol|json), sender, recipient, correlation_id, api_call_id, request_id, workflow_id, hcx_status, status, error{code,message}, redelivery, duration_ms, peer{url,status_code,response}, also[], headers{}, fhir{}, fhir_summary{resource_type,bundle_type,entries,resource_types,focus,identifier,patient,outcome}`. + +`status` values: outbound `accepted`, `rejected`, `failed`; inbound `delivered`, `delivery_failed`, `rejected`. + +Thread: `{correlation_id, entity, workflow_id, counterparty, role (initiator|responder), state, started, updated, messages[]}`. `state` is derived by walking the messages in order: + +- `awaiting_response`: you sent a request. +- `awaiting_our_response`: a request reached you. +- `partial`: a `response.partial` arrived. +- `completed`: a response closed it. +- `error`: a rejection, a failed send or delivery, a protocol message, or an `error` status. +- `unknown`. + +Two ledger behaviours you rely on. An outbound `on_` response with no `correlation_id` is threaded to the newest matching inbound request. An inbound whose `api_call_id` was seen before is flagged `redelivery: true`. + +CLI, same data, no server needed for `follow`: + +```sh +nhcx-adapter ledger list --since 24h --entity preauth --status rejected +nhcx-adapter ledger follow --direction in +nhcx-adapter ledger show 7UMV0007 +nhcx-adapter ledger thread +nhcx-adapter ledger stats +nhcx-adapter decrypt --file body.json +nhcx-adapter cert +nhcx-adapter send --path v1/preauth/submit --recipient --file bundle.json +``` + +## 8. hcxkit-compatible endpoints + +A client written against hcxkit polls the adapter for the other side's answer instead of only waiting for its callback. The adapter serves the sliver of hcxkit's `/internal` API that such a client needs. None of these need the API key. Keep the adapter's port off any network you do not control (`nhcx-package/docs/02-Getting Started/10-NHCX Adapter.md`, "Before you expose it"). + +| Route | Body | Answers | +| --- | --- | --- | +| `GET /internal/config/get` | none | `{participant{participantId,name,callbackUrl}, participants[], CMID, env, urls{nhcx,participant,sessions}}` | +| `POST /internal/participants/search` | `{"participant_code": ""}` | `{participants:[registry record + participant_code, participant_name, endpoint_url, status, roles]}`; an unknown code is `{participants: []}` | +| `POST /internal/txn/related` | `{"txnId": ""}` | every ledger row on the same correlation id, both directions, as `{id, direction, status, sender, recipient, correlation_id, api_call_id, type, flow, created_at}`; `404 TXN_NOT_FOUND` when the ledger no longer holds it | +| `POST /internal/txn/fhir` | `{"txnId": ""}` | `{meta{type,payloadType,path,time}, jwe_headers, fhir}`, the same envelope shape a delivery carries | +| `POST /internal/txn/dispatch` | `{"txnId": ""}` | `{txnId, status}` with `dispatch_failed` for a failed or rejected send, `dispatched` for accepted or delivered, plus `errorCode`, `errorMessage` | +| `GET /internal/txn/list?limit=200` | none | the recent ledger, newest first, same row shape | +| `POST /internal/policies/search` | `{"identifiertype": "MemberId", "MobileNo" or "AbhaNumber", "identifiervalue": "..."}` (also `mobile`, `abhaNo`) | the ABDM registry's `participant/get/policies` answer, status passed through; "No policies found" is an error the caller reads as empty | +| `POST /internal/policies/abha/link`, `.../delink` | forwarded verbatim | registry answer | +| `POST /internal/participants/list` | forwarded verbatim | registry roster | +| `POST /internal/participants/certs` | `{"participantid": ""}` | `{participant_code, encryption_cert}` | +| `GET /internal/participants/saved` | none | the configured profiles | + +The polling pattern: + +1. After a send, call `/internal/txn/related` with the stored `txn_id`. +2. Take the inbound rows on the thread that were not sent by you. Keep only rows addressed to the participant the send came from. +3. Fetch each with `/internal/txn/fhir`, newest first. +4. Take the first whose bundle carries the resource the reply is made of (ClaimResponse, CoverageEligibilityResponse, InsurancePlan, Task). +5. Apply it through the same code path the callback uses. Dedupe on `x-hcx-api_call_id`. + +A `404` from `txn/related` means the ledger was reset. Settle the leg as an error instead of spinning. + +## 9. curl examples + +Set these once. The address is the adapter's default `listen`: + +```sh +export ADAPTER=http://127.0.0.1:8090 +export KEY= +export ME=@hcx +export PAYER=@hcx +``` + +Liveness and readiness: + +```sh +curl -s $ADAPTER/healthz +curl -s $ADAPTER/readyz +``` + +Send a coverage eligibility check. Write the envelope to a file first. The bundle is the package's validation request, `nhcx-package/fhir/B1/validation.json`, with your own identifiers substituted. Run this from the project root that holds `nhcx-package/`: + +```sh +python3 - <<'EOF' +import json, os +bundle = json.load(open("nhcx-package/fhir/B1/validation.json")) +env = {"jwe_headers": {"x-hcx-sender_code": os.environ["ME"], + "x-hcx-recipient_code": os.environ["PAYER"], + "x-hcx-workflow_id": ""}, + "fhir": bundle} +json.dump(env, open("/tmp/coverage-out.json", "w")) +EOF +curl -s $ADAPTER/fhir/out/v1/coverageeligibility/check \ + -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \ + --data-binary @/tmp/coverage-out.json +``` + +Read the answer back from the ledger with the `correlation_id` from that response: + +```sh +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger/thread/" +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger?direction=in&entity=coverageeligibility&since=1h" +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger/" +``` + +Same thread through the kit endpoints (no key): + +```sh +curl -s $ADAPTER/internal/txn/related -H 'Content-Type: application/json' -d '{"txnId":""}' +curl -s $ADAPTER/internal/txn/fhir -H 'Content-Type: application/json' -d '{"txnId":""}' +``` + +A session token for the PMJAY payer service or a registry call: + +```sh +curl -s -H "Authorization: Bearer $KEY" $ADAPTER/token +``` + +Simulate a delivery to your own callback while the adapter is not involved (useful for the callback handler's unit test). This is the exact shape the adapter posts. Wrap the package's bare payer bundle, here the pre-auth approval `nhcx-package/fhir/C5/C5-approved-wf21.json`, as `{"meta":{...},"jwe_headers":{...},"fhir":}` first: + +```sh +python3 - <<'EOF' +import json +bundle = json.load(open("nhcx-package/fhir/C5/C5-approved-wf21.json")) +env = {"meta": {"type": "in", "payloadType": "fhir", "path": "v1/preauth/on_submit"}, + "jwe_headers": {"x-hcx-correlation_id": "", "x-hcx-api_call_id": "", + "x-hcx-sender_code": "@hcx", + "x-hcx-recipient_code": "@hcx", + "x-hcx-status": "response.complete", "x-hcx-workflow_id": "21"}, + "fhir": bundle} +json.dump(env, open("/tmp/delivery.json", "w")) +EOF +curl -s -X POST "http://127.0.0.1:/nhcx/callback/v1/preauth/on_submit" \ + -H 'Content-Type: application/json' -H 'X-Nhcx-Path: v1/preauth/on_submit' \ + -H 'X-Nhcx-Payload-Kind: fhir' -H 'X-Nhcx-Correlation-Id: ' -H 'X-Nhcx-Api-Call-Id: ' \ + -H 'X-Hcxkit-Txn-Id: ' -H 'X-Hcxkit-Type: preauth' -H 'X-Hcxkit-Flow: request' -H 'X-Hcxkit-Payload-Kind: fhir' \ + -H 'Authorization: Bearer ' \ + --data-binary @/tmp/delivery.json +``` + +## 10. The HMIS-side endpoints a build exposes + +Use these as the model for what your HMIS needs. `` is the claim episode id. + +| Method | Path | Purpose | Leg | +| --- | --- | --- | --- | +| GET | `/claims`, `/claims/new`, `/claims/` | list, policy search, detail | none | +| POST | `/claims` | open an episode from a chosen policy | none | +| GET | `/claims//state` | the whole episode as JSON after the page-load polls | none | +| POST | `/claims//check` | coverage eligibility (validation, benefits, discovery) | `v1/coverageeligibility/check` | +| POST | `/claims//plan` | fetch or refresh the package master | `v1/insuranceplan/request` | +| GET | `/claims//plan/forms`, `.../forms/`, `.../plan/` | questionnaires and one package | none | +| POST | `/claims//link`, `/unlink` | attach or detach the admission | none | +| POST | `/claims//preauth` | save the dossier draft | none | +| GET, POST | `/claims//lines`, `.../lines/quantities`, `.../lines//delete` | procedure, implant and tier lines | none | +| POST | `/claims//forms` | save questionnaire answers | none | +| POST | `/claims//auth` | auth-requirements ruling | `v1/coverageeligibility/check` | +| POST | `/claims//submit` | pre-auth 12, query answer 19, enhancement 13, enhancement answer 131 | `v1/preauth/submit` | +| POST | `/claims//predetermination` | a quote | `v1/preauth/submit` | +| POST | `/claims//cancel` | cancel Task PC01 | `v1/task/submit` | +| POST | `/claims//status` | status enquiry Task | `v1/task/submit` | +| POST | `/claims//reprocess`, `/release` | reprocess or balance release, 36 | `v1/task/submit` | +| POST | `/claims//queries//reply`, `.../acknowledge` | communication reply or notification acknowledgement | `v1/communication/on_request` | +| POST | `/claims//discharge` | record how the stay ended | none | +| POST | `/claims//claim` | claim 15, query answer 161 or 151, resubmit 16 | `v1/claim/submit` | +| POST | `/claims//claim/documents`, `/documents`, `/documents/required`, `.../delete` | attachments | none | +| GET | `/claims//documents/` | view an attachment | none | +| POST | `/claims//payments//ack` | resend a payment acknowledgement | `v1/paymentnotice/on_request` | +| POST | `/v1/` under the registered `endpoint_url` (own transport), or `/callback`, `/callback/`, `/nhcx/callback` (nhcx-adapter) | a delivery | inbound | + +The HMIS configuration a build needs: + +- The transport's settings: for nhcx-adapter, its base URL (it listens on `127.0.0.1:8090` by default) and API key; for your own transport, the ABDM client id and secret, the private key, and the sessions, NHCX and registry addresses (`references/transport-knowledge.md` section 3). +- The payer's participant code (`1518@hcx` for the PMJAY SHA Himachal Pradesh sandbox) and the payer's name. +- The callback shared secret. +- A workflow-id override table, JSON, that overrides the per-payer table key by key, for example `cancel=122`. +- A map from payer code to payer adapter, for example `1518=pmjay,=generic`. +- The archive folder for cases, and a switch to turn the archive off. + +The sender code is not an environment variable. It is the facility's participant code, held in the HMIS's own settings. + +## 11. What the adapter client looks like in code + +The whole client is one function, `_api(path, payload, timeout, method, claim_id, use_case)`. It builds the URL from the base, adds `Authorization: Bearer` when a key is set, POSTs JSON, raises `GatewayError(message, status)` on any non-2xx or network failure, decodes JSON, and archives the envelope beside the case when `claim_id` is given. Every send in the module goes through it, which is what lets a test replace it with a stub: + +```python +posted = {} +def _ack(path, payload=None, **kw): + posted["path"], posted["payload"] = path, payload + return {"txn_id": "01PLAN", "correlation_id": "corr-plan-1"} +claims._api = _ack +``` + +Give your HMIS the same single door. diff --git a/plugins/nhcx/skills/nhcx-communication/references/errors-and-debugging.md b/plugins/nhcx/skills/nhcx-communication/references/errors-and-debugging.md new file mode 100644 index 000000000..9be844d82 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-communication/references/errors-and-debugging.md @@ -0,0 +1,167 @@ +# Errors and debugging + +Sources: + +- `nhcx-package/nhcx-error.yaml`: every NHCX, PAYR and ERR-PYR code, with the standard and reference payer readings side by side. +- `nhcx-package/docs/06-Reference/01-Error Codes.md`: the same codes as tables. +- `nhcx-package/docs/01-Overview/04-JWE, Status and Errors.md`, "Codes met live". +- `nhcx-package/docs/03-Building a Provider/11-PMJAY Sandbox Run.md`: one full case run, refusal by refusal. +- `nhcx-package/docs/06-Reference/02-Troubleshooting.md`. +- The nhcx-adapter release README, "Troubleshooting". + +The live readings are from runs against the PMJAY SHA Himachal Pradesh sandbox payer (`1518@hcx`). + +## 1. Where an error comes from + +Three places refuse a message, and the family of the code says which (`nhcx-error.yaml`, `spaces`): + +| Family | Who refused | How you hear it | +| --- | --- | --- | +| Gateway answers to your own send (`400`, `401`) | the exchange, before the message goes further | the HTTP answer to your POST on `/v1/...`; a `401` is an expired token or a missing `Bearer` | +| A delivery your key cannot open (own transport) | your receiving end | the JWE will not decrypt: the certificate on your participant record is not the key you hold | +| Adapter codes (`INVALID_ENVELOPE`, `CERT_NOT_FOUND`, `CALLBACK_HTTP_500`), nhcx-adapter only | nhcx-adapter, before or after the wire | the HTTP answer to your `/fhir/out` call, `{"ok": false, "error": {...}}` | +| `NHCX-*` | the exchange; the message never reached the payer | the HTTP answer to your call (`gateway_status` 4xx with `upstream_body`), or a `ProtocolResponse` delivered to your callback later | +| `PAYR-*`, `ERR-PYR-*` | the payer; the message reached it | a `ProtocolResponse` on your callback with `x-hcx-status: response.error` and `x-hcx-error_details {code, message}`, on the request's correlation id | + +A `ProtocolResponse` is plain JSON, not a bundle. The exchange delivers it with `type: ProtocolResponse` and the `x-hcx-` fields in the clear; nhcx-adapter passes it on with `X-Nhcx-Payload-Kind: protocol` and `fhir` set to the body. Read `fhir.type == "ProtocolResponse"` and `fhir["x-hcx-error_details"]`. Settle the leg as refused at the door with the payer's words, and keep the thread the payer last answered on. + +PAYR numbers are not globally unique. The same number means different things on different sheets (`nhcx-error.yaml` lists them under `collisions`), and the live sandbox reuses several with a meaning the published sheet does not give. Match on the message text and log both. + +## 2. PAYR and ERR codes met live + +The published text is from `nhcx-package/nhcx-error.yaml`. Where the standard and reference payer sheets collide, both readings are given. The live text and the fix are from the sandbox runs. + +| Code | Published text | Live text | What it means | Fix | +| --- | --- | --- | --- | --- | +| PAYR-1008 | Invalid FHIR bundle received (reference payer); Eligible coverage amount is insufficient (standard) | "Invalid content type" or "Invalid input, code and reason code" or "Invalid Base64" | Three faults on one code: a document outside pdf, jpg, jpeg, png and fhir+json; a Task code paired with a reason the scheme does not accept (every `status`, `reprocess`, `release` Task on the sandbox, and a reprocess with the intimation input misspelt); an attachment it will not decode | Check the content type. For a Task, the sandbox takes only one financial task code, `cancel` (`11-PMJAY Sandbox Run.md`, "What the sandbox will not take"). Spell the reprocess input `intimationNumber` | +| PAYR-1018 | Time limit for submission expired (standard); No task reason code received (reference payer) | asks for a `Task.reasonCode` on a status enquiry | The status Task is refused as incomplete; with a reason it is refused with PAYR-1008 | Do not offer a status enquiry on PMJAY; switch it off in the PMJAY payer adapter | +| PAYR-1019 | Requested additional information was not received in time (standard); Invalid sequence received in supporting info element (reference payer) | "Invalid sequence received in supporting info element" | A `supportingInfo` entry with no `sequence` | Number the whole list once it is assembled | +| PAYR-1027 | (item error family) | "Invalid item id found for item in claim component" | `Claim.item` has no element `id` (`Item/1`). Nothing to do with the package code | Put `id` on every item, procedure and supportingInfo | +| PAYR-1083 | (practitioner family) | "No HPR details found for the practitioner ... category code as HPIN" | The Practitioner carries no identifier typed `HPIN` | Add the `HPIN` identifier under `https://hpr.abdm.gov.in` | +| PAYR-1096, PAYR-1503 | (supporting-info value-type family) | the death date is missing | A death claim without the `ONS`/`DTM` entry | Add `ONS`/`DTM` with the death instant and answer the plan's death forms | +| PAYR-1214 | No previous preauthorization approved record found for the resubmission request | same | A 121 after a rejection | Send a fresh 12 | +| PAYR-1238 | Beneficiary is having an active preauthorization request at this hospital with reference number ... | same; the reference ends in the SHA's case id | Scheme rule, not a bundle fault: one live pre-auth per beneficiary per hospital. Perversely the first sign the bundle is right, because validation runs first | Cancel the other case (PC01) or let it be rejected; sweep before a run | +| PAYR-1245 | Rule failure | "Only one conservative procedure can be booked for a case" | The master's `ProcedureType`; an enhancement on a conservative case must add a medical package | Pick a package whose `ProcedureType` is medical | +| PAYR-1254, PAYR-1365 | Response for STG Questionnaire id ... is mandatory for procedure code ... | same | A package's treatment-guideline questionnaire unanswered | Answer every `/stgquestionnaire/` form the plan attaches to the quoted packages | +| PAYR-1256, PAYR-1363 | Response for Authentication Consent Questionnaire is missing | same | The plan's consent questionnaire unanswered where no biometric token was taken; 1256 on the pre-auth, 1363 on the claim | Answer the policy-level consent form on both legs | +| PAYR-1270 | Item LM100 is not applicable for preauthorization request | same | `LM100` on a pre-auth | Only a LAMA or DAMA claim before or during surgery carries it | +| PAYR-1321 | Error occurred while processing the request due to invalid workflow id | same | 151, 19 or 16 on `v1/claim/submit` | Answer a claim query on 161; never resubmit a decided claim, reprocess it | +| PAYR-1322 | No active case found for the given case number | "Active instance found for case number" | A request is already open on that case; the scheme takes one at a time | Wait about 30 seconds after a decision, then send again; up to three tries | +| PAYR-1362 | No procedure with code LM100 received with 'Requested' status | same | A LAMA or DAMA claim before or during surgery that still carries the package | Collapse the claim to one `LM100` line | +| PAYR-1367, PAYR-1368 | No biometric records found ... / units of cycle information received | same | A cyclic package (dialysis) claimed without a biometric record per cycle and cycle information | Do not claim a cyclic package unless the HMIS can produce both | +| PAYR-1401 | policy not allowed for the hospital | same | The plan was asked for under a policy the hospital is not empanelled under | Ask under the beneficiary's own policy code from the policy search | +| PAYR-1406 | Existing request with correlation id ... is in progress | same | A second plan request while one is still being served | Wait 15 to 60 minutes; reuse the master you hold | +| ERR-PYR-CLM-007 | on none of the published sheets; `nhcx-error.yaml` lists it as observed live | "No prior preauthorization or claim record found for case number" | The claim was sent under a number of its own instead of the pre-auth's | Send the claim under the pre-auth's claim number | + +Refusals arrive in order: the SHA validates the bundle first and applies the scheme's rules only to a bundle that passed. A refusal in the `PAYR-102x` block is structural, so check ids and sequences before values. + +## 3. Gateway protocol errors + +From `nhcx-package/nhcx-error.yaml` (the gateway space) and the live notes: + +| Code | Message | When you meet it | Fix | +| --- | --- | --- | --- | +| NHCX-1006 | Duplicate request. Request with same correlation id already exist | A request sent again on a correlation id the exchange already holds | Mint a fresh correlation id for every request; only a response echoes one | +| NHCX-1010 | No Data with given Correlation id for call back request | A response sent on a thread the exchange has retired: the request was redelivered five times without a 2xx, or the id was never a request | Acknowledge inbound requests at once; a payer that decides minutes later sends `outcome queued` first | +| NHCX-1012 | No records found with the requested api caller id | The sandbox's own `v1/status` route, whatever id you pass | Ask status as a Task on `v1/task/submit` | +| NHCX-1015 | Invalid response received from receiver (published); the registry answers "You are not authorized to update/modify details" | Updating a participant's endpoint or certificate with a client id that did not create it | Use the creator's credentials or the NHCX participant portal (nhcx-adapter release README, "Troubleshooting") | +| NHCX-1016 | Invalid Api Action / no policies found (the registry, on a policy search) | A policy search that finds nothing | Read it as an empty result | +| NHCX-1018 | Invalid ABHA number received | An ABHA not in `XX-XXXX-XXXX-XXXX` form on the envelope | Format it, or omit the header | + +With nhcx-adapter as the transport, its local codes and their HTTP statuses are in `api-knowledge.md` section 5. The ones you will meet first: + +- `CERT_NOT_FOUND`: the recipient has no certificate on the registry; nothing to fix locally. +- `SELF_ENCRYPTION_KEY`: the registry handed out your own certificate for another code; run `nhcx-adapter cert --refresh`. +- `DECRYPT_FAILED` on `/in`: your registered certificate is not the key you hold; run `nhcx-adapter check`. +- `WRONG_RECIPIENT` on `/in`: a message for a participant this adapter does not hold. +- `CALLBACK_HTTP_` and `CALLBACK_UNREACHABLE`: your HMIS refused or was down; NHCX will redeliver up to five times. +- `TOKEN_HTTP_401`: wrong `clientId` or `clientSecret`, or sandbox credentials against production. + +## 4. Reading a ledger thread + +The per-case archive is the first place to look, with any transport: every message sent and received, by correlation id, in `//transactions.txt` (step 4). With nhcx-adapter as the transport, its ledger also holds what reached it but not your HMIS; the commands below read it. + +Step 1. Find the thread. From the leg row's `correlation_id`, or from the case number in a summary: + +```sh +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger/thread/" | python3 -m json.tool +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger?since=2h&direction=in&limit=100" | python3 -c 'import json,sys; [print(r["id"], r["created_at"][11:19], r["direction"], r["path"], r["workflow_id"], r["hcx_status"], r["status"], r.get("fhir_summary",{}).get("outcome")) for r in json.load(sys.stdin)["items"]]' +nhcx-adapter ledger thread # no server needed +``` + +Step 2. Read the derived `state`: + +| state | Meaning | What to do | +| --- | --- | --- | +| `awaiting_response` | You sent a request and nothing came back | Wait; on the SHA a decision needs the desk. Check `peer.status_code` on the outbound row is 202 | +| `partial` | A `response.partial` arrived (20, 25, or the SHA's 37) | The payer has it. The decision comes on the same thread | +| `completed` | A `response.complete` arrived | The leg should be settled in the HMIS. If it is not, the callback failed or the reader misread it | +| `awaiting_our_response` | A request reached you (a CommunicationRequest, a payment notice) | Your reply is due on this correlation id | +| `error` | A rejection, a failed send or delivery, or a protocol message | Open the message with `error` or `format: protocol` | + +Step 3. Read one message in full, bundle included: + +```sh +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger/" | python3 -m json.tool | less +``` + +On an inbound row, `peer.status_code` is what your callback answered and `peer.response` is its body. A `delivery_failed` row with a 500 is your handler raising. On an outbound row, `peer.status_code` is the gateway's answer and `peer.response` its body. A `rejected` row carries `GATEWAY_HTTP_` and the NHCX error in `peer.response`. + +Step 4. Compare with the HMIS's own archive for the case, `//transactions.txt`. Each line names the workflow id, correlation id, api call id, ledger id and file. + +- A message in the ledger and not in the archive is a callback that failed. +- A message in the archive marked `outcome=unmatched` is one the HMIS could not tie to a case: the correlation id is on no leg row, and the bundle names no claim number the HMIS knows. +- A message in neither is a send that never left; look at the HMIS's error on the leg row. + +Files, when the server is down: `//.json`, and `index.jsonl` in the same folder for the summaries. `ledger.dir` is `data/ledger` by default. + +## 5. Correlation mistakes + +Each of these was made once in a real build. + +- Answering on the wrong thread. A communication reply or a payment acknowledgement must carry the request's `x-hcx-correlation_id`; every other leg must not carry one. A PMJAY query answer (19, 131, 161) goes on a new correlation id; a same-thread answer is swallowed without a refusal. +- Sending a non-UUID correlation id. nhcx-adapter replaces anything that is not an 8-4-4-4-12 UUID with a fresh one, so the thread is silently lost; store what the transport returned, not what you sent. With your own transport, a request's correlation id is its own `api_call_id` and an answer echoes the request's. +- Matching by path or by header type. Route an inbound message by its correlation id first, then by the claim number inside the bundle. With nhcx-adapter, the `X-Hcxkit-Flow` header is inverted on purpose and must not be a filter. +- Closing a thread on the first reply. The acknowledgement and the decision share one correlation id; a settled-status guard throws the approval away. +- Losing the thread after a refusal at the door. A send refused with a ProtocolResponse went out under a correlation id the payer never took in. The case still lives on the thread the payer last answered; keep it as `thread_correlation_id`. +- Reusing a correlation id after an error. The exchange retires it; the next attempt needs a fresh one. +- Forgetting the workflow id on a reply. Some payers match the payment acknowledgement on the notice's own workflow id; PMJAY wants 17. + +## 6. Redelivery and deduplication + +NHCX redelivers an unacknowledged message up to five times and then drops the correlation id. The SHA redelivers a large plan answer on its own, two or three times about a minute apart, under the same `x-hcx-api_call_id`. A case archive showed it as three lines on one api call id. With `callback.also` configured, one delivery reaches every target, and a refusal by any one of them makes NHCX redeliver to all. + +So: + +- Dedupe on `x-hcx-api_call_id` (with nhcx-adapter, `X-Hcxkit-Txn-Id` carries the same value). Either store the last applied `api_call_id` on the leg row and ignore a repeat, or keep an inbound ledger keyed on it and answer `duplicate`. A payer that omits the id is deduped on identical outcome and adjudication. +- Dedupe payment notices and communication requests on their correlation id, with a unique index on each table. +- Answer 2xx before doing slow work. The exchange allows 30 seconds for the 202 receipt (nhcx-adapter gives your HMIS 20 of them, `callback.timeoutSeconds`); anything slower is a failed delivery. +- Un-record a delivery whose application failed for a passing reason (database away), so the redelivery is not waved off as a duplicate. +- With nhcx-adapter, treat `X-Nhcx-Redelivery: true` as a hint, not a rule: the ledger flag is per adapter process and is lost on a ledger reset. + +## 7. A send reported as failed can still have landed + +Seen live on the sandbox three times in one night. A pre-authorisation went out through nhcx-adapter, the connection dropped after the request had been written, and it answered the hospital `GATEWAY_UNREACHABLE` with HTTP 502. NHCX had taken the message: the SHA acknowledged it four seconds later on the correlation the adapter had minted. A hospital that treats that 502 as "not sent" sends again. The scheme refuses the duplicate (ERR-PYR-PRE-030 "Active instance found for case number", PAYR-1238 for a fresh pre-auth), and a live case stands at the payer that the hospital has no record of. + +So: + +- nhcx-adapter's failure body names the ids the message went out under: `ledger_id`, `txn_id`, `correlation_id`, `api_call_id`, `request_id` and the `headers` map. Keep them. With your own transport the ids are the ones you minted before sealing: store them before the POST, so a failed POST still has a thread to look for. +- Record the failed leg under that correlation, not as nothing. Carry the ids on the client's error and write them onto the leg row. +- When an answer arrives on a failed leg's correlation, revive it: the leg becomes a sent leg, the record moves from draft to with-the-payer, and the desk is not offered a second send. A protocol error answer revives nothing. +- Anything that creates a record before it sends must name that record in the refusal, or the record is orphaned where nobody can see it. An enhancement handler returns the child it raised alongside the gateway's words. + +## 8. Sandbox pace rules + +What the SHA Himachal Pradesh sandbox (`1518@hcx`) did across the runs. `nhcx-package/docs/03-Building a Provider/11-PMJAY Sandbox Run.md` records one such run in order. + +- One live pre-authorisation per beneficiary per hospital (PAYR-1238). Every HMIS that shares the facility's participant code shares the limit, so sweep before a run: withdraw every approved case without a claim, then wait ten seconds. +- One request at a time per case (PAYR-1322). About 30 seconds between a decision and the next leg; an enhancement refused with "Active instance" is resent up to three times. +- Decisions are taken on the NHCX Payer Service desk, not on the exchange (`nhcx-package/docs/03-Building a Provider/12-PMJAY Adjudication APIs.md`). A case has to be driven through roles: PPD-Trust decides a pre-auth; a claim walks CEX-Trust, CPD-Trust, the Medical Audit Committee, ACO-Trust, SHA-Trust and the Claim Review Committee. The desk answers "Event Meta Log not found" or "Case not found" until the exchange has delivered the request; retry every six seconds, up to 150 seconds. A decision the desk accepts is sometimes never sent; taken again a minute later it is answered in seconds, so decide up to four rounds of 90 seconds. +- An enhancement's query has to be taken a minute after the acknowledgement. +- A claim episode with a query answered and the roles walked takes about ten minutes. Run cases one at a time and allow 20 minutes per case. +- The plan answer arrives in pieces over a minute and is redelivered; expect the same api call id three times. +- The beneficiary registry behind the ABDM session refuses a search now and then while a token refreshes. Retry the search up to four times, 30 seconds apart. +- The sandbox approves a claim query answer at zero with "No query response comments received" when the `CQD` reply is missing, and sometimes even when it is present. Report it; do not assert on the amount. +- The status Task is refused on this sandbox: without a `Task.reasonCode` it answers PAYR-1018, with any reason code PAYR-1008. PMJAY decides on its own desk and answers no status enquiry, so do not offer one for it. Record the refusal on the enquiry row and move on. +- The reprocess Task is taken only under the standard's spelling, `intimationNumber`. Use that spelling on every Task (cancel included); the package's bundles carry it too. The SHA answers workflow 37, "Arbitration claim submission process completed successfully". +- A test payer you run yourself has none of these limits; six use cases ran in under four minutes against one. diff --git a/plugins/nhcx/skills/nhcx-communication/references/fhir-knowledge.md b/plugins/nhcx/skills/nhcx-communication/references/fhir-knowledge.md new file mode 100644 index 000000000..08ffbb6c6 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-communication/references/fhir-knowledge.md @@ -0,0 +1,206 @@ +# FHIR knowledge: every bundle sent and received + +Sources: the bundles under `nhcx-package/fhir` (the hospital pins in `B1` to `B9`, the payer answers in `C3` to `C11`, the live PMJAY hospital captures in `D1` to `D13`) and the chapters under `nhcx-package/docs/05-FHIR Reference`. Get the package as `references/material.md` says. + +## 1. Where the examples live + +| Set | Path | What it is | +| --- | --- | --- | +| Pinned hospital bundles | `nhcx-package/fhir/B1` to `B9`, the lower-case files (`B3/preauth-request.json`) | One bundle per message a hospital sends, written to the specification with placeholders. A build is held to these byte for byte. The pin map is in `references/material.md`. | +| Payer answers | `nhcx-package/fhir/C3` to `C11` | One file per message the payer sends: the generic answer and, where one exists, its `-pmjay` twin. Feed these into your readers. | +| Live hospital captures | `nhcx-package/fhir/D1` to `D13` (PMJAY) and the capitalised B files such as `B3/B3-request.json` (generic) | Bundles taken from the sandbox wire, with the beneficiary's identifiers replaced | +| The catalogue | `nhcx-package/fhir/index.yaml` | For each file: direction, side, scheme (`generic` or `pmjay`), workflow id, focal resource, origin. Origin `example` means placeholders, not a payload; `wire` means a capture. | +| The NRCeS IG's own example | `nhcx-package/fhir/B4/communication-request.json` | The communication TaskBundle for the payer's request comes from the IG | +| Your build's archive | `//NNN--.json` and `transactions.txt` (modules 7.1 and 7.3) | Every envelope one episode sent and received, in order | +| Chapters | `nhcx-package/docs/05-FHIR Reference/*.md` | Element by element: `08-Preauthorisation Request.md`, `12-Claim Request.md`, `13-Claim Response.md`, `17-Communication.md`, `15-Cancel, Reprocess and Shortfall.md`, `16-Payment Notice and Acknowledgement.md`, `06-Insurance Plan Response, Package-Based.md`, `19-Codes and Value Sets.md` | + +Pins, by leg. Paths are under `nhcx-package/fhir/`. + +| Leg | Provider pin | Payer answer or capture | +| --- | --- | --- | +| Coverage eligibility | `B1/discovery.json`, `B1/validation.json`, `B1/benefits.json`, `B1/auth-requirements.json` | `C3/validation-response.json`, `C3/discovery-response.json`, `C3/benefits-response.json`, `C3/C3-response-generic.json`; PMJAY `C3/coverage-eligibility.json`, `C3/C3-benefits-pmjay.json`, `C3/C3-response-pmjay.json` | +| Insurance plan | `B2/insurance-plan-request.json` | `C4/C4-response-pmjay.json` (package-based, abridged), `C4/C4-response-generic.json` (coverage-based) | +| Pre-auth 12, enhancement 13, query answer 19 or 131 | `B3/preauth-request.json`, `B3/preauth-enhancement.json`, `B3/preauth-queryupdate.json` | `C5/C5-received-wf20.json`, `C5/C5-approved-wf21.json`, `C5/preauth-queried.json`, `C5/C5-rejected-wf23.json`, `C5/C5-enhancement-approved-wf22.json`; PMJAY the `-pmjay` twins and `C5/C5-queried-wf24.json` | +| Cancel PC01 | `B3/preauth-cancel.json` | `C10/C10-cancelled-wfPC02.json`, `C10/C10-cancelled-wfPC02-pmjay.json` | +| Claim 15, query answer 161 | `B5/claim-request.json`, `B5/claim-queryupdate.json` | `C7/C7-received-wf25.json`, `C7/C7-approved-wf26.json`, `C7/claim-queried.json`, `C7/C7-rejected-wf291.json`; PMJAY the `-pmjay` twins, `C7/C7-approved-deduction-wf26-pmjay.json` and `C7/C7-queried-wf27.json` | +| Reprocess 36, release 36 | `B5/claim-reprocess.json`, `B5/claim-release.json` | `C10/C10-arbitration-wf37.json`, `C10/C10-arbitration-wf37-pmjay.json` | +| Payment acknowledgement | `B7/payment-notice-ack.json` | The notice you answer: `C9/C9-notice-wf30.json`; PMJAY `C9/payment-notice.json`, `C9/C9-notice-tds-wf30-pmjay.json` | +| Communication reply | `B4/communication-response.json` | `B4/communication-request.json` (the query you answer; the IG's example), `C6/C6-preauth-query-wf24.json` and `C6/C6-claim-query-wf27.json` (live, generic), `C6/C6-notification-wfN02.json` (PMJAY) | +| Status enquiry | None. The published call carries no bundle (`nhcx-package/docs/05-FHIR Reference/18-Predetermination, Status and Search.md`). | None captured | + +## 2. Conventions every hospital bundle follows + +From `nhcx-package/docs/05-FHIR Reference/01-Bundles and Conventions.md` and the pins: + +- `Bundle.type` is `collection`; `Bundle.meta.profile` names the NRCES bundle profile (`ClaimBundle`, `TaskBundle`, `CoverageEligibilityRequestBundle`); every resource names its own profile under `https://nrces.in/ndhm/fhir/r4/StructureDefinition/`. +- Every entry has an absolute `fullUrl` under one base, `https://nhcx.abdm.gov.in/...`, and every reference resolves to another entry. A thing that is genuinely not in the bundle is named by identifier, not by a URL. The chapter's rule 3 also accepts `urn:uuid:` references; parse both. +- `Bundle.id` is fixed per shape: `coverage-validation-request-generic`, `preauth-request-generic`, `preauth-enhancement-request-generic`, `claim-queryupdate-request-generic`, `preauth-cancel-request-generic`. +- No `meta.versionId`, no `meta.lastUpdated`, no bundle `timestamp` on a request. The communication reply and acknowledgement are the exception: the IG example carries `meta.lastUpdated` and `timestamp`, and the build writes them. +- Money carries `currency: INR`; the total equals the sum of the item nets; whole numbers are written as integers. +- Instants are IST with `+05:30`. The four coverage pins in `B1` stamp `created` at `+05:00`, so leave `created` out of the byte comparison. + +## 3. Coverage eligibility request + +Builder: `build_coverage_request`. Seven entries, in this order and at these urls: + +1. `CoverageEligibilityRequest` at `/coverage-eligibility/request`: `identifier: [{system: https://nhcx.abdm.gov.in}]`, `status active`, `priority normal`, `purpose: []`, `patient`, `created`, `enterer` (the PractitionerRole), `provider`, `insurer`, `facility` (the Location), `insurance: [{focal: true, coverage}]`, and `item[]` on `benefits` and `auth-requirements`. +2. `Patient` at `/patient`: identifiers typed `PMJAY` (NDHM identifier-type system) and `MB` (v2-0203), both the member id. Nothing else; demographics are the payer's to return. +3. `Organization` provider at `/provider`: identifier `NPI` under `https://nhcx.abdm.gov.in` = the facility's registry id (HFR id); `type prov`; `name`. +4. `Organization` payer at `/payer`: identifier `NIIP` = the participant code without `@hcx` (`1518`); `type pay`. +5. `Location` at `/location`: `name`, `managingOrganization` the provider. +6. `Coverage` at `/coverage`: identifier `NH` = the policy code, or `NONE` on a discovery; `status active`; `type HIP`; `subscriber`, `beneficiary`, `subscriberId` = member id; `relationship self`; `payor`. +7. `PractitionerRole` at `/practitioner-role`: `code` SNOMED `307988006` Medical technician. + +Items (`eligibility_item`): `category` under `https://nhcx.abdm.gov.in/category-code` (the specialty), `productOrService` under `https://nhcx.abdm.gov.in/product-code` (the package), `quantity.value` as an integer, and each ward tier quoted through the package as a `modifier` coding with code and display and no system. No money, no diagnosis, no sequence. + +The four purposes differ only in `purpose`, the Coverage identifier and whether `item` is present. + +Reader (`parse_validation_bundle`): the payer echoes the request's entries and appends its own, so take the last `CoverageEligibilityResponse`, `Patient` and `Coverage`. Read `insurance[0].inforce`, `outcome`, `disposition`, `item[].authorizationRequired`, the largest `benefit[].allowedMoney` with its `usedMoney`, the Patient's name, gender, birth date, address, `ABHA` identifier and photo, the Coverage's `class[0].name` and `period`. The SHA answers on workflow id `5` (`nhcx-package/fhir/C3/C3-response-pmjay.json`). + +Auth-requirements reader (`parse_auth_bundle`, with `supporting_entry`; examples `C3/C3-response-generic.json` and `C3/C3-response-pmjay.json`): one `insurance[0].item` per line quoted, each with `authorizationRequired`, `excluded`, `benefit[0]` and `authorizationSupporting[]`. Each supporting entry is a CodeableConcept whose `text` is free text the scheme overloads: `fullUrl: ` marks a form to answer; `Type: pre` or `Type: post` says which leg a document is due at; `Procedure Code: X` says for which line. The space after the colon is sometimes missing; match both. A form is always wanted at pre-auth; a document only when its stage is `pre`. + +## 4. Insurance plan request and the plan + +Request (`build_plan_request`): a `TaskBundle` with one entry, a `Task` at `https://nhcx.abdm.gov.in/insurance/request`: `status requested`, `intent order`, `code poll` on the HL7 financial task code system, inputs typed `policyNumber` and `providerId` under the NDHM task-input code system. No id, no timestamp, no requester. At least one input is mandatory. Bundle id `insurance-request-generic`. + +Answer: an `InsurancePlanBundle` with one `InsurancePlan`, an `Organization`, and one `Questionnaire` per form the plan names (the same form repeated once per benefit that needs it; collect by `url`). The parser (`parse_plan_bundle`) reads both published shapes and merges them on package code: + +- `plan[].specificCost[].category` (the specialty) then `benefit[].type` (the package) then `cost[]`: the cost typed `Procedure` is the package rate; `Stratification` and `Implant` costs are money paid over the rate, named by their `qualifiers[0]`. +- `coverage[].benefit[].limit[]`: the limit whose code is the package's own is the rate; the rest (STRAT codes, implants) are tiers. +- Extensions on the plan, the coverage and each benefit, matched by a squashed url family: `Claim-Condition` children name conditions (`ProcedureType`, `IsDayCare`, and so on); `Claim-SupportingInfoRequirement` children are one nested requirement per document, each with `category`, `code` (`MAND0409` and the like) and `documentationUrl` pointing at a Questionnaire. Requirements on the `InsurancePlan` resource itself are policy-wide (proof of identity, the consent forms). +- A `Questionnaire` under `/questionnaire/` is a policy form; under `/stgquestionnaire/` a treatment-guideline checklist. Questions live on `item.prefix` far more often than `item.text`; answer options are plain strings; `initialSelected` is the payer's default. + +Store it once per facility and policy and copy it onto later episodes (`reuse_plan`). The PMJAY master runs to tens of megabytes; the validator cannot check it whole. + +## 5. The Claim bundle: pre-authorisation, enhancement, query answer, claim, predetermination + +One document for every leg (`claim_bundle`). Entries, in order and at these urls: + +1. `Claim` at `https://nhcx.abdm.gov.in//`: leg `preauth`, `claim` or `predetermination`; flow `request`, `enhancement` or `queryupdate`. +2. `Patient` at `/patient`, `id 1`: identifiers `PMJAY` (member id), `ABHA` (when known), `MB` (member id); `name.text`, `telecom`, `gender`, `birthDate`. +3. `Organization` provider at `/provider`, `id 1`; `Organization` payer at `/payer`, `id 2` (as in section 3). +4. `Coverage` at `/coverage`, `id 1`: `NH` identifier = policy code, `subscriberId` = member id. +5. `Practitioner` at `/practitioner` (the second and later at `/practitioner/2` and so on), `id n`: identifiers `HPID` under `https://nhcx.abdm.gov.in`, `MD` (licence) when known, and `HPIN` under `https://hpr.abdm.gov.in`. PMJAY looks the practitioner up by the `HPIN` typed identifier and refuses a bundle without one with PAYR-1083. `qualification.code` under HL7 v2-0360 with the table's own display (`degree_coding`). +6. `Procedure` at `/procedure/n`, `id n`, one per package: `status preparation` before treatment, `completed` on the claim; `code` SNOMED `71388002` with `text` = the package display; `performedDateTime`. +7. `QuestionnaireResponse` at `/questionnaireresponse/n`, one per answered form: `questionnaire` = the plan's Questionnaire url, `status completed`, `subject` the Patient, `authored`, `item[].answer[]` typed by the question (`valueString`, `valueDateTime`, `valueBoolean`, `valueInteger`, `valueDecimal`, `valueAttachment`). + +The Claim itself: + +- `id` = the claim number; `identifier[0]` typed `CLN` under `https://nhcx.abdm.gov.in` = the claim number. Element ids on every list the payer indexes: `item[].id = Item/n`, `procedure[].id = Procedure/n`, `supportingInfo[].id = SupportingInformation/n`. PAYR-1027 is an item without one. +- `status active`, `type` SNOMED `737481003` inpatient care, `use` = `preauthorization`, `claim` or `predetermination`, `billablePeriod`, `created`, `insurer`, `provider`, `priority normal`. +- `careTeam[]`: sequence, provider reference, role `primary` for the first and `assist` after, `qualification` SNOMED specialty. +- `diagnosis[]`: ICD-10 under `http://hl7.org/fhir/sid/icd-10`, type `admitting`, `onAdmission yes`. +- `procedure[]`: sequence, `type` under `https://nhcx.abdm.gov.in/procedure-type` = the plan's `ProcedureType` condition lower-cased (`conservative`, `medical`, `surgical`), `date`, `procedureReference` with the package display. +- `insurance[0]`: `sequence 1`, `focal true`, `coverage`; on the claim `preAuthRef: [""]`. The pin carries the pre-auth's own claim number there (`B5/claim-request.json` quotes `B3/preauth-request.json`'s claim id). The build carries the payer's `ClaimResponse.preAuthRef`, which the live capture `nhcx-package/fhir/D9/D9-request.json` shows as `2026091110000810`. +- `item[]` (`claim_items`): one per procedure or implant, never per tier. `sequence`, `careTeamSequence`, `diagnosisSequence`, `procedureSequence` (its own Procedure), `informationSequence` (every supportingInfo), `category` under `ndhm-benefit-category` (the specialty), `productOrService` under `ndhm-procedure-code` (the package), `modifier[]` one coding per ward tier with code and display and no system, `programCode` `AB-PMJAY` under `ndhm-program-code` for PMJAY and none for a generic payer, `servicedPeriod` as dates, `quantity`, `unitPrice` = net divided by quantity, `factor` from the scheme's multiple-procedure rule (1, 0.5, 0.25 by cost rank; PMJAY only), `net` = the line plus its tiers. +- `total` = the sum of the nets. + +supportingInfo (`supporting_info`), every entry numbered once the list is assembled (PAYR-1019 is an entry without `sequence`): + +| When | category | code | value | +| --- | --- | --- | --- | +| every leg, one per attached document | `INV` (or the document's own category) under `ndhm-supportinginfo-category` | the plan's requirement code (`MAND0408`) under `https://nhcx.abdm.gov.in/document-code`, else `ODN` | `valueAttachment {contentType, data, title}` | +| every leg | `ONS` | `ADDD` | `valueString` admission instant | +| every leg | `OTH` | `EDT` | `valueString` admission instant | +| claim | `HDS` | the plan's summary code (`MAND0006` in the pin) else `HDS` | `valueAttachment` the discharge summary | +| claim, when a surgery time is known | `ONS` | `PSP` | `valueString` surgery instant | +| claim | `ONS` | `DSDE` | `valueString` discharge instant, or the death instant | +| claim, death only | `ONS` | `DTM` | `valueString` death instant (PAYR-1096 and PAYR-1503 without it) | +| claim | `DIS` | `DTH`, `LAMA`, `DAMA` or `DTM` | `valueString` the stage: `Before Surgery`, `During Surgery`, `After Surgery` | +| query answer (flow `queryupdate`) | `NMI` | `CQD` | `valueString` the desk's reply. The SHA reads its query response comments from here; an answer without one is decided as if none was given | +| every leg, one per answered form | `INF` (or `STG` for a treatment guideline) | `ODN` (or `STG`) | `valueReference` to the QuestionnaireResponse entry | + +Which forms ride (`required_forms`): with an auth-requirements ruling, the forms it named for the leg; without one, at pre-auth every guideline form the plan attaches to the quoted packages; and on both legs every policy-level form. The scheme refuses a pre-auth that answers neither biometrically nor with its Authentication Consent questionnaire (PAYR-1256, PAYR-1271), a claim without the consent answered again at discharge (PAYR-1363, PAYR-1364), and a package without its STG questionnaire (PAYR-1254, PAYR-1365). The live D4 capture carries two policy questionnaires; the live D9 claim carries four, including the Discharge Consent (`nhcx-package/fhir/D9/D9-request.json`). + +Which documents ride (`required_documents`, `preauth_documents`): the ruling's list for the leg, else the plan's list for the quoted packages at pre-auth and whatever was not attached there at the claim. A file attached against a requirement carries that requirement's code; a file nobody asked for carries `ODN`. Never drop one. Content types the scheme takes: pdf, jpg, jpeg, png (PAYR-1008 otherwise). + +The legs differ in these ways only: + +| Leg | flow | use | Procedure status | Extra | +| --- | --- | --- | --- | --- | +| Pre-auth 12 | `request` | `preauthorization` | `preparation` | | +| Enhancement 13 | `enhancement` | `preauthorization` | `preparation` | every line, old and new, under the same claim number; the costlier package at factor 1 and the other at 0.5 (the live capture `nhcx-package/fhir/D6/D6-enhancement.json` carries the two lines at 1 and 0.5) | +| Query answer 19 or 131 | `queryupdate` | `preauthorization` | `preparation` | the `NMI`/`CQD` reply | +| Claim 15 | `request` | `claim` | `completed` | discharge scalars, summary, `preAuthRef`, the claim under the pre-auth's number (ERR-PYR-CLM-007) | +| Claim query answer 161 | `queryupdate` | `claim` | `completed` | as the claim, plus `NMI`/`CQD` | +| Predetermination | `request` | `predetermination` | `preparation` | sent on `v1/preauth/submit` with workflow 12 | + +LAMA and DAMA before or during surgery (`claim_lines`): the claim carries one item, procedure `LM100` at the plan's rate (the sandbox prices it at zero), no tier, and the payer disqualifies every approved item (PAYR-1362 if the package is still there). After surgery the package stands and `LM100` is not used. PAYR-1270 is `LM100` on a pre-auth. + +## 6. The ClaimResponse you read + +Shape (`nhcx-package/docs/01-Overview/07-Payer Flexibility.md`, "Answer detail"): `ClaimResponse`, `Patient`, the two `Organization` entries, `Coverage`, in that order. Fields to read (`parse_claim_response`): + +- `use`: `preauthorization` or `claim`; a bundle with none is whatever you sent on that thread. +- `outcome`: `queued` (acknowledgement), `partial` (queried, or approved for less), `complete`, `error` (rejected). +- `adjudication[]` at claim level: the entry whose `category` is `status` carries `reason.coding.code`: `submitted`, `approved`, `queried`, `rejected`, `cancelled`. +- `preAuthRef`: the payer's case number; see `flow-knowledge.md` section 3 for which answers carry it. +- `identifier[0].value`: your claim number, echoed on every answer. +- `total[]`: a repeating list by `category`, never positional: `benefit` (granted this round), `eligible` (what the case stands at), `submitted`; PMJAY adds `tax` and `incentive`. +- `item[].adjudication[]` by category: `eligible` (amount), `status` (reason `Approved`, `Queried`, `Rejected`), `reason` (the desk's remark, pipe-delimited `USER~datetime~type~comment~trust`, kept verbatim), `eligpercent`, `eligquant`, `deductible` with its reason after a claim. +- `processNote[].text`. +- `type` is present only on the pre-auth acknowledgement (SNOMED `737481003`). + +The status rule (`verdict_status`): `queued` or reason `submitted` is still `submitting`; reason `cancelled` is `rejected`; reason `queried` is `queried`; outcome `error` is `rejected`; outcome `partial` is `partial` only with reason `approved`, else `queried`; outcome `complete` is `approved` with reason `approved` or none, else `queried`. Never read `outcome` alone. + +## 7. Task bundles the hospital sends + +A `TaskBundle` with the `Task` at `https://nhcx.abdm.gov.in//` followed by the provider and payer Organizations. The Task: `status requested` (`completed` on an acknowledgement), `intent order`, `code` on the HL7 financial task code system with no display, `description`, `authoredOn`, `requester` the provider, `owner` the payer. + +| Task | code | reasonCode (NDHM reason code system) | inputs | Other | +| --- | --- | --- | --- | --- | +| Cancel PC01 | `cancel` | one of `treatmentplanchanged`, `patientrequest`, `financialconstraints`, `alternativetreatment`, `duplicateclaim`, `administrativeerror`, `other` (with `other` the description is the only justification) | `claimNumber`, `intimationNumber` (both typed under `ndhm-task-input-type-code`) | anchor `/preauth/cancel` | +| Reprocess 36 | `reprocess` | `claimrejected`, `partialpayment` or `rejectiondisputed` with the reference's displays | `claimNumber`, `intimationNumber` (the standard's spelling), one `document` input per attachment as `valueAttachment` | `basedOn[0].identifier` typed `CLN`; `for.identifier` typed `PMJAY` on the scheme, `MB` elsewhere; anchor `/claim/reprocess` | +| Release 36 | `release` | `partialpayment` | `claimNumber`, `amount` as `valueMoney` under `https://nhcx.abdm.gov.in/task-input-type` | `basedOn` as above; anchor `/claim/release` | +| Status | `status` | none | `claimNumber` | anchor `//status`; not in the package, whose status call carries no bundle (`18-Predetermination, Status and Search.md`); refused by PMJAY | +| Payment acknowledgement 17 | `status`, `status completed` | none | none; `output[]`: `status` = `paymentack` under the NDHM task-output systems, and `claimNumber` | anchor `/payment/notice-ack` | + +The spelling rule: the input is `intimationNumber`, the standard's spelling, on every Task. A reprocess under any other spelling is refused with PAYR-1008 (proven live; `nhcx-package/docs/01-Overview/07-Payer Flexibility.md`, "One spelling on the Task"). The pinned cancel and reprocess Tasks carry the same spelling, so the offline comparison diffs them unchanged. + +## 8. Task answers you read + +`parse_task_response`: find the `Task`, then follow each `output[].valueReference` to the entry it names; when that is a `ClaimResponse`, read it with the same parser as a verdict. + +- PC02 (`nhcx-package/fhir/C10/C10-cancelled-wfPC02.json`): Task `completed`, code `approve`, `output[0]` an `include` reference to a `ClaimResponse` with adjudication reason `cancelled`, `use preauthorization`. Accept the cancel when the Task status is `completed` or `accepted` and the outcome is not `error`. Retire the claim number after an accepted cancel. +- 37 (`nhcx-package/fhir/C10/C10-arbitration-wf37.json`): Task `accepted`, code `approve`, a `ClaimResponse` with outcome `queued`, `use claim`. Put the claim leg back to `submitting`; the new verdict comes on the claim's own thread. +- A status answer: none captured in the package. A generic payer that answers a status Task sends a Task `completed`, code `status`, `output[]` with `claimNumber` and a `claimStatus` string; PMJAY refuses the enquiry instead. + +## 9. The communication loop + +The query, generic payer (`nhcx-package/fhir/C6/C6-preauth-query-wf24.json`; the IG's example at `nhcx-package/fhir/B4/communication-request.json`): a `TaskBundle` with a `Task` `poll`, `requested`, `intent order`, `reasonCode additionalinfo`, one `include` input pointing at the `CommunicationRequest`; the request with `identifier` (the claim number), `basedOn` the Claim, `payload[].contentString` one per ask, `reasonCode[].text` repeating them; then the Claim, Patient, the two Organizations, Practitioner and Coverage. It arrives on `v1/communication/request` on a new correlation id, with the queried leg's correlation id in `x-hcx-workflow_id` when the payer sends one. + +The notification, PMJAY (`nhcx-package/fhir/C6/C6-notification-wfN02.json`): a Task `poll`, `completed`, `intent proposal`, reason `information` under `http://terminology.hl7.org/CodeSystem/communication-category`, a `CommunicationRequest` with one `contentString`, and the two Organizations. + +Reader (`parse_communication_request`): the first `CommunicationRequest`; the claim numbers it names in `about[]`, `basedOn[]` and `identifier[]`; the asks from `payload[].contentString`, else `reasonCode[].text`, else the Task's `description`; the Task's `intent` and `reasonCode`. Match the claim by those numbers first, then by a request id already held, then by the correlation id of one of your sends, then by the workflow id as a thread. + +The reply (`build_communication_bundle`; pin `nhcx-package/fhir/B4/communication-response.json`): a `TaskBundle` with `meta.lastUpdated`, `identifier` under the payer system, `timestamp`, and entries in this order: + +1. `Task` at `urn:uuid:`: `status completed`, `intent order`, `code deliver` under `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-codes`, `authoredOn`, `requester` the provider, `owner` the payer, one `input` typed `include` (HL7 financialtaskinputtype) pointing at the Communication, `reasonCode` echoed from the request's Task when it carried one. +2. `Communication` at `urn:uuid:`: `identifier` echoed from the request, `basedOn: [{reference: }]`, `about: [{reference: }]`, `status completed`, `category notification`, `priority routine`, `recipient` the payer, `sender` the provider, `payload[]`: a `contentString` for the text, then one `contentAttachment {contentType, title, creation, data}` per document, each with an `extension` carrying the document code. The extension url is participant-defined (`17-Communication.md`): write it under your own system and keep one url. `inResponseTo` is never set: FHIR allows only a Communication there and the validator refuses a request. +3. The `CommunicationRequest` echoed as it arrived. +4. The case as the payer holds it, lifted from the queried leg's own bundle: `Claim`, `Patient`, provider `Organization`, payer `Organization`, `Practitioner`, `Coverage`. + +Envelope for the reply: `x-hcx-correlation_id` = the request's, `x-hcx-workflow_id` = the request's, else the queried leg's correlation id, else the claim number; sender and recipient swapped. + +The acknowledgement of a notification: the payer's own bundle sent back with `Task.status` set to `completed`, its intent and reason as sent, the provider Organization ahead of the payer's, a fresh `timestamp`. A request that came without a Task gets one built round it, coded `poll`, intent `proposal`, pointing at the request. The package's `B4/communication-acknowledgement.json` is a different shape: a `status` Task, `completed`, with a `status` output and the two Organizations, and no CommunicationRequest. + +## 10. The payment notice you read and the acknowledgement you send + +Notice (`nhcx-package/fhir/C9/C9-notice-wf30.json`; PMJAY `C9/payment-notice.json` and `C9/C9-notice-tds-wf30-pmjay.json`): a Task `deliver`, `requested`, with a `status` input; a `PaymentNotice` with a `CLN` identifier (the claim number), `amount`, `paymentStatus paid`; a `PaymentReconciliation` with the same identifier, `disposition`, `paymentDate`, `paymentAmount`, `paymentIdentifier` typed `UTR`, and `detail[]` lines (`RF` and `Payment` in `payment-notice.json`; `TDS` and `Payment` in the other two); the two Organizations. It arrives on `v1/paymentnotice/request` on a new thread, workflow 30, 31 or 33. + +Reader (`parse_payment_notice`): the claim number from the `CLN` identifier on the notice, the reconciliation, the Task, or the first entry's untyped identifier, never from the bundle identifier; the amount from the notice or `paymentAmount`; the UTR; the details. Dedupe on the notice's correlation id; a second notice with the same `PaymentNotice.id` updates the first (`record_payment`). Count money once per UTR (`paid_total`). + +Acknowledgement: the Task in section 7, sent on `v1/paymentnotice/on_request` to whoever sent the notice (not always the claim's payer), with `x-hcx-correlation_id` = the notice's and `x-hcx-workflow_id` = `17` for PMJAY or the notice's own id for a generic payer. + +## 11. Validating a bundle + +The package ships no validator. Use the HL7 FHIR validator (`validator_cli.jar`, from HL7) with the NRCeS IG package `ndhm.in`, version 6.5.0. A bundle refused with PAYR-1004 or PAYR-1008 goes through the validator before anything else (`nhcx-package/docs/06-Reference/02-Troubleshooting.md`). The rules it checks against are in `nhcx-package/docs/05-FHIR Reference/01-Bundles and Conventions.md`. + +```sh +java -Xmx4g -jar validator_cli.jar \ + -version 4.0.1 -ig -tx n/a -output result.json +``` + +Pass every file in one call; starting the JVM is the slow part. `-tx n/a` keeps the terminology checks offline; drop it to add them. A bundle passes when the output holds no issue of severity error or fatal. + +The provider pins carry 0 to 13 errors each and the SHA accepted every one as it stands. An error that says "a code the profile does not define" is the scheme's own vocabulary, not a fault to fix. A warning is advice. diff --git a/plugins/nhcx/skills/nhcx-communication/references/flow-knowledge.md b/plugins/nhcx/skills/nhcx-communication/references/flow-knowledge.md new file mode 100644 index 000000000..098cd9dbc --- /dev/null +++ b/plugins/nhcx/skills/nhcx-communication/references/flow-knowledge.md @@ -0,0 +1,206 @@ +# Flow knowledge: the claim episode, its workflow ids, the two payer kinds, the use cases + +Sources: the NHCX package, fetched by `scripts/fetch-package.sh` into `nhcx-package/` beside `nhcx-build/`. That means the overview chapters under `nhcx-package/docs/01-Overview`, the workflow sheet `nhcx-package/workflow.yaml`, the use-case catalogue `nhcx-package/usecases.yaml`, and the payer bundles under `nhcx-package/fhir/C3` to `nhcx-package/fhir/C11`. The published chapters live under `nhcx-package/docs/01-Overview`, `nhcx-package/docs/05-FHIR Reference` and `nhcx-package/docs/03-Building a Provider`. Everything else here was learnt live on the NHCX sandbox. + +## 1. The episode + +One hospital admission that an insurer pays for is one claim episode. Store it as one record with a claim number. Any number works if it is unique per hospital, short, sortable, and fits the payer's `CLN` identifier. The episode has these legs, each a separate exchange with its own correlation id: + +| Order | Leg | You send | Payer answers | Thread | +| --- | --- | --- | --- | --- | +| 1 | Policy lookup | The participant service's `participant/get/policies`, through the transport; the recipient of every later leg is the policy's `processingid` | synchronous JSON | none, plain REST | +| 2 | Coverage eligibility | `v1/coverageeligibility/check`, purpose `discovery`, `validation` or `benefits` | `on_check` | new per check | +| 3 | Insurance plan (package master) | `v1/insuranceplan/request` | `on_request` | new; one plan per facility and policy | +| 4 | Auth requirements | `v1/coverageeligibility/check`, purpose `auth-requirements`, with items | `on_check` (the PMJAY sandbox rarely answers; `nhcx-package/fhir/C3/C3-response-pmjay.json` is an SHA ruling, `C3/C3-response-generic.json` a generic one) | new per procedure set | +| 5 | Pre-authorisation | `v1/preauth/submit` wf 12 | `on_submit` 20 first, then 21, 23 or 24 | new; the acknowledgement comes first on the same thread | +| 5a | Pre-auth query answer | `v1/preauth/submit` wf 19 (PMJAY) or `v1/communication/on_request` (generic) | 21 or 23 | new (PMJAY) or the request's (generic) | +| 5b | Enhancement | `v1/preauth/submit` wf 13, the whole pre-auth again with the added line | 20 then 22, 231 or 241 (the SHA sandbox has also answered with 21) | new | +| 5c | Enhancement query answer | `v1/preauth/submit` wf 131 | 22 or 231 | new | +| 5d | Cancel | `v1/task/submit` wf PC01 | `task/on_submit` PC02 | new | +| 5e | Predetermination | `v1/preauth/submit`, `Claim.use = predetermination`, wf 12 | `on_submit` | new | +| 6 | Claim | `v1/claim/submit` wf 15, `Claim.use = claim`, under the pre-auth's number | 25 then 26, 27 or 291 | new | +| 6a | Claim query answer | `v1/claim/submit` wf 161 (PMJAY) or `v1/communication/on_request` (generic) | 26 or 291 | new (PMJAY) or the request's (generic) | +| 6b | Reprocess or release | `v1/task/submit` wf 36 | `task/on_submit` 37, then a fresh verdict on the claim's thread | new | +| 7 | Payment notice | the payer sends `v1/paymentnotice/request` wf 30 (31, 33) | you answer `v1/paymentnotice/on_request` wf 17 (PMJAY) or the notice's own id (generic) | the notice's | +| any | Status enquiry | `v1/task/submit`, Task code `status` | `task/on_submit` (generic); PMJAY refuses it | new | +| any | Communication | the payer sends `v1/communication/request` | you answer `v1/communication/on_request` | the request's | + +The payer's acknowledgement is `x-hcx-status: response.partial` and the decision is `response.complete`, on the same correlation id (`nhcx-package/docs/01-Overview/07-Payer Flexibility.md`, "Answer detail"). Read the acknowledgement as "the payer has it", never as a decision. Map `ClaimResponse.outcome` `queued`, or an adjudication reason `submitted`, to leg status `submitting` (`verdict_status`). + +## 2. Every workflow id + +The hospital's table. PMJAY and a generic payer differ in three rows: `claim_query_response`, `claim_resubmit` and `payment_ack`. + +| Kind | PMJAY | Generic | Path | Note | +| --- | --- | --- | --- | --- | +| `preauth` | `12` | `12` | `v1/preauth/submit` | A new pre-auth. Also a fresh request after a rejection: PMJAY refuses 121 there with PAYR-1214. | +| `preauth_resubmit` | `121` | `121` | `v1/preauth/submit` | Kept in the table. `preauth_send_kind` never picks it after a rejection. | +| `preauth_query_response` | `19` | `19` | `v1/preauth/submit` | The answer to a 24. A generic payer asks by communication instead, so this is a PMJAY leg. | +| `enhancement` | `13` | `13` | `v1/preauth/submit` | The whole pre-auth again under the parent's number, plus the added line. | +| `enhancement_resubmit` | `131` | `131` | `v1/preauth/submit` | The answer to a 241. | +| `cancel` | `PC01` | `PC01` | `v1/task/submit` | Task code `cancel`. The handbook's section 8.6 says 122 (`nhcx-package/docs/01-Overview/06-Workflow Codes.md`, "Reconciled Discrepancies and Authority Rules", takes PC01). If a payer insists on 122, override it per payer in configuration. | +| `claim` | `15` | `15` | `v1/claim/submit` | The final bill. | +| `claim_query_response` | `161` | `151` | `v1/claim/submit` | PMJAY refuses 151, 19 and 16 with PAYR-1321; 161 is taken. | +| `claim_resubmit` | none | `16` | `v1/claim/submit` | PMJAY has no claim resubmit. A decided claim goes back only as a reprocess. | +| `payment_ack` | `17` | none (echo the notice's own id) | `v1/paymentnotice/on_request` | `None` in the table means "echo". | +| `reprocess` | `36` | `36` | `v1/task/submit` | Task code `reprocess`; acknowledged on 37. | +| `release` | `36` | `36` | `v1/task/submit` | Task code `release`, reason `partialpayment`, an `amount` input. | +| status enquiry | the leg's correlation id, fallback `13` | same | `v1/task/submit` | The fallback id is `13`. The NHCX sandbox refuses `v1/status` with NHCX-1012. | +| coverage, plan, auth requirements | your case number | your case number | see section 1 | The sheet lists no code. Send the episode's case number. | + +The payer's ids you must branch on (`nhcx-package/workflow.yaml`, `nhcx-package/docs/01-Overview/06-Workflow Codes.md`), with what the sandbox actually sent: + +| Id | Meaning | Status word | +| --- | --- | --- | +| `20` | Pre-auth or enhancement received | `response.partial` | +| `21` | Pre-auth approved | `response.complete` | +| `22` | Enhancement approved. A generic payer sends 22. The SHA sandbox has answered an enhancement with 21, and `nhcx-package/fhir/C5/C5-enhancement-approved-wf22-pmjay.json` is an SHA answer on 22. Accept both. | `response.complete` | +| `23` | Pre-auth rejected | `response.complete` | +| `231` | Enhancement denied | `response.complete` | +| `24` | Pre-auth queried | the sheet says `request.initiated`; the SHA sent `response.complete` | +| `241` | Enhancement queried | as 24 | +| `25` | Claim received | `response.partial` | +| `26` | Claim approved | `response.complete` | +| `27` | Claim queried | as 24 | +| `28`, `29` | Claim in process, forwarded | `response.partial` | +| `291` | Claim rejected | `response.complete` | +| `251`, `252`, `253`, `254` | Reprocess received, approved, rejected, queried | listed; both live payers answer a 36 with 37 instead | +| `37` | Arbitration acknowledged (the reprocess taken) | `response.complete` (the SHA sent `response.partial`) | +| `PC02` | Cancellation done | `response.complete` | +| `30`, `31`, `33` | Payment initiated, processed, settled with UTR | `request.initiated`, new thread | +| `5` | The SHA's coverage eligibility and plan answers | `response.complete` (`nhcx-package/fhir/index.yaml` gives 5 for `C3/C3-response-pmjay.json` and `C4/C4-response-pmjay.json`) | +| `N02` | Notification to a provider (a PMJAY CommunicationRequest) | `request.initiated` | + +Other codes exist (10, 11, 14, 141, 18, 45 to 47, 181, 491, 34, 35, 38, 39, G11 to G13, RP1 to RP3, DC01, DC02, N01, N03, N04, the R-series). A hospital build sends none of them. See `nhcx-package/docs/01-Overview/06-Workflow Codes.md` for the full sheet and the seven codes the handbook and the sheet publish differently. + +## 3. Two kinds of payer + +Read `nhcx-package/docs/01-Overview/07-Payer Flexibility.md` in full. A generic payer is any payer on the exchange, IRDAI-regulated insurers and TPAs included (`nhcx-package/fhir/README.md`). The rule, as coded: + +| | PMJAY (`query_mode: resubmit`) | Generic (`query_mode: communication`) | +| --- | --- | --- | +| The query arrives as | a `ClaimResponse` on the case's own thread, `outcome: partial`, item status `Queried`, wf 24, 241 or 27 | a `CommunicationRequest` TaskBundle on `v1/communication/request`, on a new thread, wf 24, 241 or 27 | +| The answer | the whole bundle again on `v1/preauth/submit` or `v1/claim/submit`, wf 19, 131 or 161, a new correlation id, the reply text on the `NMI`/`CQD` supportingInfo entry | a Communication TaskBundle on `v1/communication/on_request`, the request's correlation id and workflow id echoed | +| A `CommunicationRequest` from this payer | always a notification: acknowledge and leave the case alone | classified (below) | + +Where the payer's case number arrives. The package files are under `nhcx-package/fhir/`; the rule is in `07-Payer Flexibility.md`, "When the case number arrives". + +| Answer | PMJAY | Generic | +| --- | --- | --- | +| 20 on a fresh pre-auth | The package says none, and `C5/C5-received-wf20-pmjay.json` carries none. A live SHA 20 has also carried the path form, `PMJAY/HP/S/2024/R2/`. Handle both. | present (`C5/C5-received-wf20.json`) | +| 20 on an enhancement | none; keep the parent's | present | +| 21, 23, 24 | the bare number (`C5/C5-approved-wf21-pmjay.json`, `C5/C5-rejected-wf23-pmjay.json`, `C5/C5-queried-wf24.json`) | present (`C5/C5-approved-wf21.json`, `C5/C5-rejected-wf23.json`) | +| 25 | the path form (`C7/C7-received-wf25-pmjay.json`) | present (`C7/C7-received-wf25.json`) | +| 26, 27, 291, PC02, 37 | none | none | + +So the brief's rule holds with care. A generic payer's `response.partial` acknowledgement carries the payer's case number. PMJAY's 25 carries it; its 20 may not. Read `ClaimResponse.preAuthRef` on every answer. Keep a value and never overwrite it with an empty one (`apply_preauth`). The bare number is what the payer service desk wants; the path form ends in it. + +`query_mode` lives on the payer adapter. Choose the adapter by the payer's participant code through configuration: `1518@hcx` is PMJAY, and an unmapped code is generic. + +### The classification rule + +`classify_communication(adapter, reason, intent)` applies these, in order: + +1. If the payer's `query_mode` is `resubmit`: notification. +2. Else if `Task.intent` is `proposal`: notification. If `order`: query. +3. Else look at `Task.reasonCode`: absent, `additionalinfo`, `questionnaire` or `query` is a query; anything else (`tatquery`, `grievance`, `walletupdate`, `policychange`, `claimarbitration`) is a notification. Fold `claimArbitartion` into `claimarbitration`. +4. A bare `Communication` with no `CommunicationRequest` is a note: recorded, shown, never acted on. + +Acknowledge a notification at once. Send the payer's own bundle back with `Task.status` flipped to `completed`, the reason echoed and the provider Organization first. File a query open for the desk, and answer it later with the TaskBundle reply (see `fhir-knowledge.md`). The reply names the request in `Communication.basedOn`, never `inResponseTo`. + +The live shapes. A generic payer's query (`nhcx-package/fhir/C6/C6-preauth-query-wf24.json`) carries a Task `poll`, `requested`, `intent order`, reason `additionalinfo`, and a CommunicationRequest with one `contentString` per ask and `basedOn` the Claim. PMJAY's notification (`nhcx-package/fhir/C6/C6-notification-wfN02.json`) carries a Task `poll`, `completed`, `intent proposal`, reason `information` under the HL7 communication-category system. + +## 4. Stage, sub-stage, next actions + +Stamp two words onto the episode after every leg write (`stamp_case`), and compute a next-action list from them. Copy the vocabulary; it is what a desk needs to see. + +Stages: `eligibility`, `preauth`, `enhancement`, `claim`, `payment`. + +Sub-stages: `draft`, `checking`, `eligible`, `not-eligible`, `requested`, `resubmitted`, `answered`, `queried`, `approved`, `partial`, `rejected`, `cancelling`, `cancelled`, `refused`, `noticed`, `paid`. + +How a send kind maps to a sub-stage: `preauth`, `claim`, `enhancement` set `requested`; `*_resubmit` sets `resubmitted`; `*_query_response` and `enhancement_resubmit` set `answered`. `requested`, `answered` and `resubmitted` mean "with the payer". + +Derivation (`case_stage`): a payment notice wins, then the filed claim, then the pre-auth (stage `enhancement` if the last submission kind was an enhancement), then a saved draft, then the eligibility status. An open communication query on a leg that is with the payer flips the sub-stage to `queried`, because a generic payer's query never touches the leg row. + +Next actions (`next_actions`) are `{label, tab, tone}`; the first is what the case waits for. Rules worth copying: + +- An unanswered query always leads with "Answer the payer (n)". +- The leg's own reply box is offered only for a `resubmit` payer. A `communication` payer's desk is sent to the communication tab. +- A claim refused at the door offers "send again" while `claim_send_kind` still yields a kind, else "Ask for a reprocess". +- After a rejection the pre-auth offers a fresh 12, not 121. + +## 5. Rules the exchange enforces that no document states + +Each was found live on the sandbox. + +- Acknowledge or lose the thread. NHCX redelivers an unanswered submission, then drops it and retires the correlation id; a verdict sent later is refused with NHCX-1010. Both live payers answer twice on one correlation: `outcome: queued` first, the decision after. Your reader must not close a thread on the first reply. +- One message is taken once. The SHA redelivers the same `api_call_id` two or three times, about a minute apart, and a transport can fan one delivery out to several receivers (nhcx-adapter's `callback.also`). Dedupe on `x-hcx-api_call_id`. +- One live pre-auth per beneficiary per hospital (PAYR-1238). Clear it with PC01 or a rejection (`nhcx-package/docs/03-Building a Provider/11-PMJAY Sandbox Run.md`, "PAYR-1238 An active preauthorisation exists"). Sweep live pre-auths before a test run. +- One request at a time per case (PAYR-1322, "Active instance found"). Wait about 30 seconds after a decision before the next leg. When a refusal says "Active instance", wait and resend, up to three times. +- One plan per facility and policy. Key it on policy code, provider id and payer. Copy the held master onto a new episode instead of asking again (`reuse_plan`). A PMJAY master runs to tens of megabytes; one fetched live was 56 MB. +- Never drop a document. A file nobody asked for by name goes under `ODN`, "other document". A file attached against a requirement carries that requirement's code (`attach_required_document`). Take the code list from the plan, not from a constant. +- Ask the auth-requirements check, never await it (`ensure_auth_requirements`). Fingerprint the quoted set (`procedure_set`) so an unchanged set is not asked twice. Send the quantity as a whole number. +- Tiers are modifiers, not lines. A ward or ICU tier rides on `Claim.item.modifier` under its procedure, and that item's `net` carries both. +- The claim goes under the pre-auth's number (ERR-PYR-CLM-007), and PMJAY bills the package alone at the whole amount (`11-PMJAY Sandbox Run.md`, "ERR-PYR-CLM-007" and "What the package master decides"). +- Answers to a PMJAY query go on a new correlation id (`07-Payer Flexibility.md`, "On the claim thread"). A same-thread answer is swallowed: no acknowledgement, no refusal, and the desk dies on the old id. +- Cancel retires the number. Give the episode a fresh claim number after an accepted PC01, and keep the withdrawn one on the leg. +- A send refused at the door keeps the case on the thread the payer last answered. An enhancement refused at the door leaves the pre-auth approved. + +## 6. The use-case catalogue + +Codes and titles are quoted from `nhcx-package/usecases.yaml`, rendered as `nhcx-package/docs/01-Overview/05-NHCX Use Cases.md`. "Proves" is what a test run must show for each one. "Package file" is the provider bundle the package holds for it, under `nhcx-package/fhir/`. + +### A: shared + +| Code | Title | What it proves | +| --- | --- | --- | +| A1 | Get participant list | You can find the payer's code in the registry (the participant service's `fetch/participants/list`). | +| A2 | Get policy | You can find a beneficiary's policy and the processor code that becomes `x-hcx-recipient_code` (the participant service's `participant/get/policies`). | +| A3 | Get public key | The transport fetches the recipient's certificate (`fetch/certs`) and caches it. | +| A4 | Get auth token | The transport holds an ABDM session token (the gateway's sessions call) and refreshes it. | +| A5 | Get status | A status Task on `v1/task/submit` gets a Task back (generic), or a PAYR-1018 then PAYR-1008 refusal (PMJAY). The package holds no bundle for A5 (`nhcx-package/fhir/README.md`). | +| A6 | Receive errors | Your callback accepts a `ProtocolResponse` on any path and answers 2xx. | + +### B: hospital on the generic network + +| Code | Title | Workflow | Proves | Package file | +| --- | --- | --- | --- | --- | +| B1 | Check coverage eligibility | none | The check goes out; `inforce` and the wallet come back. | `B1/B1-check.json` | +| B2 | Request insurance plan | none | The package master lands and is stored once per policy. | `B2/B2-request.json` | +| B3 | Submit pre-authorisation | 12, 13 | Sent, acknowledged on 20, decided on 21 or 23; an enhancement on 13 decided on 22. | `B3/B3-request.json`, `B3/B3-enhancement.json` | +| B4 | Respond to a communication | 24, 27 echoed | A CommunicationRequest is classified and the TaskBundle reply goes on the request's thread. | `B4/B4-preauth-query-answer.json`, `B4/B4-claim-query-answer.json` | +| B5 | Submit claim | 15 | The claim under the pre-auth's number, acknowledged 25, decided 26 or 291. | `B5/B5-request.json` | +| B6 | Search claims | none | Not built by these skills. | `B6/claim-search.json` (example) | +| B7 | Acknowledge payment notice | 30 echoed | The notice is filed by claim number, deduped by correlation id, acknowledged on `on_request`. | `B7/B7-acknowledgement.json` | +| B8 | Reprocess or cancel | 36, PC01 | A decided claim is reopened (37 then a new verdict); a live pre-auth is withdrawn (PC02). | `B8/B8-reprocess.json`, `B8/B8-cancel.json` | +| B9 | Submit predetermination | 12 | A quote comes back as a ClaimResponse; nothing else changes. | `B9/predetermination-request.json` (example); the answer is `C11/predetermination-response.json` | + +### C: payer answering (for reference; you build the reader, not the sender) + +C3 coverage answer, C4 plan answer, C5 pre-auth answers (20, 21, 22, 23, 24, 231, 241), C6 communication (24, 241, 27, N02), C7 claim answers (25, 26, 27, 28, 29, 291), C9 payment notice (30, 31, 33), C10 Task answers (PC02, 37, 251 to 254), C11 predetermination. Reader inputs: `nhcx-package/fhir/C3` to `nhcx-package/fhir/C11`. The files ending `-pmjay` are the SHA's own; the rest are the generic payer's. `nhcx-package/fhir/index.yaml` gives each file's scheme, workflow id and origin. The PMJAY captures have the beneficiary's identifiers replaced. + +### D: hospital on PMJAY + +| Code | Title | Workflow | Proves | Package file | +| --- | --- | --- | --- | --- | +| D1 | Fetch the insurance plan | none | The scheme's master, both `coverage[]` and `specificCost[]`, nested document requirements, questionnaires. | `D1/D1-request.json` | +| D2 | Authenticate the beneficiary | not NHCX | Biometric token or the consent questionnaire fallback. | none | +| D3 | Check coverage eligibility | none | The wallet answer on wf 5. | `D3/D3-check.json` | +| D4 | Submit pre-authorisation | 12 | Element ids, HPIN, consent QuestionnaireResponse, documents from the master; acknowledged 20, decided 21 or 23 with `preAuthRef`. | `D4/D4-request.json` | +| D5 | Resubmit pre-authorisation | 121 | Not reachable on the sandbox after a rejection (PAYR-1214); send a fresh 12. | none | +| D6 | Raise an enhancement | 13, 131 | A second package (medical, not conservative: PAYR-1245) under the parent's number; a 241 answered on 131. | `D6/D6-enhancement.json`, `D6/D6-enhancement-query-answer.json` | +| D7 | Answer a pre-authorisation query | 19 | The 24 answered as a fresh submit with `CQD` reply text, new correlation id, then 21. | `D7/D7-query-answer.json` | +| D8 | Cancel pre-authorisation | PC01 | Task `cancel` with `claimNumber` and `intimationNumber`; PC02 back. | `D8/D8-cancel.json` | +| D9 | Submit claim | 15 | Under the pre-auth's number, the package alone, discharge scalars, Discharge Consent answered, PDF documents; 25 then 26. | `D9/D9-request.json` | +| D10 | Answer a claim query | 161 | The 27 answered on 161 with a written reply; the sandbox approves at zero. | `D10/D10-query-answer.json` | +| D11 | Reprocess a rejected claim | 36 | Task `reprocess`, reason `claimrejected`, second input spelled `intimationNumber` on every Task (a reprocess under any other spelling is refused PAYR-1008). The SHA answers 37, "Arbitration claim submission process completed successfully", and reopens the case; a generic payer answers 37 too. | `D11/D11-reprocess.json` | +| D12 | Claim a shortfall | 36 | Task `reprocess` with `partialpayment` after a settled payment. Out of reach on the sandbox: its finance side issues the notice on its own schedule, and the combination is refused before notice 33 is acknowledged (`11-PMJAY Sandbox Run.md`, "What the sandbox will not take"). | none | +| D13 | Acknowledge the payment notice | 17 | Notice 30 filed and acknowledged on `on_request` with 17. | `D13/D13-acknowledgement.json` | + +Discharge variants the D9 claim must cover, each proven on the sandbox: normal after surgery; LAMA and DAMA before, during and after surgery; death before, during and after surgery. Before or during surgery, LAMA and DAMA collapse the claim to one `LM100` line; a death carries `ONS`/`DTM`. `nhcx-package/docs/03-Building a Provider/08-PMJAY Provider.md` states the LAMA and DAMA rule. + +## 7. What each payer sends back, in order + +A pre-authorisation on the SHA sandbox: 20 (`queued`, `response.partial`, `ClaimResponse.type` present only here, as in `nhcx-package/fhir/C5/C5-received-wf20-pmjay.json`), then 24 (query) or 21 or 23. A claim: 25, then 27 or 26 or 291. A cancel: PC02 as a Task `completed`, code `approve`, `output[0]` an `include` reference to a ClaimResponse whose adjudication reason is `cancelled` (`C10/C10-cancelled-wfPC02-pmjay.json`). A reprocess: 37 as a Task `accepted` with a `queued` ClaimResponse (`C10/C10-arbitration-wf37-pmjay.json`), then 26 or 291 on the claim's thread. A payment: 30 on a new thread with a Task `deliver`, a `PaymentNotice` and a `PaymentReconciliation` (`C9/payment-notice.json`). + +A generic payer sends the same ids with the generic differences: 22 for an enhancement, `preAuthRef` on every acknowledgement and every pre-auth decision, queries as CommunicationRequests, `response.complete` on 37. Its files are the ones without `-pmjay` under `nhcx-package/fhir/C5`, `C6`, `C7`, `C9` and `C10`. diff --git a/plugins/nhcx/skills/nhcx-communication/references/material.md b/plugins/nhcx/skills/nhcx-communication/references/material.md new file mode 100644 index 000000000..d8882931d --- /dev/null +++ b/plugins/nhcx/skills/nhcx-communication/references/material.md @@ -0,0 +1,120 @@ +# Material: where the pins, fixtures and docs live + +The stage and module files cite pins, payer fixtures and chapters. All of them come from one source, the NHCX package. This file says how to get it, what it holds, and which package file each citation means. + +## The package + +| Source | Has | Get it | +| --- | --- | --- | +| The NHCX package (`nhcx-package/`) | The docs, every API as a request, the FHIR bundles (the fifteen hospital pins, the payer answers, the live PMJAY captures with identifiers replaced), the field mappings per use case, `workflow.yaml`, `usecases.yaml`, `nhcx-error.yaml`, `baseurl.yaml`, a `MANIFEST` with a sha256 per file | `scripts/fetch-package.sh`, or by hand (below) | +| nhcx-adapter (optional: only when the user asks for it) | The binary, `config.sample.json`, `serve.sh`, `README.md` | The latest release of https://github.com/nha-in/nhcx-adapter, downloaded only when the user chose it (`references/transport-knowledge.md` section 5). Its contract is in `references/api-knowledge.md`. | + +By default `scripts/fetch-package.sh` takes the build attached to the latest GitHub release of `nha-in/nhcx-package`. It checks the download against the sha256 the release records. To use a different build, pass a link or a local path: `scripts/fetch-package.sh `. + +By hand: download the `nhcx-package-v.zip` asset from https://github.com/nha-in/nhcx-package/releases/latest. Unzip it beside `nhcx-build/`. It unpacks to `nhcx-package/`. + +Where the web is off, copy the package in. Do not try to fetch it. + +After unpacking, check it. `nhcx-package/MANIFEST` names the version and lists every file with its size and sha256. Verify at least the pins you will be held to. + +What the package holds: + +| Path | What it is | +| --- | --- | +| `nhcx-package/fhir/B1` to `B9` | Hospital bundles. Lower-case files (`preauth-request.json`) are the pins, written to the specification with placeholders. Capitalised files (`B3-request.json`) are live captures. | +| `nhcx-package/fhir/C3` to `C11` | Payer answers. A generic file and, where one exists, its `-pmjay` twin. | +| `nhcx-package/fhir/D1` to `D13` | Live PMJAY hospital captures, identifiers replaced | +| `nhcx-package/fhir/index.yaml` | The catalogue: for each file its direction, side, scheme (`generic` or `pmjay`), workflow id, focal resource, origin (`wire` or `example`) | +| `nhcx-package/docs/` | The chapters, `01-Overview` to `07-Go Live` | +| `nhcx-package/mappings/.yaml` | Field mappings per bundle; `A1.yaml` is the master dictionary | +| `nhcx-package/apis/` | Every API as a request (a Bruno collection) | +| `nhcx-package/workflow.yaml`, `usecases.yaml`, `nhcx-error.yaml`, `baseurl.yaml` | Workflow ids, use cases, error codes, base URLs | +| `nhcx-package/MANIFEST` | Version, and a size and sha256 per file | + +## The pin map + +Every hospital-side pin, and its file in the package. The fifteen hospital-built pins are the bytes a build is held to (canonical JSON). The last row is a payer's message, the reader's input. + +| Pin | Package | Module | +| --- | --- | --- | +| `coverage/discovery` | `nhcx-package/fhir/B1/discovery.json` | 7.4 | +| `coverage/validation` | `nhcx-package/fhir/B1/validation.json` | 7.4 | +| `coverage/benefits` | `nhcx-package/fhir/B1/benefits.json` | 7.4 | +| `coverage/authrequirements` | `nhcx-package/fhir/B1/auth-requirements.json` | 7.6 | +| `insurance` | `nhcx-package/fhir/B2/insurance-plan-request.json` | 7.5 | +| `preauth/request` | `nhcx-package/fhir/B3/preauth-request.json` | 7.7 | +| `preauth/enhancement` | `nhcx-package/fhir/B3/preauth-enhancement.json` | 7.7 | +| `preauth/queryupdate` | `nhcx-package/fhir/B3/preauth-queryupdate.json` | 7.7 | +| `preauth/cancel` | `nhcx-package/fhir/B3/preauth-cancel.json` | 7.9 | +| `claim/request` | `nhcx-package/fhir/B5/claim-request.json` | 7.7 | +| `claim/queryupdate` | `nhcx-package/fhir/B5/claim-queryupdate.json` | 7.7 | +| `claim/reprocess` | `nhcx-package/fhir/B5/claim-reprocess.json` | 7.9 | +| `claim/release` | `nhcx-package/fhir/B5/claim-release.json` | 7.9 | +| `communication/response` | `nhcx-package/fhir/B4/communication-response.json` | 7.10 | +| `payment/notice-ack` | `nhcx-package/fhir/B7/payment-notice-ack.json` | 7.10 | +| `communication/request` (a payer's message, the reader's input) | `nhcx-package/fhir/B4/communication-request.json`. It is the NRCeS IG's own example, with the Patient's name, identifier, birth date and phone replaced. | 7.10 | + +## The payer fixtures + +What the readers are fed. `generic` is what any payer on the exchange sends, IRDAI-regulated insurers and TPAs included. `pmjay` is the SHA's own message, a live capture with the beneficiary's identifiers replaced. Some identifiers are absent from the PMJAY files: `C5-received-wf20-pmjay.json` carries no `preAuthRef`. Read a value from the file before you assert it. Paths are under `nhcx-package/fhir/`. + +| Answer | Generic | PMJAY | Reader | +| --- | --- | --- | --- | +| Coverage, validation | `C3/validation-response.json` | `C3/coverage-eligibility.json` | 7.4 | +| Coverage, discovery | `C3/discovery-response.json` | none | 7.4 | +| Coverage, benefits | `C3/benefits-response.json` | `C3/C3-benefits-pmjay.json` | 7.4 | +| Coverage, auth-requirements | `C3/C3-response-generic.json` | `C3/C3-response-pmjay.json` (workflow 5) | 7.6 | +| Insurance plan | `C4/C4-response-generic.json` (coverage-based) | `C4/C4-response-pmjay.json` (package-based) | 7.5 | +| Pre-auth received 20 | `C5/C5-received-wf20.json` | `C5/C5-received-wf20-pmjay.json` | 7.8 | +| Pre-auth approved 21 | `C5/C5-approved-wf21.json` | `C5/C5-approved-wf21-pmjay.json` | 7.8 | +| Enhancement approved 22 | `C5/C5-enhancement-approved-wf22.json` | `C5/C5-enhancement-approved-wf22-pmjay.json` | 7.8 | +| Pre-auth rejected 23 | `C5/C5-rejected-wf23.json` | `C5/C5-rejected-wf23-pmjay.json` | 7.8 | +| Pre-auth queried 24 | `C5/preauth-queried.json` | `C5/C5-queried-wf24.json` | 7.8 | +| Claim received 25 | `C7/C7-received-wf25.json` | `C7/C7-received-wf25-pmjay.json` | 7.8 | +| Claim approved 26 | `C7/C7-approved-wf26.json` | `C7/C7-approved-wf26-pmjay.json`, `C7/C7-approved-deduction-wf26-pmjay.json` | 7.8 | +| Claim queried 27 | `C7/claim-queried.json` | `C7/C7-queried-wf27.json` | 7.8 | +| Claim rejected 291 | `C7/C7-rejected-wf291.json` | `C7/C7-rejected-wf291-pmjay.json` | 7.8 | +| Cancellation done PC02 | `C10/C10-cancelled-wfPC02.json` | `C10/C10-cancelled-wfPC02-pmjay.json` | 7.9 | +| Arbitration acknowledged 37 | `C10/C10-arbitration-wf37.json` | `C10/C10-arbitration-wf37-pmjay.json` | 7.9 | +| Query on the communication API, 24 and 27 | `C6/C6-preauth-query-wf24.json`, `C6/C6-claim-query-wf27.json` | none | 7.10 | +| Notification N02 | none | `C6/C6-notification-wfN02.json` | 7.10 | +| The query the reply answers | `B4/communication-request.json` (the IG's example) | none | 7.10 | +| Payment notice 30 | `C9/C9-notice-wf30.json` | `C9/payment-notice.json`, `C9/C9-notice-tds-wf30-pmjay.json` | 7.10 | +| Predetermination | `B9/predetermination-request.json` (the request), `C11/predetermination-response.json` | none | 7.7, 7.8 | + +`nhcx-package/fhir/index.yaml` catalogues every file: direction, side, scheme, workflow id, focal resource, origin (`wire` or `example`). An `example` file is placeholders written to the specification, not a payload. + +## The live hospital captures + +What a hospital actually sent, as the payer accepted it. The module files quote these shapes. Paths are under `nhcx-package/fhir/`. + +| Scheme | Files | +| --- | --- | +| PMJAY | `D1/D1-request.json` (plan), `D3/D3-check.json` (auth-requirements), `D4/D4-request.json` (pre-auth 12), `D6/D6-enhancement.json` (13), `D6/D6-enhancement-query-answer.json` (131), `D7/D7-query-answer.json` (19), `D8/D8-cancel.json` (PC01), `D9/D9-request.json` (claim 15), `D10/D10-query-answer.json` (161), `D11/D11-reprocess.json` (36), `D13/D13-acknowledgement.json` (17) | +| Generic | `B1/B1-check.json`, `B2/B2-request.json`, `B3/B3-request.json`, `B3/B3-enhancement.json`, `B4/B4-preauth-query-answer.json`, `B4/B4-claim-query-answer.json`, `B5/B5-request.json`, `B7/B7-acknowledgement.json`, `B8/B8-cancel.json`, `B8/B8-reprocess.json` | + +## The docs and the data files + +| Cited | Package | +| --- | --- | +| a chapter | `nhcx-package/docs/`, from `01-Overview` to `07-Go Live` | +| workflow ids (`references/flow-knowledge.md` section 2) | `nhcx-package/workflow.yaml`, the maintained source; rendered as `nhcx-package/docs/01-Overview/06-Workflow Codes.md` | +| use cases (`flow-knowledge.md` section 6) | `nhcx-package/usecases.yaml`; rendered as `nhcx-package/docs/01-Overview/05-NHCX Use Cases.md` | +| PAYR and ERR codes (`references/errors-and-debugging.md`) | `nhcx-package/nhcx-error.yaml` | +| field mappings per bundle (stage 4) | `nhcx-package/mappings/.yaml`; `A1.yaml` is the master dictionary | +| base URLs, sandbox and production | `nhcx-package/baseurl.yaml` | +| every API as a request | `nhcx-package/apis/` (a Bruno collection) | +| the bundle catalogue | `nhcx-package/fhir/index.yaml` | + +## What the package does not hold + +| Missing | Without it | +| --- | --- | +| A status-enquiry answer | None captured. The published status call carries no bundle either way (`nhcx-package/docs/05-FHIR Reference/18-Predetermination, Status and Search.md`). | +| A validator wrapper | Run the HL7 FHIR validator directly, as `references/fhir-knowledge.md` section 11 describes | +| Reference application source | The decisions are written into the module files and the references. Build from them. Record in `NOTES.md` where you would have wanted more. | +| End-to-end drivers and checkers | Write the stage 10 driver against your own build's state address | + +## Which is newer + +Where the references and the package disagree, the package is newer for the published facts (workflow ids, error text, base URLs). The references are newer for what was seen live (which ids a payer actually sent, which refusals mean what). Say which you followed in `NOTES.md`. diff --git a/plugins/nhcx/skills/nhcx-communication/references/testing-knowledge.md b/plugins/nhcx/skills/nhcx-communication/references/testing-knowledge.md new file mode 100644 index 000000000..4a24d7946 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-communication/references/testing-knowledge.md @@ -0,0 +1,405 @@ +# Testing knowledge + +Sources: the NHCX package, fetched by `scripts/fetch-package.sh` into `nhcx-package/` beside `nhcx-build/`. That means the pins and payer fixtures under `nhcx-package/fhir` (catalogued in `nhcx-package/fhir/index.yaml`), the use-case catalogue `nhcx-package/usecases.yaml`, and the chapters named below. Also what live runs on the NHCX sandbox taught. + +## 1. The pyramid + +| Rung | What it proves | Needs | How | +| --- | --- | --- | --- | +| 1. Offline | Every builder equals its pin (`created` excepted); every reader settles the right state from a payer fixture; the state machine refuses what it should | nothing running; a throwaway database; the transport's send stubbed; `nhcx-package/` | one suite in one process (sections 2 to 4) | +| 2. Validator | Every built bundle validates against the NRCeS profiles with no error you cannot explain | Java, the HL7 FHIR validator, the bundles your tests wrote | section 5 | +| 3. A generic payer on the sandbox | Every leg over the real exchange with a payer whose desk you can drive; queries as CommunicationRequests; payment released | the transport on the sandbox (your app's own, or nhcx-adapter when the user chose it), a generic payer you can drive, the sandbox reaching your callback | section 6 | +| 4. Live PMJAY sandbox | `1518@hcx`: the scheme's own refusals and rules, decisions taken on the payer service desk | the sandbox, a real beneficiary, patience | section 6 | + +Climb in order. Rungs 1 and 2 need no service and no consent. Rungs 3 and 4 put traffic on the live NHCX sandbox, and only the user starts them. + +## 2. Writing rung 1 for a new HMIS + +Build one suite with this shape, whatever the language: + +- One process, one seeded database under a temporary path, sections in the order the episode runs. `section(name)` starts a group; `check(label, condition, detail)` records one assertion and never raises. The run exits non-zero at the end if anything failed. +- The transport's `send` is one function, and the test replaces it. Every send goes through it; the test assigns a stub that records the path, recipient, workflow id, correlation id and bundle, and returns `{"txn_id": ..., "correlation_id": ..., "api_call_id": ...}`. Restore the real one in `finally`. The receiving end is tested apart from the door: for your own transport, seal a payer bundle with a test key pair, POST it, and check the 202 receipt and the envelope the door receives. +- Call the callback handler directly with an envelope, not over HTTP: `receive({"jwe_headers": {...}, "fhir": bundle}, "", "", "fhir")`. The return value is one of `settled`, `unmatched`, `ignored`. Feed it the payer bundles under `nhcx-package/fhir/C3` to `nhcx-package/fhir/C11`, both the generic files and the `-pmjay` ones. The auth-requirements rulings are `C3/C3-response-generic.json` (one line, 10 supporting entries) and `C3/C3-response-pmjay.json` (two lines, 22 entries). +- The pin comparison builds each bundle from the pin's own data and compares canonical JSON (`json.dumps(bundle, sort_keys=True)`) against the pin. The data is all in `nhcx-package/fhir/B3/preauth-request.json`: member `MD5SLS4X5`, policy `PMJAY/HP/S/G`, provider `IN1910000151`, payer `1518@hcx`, package `MG0111A` with tier `STRAT006b`, the four `MAND` documents. Drop from both sides only `created`. The bundle id and every entry's `fullUrl` are fixed strings in the pins (`preauth-request-generic`, `https://nhcx.abdm.gov.in/preauth/request`), and the build produces them as they are. +- The single-item pins carry `factor 0.5`. That contradicts the rule their own enhancement follows (`nhcx-package/fhir/B3/preauth-enhancement.json`: the costlier line 1, the next 0.5), so compare those with `factor` removed. Compare the cancel and reprocess pins as they are; they carry `intimationNumber`, the spelling the build sends. +- Read every expected value in a reader check from the fixture you feed: `preAuthRef`, amounts, claim numbers, the UTR. The PMJAY captures have the beneficiary's identifiers replaced, and some fields are absent (`C5/C5-received-wf20-pmjay.json` carries no `preAuthRef`). A typed literal tests your memory, not the reader. +- Negative checks are half the value. A code the plan does not carry is refused. A send while the leg is with the payer is refused. A redelivered api call id is ignored. A claim refused at the door goes back to `queried` with the question restored. A cancel while the payer holds the case is accepted, and a cancel of a rejected one is refused. +- Put the regression sections near the bottom. Each is a defect that reached working code, named after what went wrong. Add one each time the sandbox teaches you something. + +In a language whose JSON encoder does not sort keys, decode into a map and encode again before comparing, so key order cannot fail a check. Where a byte comparison is too strict, as with the wire captures, compare element by element. + +## 3. The test-case matrix + +One row per hospital-side use case. Preconditions are the state the HMIS must be in. The action is what the desk or the test does. The expected wire is what must go out and come back; the per-case archive shows it (and the adapter's ledger, when it is the transport). The expected state is what the HMIS must hold afterwards. Codes are those of `nhcx-package/usecases.yaml`. Workflow ids are the PMJAY table unless the row says generic. + +| Use case | Preconditions | Action | Expected wire | Expected state | +| --- | --- | --- | --- | --- | +| A5 Get status (generic) | A pre-auth or claim leg with the payer; a generic payer | Ask status for the leg | `v1/task/submit`, Task `status` with `claimNumber`, workflow = the leg's correlation id; a Task back with `claimStatus` | An enquiry row `answered` with the status word; the leg unchanged | +| A5 Get status (PMJAY) | as above; PMJAY | Ask status | the same Task; a ProtocolResponse PAYR-1018 (no reason) or PAYR-1008 (with one) | The enquiry row `error` with the payer's words; nothing else changes | +| B1 Check coverage eligibility | A patient with a member id and policy from the policy search; facility HFR id and participant code set | Validate, then discover | `v1/coverageeligibility/check` twice, new correlation each, workflow = the case number; `on_check` with the request echoed and a `CoverageEligibilityResponse` | `claim.status eligible`, `inforce 1`, allowed and used amounts, the payer's Patient demographics | +| B2 Request insurance plan | Eligible; no master held for this facility and policy | Fetch the plan | `v1/insuranceplan/request`, a Task `poll` with `policyNumber` and `providerId`; `on_request` with the InsurancePlan and Questionnaires | `claim_plan.status ready`, benefits with rates, tiers, requirements, forms by url; a second episode on the same policy copies it without a send | +| B3 Submit pre-authorisation | Plan ready; lines quoted from it; dossier saved; admission linked; documents and forms for the pre-auth stage attached | Submit | `v1/coverageeligibility/check` purpose `auth-requirements` first (sent, not awaited), then `v1/preauth/submit` workflow 12 equal to the pin but for identifiers; `on_submit` 20 (`queued`, `response.partial`) then 21 | `claim_preauth.status submitting` after the 20 with `preauth_ref` kept, `approved` after the 21 with `approved_amount`; stage `preauth`, sub-stage `approved` | +| B3 Auth-requirements ruling | The check sent with the pre-auth; the payer answers it | Nothing; read on arrival | inbound `on_check`, a CoverageEligibilityResponse with purpose `auth-requirements`, one `insurance[0].item` per quoted line with `authorizationRequired`, `excluded` and `authorizationSupporting[]` (`C3/C3-response-generic.json`, `C3/C3-response-pmjay.json`) | each quoted line holds its ruling and what is due at pre-auth (a form always, a document only when its `Type` is `pre`); the pre-auth leg unchanged | +| B3 Enhancement | Approved; a line added since (`enhancement_lines` non-empty) | Submit again | `v1/preauth/submit` workflow 13, every line old and new, factors 1 and 0.5; 20 then 22 (generic); the SHA has answered 21 or 22 | `submission_kind enhancement`, `enhancement_no 1`, `preauth_ref` kept, then `approved`; stage `enhancement` | +| B4 Respond to a communication (generic) | A pre-auth or claim with the payer; the payer sends a CommunicationRequest on a new thread | The desk replies with text and a document | inbound `v1/communication/request` with Task `poll`, reason `additionalinfo`; outbound `v1/communication/on_request` with the request's correlation id and workflow id, a TaskBundle: Task `deliver`, Communication `basedOn` the request, the request echoed, the case entries | `claim_query` row `kind query`, `status open` then `answered` with `reply_json`; the leg row untouched; sub-stage `queried` while open | +| B4 Notification | Any leg; the payer sends a CommunicationRequest with intent `proposal` or reason `tatquery` | Nothing; it is acknowledged on arrival | outbound `v1/communication/on_request` at once, the payer's bundle with `Task.status completed`, provider Organization first | `claim_query` row `kind notification`, `status acknowledged`; the case's stage unchanged | +| B5 Submit claim | Approved pre-auth; discharge recorded with mode and stage; claim-stage documents and forms attached | Submit the claim | `v1/claim/submit` workflow 15, `use claim`, `preAuthRef`, the discharge scalars, the summary; 25 (`queued`) then 26 | `claim_submission.status submitting` then `approved` with amounts and item verdicts; stage `claim` | +| B7 Acknowledge payment notice (generic) | An approved claim; the payer's desk releases payment | Nothing; acknowledged on arrival | inbound `v1/paymentnotice/request` workflow 30 on a new thread; outbound `v1/paymentnotice/on_request` with the notice's correlation id and its own workflow id echoed, Task `status completed` with `paymentack` | `claim_payment` row with amount, UTR, `ack_status sent`; stage `payment`, sub-stage `paid`; a redelivery of the notice is `ignored` | +| B8 Cancel | A pre-auth `submitting`, `approved`, `partial` or `queried` | Cancel with a reason | `v1/task/submit` workflow PC01, Task `cancel`, inputs `claimNumber` and `intimationNumber`; `task/on_submit` PC02 with a ClaimResponse adjudicated `cancelled` | `claim_preauth.status cancelling` then `cancelled`; the episode gets a fresh claim number, the old one stays on `claim_ref`; a cancel of a `rejected` pre-auth is refused before sending | +| B8 Reprocess (generic) | A claim `rejected` or `partial` | Reprocess with reason `claimrejected` and a document | `v1/task/submit` workflow 36, Task `reprocess`, `intimationNumber`, `basedOn` CLN, `document` inputs, `for` the member; 37 (Task `accepted`, ClaimResponse `queued`); then 26 on the claim's thread | The enquiry row `answered` with `reopened`; `claim_submission` back to `submitting`, then `approved` | +| B9 Submit predetermination | Eligible; dossier saved | Ask for a quote | `v1/preauth/submit` workflow 12 with `use predetermination`; a ClaimResponse back | A `claim_predetermination` row `answered` with `allowed_amount`; the pre-auth row untouched | +| D1 Fetch the insurance plan | Eligible on PMJAY | Fetch | as B2; the answer on workflow 5, both `specificCost[]` and `coverage[]`, nested document requirements, `/questionnaire/` and `/stgquestionnaire/` forms | as B2, with `ProcedureType` conditions and the consent forms among the policy documents | +| D2 Authenticate the beneficiary | A policy from the BIS | Not NHCX; take the consent questionnaire path | none | The consent form answered for the pre-auth stage | +| D3 Check coverage eligibility | as B1 with member `MD5SLS4X5` style ids | Validate | as B1; the answer on workflow 5 with the wallet | as B1 | +| D4 Submit pre-authorisation | as B3, plus: HPIN on the doctor, `Item/n` ids, consent and STG forms answered, documents under the plan's `MAND` codes | Submit | `v1/preauth/submit` workflow 12; 20 with the path-form `preAuthRef` or none (flow-knowledge.md section 3), then 21 with the bare number | as B3; `preauth_ref` = the bare case number after the 21 | +| D5 Resubmit pre-authorisation | A pre-auth `rejected` | Submit again | a fresh 12, never 121 | a new `submitting` round; 121 would be PAYR-1214 | +| D6 Raise an enhancement | Approved; a medical package added (not conservative) | Submit | workflow 13; 20 without `preAuthRef` (keep the parent's); 241 arrives as a ClaimResponse `partial` on the case thread; the desk answers on 131 with a `CQD` reply; then approved | `enhancement_no 1`; `queried` then `answered` then `approved`; a second conservative package would be PAYR-1245 | +| D7 Answer a pre-authorisation query | The 24 arrived as a ClaimResponse `partial`, item status `Queried` | The desk writes a reply and submits again | `v1/preauth/submit` workflow 19, flow `queryupdate`, `NMI`/`CQD` carrying the words, a new correlation id; 20 then 21 | `submission_kind preauth_query_response`, `query_note` holding the payer's question, then `approved`; an empty reply is refused before sending | +| D8 Cancel pre-authorisation | as B8 on PMJAY | Cancel | as B8 | as B8 | +| D9 Submit claim | as B5, plus: the claim under the pre-auth's claim number, the package alone at the whole amount, Discharge Consent answered, PDF documents | Submit | `v1/claim/submit` workflow 15; 25 with `preAuthRef` as a path; then 26 | as B5; item verdicts with `eligible`, `status Approved` | +| D9 LAMA or DAMA before or during surgery | Discharge mode `lama` or `dama`, stage `Before Surgery` or `During Surgery` | Submit the claim | one item `LM100`, no tier, `DIS` = `LAMA` or `DAMA` with the stage | approved; the package would be PAYR-1362 | +| D9 Death | Discharge mode `death` with a date and time | Submit the claim | `ONS`/`DTM` and `DSDE` with the death instant, `DIS`/`DTM`, the death forms | approved; without `DTM` PAYR-1096 | +| D10 Answer a claim query | The 27 arrived as a ClaimResponse `partial` | The desk writes a reply and submits again | `v1/claim/submit` workflow 161, `NMI`/`CQD`, a new correlation id; 25 then 26 | `submission_kind claim_query_response`, then `approved`, possibly at zero | +| D11 Reprocess a rejected claim | A claim `rejected` | Reprocess | as B8 reprocess; on the sandbox a ProtocolResponse PAYR-1008 | the enquiry row `error` with the refusal; on a generic payer as B8 | +| D12 Claim a shortfall | A settled payment short of the approved amount | Release with `partialpayment` and the amount | `v1/task/submit` workflow 36, Task `release`, `valueMoney` | an enquiry row; out of reach on the sandbox | +| D13 Acknowledge the payment notice | An approved claim; the SHA's finance side sends 30 | Nothing; acknowledged on arrival | outbound `v1/paymentnotice/on_request` with workflow 17, the notice's correlation id, to the notice's sender | as B7 | + +Cross-cutting rows every matrix needs: + +| Case | Action | Expected | +| --- | --- | --- | +| Redelivery | Deliver the same envelope twice | the second returns `ignored`; state unchanged | +| Unmatched | Deliver an answer on an unknown correlation id | `unmatched`; archived under `unmatched`; nothing changes | +| Refusal at the door | Deliver a ProtocolResponse on a leg's thread | the leg `error` (or `queried` restored for a query answer, `approved` restored for an enhancement) with the payer's words; `correlation_id` restored to `thread_correlation_id` | +| Ledger reset (nhcx-adapter only) | The adapter answers 404 on `txn/related` | the leg `error` with "send again"; no spinning | +| Stage after every write | Any of the above | `stage` and `sub_stage` on the episode agree with `case_stage` recomputed from the legs | + +## 4. A skeleton offline test + +Replace the placeholders marked `` with your HMIS's own. Every pin and payer answer is loaded from the package. + +```python +#!/usr/bin/env python3 +"""Offline NHCX checks for : builders against the package pins, readers against the payer fixtures. + + NHCX_PACKAGE=nhcx-package python3 nhcx_offline_test.py # exit 0 when every check passes +""" +from __future__ import annotations + +import copy +import json +import os +import tempfile + +PKG = os.environ.get("NHCX_PACKAGE", "nhcx-package") +GENERIC_PAYER = "" + +os.environ[""] = os.path.join(tempfile.mkdtemp(prefix="nhcx-test-"), "t.db") + +import as nhcx # noqa: E402 the module that owns transport, build_*, receive + +failures = 0 +current = "general" +tally: dict[str, list[int]] = {} + + +def section(name: str) -> None: + global current + current = name + tally.setdefault(name, [0, 0]) + print(f"\n-- {name} " + "-" * max(3, 60 - len(name))) + + +def check(label: str, condition: bool, detail: str = "") -> None: + global failures + tally.setdefault(current, [0, 0]) + tally[current][0 if condition else 1] += 1 + if not condition: + failures += 1 + print(f"[{' ok ' if condition else ' FAIL '}] {label}" + (f" ({detail})" if detail else "")) + + +def pin(rel: str) -> dict: + """A bundle from the package by its path under fhir/, e.g. pin("B3/preauth-request.json").""" + with open(os.path.join(PKG, "fhir", rel), encoding="utf-8") as fh: + return json.load(fh) + + +def resource(bundle: dict, kind: str) -> dict: + return next(e["resource"] for e in bundle["entry"] if e["resource"]["resourceType"] == kind) + + +def task_input(task: dict, code: str): + return next(i.get("valueString") for i in task.get("input", []) if i["type"]["coding"][0]["code"] == code) + + +def total(claim_response: dict, category: str): + return next((t["amount"].get("value") for t in claim_response.get("total", []) + if t["category"]["coding"][0]["code"] == category), None) + + +def normalised(bundle: dict, factor: bool = True) -> dict: + """Drop only `created`, which a builder stamps when it sends; with factor=False, the Claim items' factor too.""" + out = copy.deepcopy(bundle) + + def walk(node): + if isinstance(node, dict): + node.pop("created", None) + for value in node.values(): + walk(value) + elif isinstance(node, list): + for value in node: + walk(value) + + walk(out) + if not factor: + for entry in out["entry"]: + if entry["resource"]["resourceType"] == "Claim": + for item in entry["resource"].get("item", []): + item.pop("factor", None) + return out + + +def canonical(bundle: dict, factor: bool = True) -> str: + return json.dumps(normalised(bundle, factor), sort_keys=True, ensure_ascii=False) + + +def same(label: str, ours: dict, want: dict, factor: bool = True) -> None: + a, b = canonical(ours, factor), canonical(want, factor) + check(label, a == b, "" if a == b else a[:300]) + + +# The package pins' own data: nhcx-package/fhir/B3/preauth-request.json and B1/*.json. +# Every builder is fed this and must produce the pin. +REF = { + "claim_no": "VB26AA2600001", "member_id": "MD5SLS4X5", "policy": "PMJAY/HP/S/G", + "provider": {"id": "IN1910000151", "name": "Facility Name"}, + "payer": {"code": "1518@hcx", "id": "1518", "name": "Insurance Company"}, + "patient": {"name": "Patient Name", "gender": "male", "dob": "2004-09-18", + "phone": "9999999999", "abha": "91718280654077", "member_id": "MD5SLS4X5"}, + "practitioner": {"name": "Practitioner Name", "hpr_id": "982374978-2343", "license_no": "MCI-12345", + "qualification": "Doctor of Medicine", "qualification_code": "MD", + "specialty": "General medicine", "specialty_code": "394802001"}, + "diagnosis": {"code": "A97", "display": "Dengue"}, + "item": {"code": "MG0111A", "display": "Pleural Effusion", "category_code": "MG", + "category_display": "General Medicine", "quantity": 1, "unit_price": 3300, "net": 3300, + "kind": "Procedure", "procedure_type": "conservative"}, + "tier": {"code": "STRAT006b", "display": "HDU", "kind": "Stratification", "parent_code": "MG0111A"}, + # The benefits and auth-requirements pins quote a different package. + "coverage_item": {"code": "MG004C", "display": "Dengue shock syndrome (Dengue fever)", + "category_code": "MG", "category_display": "General Medicine", "quantity": 1, + "tier": {"code": "STRAT006c", "display": "ICU - Without Ventilator"}}, +} + + +def main() -> int: + section("coverage eligibility: ours is the pin") + for purpose, rel in (("discovery", "B1/discovery.json"), ("validation", "B1/validation.json"), + ("benefits", "B1/benefits.json"), ("auth-requirements", "B1/auth-requirements.json")): + want = pin(rel) + ours = nhcx.build_coverage_request((purpose, want)) + same(f"coverage {purpose}", ours, want) + + section("insurance plan request: ours is the pin") + same("plan request", nhcx.build_plan_request(REF["policy"], REF["provider"]["id"]), + pin("B2/insurance-plan-request.json")) + + section("claim bundles: ours is the pin") + ref_pa = pin("B3/preauth-request.json") + ref_pdf = next(si["valueAttachment"]["data"] for si in resource(ref_pa, "Claim")["supportingInfo"] + if "valueAttachment" in si) + dossier = (REF, ref_pdf, ref_pa) + same("preauth request", nhcx.build_preauth_bundle(dossier, flow="request"), ref_pa, factor=False) + ref_qu = pin("B3/preauth-queryupdate.json") + reply = next(si["valueString"] for si in resource(ref_qu, "Claim")["supportingInfo"] + if si["category"]["coding"][0]["code"] == "NMI") + same("preauth query update", + nhcx.build_preauth_bundle(dossier, flow="queryupdate", query_response=reply), + ref_qu, factor=False) + ref_cancel = pin("B3/preauth-cancel.json") + cancel = resource(ref_cancel, "Task") + reason = cancel["reasonCode"]["coding"][0] + same("preauth cancel", + nhcx.build_cancel_task(task_input(cancel, "claimNumber"), (reason["code"], reason["display"]), + cancel["authoredOn"], REF["provider"], REF["payer"]), + ref_cancel) + ref_ack = pin("B7/payment-notice-ack.json") + ack = resource(ref_ack, "Task") + acked_claim = next(o["valueString"] for o in ack["output"] if "valueString" in o) + same("payment acknowledgement", + nhcx.build_payment_ack(acked_claim, ack["authoredOn"], REF["provider"], REF["payer"]), + ref_ack) + + section("the transport is the one door, and it can be stubbed") + posted: list[dict] = [] + real_send = nhcx.transport.send + + def submitted(payer: str, corr: str): + def _send(path, bundle, recipient, workflow_id, correlation_id=None, **kw): + posted.append({"path": path, "recipient": recipient, "workflow_id": workflow_id, + "correlation_id": correlation_id, "bundle": bundle}) + return {"txn_id": "01TEST", "correlation_id": corr, "api_call_id": "acid-" + corr} + + seeded = (payer) # eligible, plan ready, lines quoted, dossier saved + nhcx.transport.send = _send + try: + nhcx.submit_preauth(seeded) + finally: + nhcx.transport.send = real_send + return seeded + + episode = submitted(REF["payer"]["code"], "corr-preauth-1") + sent = posted[-1] + leg = nhcx.preauth(episode) + check("the pre-auth goes out on the preauth route under workflow 12", + sent["path"] == "v1/preauth/submit" and str(sent["workflow_id"]) == "12") + check("no correlation id is passed on a request", sent["correlation_id"] is None) + check("the leg waits with the transport's ids", + leg["status"] == "submitting" and leg["txn_id"] == "01TEST" and leg["correlation_id"] == "corr-preauth-1") + + section("readers: the payer answers settle the right state") + + def deliver(bundle: dict, acid: str, workflow: str, status: str = "response.complete", + corr: str = "corr-preauth-1", sender: str = "1518@hcx") -> str: + return nhcx.receive({"jwe_headers": {"x-hcx-correlation_id": corr, + "x-hcx-api_call_id": acid, + "x-hcx-sender_code": sender, + "x-hcx-status": status, "x-hcx-workflow_id": workflow}, + "fhir": bundle}, "preauth", "request", "fhir") + + received = pin("C5/C5-received-wf20-pmjay.json") + before = nhcx.preauth(episode)["preauth_ref"] + check("the PMJAY acknowledgement leaves the leg waiting", + deliver(received, "acid-20", "20", "response.partial") == "settled" + and nhcx.preauth(episode)["status"] == "submitting") + check("an acknowledgement without preAuthRef overwrites nothing", + not resource(received, "ClaimResponse").get("preAuthRef") + and nhcx.preauth(episode)["preauth_ref"] == before) + check("the same api call id delivered again is ignored", + deliver(received, "acid-20", "20", "response.partial") == "ignored") + approval = pin("C5/C5-approved-wf21-pmjay.json") + approved = resource(approval, "ClaimResponse") + check("the approval settles the leg on the same thread with the payer's case number", + deliver(approval, "acid-21", "21") == "settled" + and nhcx.preauth(episode)["status"] == "approved" + and nhcx.preauth(episode)["approved_amount"] == total(approved, "benefit") + and nhcx.preauth(episode)["preauth_ref"] == approved["preAuthRef"]) + stage, sub_stage = nhcx.case_stage(episode) + check("the episode is stamped preauth / approved", (stage, sub_stage) == ("preauth", "approved")) + + other = submitted(GENERIC_PAYER, "corr-preauth-2") + generic = pin("C5/C5-received-wf20.json") + check("a generic payer's acknowledgement carries the case number, and it is kept", + deliver(generic, "acid-20g", "20", "response.partial", corr="corr-preauth-2", + sender=GENERIC_PAYER) == "settled" + and nhcx.preauth(other)["status"] == "submitting" + and nhcx.preauth(other)["preauth_ref"] == resource(generic, "ClaimResponse")["preAuthRef"]) + + section("auth requirements: the payer's ruling is read line by line") + for rel in ("C3/C3-response-generic.json", "C3/C3-response-pmjay.json"): + ruling = pin(rel) + answer = [e["resource"] for e in ruling["entry"] + if e["resource"]["resourceType"] == "CoverageEligibilityResponse"][-1] + want = {i["productOrService"]["coding"][0]["code"]: i.get("authorizationRequired") + for i in answer["insurance"][0]["item"]} + got = nhcx.parse_auth_bundle(ruling) # {procedure code: {"required": bool, "supporting": [...]}} + check(f"{rel}: one ruling per quoted line, required as the payer says", + {code: line["required"] for code, line in got.items()} == want) + + section("the query loop") + queried = pin("C5/C5-queried-wf24.json") + check("a PMJAY query is the leg queried, with the payer's words and case number kept", + deliver(queried, "acid-24", "24") == "settled" + and nhcx.preauth(episode)["status"] == "queried" + and bool(nhcx.preauth(episode)["query_note"]) + and nhcx.preauth(episode)["preauth_ref"] == resource(queried, "ClaimResponse")["preAuthRef"]) + try: + nhcx.submit_preauth(episode, reply="") + check("an empty reply is refused before sending", False) + except ValueError: + check("an empty reply is refused before sending", True) + check("a generic payer's CommunicationRequest is classified a query", + nhcx.classify_communication(nhcx.GENERIC_ADAPTER, "additionalinfo", "order") == "query" + and nhcx.classify_communication(nhcx.PMJAY_ADAPTER, "additionalinfo", "order") == "notification" + and nhcx.classify_communication(nhcx.GENERIC_ADAPTER, "tatquery", None) == "notification") + + section("refusal at the door") + refusal = {"type": "ProtocolResponse", "x-hcx-status": "response.error", + "x-hcx-correlation_id": "corr-preauth-1", + "x-hcx-error_details": {"code": "PAYR-1238", "message": "Beneficiary is having an active preauthorization request"}} + (episode) + check("a ProtocolResponse settles the leg as refused with the payer's words", + nhcx.receive({"jwe_headers": {"x-hcx-correlation_id": "corr-preauth-1"}, "fhir": refusal}, + "preauth", "request", "protocol") == "settled" + and nhcx.preauth(episode)["status"] == "error" + and "PAYR-1238" in (nhcx.preauth(episode)["error_message"] or "")) + + section("tasks and payment") + cancelled = pin("C10/C10-cancelled-wfPC02-pmjay.json") + verdict = resource(cancelled, "ClaimResponse")["adjudication"][0]["reason"]["coding"][0]["code"] + check("PC02 is read as an accepted cancellation", + nhcx.parse_task_response(cancelled)["adjudication"] == verdict == "cancelled") + arbitration = pin("C10/C10-arbitration-wf37-pmjay.json") + check("37 is read as the reprocess taken", + nhcx.parse_task_response(arbitration)["task_status"] == resource(arbitration, "Task")["status"]) + paid = pin("C9/payment-notice.json") + pn, pr = resource(paid, "PaymentNotice"), resource(paid, "PaymentReconciliation") + notice = nhcx.parse_payment_notice(paid) + check("the payment notice names the claim, the amount and the UTR", + notice["claim_ref"] == pn["identifier"][0]["value"] + and notice["amount"] == pn["amount"]["value"] + and notice["utr"] == pr["paymentIdentifier"]["value"]) + + print("\n" + "=" * 64) + total_checks = sum(ok + bad for ok, bad in tally.values()) + for name, (ok, bad) in tally.items(): + print(f" {name:44s} {ok:3d} passed {bad:2d} failed [{'FAIL' if bad else 'ok'}]") + print("=" * 64) + if failures: + print(f"{failures} of {total_checks} check(s) FAILED") + return 1 + print(f"all {total_checks} checks passed") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) +``` + +What each placeholder must do: + +- `` names the variable your HMIS reads its database path from, so the suite runs on a throwaway file. +- `` is the module that owns `transport`, the builders and `receive`. +- `` is the participant code of a generic payer (``) that your configuration maps to `query_mode: communication`. +- `` returns the dict your coverage builder takes, filled from `REF`. The discovery pin carries policy `NONE`. The benefits and auth-requirements pins quote `REF["coverage_item"]`. Copy the Location and PractitionerRole from the pin it is given. +- `` returns whatever your claim builder takes. That is the claim number, the item, the tier, the program `AB-PMJAY` and factors `(1, 0.5, 0.25)`. Add the four `MAND` documents (`MAND0408`, `MAND0455`, `MAND0409`, `MAND0570`, each with the pin's PDF), and copy the stay and procedure dates from the pin it is given. +- `` takes a payer code and inserts an eligible episode for that payer, with the plan and lines seeded straight into the database. +- `` puts the pre-auth row back to `submitting` on `corr-preauth-1`. + +Run the suite from the folder that holds `nhcx-package/`, or set `NHCX_PACKAGE` to its path. + +## 5. Running rung 2 + +Have your tests and live runs write every bundle they build into one archive folder. The package ships no validator. Run the HL7 FHIR validator with the NRCeS IG `ndhm.in` on the whole folder in one call, with the command and flags in `references/fhir-knowledge.md` section 11. + +Read the results in three piles. "A code the profile does not define" is the scheme's vocabulary, and it is expected. "A required element is missing" and "an id or value the base rules refuse" are yours to fix. Warnings are advice; the sandbox accepted every pin as it stands. Skip the package master; it exhausts the validator's memory. A live PAYR-1004 or PAYR-1008 is the first reason to run this rung again (`nhcx-package/docs/06-Reference/02-Troubleshooting.md`). + +## 6. Running rungs 3 and 4 + +Only the user runs these. Prepare what they start and the driver, then stop and ask. + +What the user starts: + +1. The transport. Your own or the app's existing one needs a participant record carrying its certificate and a public HTTPS `endpoint_url` the exchange can reach (`references/transport-knowledge.md` section 3). nhcx-adapter, only when the user chose it, comes from its release: `config.sample.json` filled in, started with `serve.sh`. +2. Your HMIS, reachable by the exchange through that transport. +3. For rung 3, a generic payer on the sandbox whose desk you can drive (``), mapped to `query_mode: communication`. For rung 4, nothing more: the PMJAY payer is `1518@hcx`, and its decisions are taken on the payer service desk. + +The driver is a script or a browser spec. It walks the matrix rows through the app's JSON state address or its own screens, one episode per test, in series, with a 20 minute timeout per episode. + +- Before a PMJAY run, sweep every live pre-auth for the beneficiaries the tests use. Cancel it on PC01, or have the desk reject it. Otherwise the first pre-auth is refused with PAYR-1238. +- One request at a time per case. Wait about 30 seconds after a decision before the next leg. On "Active instance found" (PAYR-1322), wait and resend, up to three times. +- Wait on the case's own state, never on a fixed sleep or a checklist. +- Log every verdict the sandbox gives, with its workflow id and words, so a refusal is a finding, not a mystery. +- Expect about four minutes for the rung 3 matrix and about ten minutes per episode on PMJAY. + +After the run, package its bundles by correlation id from the per-case archive: every message sent and received, filed under its case. With nhcx-adapter as the transport, `nhcx-adapter ledger thread ` gives the same conversation, with bodies only while `ledger.storeBodies` is true (`nhcx-package/docs/02-Getting Started/10-NHCX Adapter.md`). File each thread under its use case. diff --git a/plugins/nhcx/skills/nhcx-communication/references/transport-knowledge.md b/plugins/nhcx/skills/nhcx-communication/references/transport-knowledge.md new file mode 100644 index 000000000..a0838b9cd --- /dev/null +++ b/plugins/nhcx/skills/nhcx-communication/references/transport-knowledge.md @@ -0,0 +1,283 @@ +# Transport knowledge: how the build reaches NHCX + +Every NHCX message is a FHIR bundle sealed in a JWE, sent with an ABDM session token, and answered later on the sender's own callback. Something has to do that work. This file says which of three things does it for a build, what the rest of the build expects from it, and how to build it yourself. + +Section 3 is drawn from NHA's published chapters: `nhcx-package/docs/02-Getting Started` (01 to 09, and 11), `nhcx-package/docs/01-Overview/04-JWE, Status and Errors.md` and `nhcx-package/docs/06-Reference/03-Envelope Fields.md`. Open them when a detail matters. Where they and this summary differ, they win. + +## 1. Three transports + +| Transport | Choose it when | The build | +| --- | --- | --- | +| `existing` | Stage 0 found the app already speaks NHCX: its own client that seals and posts JWEs, a vendor gateway or middleware, an HCX SDK, callbacks under `/v1/...` | Keeps it. Wraps it behind the contract in section 2 and closes the gaps section 4 lists. Never replaces a working one. | +| `own` | The app has no NHCX integration, and the user has not asked for nhcx-adapter. This is the default. | Builds the protocol into the app (section 3): the session token, the key and certificate, the participant record, the recipient's certificate, sealing and sending, the callback and its receipt. | +| `adapter` | Only when the user asks for nhcx-adapter, by name or by asking for "the adapter" | Downloads it (section 5) and talks plain FHIR to it. `references/api-knowledge.md` is its contract. | + +The rules: + +- Never propose nhcx-adapter, and never choose it because it is easier. Use it only when the user has asked for it, and write their words into `nhcx-build/1-idea.md`. +- An app with an NHCX integration of its own keeps it, even when it is partial. Extend it; never put a second transport beside it. +- The choice is made once per app, at stage 1, from stage 0's verdict on `foundation.transport`. Every skill after the first reads it from `1-idea.md`. + +## 2. The contract every transport meets + +The rest of the build (modules 7.2 to 7.13) never sees the transport, only these functions: + +| Function | Takes | Gives | Notes | +| --- | --- | --- | --- | +| `send(path, bundle, recipient, workflow_id, correlation_id = null, ben_abha_id = null, claim_no, usecase)` | The NHCX path (`v1/preauth/submit`), the bundle, the recipient's participant code, the workflow id; a correlation id only when answering (the communication reply, the payment acknowledgement); the beneficiary's ABHA, else the episode's by `claim_no` | `{txn_id, correlation_id, api_call_id, raw}` | Raises `TransportError(code, message, protocol_response, retryable)` on a refusal. Archives the outbound message. Every leg stores the three ids. | +| The receiving end | A delivery from the exchange (`own`, `existing`) or from nhcx-adapter | Calls 7.3's `receive(envelope)` with `{meta: {path, payloadType, redelivery}, jwe_headers: {every x-hcx- field}, fhir: }`; `payloadType` is `fhir`, `protocol` or `error` | Answers the sender as its transport requires (section 3.9 for `own`). The door does the rest. | +| `policies(id_type, value)` | `AbhaNumber`, `MemberId` or `MobileNo`, and the value | The participant service's answer, raw | Module 7.4 normalises it (section 3.6). | +| `participants(role)` | `PAYER`, `PROVIDER` or `TPA` | The registry's list | Cached for the day. | +| `token()` | nothing | The ABDM session token | For calls the transport does not make itself, such as the PMJAY payer service. | +| `thread(correlation_id)`, `fetch_missed(txn_id)` | | The messages on one thread; a missed answer | Only nhcx-adapter keeps a ledger to answer these. With `own` and `existing`, `thread` reads the per-case archive and `fetch_missed` answers `unavailable`; a lost answer surfaces through `/v1/error` and the status exchange instead (section 3.10). | + +Two values every transport needs from the build, both from the policy lookup (section 3.6). The recipient is the policy's `processingid`, kept on the episode as `recipient_code`. The insurer is its `payerid`, kept as `payer_code`: it goes inside the bundle and chooses the payer adapter (module 7.11). And every message carries the beneficiary's ABHA number in `x-hcx-ben-abha-id`. + +A test replaces `send` with a stub of the same signature (stage 9). Nothing else in the build changes for a test. + +## 3. Building it yourself (`own`) + +Seven things, in this order (`01-The Base Framework.md`): a token, a key and certificate, a participant record, the payer and policy lookups, the recipient's certificate, sealing and sending, and the callback. The last two are the ones every message uses. + +### 3.1 Before you start + +| Need | Why | +| --- | --- | +| The facility's HFR id | The registry that vouches for a hospital | +| ABDM sandbox client id and secret, Milestone 1 completed | NHCX uses the same credentials; there is no separate login | +| A public HTTPS server in India with a domain name | The exchange calls your callback; it will not call an IP address or a port number | +| `openssl` where the private key will live | The key pair | +| A JOSE library | RSA-OAEP-256 with A256GCM: `jose` on Node, `jwcrypto` on Python, Nimbus on Java, `jose-jwt` on .NET | + +Ask the user for the credentials. Never write them, the token or the private key into code, a log or `nhcx-build/`. + +### 3.2 Addresses and headers + +From `nhcx-package/baseurl.yaml`: + +| Service | Sandbox | Production | +| --- | --- | --- | +| ABDM session token | `https://dev.abdm.gov.in/api/hiecm/gateway/v3/sessions` | `https://apis.abdm.gov.in` plus the same path; confirm it in the onboarding letter | +| NHCX exchange, every use-case call under `/v1` | `https://apisbx.abdm.gov.in/hcx` | Shared by NHA after sandbox exit | +| Participant service | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice` | `https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice` | + +Keep every address in configuration. Every call to the participant service and the use-case endpoints carries `Accept: application/json`, `Content-Type: application/json` and `bearer_auth: Bearer `. The header is `bearer_auth`, not `Authorization`; some NHA pages write `Authorization`, so send both with the same value. + +### 3.3 The session token + +`POST` to the sessions address with three headers, none optional: `REQUEST-ID` (a fresh UUID on every call), `TIMESTAMP` (UTC with milliseconds and a trailing `Z`, from the system clock) and `X-CM-ID` (`sbx` on the sandbox, `abdm` in production). The body is `{"clientId", "clientSecret", "grantType": "client_credentials"}`. The answer carries `accessToken` and `expiresIn`. + +- NHA's documents give its life as 300, 1200 and 6000 seconds. Rely on none: keep the token and when you got it, and fetch a new one when it is a few minutes old. +- On any `401`, get a new token and retry that call once. Never retry with the same token. +- Put `Bearer` and a space before the token. Without it, `401`. + +`03-Session Token.md` also shows the two timestamp shapes in ten languages: the gateway's UTC `...975Z`, the exchange's `+05:30`. + +### 3.4 Your key and certificate + +```bash +openssl genpkey -algorithm RSA -out private.key -pkeyopt rsa_keygen_bits:2048 +openssl req -new -key private.key -out request.csr +openssl x509 -req -in request.csr -signkey private.key -out certificate.crt -days 365 +base64 -w 0 certificate.crt > certificate.b64 # macOS: base64 -i certificate.crt -o certificate.b64 +``` + +`private.key` never leaves the server that receives callbacks. `certificate.b64` goes on the participant record as `encryption_cert`. Note the expiry: a lapsed certificate stops every sender. Replace it yearly (`04-Your Certificate.md`). + +### 3.5 The participant record + +On the sandbox, `POST /participant/create` with: + +| Field | Value | +| --- | --- | +| `linked_registry_codes` | `["10001"]` (HFR) | +| `registryid` | Your ABDM client id on the sandbox; the HFR id in production | +| `roles` | `["10001"]` (provider) | +| `participant_name`, `scheme_code`, `state`, `district`, `primaryEmail`, `phone`, `primaryMobile` | The facility's | +| `encryption_cert` | The base64 certificate | +| `endpoint_url` | The base of your callback server | + +The answer is your `participant_code`: the `x-hcx-sender_code` on everything you send. `participant/update` changes the certificate or the address. Production takes four steps with a passcode to the mobile on the HFR record (`v2/participant/create`, `validate`, `v2/participant/update`, `update/validate`), and `v2/update/cert` rotates only the certificate (`05-Creating and Updating a Participant.md`). + +The exchange appends the use-case path to `endpoint_url`: a pre-auth decision arrives at `/v1/preauth/on_submit`. Only the client id that created the record may change it; any other gets NHCX-1015. + +This is the user's onboarding, not the build's. The build writes the script or the settings screen; the user runs it with their credentials. Check it worked by fetching your own certificate back (section 3.7). + +### 3.6 The payer and the policy + +- Payers: `POST /fetch/participants/list` with `role` (`PAYER`, `PROVIDER`, `TPA`), `fromdate` and `todate` (`dd/MM/yyyy`), and optionally `entitytype` (`Gov`). There is no server-side search by name: fetch, filter locally, and cache for the day. +- Policies: `POST /participant/get/policies` with `identifiertype` and `identifiervalue`. Try `AbhaNumber` (no hyphens), then `MemberId`, then `MobileNo`, and stop at the first that returns a policy. Each policy carries `payerid`, `processingid`, `memberid`, `productid` and `productname`. The published answer is a sketch: read a real one before writing the parser, and keep it raw on the episode. +- Send to the processor. `processingid` is the envelope's recipient and whose certificate seals the message; `payerid` is the insurer named inside the bundle. They are the same when the insurer processes its own claims and differ when a TPA does. Addressing the `payerid` is the portal's seventh most common mistake. A policy with no `processingid` cannot be addressed: stop and say so (`06-Finding Participants and Policies.md`). + +### 3.7 The recipient's certificate + +`POST /fetch/certs` with `{"participantid": ""}`. The answer is PEM text: usually an X.509 certificate, sometimes a bare SPKI public key (anything under about 400 bytes). Load it as a certificate and take its key; if that fails, load it as a key. NHA does not publish the JSON envelope around it, so read one real answer first. Cache by participant code for 24 hours, and refresh early when the other side stops being able to open your messages (`07-Fetching a Recipient Certificate.md`). + +### 3.8 Sealing and sending + +The protected header (`08-Building and Sending a JWE.md`, `06-Reference/03-Envelope Fields.md`): + +| Field | Value | +| --- | --- | +| `alg`, `enc` | `RSA-OAEP-256`, `A256GCM`; not `RSA-OAEP` | +| `x-hcx-sender_code` | Your participant code | +| `x-hcx-recipient_code` | The policy's `processingid` on a request; the request's sender on an answer | +| `x-hcx-api_call_id` | A fresh UUID on every message, answers included | +| `x-hcx-request_id` | A UUID per request; optional, send it | +| `x-hcx-correlation_id` | On a request, this message's own `api_call_id`. On an answer, the request's `correlation_id`, so the two ids differ on an answer | +| `x-hcx-workflow_id` | The step code (`references/flow-knowledge.md` section 2). Optional in the specification, but payers key on it: send it wherever the sheet gives one | +| `x-hcx-timestamp` | ISO 8601 with `+05:30`, no milliseconds, from the system clock | +| `x-hcx-status` | `request.initiated` on a request; `response.complete` on an answer (an `on_` path) | +| `x-hcx-ben-abha-id` | The beneficiary's ABHA number without hyphens. Mandatory on every exchange | +| `x-hcx-use_case` | Optional: `New`, `Enhancement` or `Resubmit` on a pre-auth; `New` or `Resubmit` on a claim | + +Seal with the JOSE library: the bundle as plaintext, the recipient's public key, the header above as the protected header, compact serialisation (five parts, four dots). POST `{"payload": ""}` to `/v1/` with the headers of section 3.2. The sandbox collection also repeats the `x-hcx-` fields as HTTP headers; send them both ways. + +What comes back: + +| Answer | Means | The build | +| --- | --- | --- | +| `202` with a receipt (`protocol_status: request.queued`) | The envelope was valid and is queued. It is not the decision | Store `api_call_id` and `correlation_id`, and the archive id as `txn_id`; the leg waits | +| `400` | The envelope failed validation | Raise with the gateway's body; nothing went to the payer | +| `401` | The token expired, or `Bearer` is missing | New token, retry once | +| A connection dropped after the request was written | Unknown: it may have landed | Do not resend at once (`references/errors-and-debugging.md` section 7) | + +A correlation id that failed at the gateway is retired. The next attempt needs a fresh `api_call_id` and a fresh `correlation_id` (`01-Overview/04-JWE, Status and Errors.md`). + +### 3.9 Receiving + +Host these under `endpoint_url` (`09-Receiving a Callback.md`): `/v1/coverageeligibility/on_check`, `/v1/insuranceplan/on_request`, `/v1/preauth/on_submit`, `/v1/claim/on_submit`, `/v1/predetermination/on_submit`, `/v1/search/on_submit`, `/v1/communication/request`, `/v1/paymentnotice/request`, `/v1/task/on_submit`, `/v1/on_status` and `/v1/error`. Build one handler. The path gives the receipt's `entity_type`; the correlation id routes everything else (module 7.3). + +- The address: a domain over HTTPS with TLS 1.2 or newer, hosted in India, reachable from the exchange's outbound addresses `3.109.99.210`, `13.126.152.0` and `13.200.129.223`. +- The body: `{"type": "JWEPayload", "payload": ""}`; or, when the recipient refused your message, `{"type": "ProtocolResponse", "x-hcx-...": ..., "x-hcx-status": "response.error", "x-hcx-error_details": {code, message, trace}}` with the fields in the clear. `/v1/error` carries neither: it is a plain report of a request the exchange gave up on after five attempts. Store it whole and do not parse it against a fixed schema. +- Open a `JWEPayload` with your private key: the protected header comes out in the clear and the bundle is the plaintext. A failure to decrypt means the message was sealed for a certificate that is not the one on your participant record. +- Answer every delivery with `202` and the receipt within 30 seconds, `/v1/error` and unrecognised messages included. Not `200`, and not an empty body: + + ```json + {"timestamp": "dd/MM/yyyy HH:mm:ss:SSS", "api_call_id": "", "correlation_id": "", + "result": {"sender_code": "", "recipient_code": "", "entity_type": "preauth", "protocol_status": "request.queued"}, + "error": {"code": "", "message": ""}} + ``` + + `entity_type` is the path's second-to-last segment, or the last where that is `v1`, with `on_` stripped. +- Hand the door `{meta: {path, payloadType, redelivery}, jwe_headers, fhir}`: `payloadType` `fhir` with the bundle, `protocol` with the ProtocolResponse body as `fhir`, `error` with the `/v1/error` report. The door dedupes on `x-hcx-api_call_id`, archives, matches and applies, fast and with no outbound calls, so the receipt still goes inside the 30 seconds. +- The exchange signs its calls to you with a JWT (RS256; claims `jti`, `iss`, `sub`, `iat`, `exp`). No published source gives the NHCX public key or the header the token arrives in. Build the check with the key in configuration. While no key is configured, log that at every start, accept calls only from the three addresses above, and ask NHA for the key at onboarding. Never leave the check off silently. + +### 3.10 Status and the error endpoint + +- `/v1/status` asks the exchange what became of a message you sent. The payload is empty; `x-hcx-correlation_id` is that message's `api_call_id`. The answer arrives on `/v1/on_status` with `request.queued`, `request.dispatched` or `request.stopped` (redelivery exhausted; the correlation is retired). Call it when a case has been quiet longer than the payer's turnaround, never on a timer (`11-Status and Search.md`). `references/flow-knowledge.md` section 2 records what the sandbox did with it; keep the path configurable. This is not the claim's status Task of module 7.9. +- `/v1/error` is how you learn a request died. Without it a lost message is silent. + +With no ledger to poll, these two, the per-case archive and the receipts are what an `own` transport has. A leg with no answer stays waiting; it never turns into an error on a timer. + +### 3.11 Proving it + +The sandbox's dummy payer answers when you trigger it. Send it a bundle, then `POST https://apisbx.abdm.gov.in/pmjay/sbxhcx/dummyhcxpayer/process/request` with `{"action": "Approve" | "Reject" | "Query", "method": "Preauth" | "Claim", "correlationId": ""}`. Its answer reaching your `/v1/preauth/on_submit`, sealed or as a ProtocolResponse, proves the token, the participant record, the address, the sealing and the opening together (`09-Receiving a Callback.md`, "Closing the loop"). This is live traffic: stage 10, rung 3, started by the user. + +### 3.12 Pseudo code + +``` +settings.nhcx = {sessions, base, registry, cm_id, client_id, client_secret, # from configuration, never from code + private_key, signing_key} # signing_key empty until onboarding gives it + +function token(): + if cache.token and age(cache.at) < 240s: return cache.token + r = http_post(settings.nhcx.sessions, json = {clientId: settings.nhcx.client_id, clientSecret: settings.nhcx.client_secret, + grantType: "client_credentials"}, + headers = {"REQUEST-ID": uuid4(), "TIMESTAMP": utc_millis_z(), "X-CM-ID": settings.nhcx.cm_id}) + cache = {token: r.json().accessToken, at: now()} + return cache.token + +function authed_post(url, body, extra_headers = {}): + for attempt in (1, 2): + t = token() + r = http_post(url, json = body, timeout = 90, + headers = {"Accept": "application/json", "Content-Type": "application/json", + "bearer_auth": "Bearer " + t, "Authorization": "Bearer " + t} + extra_headers) + if r.status != 401: return r + cache.token = null # one retry, with a fresh token + return r + +function registry(path, body): return authed_post(settings.nhcx.registry + "/" + path, body) + +function recipient_key(code): # cached for 24 hours + if certs[code] and age(certs[code].at) < 24h: return certs[code].key + pem = pem_in(registry("fetch/certs", {participantid: code}).json()) # read one real answer first + key = try_certificate(pem).public_key() or load_public_key(pem) # X.509 first, bare SPKI second + certs[code] = {key, at: now()} + return key + +function send(path, bundle, recipient, workflow_id, correlation_id = null, ben_abha_id = null, claim_no = null, usecase = ""): + abha = digits(ben_abha_id or ben_abha(claim_no)) + if not recipient or not workflow_id or not abha: raise ValueError("recipient, workflow id and beneficiary ABHA are required") + answer = path.split("/")[-1].startswith("on_") + api_call_id = uuid4() + header = {"alg": "RSA-OAEP-256", "enc": "A256GCM", + "x-hcx-sender_code": with_hcx(settings.participant_code), "x-hcx-recipient_code": with_hcx(recipient), + "x-hcx-api_call_id": api_call_id, "x-hcx-request_id": uuid4(), + "x-hcx-correlation_id": correlation_id if answer else api_call_id, + "x-hcx-workflow_id": str(workflow_id), "x-hcx-timestamp": now_ist_seconds(), + "x-hcx-status": "response.complete" if answer else "request.initiated", + "x-hcx-ben-abha-id": abha} + jwe = jose_encrypt_compact(to_json(bundle), recipient_key(with_hcx(recipient)), protected = header) + r = authed_post(settings.nhcx.base + "/" + path, {"payload": jwe}, extra_headers = without(header, "alg", "enc")) + txn = archive.record(claim_no, usecase, "out", {path, header, bundle, status: r.status, response: r.text}) + if r.status >= 300: + raise TransportError(code = "GATEWAY_HTTP_" + r.status, message = r.text, retryable = r.status >= 500) + return {txn_id: txn, correlation_id: header["x-hcx-correlation_id"], api_call_id: api_call_id, raw: r.json()} + +route POST /v1/ # under endpoint_url; exempt from session auth and CSRF; the exchange's addresses only +function inbound(request, path): + verify_nhcx_jwt(request, settings.nhcx.signing_key) # when the key is configured; else logged at start, never silent + body = parse_json_or_null(request.body) + if path == "error": + env = {meta: {path: "v1/error", payloadType: "error"}, jwe_headers: {}, fhir: body} + elif body and body.type == "ProtocolResponse": + env = {meta: {path: "v1/" + path, payloadType: "protocol"}, jwe_headers: x_hcx_fields(body), fhir: body} + else: + try: header, plaintext = jose_decrypt_compact(body.payload, settings.nhcx.private_key) + except: archive.record(null, "undecryptable", "in", request.body); return 202, receipt({}, path, error = "DECRYPT_FAILED") + env = {meta: {path: "v1/" + path, payloadType: "fhir"}, jwe_headers: header, fhir: parse_json(plaintext)} + receive(env) # module 7.3: dedupe, archive, match, apply; fast, no sends + return 202, receipt(env.jwe_headers, path) # within 30 seconds + +function receipt(h, path, error = ""): + return {"timestamp": now_ist("dd/MM/yyyy HH:mm:ss:SSS"), + "api_call_id": h["x-hcx-api_call_id"], "correlation_id": h["x-hcx-correlation_id"], + "result": {"sender_code": h["x-hcx-sender_code"], "recipient_code": h["x-hcx-recipient_code"], + "entity_type": entity_type(path), "protocol_status": "request.queued"}, + "error": {"code": error, "message": ""}} + +function entity_type(path): # "v1/preauth/on_submit" -> "preauth"; "v1/on_status" -> "status" + parts = ("v1/" + path).split("/"); seg = parts[-2] if parts[-2] != "v1" else parts[-1] + return seg.removeprefix("on_") +``` + +## 4. Using an existing integration (`existing`) + +How stage 0 recognises one: `x-hcx-`, `JWEPayload`, `RSA-OAEP-256`, `A256GCM`, a JOSE library among the dependencies, `bearer_auth`, a sessions URL on the ABDM gateway, `participanthcxservice`, `fetch/certs`, `participant/get/policies`, routes ending in `on_submit`, `on_check` or `on_request`, a vendor's NHCX or HCX client library, a separate gateway service the app calls. + +What it must do, checked by running it offline with the network stubbed and a test key pair for the seal: + +| Contract item (section 2) | Look at | Common gap | +| --- | --- | --- | +| `send` emits the protected header of section 3.8 | What it seals or posts | No `x-hcx-ben-abha-id`; a request correlation id that is not its own `api_call_id`; UTC timestamps; `RSA-OAEP` | +| The recipient | Who it addresses | The `payerid` instead of the `processingid` | +| The three ids back to the caller | Its return value | Only a success flag; the ids stay inside it | +| Receiving: a `202` receipt within 30 seconds on every path, `/v1/error` included | Its callback handler | `200` or an empty body; no `/v1/error`; slow work before answering | +| Handing on the header and the bundle | What it gives the app | The bundle without the header; no ProtocolResponse path | +| Dedupe on `x-hcx-api_call_id` | Its store | None | +| A record of every message | Its logs | Bodies not kept | + +The build wraps it. 7.1's `send` calls the existing client and returns the three ids. The existing callback handler, after its receipt, calls 7.3's `receive` with the envelope of section 2. Each gap is closed in the existing code, in its style (stage 7, action `extend`). The existing transport is not rewritten, and no second one is added beside it. If it cannot be made to hand on the ids or the header, record `partial` and ask the user whether to extend it further or, with their agreement, build `own` in its place. + +## 5. nhcx-adapter, only when asked + +nhcx-adapter is NHA's optional single binary that does section 3 for you (`nhcx-package/docs/02-Getting Started/10-NHCX Adapter.md`, titled "Optional"). Use it only when the user has asked for it. Then: + +1. Get it, with the user's go-ahead, from https://github.com/nha-in/nhcx-adapter/releases (the latest). Each release carries one archive per platform, `nhcx-adapter___.tar.gz` (darwin, linux, windows, freebsd; amd64, arm64, 386), holding the binary, `config.sample.json`, `serve.sh`, `stop.sh`, `update.sh` and `README.md`. Put it in a folder of the user's, not in the skill. +2. Its contract is `references/api-knowledge.md`: configuration (section 2), routes (3), the outbound envelope and answer (4, 5), the delivery your HMIS receives (6), the ledger (7), the kit endpoints (8). +3. Onboarding is sections 3.1 to 3.5 again: credentials, a key, a participant record, a public address. The adapter can generate and register the key itself (`config init`, `cert generate`, its startup checks). +4. It does not queue or retry, does not build or validate bundles, and does not verify who sent an inbound message beyond decrypting it. Its `/internal/*` routes have no authentication: bind it to loopback. + +How it maps onto section 2: `send` POSTs `{jwe_headers, fhir}` to `/fhir/out/`; the receiving end is the HMIS route the adapter posts to (`api-knowledge.md` section 6); `policies` is `/internal/policies/search`; `thread` and `fetch_missed` are its ledger and `/internal/txn/*`. diff --git a/plugins/nhcx/skills/nhcx-communication/scripts/fetch-package.sh b/plugins/nhcx/skills/nhcx-communication/scripts/fetch-package.sh new file mode 100755 index 000000000..efbafa50b --- /dev/null +++ b/plugins/nhcx/skills/nhcx-communication/scripts/fetch-package.sh @@ -0,0 +1,122 @@ +#!/usr/bin/env bash +# Fetch the NHCX package and unpack it beside nhcx-build/ as nhcx-package/. +# +# scripts/fetch-package.sh [url-or-path] [target-dir] +# +# With no [url-or-path] (or "latest"), the zip is the build attached to the latest +# release of https://github.com/nha-in/nhcx-package (the nhcx-package-v.zip +# asset); its sha256 is checked against the digest GitHub records for the asset. +# Otherwise [url-or-path] is a link to the zip or a local path to it. +# [target-dir] defaults to the current directory. The zip unpacks to /nhcx-package/. +# +# Afterwards MANIFEST is checked: every file it lists must exist with the sha256 +# it records. Nothing is deleted; an existing nhcx-package/ is replaced. +set -euo pipefail + +repo="nha-in/nhcx-package" +src="${1:-latest}" +target="${2:-.}" +if [[ "$src" == "-h" || "$src" == "--help" ]]; then + echo "usage: $0 [latest|url-or-path-to-package.zip] [target-dir]" >&2 + exit 2 +fi + +download() { # + if command -v curl >/dev/null 2>&1; then + curl -fsSL -o "$2" "$1" + elif command -v wget >/dev/null 2>&1; then + wget -qO "$2" "$1" + else + echo "neither curl nor wget is available" >&2 + exit 1 + fi +} + +mkdir -p "$target" +tmp="$(mktemp -d)" +zip="$tmp/package.zip" +want_sha="" + +if [[ "$src" == "latest" ]]; then + # Ask the releases API for the latest release's zip asset and its digest. + api="https://api.github.com/repos/$repo/releases/latest" + if download "$api" "$tmp/release.json" 2>/dev/null; then + read -r tag url want_sha < <(python3 - "$tmp/release.json" <<'PY' +import json, sys +rel = json.load(open(sys.argv[1], encoding="utf-8")) +assets = [a for a in rel.get("assets", []) + if a["name"].startswith("nhcx-package") and a["name"].endswith(".zip")] +if not assets: + sys.exit(f"release {rel.get('tag_name')} has no nhcx-package*.zip asset") +a = assets[0] +digest = a.get("digest") or "" +print(rel["tag_name"], a["browser_download_url"], + digest.split(":", 1)[1] if digest.startswith("sha256:") else "") +PY + ) + else + # API unreachable or rate limited: read the tag off the releases/latest redirect + # and build the asset name from it. No digest to check in this case. + tag="$(curl -fsSIL -o /dev/null -w '%{url_effective}' "https://github.com/$repo/releases/latest")" + tag="${tag##*/}" + if [[ -z "$tag" || "$tag" == "latest" ]]; then + echo "could not resolve the latest release of $repo" >&2 + exit 1 + fi + url="https://github.com/$repo/releases/download/$tag/nhcx-package-v$tag.zip" + fi + echo "fetching $repo release $tag: $url" + download "$url" "$zip" + if [[ -n "$want_sha" ]]; then + got_sha="$(python3 -c 'import hashlib,sys; print(hashlib.sha256(open(sys.argv[1],"rb").read()).hexdigest())' "$zip")" + if [[ "$got_sha" != "$want_sha" ]]; then + echo "sha256 mismatch for $url: got $got_sha, release says $want_sha" >&2 + exit 1 + fi + fi +elif [[ -f "$src" ]]; then + cp "$src" "$zip" +else + download "$src" "$zip" +fi + +rm -rf "$target/nhcx-package" +unzip -q "$zip" -d "$target" +if [[ ! -f "$target/nhcx-package/MANIFEST" ]]; then + echo "unpacked, but $target/nhcx-package/MANIFEST is missing; is this the NHCX package?" >&2 + exit 1 +fi + +# Verify every file the MANIFEST lists. The MANIFEST is YAML; its file entries +# carry path, bytes and sha256 on separate lines. +python3 - "$target/nhcx-package" <<'PY' +import hashlib, os, re, sys +root = sys.argv[1] +text = open(os.path.join(root, "MANIFEST"), encoding="utf-8").read() +# Only the `files:` section lists a sha256 per path; the `contents:` summary above it +# lists directories. Parse entry by entry so a directory entry never borrows the next +# file's hash. +files_section = text.split("\nfiles:\n", 1)[1] if "\nfiles:\n" in text else "" +entries = [] +for chunk in re.split(r"\n\s*-\s+path:\s*", "\n" + files_section)[1:]: + path = chunk.split("\n", 1)[0].strip() + m = re.search(r"^\s+sha256:\s*([0-9a-f]{64})", chunk, re.M) + if path and m: + entries.append((path, m.group(1))) +bad = [] +for path, want in entries: + p = os.path.join(root, path) + if not os.path.isfile(p): + bad.append(f"missing {path}") + continue + got = hashlib.sha256(open(p, "rb").read()).hexdigest() + if got != want: + bad.append(f"sha256 mismatch {path}") +print(f"nhcx-package: {len(entries)} file(s) listed, {len(bad)} problem(s)") +for b in bad[:20]: + print(" " + b) +sys.exit(1 if bad else 0) +PY + +rm -rf "$tmp" +echo "ready: $target/nhcx-package (see references/material.md for the path map)" diff --git a/plugins/nhcx/skills/nhcx-communication/stages/0-capability-check.md b/plugins/nhcx/skills/nhcx-communication/stages/0-capability-check.md new file mode 100644 index 000000000..8186c3288 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-communication/stages/0-capability-check.md @@ -0,0 +1,92 @@ +# Stage 0: capability check + +Purpose: before anything is planned, find out what the app already does. For this skill's own capabilities, for the foundation it stands on, and for what it needs from the use cases before it, write one verdict each with the evidence that decides it. The verdicts decide what the later stages reuse, extend, build or wait for. Nothing is built twice, and nothing is reused on faith. + +## Inputs + +- This skill's `SKILL.md`, section "Capability check": its own capabilities (what to look for, what makes each present), and its prerequisites with the check that proves each present. The skills that own the prerequisites do not need to be installed; their checks are in this skill's `SKILL.md`. +- `core/FOUNDATION.md`: the six foundation capabilities. +- `nhcx-build/capabilities.json` and `nhcx-build/0-capability.md`, if another NHCX skill already ran on this app. +- The target: the codebase (integrate), or the folder where the standalone app lives or will live. +- The pins and payer fixtures each check names, in `nhcx-package/`. If it is not beside `nhcx-build/`, fetch it now (`scripts/fetch-package.sh`); `references/material.md` names each pin's file. + +## The verdicts + +| Verdict | Means | What happens next | +| --- | --- | --- | +| `present` | Located, and its check was run and observed passing | Reuse. Stage 7 builds nothing for it. Stage 8 still runs its Validate rows; stage 9 still tests it. | +| `partial` | Located, but its check fails; or it covers some legs or branches and not others; or it was located and could not be run | Extend. Stage 7 builds the difference, in the existing code. | +| `absent` | Searched for as the skill says and not found | Build. Stage 7 builds it. | +| `unknown` | Could not be searched: no code is reachable | Planned as absent; stage 0 runs again when the code is reachable. | +| `not applicable` | The mode or the scope excludes it: 7.13 in integrate mode, a leg the user marked out | Nothing. | + +For a prerequisite, a verdict of `absent` or `unknown` is a stop: see step 5. + +Present is a claim about behaviour. Code that looks right is `partial` until its check has run. + +## Do + +### 1. Find the target + +Integrate: the codebase root, its language and framework, enough to search and to run code offline (stage 3 does the full survey). Standalone: the app folder. If it is empty and no other NHCX skill has built anything there, every capability is `absent` and this stage is short. Write which in one line. + +If `nhcx-build/capabilities.json` exists, read it. A verdict another skill recorded is a lead, not a result. If the code changed since its date (the version control log says), run its check again; otherwise carry it forward with its evidence and date. + +### 2. Locate + +For each capability in the three lists (own, foundation, prerequisites), search for the markers: NHCX paths such as `v1/preauth/submit`, resource names such as `CoverageEligibilityRequest`, workflow ids as strings, table and column names. `SKILL.md` lists them for its own capabilities; for a prerequisite, the marker is what its check names. Record every hit as `path:line`. A hit in a comment, a dead branch or a test fixture is not the capability; say so. + +Look also for the same job done another way: a pre-auth sent to a TPA portal, an eligibility check recorded from a phone call, a payment keyed in from a bank statement. That is a host capability that stages 3 and 4 may link to. The NHCX capability is still `absent`. + +### 3. Check + +For every capability located, run the check `SKILL.md` names, offline: + +- a builder: feed it the pin's own data and compare its output with the pin (canonical JSON, `created` excluded, and only the exclusions the module names); +- a reader: feed it the payer fixture and read the state it settles; +- a sender: call it with the 7.1 stub, or a stub of the app's own client, and read what it posted; +- the door: call the handler with an envelope; +- a screen: render it on a seeded state and read the text. + +Use the app's own test runner where it can host the check, else a one-off script under `nhcx-build/0-capability/`. Nothing leaves the machine. + +Where the existing code cannot be called without the network or a running service, record `partial` with `not run: `. Never `present`. + +### 4. Decide + +One verdict per capability, with where (the paths), how (the command), observed (the output, or the first lines of the diff), and the action: reuse, extend, build or wait. For `partial`, name the difference: which pin fails and at which element, which branch is missing (a PMJAY query answer on 19 but none on 131), which column is missing. + +### 5. When a prerequisite is missing + +A prerequisite is a capability another skill owns that this skill's legs cannot run without. `SKILL.md` lists them with their checks. If one is `absent` or `unknown`: + +1. Stop and tell the user which capability is missing, which skill owns it, and what this skill cannot do without it. +2. Offer the two ways on: run the owning skill first (installing it if it is not beside this one; it is the default); or continue with this skill's offline work only (builders, readers and tests against seeded rows), with the live legs marked `later` in stage 1 and the dependency written in `NOTES.md`. +3. Never build another skill's capability inside this one. It would be built without that skill's checks. + +A `partial` prerequisite does not stop the skill. Its gap goes into stage 2's risk table. + +## Write + +- `nhcx-build/capabilities.json` from `templates/capabilities.json`: one entry per capability, keyed by id, with `skill`, `module`, `verdict`, `located`, `how`, `observed`, `action`, `checked_by` and `date`. Update the entries this skill checked; leave the others. +- `nhcx-build/0-capability.md` from `templates/0-capability.md`: a section headed with this skill's name, holding the three tables (own, foundation, prerequisites) and the summary line. +- The scratch checks under `nhcx-build/0-capability/`, kept: stage 8 runs them again. +- This skill's block in `nhcx-build/STATE.md` (create the file from `templates/STATE.md` if it does not exist), with stage 0's row closed and its evidence. + +## Gate + +- [ ] Every capability in this skill's list, every foundation capability, and every prerequisite has a verdict. +- [ ] Every `present` names the command run and its observed output. None rests on reading alone. +- [ ] Every `partial` names the difference. +- [ ] Every `absent` names what was searched for, so a reader can repeat the search. +- [ ] A missing prerequisite was put to the user, and the answer is recorded. +- [ ] `capabilities.json` parses and holds this skill's entries. + +## Common mistakes + +- Marking a capability present because its endpoint name appears in the code. The pin decides. +- Rebuilding a working NHCX transport or callback door because this skill did not write it. An app that already seals, sends and receives NHCX messages keeps its own; the verdict says reuse. +- Proposing nhcx-adapter for an app that lacks a transport. The transport is then `own`; the adapter is used only when the user asks for it. +- Treating a legacy TPA workflow as the NHCX capability. It is a host capability; the NHCX one is absent. +- Checking against the live sandbox. Stage 0 is offline; the live rungs are stage 10's, and the user's. +- Carrying another skill's verdict forward after the code changed. diff --git a/plugins/nhcx/skills/nhcx-communication/stages/1-idea.md b/plugins/nhcx/skills/nhcx-communication/stages/1-idea.md new file mode 100644 index 000000000..b9f391316 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-communication/stages/1-idea.md @@ -0,0 +1,80 @@ +# Stage 1: the idea + +Purpose: agree with the user what is being built before anything is designed. One page, shared by the seven skills. Wrong answers here cost the most later, so this is the one stage that always ends with a question to the user when it is first written. + +The first skill to reach this stage writes `1-idea.md` whole: the mode, the payers, the constraints, and a scope row for every step of the flow, each naming the skill that owns it. A later skill reads the page, confirms that the mode and the payers still hold, and marks its own rows. It asks the user only when it would change a row or an answer. + +## Inputs + +- This skill's section of `nhcx-build/0-capability.md`: what the app already does. A leg found present is still in scope: it is validated and tested, not rebuilt. Say so in the scope table's reason column. A prerequisite the user chose to wait for makes this skill's live legs `later`. +- `flow/FLOW.md`, whole. The build walks this path; the scope table below marks its steps in, later or out, and nothing else. `flow/flow.json` names the skills of each step in `skills`. +- What the user said. If they pasted a brief, quote it in the artefact. +- `references/flow-knowledge.md` sections 1, 3 and 6: the legs, the two payer kinds, the use-case catalogue. Read them so the scope table below uses the catalogue's codes. + +## Do + +Decide five things, in this order. A later skill confirms the first two and the fourth, and does the third for its own rows. + +### 1. Mode + +| Signal | Mode | +| --- | --- | +| A codebase, a database, a running system is named | `integrate` | +| "from scratch", "standalone", "a claims app", no existing system | `standalone` | +| Unclear | Ask. Do not guess; the two modes diverge at stage 3. | + +### 2. Payers + +Which participant codes the software will talk to, and which kind each is: + +| Payer | Participant code | Kind | Query mode | +| --- | --- | --- | --- | +| PMJAY (SHA Himachal Pradesh, sandbox) | `1518@hcx` | scheme | `resubmit` | +| A generic sandbox payer you can drive, for testing | from the participant registry | generic | `communication` | +| Any other insurer | from the registry | generic unless told otherwise | `communication` | + +Both kinds are in scope by default. A build that targets only one still keeps the payer adapter switch (module 7.11), because the second is one config line away. + +### 3. Scope of legs + +Copy the steps of `flow/flow.json` (F1 to F13 with their branches) into a scope table, with the skill that owns each (`skills`), and mark each `in`, `later` or `out`, with a reason; add the catalogue code from `flow-knowledge.md` section 6 beside each. The default scope for a first release is every hospital-side leg in `flow-knowledge.md` section 1. Cutting a leg is the user's call; propose it, do not decide it. Legs that are commonly `later`: predetermination, status enquiry (PMJAY refuses it), release of a shortfall (out of reach on the sandbox). + +A later skill changes only its own rows. + +### 4. Constraints + +Ask the codebase, not the user, where you can: + +- Language and framework (integrate: whatever the HMIS uses; standalone: Python standard library unless the user names another, because the module files' pseudo code maps onto it directly). +- The transport (`references/transport-knowledge.md` section 1): `existing` when stage 0 found the app already speaks NHCX; else `own`, built into the app from NHA's protocol; `adapter` (nhcx-adapter) only when the user has asked for it, their words quoted. Never propose the adapter. +- The inbound path. For `own`: a public HTTPS domain in India, registered as the participant's `endpoint_url` and reachable from the exchange. For `existing`: the app's own callback. For `adapter`: whether the app can receive the adapter's POST; if not, polling the adapter's ledger is the only inbound path. Write it down now. +- What onboarding needs from the user: the ABDM sandbox client id and secret (Milestone 1), the facility's HFR id, and a participant record carrying the build's certificate and callback address. +- Document storage: blob, filesystem, object store. +- Whether a background worker exists. Without one, polls happen on the request path. +- Anything the user forbids: new dependencies, schema changes to existing tables, a build step. + +### 5. Definition of done + +Write the compliance points from `core/LADDER.md` as they apply to this build, and the highest rung of the test pyramid the user wants climbed before handover (`references/testing-knowledge.md` section 1). The offline rung is never optional. + +## Write + +`nhcx-build/1-idea.md` from `templates/1-idea.md`. Keep the headings. Under two pages. A later skill edits only its scope rows and adds a line under "Agreed". + +## Gate + +- [ ] Mode is `integrate` or `standalone`, and the reason is one sentence. +- [ ] Every payer has a participant code and a query mode. +- [ ] The scope table has every step of the flow and every catalogue row, each with its skill, marked in, later or out. +- [ ] Constraints name the language, the transport (existing, own, or nhcx-adapter because the user asked for it), the inbound path and the document store. +- [ ] Definition of done names the target rung. +- [ ] The user has read the page and agreed, or a written brief stands in for the user. A later skill that changed nothing records that it confirmed the page. + +Record the gate in the Shared block of `nhcx-build/STATE.md`. + +## Common mistakes + +- Choosing `standalone` because the HMIS is unfamiliar. Unfamiliar is what stage 3 is for. +- Leaving PMJAY out because the user only named an insurer. PMJAY is the payer that refuses most; a build that handles it handles the rest. +- Dropping a leg from scope because stage 0 found it present. It stays in: present capabilities are validated and tested. +- Writing design here. Tables, screens and modules belong to stages 4 to 6. diff --git a/plugins/nhcx/skills/nhcx-communication/stages/10-run-tests.md b/plugins/nhcx/skills/nhcx-communication/stages/10-run-tests.md new file mode 100644 index 000000000..e7e5d8d32 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-communication/stages/10-run-tests.md @@ -0,0 +1,59 @@ +# Stage 10: run the tests + +Purpose: climb the pyramid as far as the user asked in stage 1, for this skill's rows, and record every rung honestly. Rung 1 you run yourself. Rungs 2 to 4 need services or live payers, and only the user starts those. + +## Inputs + +- `nhcx-build/1-idea.md` (the target rung), `nhcx-build/9-tests.md` (the run command, this skill's rows) +- This skill's `SKILL.md`: its stage 10 row (which matrix rows each rung walks) +- `references/testing-knowledge.md` sections 1, 5 and 6 +- `references/errors-and-debugging.md` sections 4 to 8 (reading the ledger, sandbox pace) + +## The rungs + +| Rung | What | Who starts it | Record | +| --- | --- | --- | --- | +| 1 Offline | The suite from stage 9, against the pins and fixtures, no network | you | the full output | +| 2 Validator | The HL7 FHIR validator on every bundle this skill builds, run as `references/fhir-knowledge.md` section 11 says | you, if Java and the validator are installed | one table: bundle, errors, warnings | +| 3 Generic payer | The transport on the sandbox (the app's own, or nhcx-adapter when the user chose it) and a generic sandbox payer whose desk you can drive; this skill's legs, every query as a CommunicationRequest, payment from its desk | the user | the ledger thread per leg, the state address after each | +| 4 PMJAY sandbox | SHA Himachal Pradesh, `1518@hcx`; sweep live pre-auths first; one request at a time per case, 30 seconds between; decisions on the payer service desk | the user | the ledger, the archive folder, every refusal verbatim | + +## Do + +### Rung 1 + +Run the command from `nhcx-build/9-tests.md`: the whole suite, not only this skill's tests, because a skill that extended a shared module can break another skill's test. Save the whole output to `nhcx-build/10-test-run/-rung1.log`. In `integrate` mode also run the HMIS's own suite and save it. A failure goes back to stage 7 (the module) or stage 9 (the test); record the fix and the re-run. Do not edit a test to make it pass unless the test was wrong, and say so. + +### Rung 2 + +If the validator runs, validate every bundle this skill's tests built (write them to a folder from the tests). Warnings are advice; the sandbox accepted every pin as it stands. Errors are findings. If it does not run, write `not run` and why. + +### Rungs 3 and 4 + +Prepare, do not run: + +1. The commands the user runs: the HMIS with its public callback (`own` or `existing`), nhcx-adapter with its filled config only when the user chose it, and the payer (rung 3). For `own`, the sandbox's dummy payer proves the loop first (`references/transport-knowledge.md` section 3.11). Write them into this skill's section of `nhcx-build/10-test-run.md` under "Runbook". +2. The driver: a script or a spec that walks this skill's matrix rows through the JSON state address, waiting on the case's own state and never on a fixed sleep, logging every verdict the payer gives. The earlier legs a row needs (an eligible case, an approved pre-auth) are reached by the earlier skills' drivers or through the app's own screens. +3. The sweep for rung 4: cancel or let expire every live pre-auth for the beneficiaries the tests use (PAYR-1238 otherwise). +4. Then stop and ask the user to start the services. When they have, run the driver, save its log, and package the run's bundles by correlation id from the per-case archive (or the adapter's ledger, when it is the transport). + +While a live run is going: one request at a time per case; wait about 30 seconds after a decision; on "Active instance found" wait and resend up to three times; on a refusal read the ledger thread before touching the code. + +## Write + +This skill's section of `nhcx-build/10-test-run.md` from `templates/10-test-run.md`: per rung, `passed`, `failed`, `not run` with the reason, the log path, and the findings (each a line: what, where, the PAYR or rule, the fix or the open question). The raw logs under `nhcx-build/10-test-run/`, named for the skill. + +## Gate + +- [ ] This skill's rung 1 log exists and shows every test in the suite passing, or the failures are listed as findings with a stage to return to. +- [ ] In `integrate` mode the HMIS's own suite log exists and passes. +- [ ] Rung 2 has a table or `not run` with a reason. +- [ ] Rungs 3 and 4 have a runbook and a driver for this skill's rows, and either a log or `not run: user has not started the services`. +- [ ] No rung is marked passed without a log. + +## Common mistakes + +- Starting a service yourself: the app's public callback, or nhcx-adapter. Only the user does. +- Running only this skill's tests at rung 1. A shared module may have broken another skill's. +- Sleeping a fixed time in a driver. Wait on the state address. +- Reading a refusal as a code bug before reading the ledger thread. Half of them are scheme rules (flow-knowledge section 5). diff --git a/plugins/nhcx/skills/nhcx-communication/stages/11-build-report.md b/plugins/nhcx/skills/nhcx-communication/stages/11-build-report.md new file mode 100644 index 000000000..4ea8a0806 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-communication/stages/11-build-report.md @@ -0,0 +1,64 @@ +# Stage 11: the report + +Purpose: one document a stranger can pick up to know what was built, what was found already there, what was proven, what was not, and what to do next. Written from the artefacts in `nhcx-build/`, not from memory. Its value is its honesty. + +`11-report.md` has a summary across the skills at the top and one section per skill below it. This skill writes its section and updates its row of the summary. + +## Inputs + +- Everything in `nhcx-build/`, `STATE.md` first, `NOTES.md` last +- This skill's sections of `0-capability.md`, `8-validation.md` and `10-test-run.md` + +## Do + +### 1. Read STATE.md + +Every gate row in this skill's block, and the foundation rows it built, with their evidence. A gate without evidence is reported as open, whatever you remember. + +### 2. Write this skill's section + +From `templates/11-report.md`, in this order: + +| Section | Holds | +| --- | --- | +| Capabilities | Every capability in this skill's section of `0-capability.md`: its verdict at stage 0, what was done (reused, extended, built), and its evidence after stage 8 | +| What was built | Each module part this skill built or extended, with its files and its record (`7-modules/7.N.md`) | +| Compliance | The seven points from `core/LADDER.md` for this skill's legs, each with the evidence path (the pin comparisons, the door tests, the screen tests, the rung logs) | +| The test pyramid | Per rung: passed, failed, not run, the log | +| Findings | Every failure from stages 8 and 10 with its resolution or its open state | +| Gaps | This skill's entries in `NOTES.md` folded in: what the skills did not say, what the docs did not say, what the sandbox did that no document states | +| Exceptions | Every accepted exception from stage 8 and the user's agreement | +| Runbook | How to start it, how to run the suite, how to run rungs 3 and 4, what to sweep first, where the archive and the ledger are | +| Next | The `later` legs from stage 1, the open gates, the rungs not climbed, and the skill to run next in the order `core/LADDER.md` gives | + +Then update this skill's row in the summary table: stages closed, rung reached, what it reused, extended and built, what is open. Mode, payers and "today a user can" are for the whole build; bring them up to date. + +### 3. Check the report against the rules + +- Every claim of "passes" has a log or a record path beside it. +- Every rung not run says so. +- Every capability reported as reused has its stage 8 evidence, not only stage 0's. +- No em dashes, short sentences, tables for facts. +- A stranger with this report and the target project could resume at the first open gate. + +## Write + +This skill's section of `nhcx-build/11-report.md`, and its summary row. Update `STATE.md` with the final gate. + +## Gate + +- [ ] Every section in the template is present in this skill's section. +- [ ] Every capability in this skill's section of `0-capability.md` appears under Capabilities. +- [ ] Every module part this skill touched appears in "What was built" or, if reused, under Capabilities. +- [ ] Every compliance point names evidence. +- [ ] The pyramid table matches this skill's section of `10-test-run.md`. +- [ ] This skill's entries in `NOTES.md` are folded into "Gaps" in full. +- [ ] The runbook has the start commands, the test command and the sweep. +- [ ] The summary table has this skill's row. + +## Common mistakes + +- Reporting the rung the user asked for as reached because the offline rung passed. +- Reporting a reused capability as working on the strength of stage 0 alone. +- Dropping a finding that was fixed. Fixed findings are the most useful part of the report for the next build. +- Writing the report before stage 10's logs exist. diff --git a/plugins/nhcx/skills/nhcx-communication/stages/2-planning.md b/plugins/nhcx/skills/nhcx-communication/stages/2-planning.md new file mode 100644 index 000000000..06c405cdc --- /dev/null +++ b/plugins/nhcx/skills/nhcx-communication/stages/2-planning.md @@ -0,0 +1,67 @@ +# Stage 2: planning + +Purpose: turn the idea and the capability check into this skill's schedule of gates, and add its block to the ledger every later stage writes to. This is bookkeeping, and it is short. + +## Inputs + +- `nhcx-build/1-idea.md` +- This skill's section of `nhcx-build/0-capability.md`: the verdict of every capability it owns or stands on +- `core/LADDER.md`, "The ladder"; this skill's `SKILL.md`, "The ladder, for this skill" +- `references/testing-knowledge.md` section 1 (the pyramid) and section 3 (the matrix), so the acceptance tests below are the matrix's rows and not invented ones + +## Do + +### 1. Size each stage + +For every stage 3 to 11, write one row for this skill: what it produces for this build, how big it is (small, medium, large), and what proves it done. "What proves it done" is the stage's gate, restated for this skill. + +For stage 7, list the modules this skill's `SKILL.md` names and the foundation modules, each with its verdict from stage 0 turned into an action: + +| Verdict | Action in stage 7 | +| --- | --- | +| `present` | reuse: nothing built; validated in stage 8, tested in stage 9 | +| `partial` | extend: the difference, in the existing code | +| `absent`, `unknown` | build | +| `not applicable` | nothing | + +Module 7.13 depends on the mode: + +| Module | integrate | standalone | +| --- | --- | --- | +| 7.1 to 7.12 | yes | yes | +| 7.13 standalone shell | no | yes | + +Module 7.12 (screens) is smaller in `integrate` mode when the HMIS already has patients, admissions and documents; the plan says which existing screens gain a panel and which are new. + +### 2. Order and dependencies + +The ladder is sequential by stage. Inside stage 7, foundation modules come first, then this skill's modules in the order of `stages/7-write-code/README.md`; the plan may not reorder them, because each module's validation assumes the ones before it exist. + +### 3. Risks + +Copy into a risk table the rules from `references/flow-knowledge.md` section 5 that touch this skill's legs; its `SKILL.md` names them in its stage 2 row. Each rule is a way the build fails live even when the offline tests pass. When this skill builds or extends a foundation module, add the foundation's rules too: acknowledge or lose the thread; one message is taken once (dedupe on `x-hcx-api_call_id`). Add every `partial` prerequisite from stage 0, and the build's own risks: a missing HPIN on the practitioner table, no inbound route to the HMIS, a plan master too large for the database column, a callback behind auth middleware. + +### 4. What the user must do + +List every point where the ladder stops for the user: agreeing stage 1, running an owning skill first when a prerequisite is missing, supplying participant credentials (the ABDM client id and secret), registering the participant's certificate and callback address, starting the services for stage 10 rungs 3 and 4 (the app's public callback, or nhcx-adapter when the user chose it), sweeping live pre-auths before a PMJAY run. + +## Write + +- This skill's section of `nhcx-build/2-planning.md`, from `templates/2-planning.md`. +- This skill's block in `nhcx-build/STATE.md` (created at stage 0 from `templates/STATE.md`), with a row per stage and a row per module part, each module row carrying its action. +- `nhcx-build/NOTES.md`, empty but for its heading, if it does not exist. + +## Gate + +- [ ] Every stage 3 to 11 has a row with a size and a proof, for this skill. +- [ ] Every module this skill touches, and every foundation module, has its verdict and its action; 7.13 is marked by mode. +- [ ] The risk table holds every rule this skill's `SKILL.md` names for stage 2, and the foundation's rules when this skill builds or extends a foundation module. +- [ ] The user-action list names the credentials and the service starts. +- [ ] STATE.md has this skill's block with a row per stage and per module part. + +## Common mistakes + +- Estimating in days. Estimate in size; the user turns size into time. +- Planning to skip stage 8 or 9 "for the first pass". They are what makes the report true. +- Planning to rebuild a capability stage 0 found present. +- Reordering modules so screens come first. Screens derive from messages; without readers there is nothing to derive from. diff --git a/plugins/nhcx/skills/nhcx-communication/stages/3-discovery.md b/plugins/nhcx/skills/nhcx-communication/stages/3-discovery.md new file mode 100644 index 000000000..9feb26eca --- /dev/null +++ b/plugins/nhcx/skills/nhcx-communication/stages/3-discovery.md @@ -0,0 +1,97 @@ +# Stage 3: discovery + +Purpose: find the surface you will build on. In `integrate` mode that is the HMIS; in `standalone` mode it is the runtime, the storage and the deployment target the user has chosen. Every answer names the file, table or endpoint that proves it. An answer without proof is a gap. + +`3-discovery.md` is shared by the seven skills: one row per concern, each naming the skill that answered it. This skill answers the rows its `SKILL.md` lists under "Host facts", and the framework and runtime rows if no skill has. A row an earlier skill answered with proof is reused; check it again only if the code changed since. + +Stage 0 looked for NHCX capabilities. This stage looks at the host: where patients, admissions, doctors, documents and bills live. + +## Inputs + +- `nhcx-build/1-idea.md`, `nhcx-build/2-planning.md`, this skill's section of `nhcx-build/0-capability.md` +- This skill's `SKILL.md`, "Host facts" +- The target codebase (integrate) or the chosen runtime (standalone) +- `stages/7-write-code/7.2-storage.md` (the claim tables) and `stages/7-write-code/7.13-standalone-shell.md` (patient, encounter, practitioner, document), as the shape to compare against + +## Do + +Answer in writing every question below that this skill's host facts name, plus the framework and runtime questions when they are not yet answered. Reading only; change nothing. + +### Framework and runtime + +| Question | Why it matters | +| --- | --- | +| Language, web framework, ORM, database engine, migration tool | Where a new table goes and how it is created | +| How configuration is read (env, file, database) | Where the transport's settings live: the participant code, and the client id and secret and the private key (`own`), or the adapter URL and key (`adapter`) | +| How the app exposes an HTTP endpoint an outside process can POST to; which auth middleware must be exempted | The callback door, module 7.3 | +| Background worker or scheduler, or none | Whether polls run on the request path or in a worker | +| How the app serves a page and what the screen conventions are | Module 7.12 must match them | +| How tests are run and where they live | Stage 9 must match them | + +### Patients + +| Question | Why it matters | +| --- | --- | +| The patient table, its primary key, the unique identifier (MRN) | `claim.patient_id` | +| Where name, gender, date of birth, phone, ABHA number live | The Patient resource in every bundle | +| Where a scheme member id (PMJAY id) and a policy code can be stored, per patient or per visit | The Coverage resource; the policy search result | + +### Admissions and encounters + +| Question | Why it matters | +| --- | --- | +| The inpatient encounter table: admission time, discharge time, ward or bed, admitting doctor, status | `billablePeriod`, `ONS/ADDD`, the care team | +| How discharge is recorded, and whether it can carry a mode (normal, LAMA, DAMA, death) and a stage (before, during, after surgery) | `DIS` and `DSDE` on the claim; the LM100 collapse | +| Diagnoses: SNOMED, ICD-10 or free text | The payer needs ICD-10 with a display | +| Procedures or surgeries, and whether a surgery time is recorded | `ONS/PSP` | + +### Billing + +| Question | Why it matters | +| --- | --- | +| Billing lines: code, quantity, unit price, net; which charge master | Lines are quoted from the payer's plan, not the HMIS master, but the two must be reconcilable | +| Whether a line can be tagged with a payer package code and a category | `claim_line` | +| Invoices and receipts: where a settlement amount and a UTR go | Payment notices, module 7.10 | + +### Documents + +| Question | Why it matters | +| --- | --- | +| Where PDFs and images live (blob column, filesystem, object store) | `valueAttachment` needs the bytes and the content type | +| Whether a file can be tagged with a payer document code and a stage (pre-auth or claim) | The plan's requirement codes; never `ODN` for a file that was asked for by name | +| Accepted content types | The scheme takes pdf, jpg, jpeg, png only (PAYR-1008) | + +### Doctors + +| Question | Why it matters | +| --- | --- | +| The practitioner table; an HPR id (HPIN); a licence number; a qualification string | PMJAY refuses a pre-auth without an HPIN typed identifier (PAYR-1083) | + +### Facility + +| Question | Why it matters | +| --- | --- | +| The facility's HFR id, name, phone; its NHCX participant code | The provider Organization; the sender code | + +### Standalone mode + +The same questions, answered for the runtime the user chose. Where the answer is "nothing exists yet", write what module 7.13 will create: `patient`, `encounter`, `practitioner`, `document`, `settings`. A standalone app still has to hold every fact the questions ask for; it simply has to capture it itself. + +## Write + +`nhcx-build/3-discovery.md` from `templates/3-discovery.md`: one table, concern by concern, columns `Concern | Where it lives (proof) | Gap | Answered by`. A gap is what stage 4 fills. Add rows; do not rewrite another skill's rows. + +## Gate + +- [ ] Every host fact this skill's `SKILL.md` names has a row, and so does every framework and runtime question. +- [ ] Every row that is not a gap names a file path, a table, or an endpoint. +- [ ] When this skill builds or extends the callback door, the callback route is answered: which URL, which middleware to exempt, or "no inbound route, poll only". +- [ ] When this skill's bundles carry a Practitioner, the HPIN question is answered; if the practitioner table has no HPR id, the gap says so. +- [ ] When this skill attaches documents, the document store is answered with content-type handling. + +## Common mistakes + +- Answering from the framework's documentation instead of the codebase. The proof column is the codebase. +- Skipping the discharge-mode question. A death claim without `DTM` is refused (PAYR-1096); the HMIS must be able to say the patient died and when. +- Treating "no background worker" as a blocker. Without one, polls run on the request path; it is a design input, not a stop. +- Answering every concern for every skill. Answer the ones this skill needs; the next skill adds its own. diff --git a/plugins/nhcx/skills/nhcx-communication/stages/4-flow-and-data-mapping.md b/plugins/nhcx/skills/nhcx-communication/stages/4-flow-and-data-mapping.md new file mode 100644 index 000000000..bf51c7991 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-communication/stages/4-flow-and-data-mapping.md @@ -0,0 +1,92 @@ +# Stage 4: flow and data mapping + +Purpose: decide where every fact the exchange needs comes from and where every fact the exchange returns goes, leg by leg. This is the design stage with the most rows; get it right and stages 6 and 7 are transcription. + +Two parts of this stage belong to the episode, not to one skill: the flow table (section 1) and the home of every table (section 2), with the matching order (section 4). The first skill to run this stage writes them whole, so every later skill builds on one design; a later skill checks them and adds only what its gaps need. The field mapping (section 3) is this skill's own bundles only. + +## Inputs + +- `nhcx-build/1-idea.md` (scope), `nhcx-build/3-discovery.md` (the surface and its gaps), this skill's section of `nhcx-build/0-capability.md` (what exists already) +- This skill's `SKILL.md`: its steps, legs, bundles and tables +- `flow/FLOW.md` and `flow/flow.json`: the steps this build implements. They are copied, not redesigned. +- `references/flow-knowledge.md` sections 1, 2, 4 and 5 +- `references/transport-knowledge.md` section 2 (what a send returns, what arrives at the door) +- `references/fhir-knowledge.md` sections 3 to 10 (what each bundle needs); `fhir/FHIR.md` for the exact elements, as the builders' data dictionaries name them +- `stages/7-write-code/7.2-storage.md`: the claim tables and the columns each must hold + +## Do + +### 1. The flow, for this build + +The first skill copies every step of `flow/flow.json` into the flow table, in order, with its id and its skills, and adds two columns for this build: the HMIS event it hangs off (admission, discharge, a desk action) and the mark from stage 1 (`in`, `later`, `out`). The steps, their order, their tabs, their guards and their action labels are the flow's; this build adds where each fact comes from, nothing else. Then note the payer branches as the flow has them (F9b, F11, F12: `19`/`131`/`161` resubmits against a Communication reply; `17` against an echoed id). The stage and sub-stage vocabulary is copied as is; do not rename it. + +Write the step ids into `mapping.json` under `flow.steps` and the eight tabs, in order and with their labels, under `flow.tabs`. + +A later skill checks its own steps' rows and fills their HMIS event where the first skill left it open. + +### 2. The episode tables + +The first skill gives every table below a home, not only its own. The home is one decision for the episode (sidecar tables, or columns on the HMIS's tables), and a skill that chose differently later would split the design. It writes the columns each table must hold, and the legs' columns under `legs`. Later skills read the homes and add only the columns their gaps need. + +For each table below, decide one of three homes and write it down: + +| Home | When | +| --- | --- | +| A new sidecar table keyed on the HMIS's own ids | Default. Keeps the HMIS schema untouched and the integration removable. | +| Columns added to an existing HMIS table | Only for a scalar the HMIS already half-holds (a member id on the visit, an HPIN on the doctor) | +| An existing table used as is (`existing`) | Only when it already holds every column named below. This is the home of a capability stage 0 found present: record its real name and its columns, and a gap for each column it lacks | + +| Table | Why it exists | Must hold | +| --- | --- | --- | +| `claim` | The episode: beneficiary, policy, payer, eligibility verdict, link to the admission, pre-auth draft, stage and sub-stage | claim number, member id, policy code, payer participant code, patient and encounter keys, `txn_id`, `correlation_id`, `stage`, `sub_stage` | +| `claim_plan`, `claim_plan_benefit`, `claim_plan_form` | The payer's package master, flattened; one per facility and policy, copied onto later episodes | packages with rate, kind, conditions, extras (tiers, implants), document requirements; questionnaires by url | +| `claim_auth`, `claim_auth_item`, `claim_auth_requirement` | The auth-requirements ruling on the quoted set | per line: authorised, excluded; per requirement: kind (document or form), code, url, stage | +| `claim_line` | What is quoted: procedures, implants, ward tiers with a parent procedure | code, kind, quantity, unit price, amount, parent code | +| `claim_form_answer` | Answers to the plan's questionnaires | url, linkId, answer, stage | +| `claim_preauth` | The pre-auth leg, one row rewritten each round (12, 19, 13, 131) | status, `txn_id`, `correlation_id`, `thread_correlation_id`, `api_call_id`, `preauth_ref`, `submission_kind`, `workflow_id`, request and response json, cancel fields | +| `claim_submission` | The claim leg plus the discharge | discharge mode, stage, dates; the same exchange columns as the pre-auth | +| `claim_query` | Every CommunicationRequest or Communication from the payer, classified | `correlation_id` (unique), request id, kind, reason code, status, reply fields | +| `claim_payment`, `claim_payment_detail` | Payment notices, matched by claim number, deduped by correlation id | amount, UTR, payment status, ack fields | +| `claim_enquiry` | Status, reprocess and release Tasks, one row per ask | kind, `correlation_id`, answer | +| `claim_predetermination` | A quote, one row per ask | as a pre-auth, without state effects | +| `claim_document` | Attachments with the payer's code, category and stage | bytes or a pointer, content type, code, stage | +| `claim_diagnosis`, `claim_care_team`, `claim_item` | ICD-10 codes, doctors, non-package items | as named | + +The rule that never bends: every leg row holds `txn_id`, `correlation_id` and `api_call_id` from the transport's answer, and `thread_correlation_id` separately, because a send refused at the door must not lose the thread the payer last answered on. + +### 3. Field mapping, per bundle + +For each bundle this skill sends (its `SKILL.md` lists them; `fhir-knowledge.md` sections 3, 4, 5, 7, 9, 10), one table: `FHIR element | Source (table.column or constant or payer answer) | Transform | Gap`. Do not fill values; name sources. The elements that are always mapped from a payer answer and never from the HMIS: package codes and rates (the plan), document codes and questionnaire urls (the plan or the ruling), `preAuthRef` (the ClaimResponse), the payer's own case number. + +For each bundle this skill reads (sections 6, 8, 9, 10 and the coverage answer in section 3), one table: `FHIR element | Destination | Rule`. The status rule for a ClaimResponse is `verdict_status`, copied verbatim; never read `outcome` alone. + +Where stage 0 found a builder or reader present, map what it does today, and name each element where it differs from the pin as a gap. + +### 4. Inbound matching + +Written once, by the first skill. Write the matching order as a numbered list: `x-hcx-correlation_id` against every leg table; then the claim number inside the bundle; then unmatched, archived, 2xx returned. Write the dedupe key: `x-hcx-api_call_id`. Write the archive path: `//NNN--.json` plus `transactions.txt`. A later skill adds its leg tables to the correlation order. + +## Write + +- `nhcx-build/4-flow-data-mapping.md` from `templates/4-flow-data-mapping.md`. The first skill writes the flow table, the table homes and the matching order at the top; each skill writes a section headed with its name holding its field mappings. +- `nhcx-build/mapping.json` in the shape of `templates/mapping.json`. The first skill writes `flow`, `episode`, `tables`, `legs` and `inbound` whole; every skill adds its bundles under `bundles`, each entry with `"skill"`. Stage 6 reads it. + +## Gate + +- [ ] The flow table has every step of `flow/flow.json`, in its order, with its id, its skills and an in/later/out mark; `mapping.json` `flow.steps` lists every id and `flow.tabs` the eight tabs verbatim. +- [ ] Every table above has a home in `mapping.json` under `tables`. +- [ ] Every leg table's columns in `mapping.json` include `txn_id`, `correlation_id`, `api_call_id` and `thread_correlation_id`. +- [ ] `mapping.json` `episode.columns` includes `stage` and `sub_stage`. +- [ ] Every bundle this skill sends has a source table; every element with no source is listed as a gap, not omitted. +- [ ] Where this skill's bundles carry a Practitioner, the HPIN element's source is named (or its gap is). +- [ ] Every capability stage 0 found present is mapped to what exists, with its differences from the pin as gaps. +- [ ] The matching order, the dedupe key and the archive path are written. + +## Common mistakes + +- Redesigning the flow: merging tabs, adding a "status" step, moving the discharge out of the claim tab. The flow is the reference flow; copy it. +- Giving homes only to this skill's tables when it is the first to run the stage. The next skill would choose differently. +- Mapping package rates to the HMIS charge master. Prices come from the plan; the master is for reconciliation. +- One `correlation_id` column on the episode instead of one per leg. Each leg is its own thread. +- Forgetting `thread_correlation_id`. It is the difference between a recoverable door refusal and a dead case. +- Mapping `Patient` demographics on the coverage request. Only the member id goes out; the payer returns the rest. diff --git a/plugins/nhcx/skills/nhcx-communication/stages/5-screen-plan.md b/plugins/nhcx/skills/nhcx-communication/stages/5-screen-plan.md new file mode 100644 index 000000000..9ec0d8bc2 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-communication/stages/5-screen-plan.md @@ -0,0 +1,74 @@ +# Stage 5: screen plan + +Purpose: decide the screens, and for every value on every screen, the received message it is derived from. The two honesty rules are the whole point of this stage, and a reviewer tests them before anything else. + +The case screen is the episode's (`foundation.screens`): its eight tabs, the status line and actions, the JSON state address and the cases list. The first skill to run this stage lays them out whole, every tab present with its opening condition. Each skill then plans the values and actions of its own tabs and screens, which its `SKILL.md` lists. + +## Inputs + +- `nhcx-build/1-idea.md`, `nhcx-build/3-discovery.md` (screen conventions), `nhcx-build/4-flow-data-mapping.md` +- This skill's `SKILL.md`: its tabs, its screens, its next actions +- `flow/FLOW.md` ("The shape", "The status line and the actions", every step's Screen line) and `flow/flow.json`: the screens are put on these steps, not invented. +- `references/flow-knowledge.md` section 4 (stage, sub-stage, next actions) +- `ui/UI-GUIDE.md`: the screens, a layout per screen, where every value comes from, the state words. Read it whole before planning. +- `nhcx-package/docs/03-Building a Provider/09-UI Guide.md` (the published source of the guide) + +## The two rules + +1. No screen shows a decision the exchange has not sent. Every state on every screen is derived from a stored message. A case with a request sent and no answer back reads as waiting, never approved, never rejected. That case exists only because module 7.3 kept a record of what was sent, so the screen must be able to render a leg with a request and no response. +2. Nothing the exchange already knows is typed. Payer names, policies, balances, package rates, the payer's own wording, `preAuthRef`, the approved amount, the UTR are rendered from the message that carried them. A package rate is never an editable field. + +## Do + +### 1. The screen list + +The case screen carries the eight tabs of `flow.json` `tabs`, in that order, with those labels, opening under those conditions. The status line and the action list above the tabs use the labels of `flow.json` `next_actions` verbatim. Then, minimum, once every skill has run: + +| Screen | Who | Shows | Derived from | Planned by | +| --- | --- | --- | --- | --- | +| Cases list | billing clerk | every episode, its stage and sub-stage, what it waits for | `claim.stage`, `sub_stage`, `next_actions` | the first skill | +| Case | everyone | the timeline of legs, the payer's answer verbatim, the actions open now | every leg row and its archived messages | the first skill; each skill its tabs | +| Inbox | desk | payer messages routed by kind: query, notification, note | `claim_query` | `nhcx-communication` | +| Payments | accounts | notices, deductions, UTR, reconciliation | `claim_payment`, `claim_payment_detail` | `nhcx-payment` | +| Find and cover | registration clerk | policy search, eligibility verdict, register or link | the policy search answer and the `on_check` bundle | `nhcx-coverage` | +| Plan | doctor | specialty, package, add-ons, tiers, the documents and forms the plan wants | `claim_plan_*`, `claim_auth_*` | `nhcx-insurance`, with the ruling from `nhcx-preauth` | + +`integrate` mode adds a panel to the HMIS's own admission screen linking the admission to its episode. `standalone` mode adds the capture screens module 7.13 describes (patient, admission, discharge, documents, settings). + +Where stage 0 found a screen present, plan what it shows today against the rules, and list every value that breaks one as a gap. + +### 2. Per screen, per value + +For every value on this skill's screens, one row: `Value | Message and element | Empty state`. The empty state is what the screen shows before the message arrives (for a decision: "waiting"; for a rate: nothing, the field does not exist yet). A value whose source is "the user types it" is allowed only for things the exchange cannot know: the discharge mode and dates, the desk's reply to a query, the documents, the questionnaire answers, the chosen lines. + +### 3. Actions + +Every action is one step of `flow.json` and carries its id in `step`. For every action this skill's screens offer, the leg it sends, the sub-stage that must hold for it to be offered, and the sub-stage it moves to. Take the offered-when rules from `next_actions` in flow-knowledge section 4: an unanswered query always leads; the reply box is offered only to a `resubmit` payer; after a rejection the pre-auth offers a fresh 12, not 121. + +### 4. Addresses and conventions + +Write the route for each screen in the HMIS's own style (from stage 3). The state of a case must also be readable as JSON at one address, because stage 10 drives the screens through it (for example `GET /claims//state`). Each skill adds its legs to what the address returns. + +## Write + +- `nhcx-build/5-screen-plan.md` from `templates/5-screen-plan.md`: the shell at the top (first skill), then a section per skill. +- `nhcx-build/screens.json` in the shape of `templates/screens.json`: the first skill writes `rules`, `tabs`, `state_address`, the cases list and the case screen; each skill adds its screens and actions. + +## Gate + +- [ ] `screens.json` `tabs` lists the eight tabs of `flow.json` in order with the same keys and labels. +- [ ] Every user-driven step this skill owns (its steps among F1 to F13, except F9a, F12 and F12b, which the payer starts) appears as an action with its `step` id, and every action's `label` is one of `flow.json` `next_actions` or the step's own button. +- [ ] `screens.json` holds the cases list, the case screen, and every screen this skill plans, each with a route (plus 7.13's in standalone mode). +- [ ] Every screen this skill plans has a `values` list and every value names a message element or is marked `typed` with a reason from the allowed list. +- [ ] Every decision-bearing value has an empty state of waiting. +- [ ] No `values` entry marks a rate, a payer name, a `preAuthRef` or a UTR as typed. +- [ ] Every action names its leg, its offered-when sub-stage and its resulting sub-stage. +- [ ] A JSON state address exists for a case. + +## Common mistakes + +- A status dropdown on the case. Status is derived; there is no dropdown. +- Showing `preAuthRef` from the pre-auth's own claim number. It comes from the ClaimResponse. +- Designing the desk's reply box for a `communication` payer on the leg. It belongs on the inbox item. +- Laying out only this skill's tab when it is the first to run the stage. The shell has all eight. +- Screens that need JavaScript. Forms post and the page re-renders; that is enough. diff --git a/plugins/nhcx/skills/nhcx-communication/stages/6-code-plan.md b/plugins/nhcx/skills/nhcx-communication/stages/6-code-plan.md new file mode 100644 index 000000000..2167000f1 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-communication/stages/6-code-plan.md @@ -0,0 +1,68 @@ +# Stage 6: code plan + +Purpose: turn the mapping, the screen plan and the capability verdicts into a list of modules with files, dependencies, the pin each is held to, and what this skill does to each. Stage 7 builds this list in order; stage 8 validates it in order. + +The transport's shape, the configuration, the archive and the test placement (sections 2 to 5) are the episode's: the first skill to run this stage writes them, and later skills use them. + +## Inputs + +- `nhcx-build/3-discovery.md`, `nhcx-build/4-flow-data-mapping.md`, `mapping.json`, `nhcx-build/5-screen-plan.md`, `screens.json` +- This skill's section of `nhcx-build/0-capability.md` and `nhcx-build/2-planning.md` (the action per module) +- `stages/7-write-code/README.md` and every `7.N-*.md` this skill touches: the module ladder is fixed; the plan decides the files +- `references/fhir-knowledge.md` section 1: where the pins live +- `fhir/FHIR.md`: the builders and readers the modules 7.4 to 7.10 implement, so the plan names them + +## Do + +### 1. Place each module + +For each module this skill touches (its `SKILL.md` lists them) and each foundation module it builds or extends, write: + +| Field | Meaning | +| --- | --- | +| `skills` | A map from skill to action: `build`, `extend` or `reuse`. A module another skill already placed keeps its entry; add this skill and its action | +| `files` | The files it creates or changes, in the target's layout and naming (from stage 3). For a reused or extended module, the files that exist | +| `depends_on` | The modules that must exist first; the ladder's order is the floor, the plan may add more | +| `held_to` | The pin in `nhcx-package/fhir` (its file, from `references/material.md`), the payer fixture, or the rule (for modules with no bundle) | +| `copy_from` | What the module follows: its own Pseudo code section and the `fhir/FHIR.md` section it names | +| `tables` | The tables from `mapping.json` it reads and writes | +| `screens` | The screens from `screens.json` it serves (7.12 and 7.13 only) | + +`modules.json` holds one entry per module, in ladder order (7.1 to 7.13), whichever skill adds it. + +### 2. The transport's shape + +Decide once, and every module uses it: the transport kind from stage 1, and the functions of the contract in `references/transport-knowledge.md` section 2: `send`, the receiving end that hands the door a normalised envelope, `policies`, `participants`, `token`, and `thread` and `fetch_missed` where the kind has them. Name them here so 7.4 to 7.10 call the same thing. A stub of `send`, recording the path, recipient, workflow id, correlation id and bundle and returning `{"txn_id", "correlation_id", "api_call_id"}`, is what stage 9 injects. When stage 0 found an existing transport, name its functions and what wraps them. + +### 3. Configuration + +List every setting and where it lives (from stage 3): the transport kind, participant code, facility HFR id and name, cases directory, per-payer overrides for workflow ids, and the transport's own. For `own`: the ABDM client id and secret, the private key, the sessions, NHCX and registry addresses, and the NHCX signing key once onboarding gives it. For `adapter`: its URL, API key and callback secret. For `existing`: whatever its client reads. Name the environment variables or config keys in the target's convention. + +### 4. The archive + +The per-case archive path from stage 4, and which module writes it (7.3 for inbound, 7.1 for outbound). + +### 5. Test placement + +Where the offline test lives (from stage 3's "how tests are run"), and how the pin comparison is wired: canonical JSON, `created` excluded, one comparison per pin. + +## Write + +- `nhcx-build/6-code-plan.md` from `templates/6-code-plan.md`: the episode sections once, the modules table, and this skill's section. +- `nhcx-build/modules.json` in the shape of `templates/modules.json`. + +## Gate + +- [ ] `modules.json` has an entry, in ladder order, for every module this skill touches and every foundation module (7.13 in standalone mode). +- [ ] Every entry this skill touches has non-empty `files`, `depends_on` (7.1 may be empty), `held_to` and `copy_from`, and this skill in `skills` with its action. +- [ ] Every pin this skill owns appears in some module's `held_to`. +- [ ] The transport kind and its functions are named. +- [ ] The configuration list includes the transport kind, the participant code, the cases directory, and every setting the chosen transport needs. +- [ ] The test file's location and the pin comparison rule are written. + +## Common mistakes + +- Splitting the claim bundle builder across modules by leg, or by skill. One builder, one `leg` and `flow` argument, is what the pins expect; `nhcx-claim` extends what `nhcx-preauth` built. +- Planning a second transport for the reply legs. Same function; the reply legs add `x-hcx-correlation_id` to the headers. +- Planning new files for a module stage 0 found present. +- Planning the screens before the readers exist in the dependency list. diff --git a/plugins/nhcx/skills/nhcx-communication/stages/7-write-code/7.1-config-and-transport.md b/plugins/nhcx/skills/nhcx-communication/stages/7-write-code/7.1-config-and-transport.md new file mode 100644 index 000000000..2ad046569 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-communication/stages/7-write-code/7.1-config-and-transport.md @@ -0,0 +1,131 @@ +# Module 7.1: configuration and the NHCX transport + +Purpose: the one path every message leaves by, whichever transport carries it. The settings, the transport chosen at stage 1 behind one `send`, the policy lookup, and the outbound half of the per-case archive. + +Skills: the foundation (`core/FOUNDATION.md`). Built whole by the first skill whose stage 0 finds it absent; every skill sends through it. + +## Depends on + +Nothing. First module. + +## Inputs + +- `nhcx-build/1-idea.md`: the transport, `existing`, `own`, or `adapter` because the user asked for it +- `nhcx-build/6-code-plan.md` sections 2 to 4 (the transport's functions, the configuration keys, the archive path) +- `references/transport-knowledge.md` section 2 (the contract), and section 3 (`own`), 4 (`existing`) or 5 (`adapter`) for the kind chosen +- With `adapter` only: `references/api-knowledge.md` sections 2 to 5, 7, 8 and 11 + +## Build + +### Settings + +Read from the target's configuration mechanism (stage 3). + +| Setting | Transport | Meaning | +| --- | --- | --- | +| transport kind | all | `existing`, `own` or `adapter` | +| participant code | all | The hospital's, with `@hcx`: `x-hcx-sender_code` | +| facility HFR id, name, phone | all | The provider Organization | +| cases directory | all | The per-case archive root | +| per-payer workflow id overrides | all | Optional, for a payer that insists on a code the table does not carry (`cancel` as 122) | +| ABDM client id and secret | own | The session token (`transport-knowledge.md` section 3.3) | +| private key | own | The PEM behind the certificate on the participant record, read from a file or a secret store | +| sessions, NHCX and registry addresses, `X-CM-ID` | own | From `nhcx-package/baseurl.yaml`; the sandbox by default | +| NHCX signing key | own | For the exchange's JWT on inbound calls. Empty until onboarding gives it, and logged while empty | +| adapter URL, adapter API key, callback secret | adapter | `references/api-knowledge.md` section 2. Also fill the adapter's `config.sample.json` into `nhcx-build/adapter.config.json`, secrets as `${ENV}` placeholders | +| whatever the existing client reads | existing | Named here, not duplicated | + +Secrets are read from configuration: never in code, never in `nhcx-build/`. + +### The transport + +One `send` with the signature in `transport-knowledge.md` section 2, and beside it `policies`, `participants`, `token`, `thread` and `fetch_missed`. What sits under them depends on the kind: + +| Kind | `send` | `policies`, `participants`, `token` | `thread`, `fetch_missed` | +| --- | --- | --- | --- | +| `own` | Seal and post (`transport-knowledge.md` sections 3.3 to 3.8): the token, the recipient's certificate, the protected header, a compact JWE, `{"payload"}` to `/v1/`, a `401` retried once | The participant service directly (sections 3.6 and 3.7) | `thread` reads the per-case archive; `fetch_missed` answers `unavailable` | +| `existing` | Calls the app's own client and maps its answer onto `{txn_id, correlation_id, api_call_id}` (section 4) | The app's own calls, or the participant service directly | What the app keeps; else as `own` | +| `adapter` | POSTs `{jwe_headers, fhir}` to `/fhir/out/` with the bearer key (`api-knowledge.md` sections 4 and 5) | `/internal/policies/search`, `/internal/participants/list`, `/token` | The adapter's ledger and `/internal/txn/*` (`api-knowledge.md` sections 7 and 8) | + +Common to every kind: + +1. A send without a recipient, a workflow id or the beneficiary's ABHA is refused before anything goes on the wire. +2. The recipient is the policy's processor: `recipient_of(row)` is `claim.recipient_code`, else `claim.payer_code` for an episode opened before the processor was kept. +3. A correlation id is passed only on the two answer legs, the communication reply and the payment acknowledgement. On a request the transport mints it (`own`: the message's own `api_call_id`). +4. A refusal raises `TransportError(code, message, protocol_response, retryable)`: the gateway's status and body (`own`), the adapter's `error.code` and `upstream_body` (`adapter`), or the existing client's error. A ProtocolResponse inside it is a refusal at the door; the caller records the payer's words. +5. The outbound message is archived before `send` returns: `//NNN--out.json` with what was sent and what came back, and a `transactions.txt` line (sequence, time, direction, path, workflow id, correlation id, api call id, txn id, outcome). With `own`, the archive entry is the `txn_id`. +6. The caller stores `txn_id`, `correlation_id` and `api_call_id` on the leg. + +## Rules + +- Use nhcx-adapter only when the user asked for it; `1-idea.md` records their words. Never propose it. +- Keep an existing NHCX integration and wrap it. Never put a second transport beside it. +- Seal and open JWEs only for `own`, and only with a JOSE library: `RSA-OAEP-256`, `A256GCM`, compact serialisation. Never hand-roll the cryptography. +- The workflow id goes out on every leg that has one; `x-hcx-ben-abha-id` goes out on every message. +- The sandbox refuses sends faster than one per 30 seconds per case (PAYR-1322). The transport does not throttle; the caller does. Say so in the docstring. +- The private key never leaves the server that receives callbacks, and never enters a log. + +## Validate + +- [ ] A send with no recipient, no workflow id or no beneficiary ABHA is refused before anything goes on the wire. +- [ ] The protected header of a send carries every mandatory field under the protocol's rules: sender and recipient with `@hcx`, a fresh `api_call_id`, a `correlation_id` equal to the `api_call_id` on a request and to the request's on an answer, the workflow id, `x-hcx-timestamp` in ISO 8601 with `+05:30`, `x-hcx-status` `request.initiated` or `response.complete`, and `x-hcx-ben-abha-id`. Observed on what the transport emits: the JWE header opened with a test key pair (`own`), the posted `jwe_headers` with the adapter's completion rules (`adapter`), the existing client's output (`existing`). +- [ ] The recipient is the episode's `recipient_code`, the policy's `processingid`, whenever the episode has one. +- [ ] A refusal raises `TransportError` carrying the code and the words the exchange or the adapter gave. With `own`, a `401` is retried once with a fresh token, and a second `401` raises. +- [ ] The archive file and the `transactions.txt` line exist after a send, with the sequence number zero-padded to three digits. +- [ ] Secrets are read from configuration, not present in code or in `nhcx-build/`. +- [ ] With `own`: a bundle sealed for a test certificate opens with its private key to the same bytes and the same protected header; the token is reused while fresh and fetched again when stale; a recipient's certificate is fetched once and then read from the cache. + +## Tests + +- Stub the HTTP layer and assert the URL, the headers and the body of one send with and one without a correlation id: `bearer_auth` and `{"payload"}` for `own`; the bearer key and `{jwe_headers, fhir}` for `adapter`. +- `own`: seal with a test key pair and open it again; check the header fields above; a `401` then a `202` sends twice with two tokens; a certificate in SPKI form loads as well as an X.509 one. +- `adapter`: a `502` with a ProtocolResponse `upstream_body` raises an error whose text carries the payer's `x-hcx-error_details` message; a `404` from `txn/related` is terminal, not retried. +- The archive sequence increments across two sends on one case. + +## Pseudo code + +The `own` transport's token, certificate cache, sealing and receiving end: `references/transport-knowledge.md` section 3.12. The adapter client: `references/api-knowledge.md` section 11. What every kind shares: + +``` +settings = { + transport: env("NHCX_TRANSPORT", "own"), # own | existing | adapter; adapter only when the user asked for it + participant_code: env("NHCX_PARTICIPANT_CODE"), # "@hcx" + facility: {hfr_id: env("NHCX_HFR_ID"), name: env("NHCX_FACILITY_NAME"), phone: ...}, + cases_dir: env("NHCX_CASES_DIR", "data/cases"), + workflow_overrides: parse_json(env("NHCX_WORKFLOW_IDS", "{}")), # {"1518@hcx": {"cancel": "122"}} + nhcx: {sessions: env("NHCX_SESSIONS_URL", "https://dev.abdm.gov.in/api/hiecm/gateway/v3/sessions"), # own + base: env("NHCX_BASE_URL", "https://apisbx.abdm.gov.in/hcx"), + registry: env("NHCX_REGISTRY_URL", "https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice"), + cm_id: env("NHCX_CM_ID", "sbx"), + client_id: env("NHCX_CLIENT_ID"), client_secret: env("NHCX_CLIENT_SECRET"), + private_key: read_secret(env("NHCX_PRIVATE_KEY_FILE")), signing_key: env("NHCX_SIGNING_KEY", "")}, + adapter: {url: env("NHCX_ADAPTER_URL"), api_key: env("NHCX_ADAPTER_API_KEY"), # adapter only + callback_secret: env("NHCX_CALLBACK_SECRET")}, +} + +transport = {"own": OwnTransport, "existing": ExistingTransport, "adapter": AdapterTransport}[settings.transport]() +# each offers send, policies, participants, token, thread, fetch_missed (transport-knowledge.md section 2) + +function recipient_of(row): return row.recipient_code or row.payer_code + +function ben_abha(claim_no): # the payer's Patient from the coverage answer, else the HMIS patient + row = claim_by_no(claim_no) + return digits(abha_in(row.patient_json) or patient(row.patient_id).abha) + +function with_hcx(code): return code if code.endswith("@hcx") else code + "@hcx" + +# the archive, outbound half; 7.3 writes the inbound half through the same function +function archive.record(claim_no, usecase, direction, payload): + folder = settings.cases_dir + "/" + (claim_no or "unmatched"); mkdir(folder) + n = next_sequence(folder) # 001, 002, ... + write(folder + f"/{n:03d}-{usecase}-{direction}.json", pretty(payload)) + append(folder + "/transactions.txt", f"{n:03d} {now()} {direction} {payload.path} wf={payload.workflow_id} " + f"cid={payload.correlation_id} acid={payload.api_call_id} txn={payload.txn_id} {payload.outcome}") + return f"{claim_no or 'unmatched'}/{n:03d}" +``` + +## Done when + +- Validate passes for the transport chosen. +- `own`: the onboarding the user must do is written into `nhcx-build/7-modules/7.1.md`: the credentials, the key and certificate, the participant record, the `endpoint_url`, and the NHCX signing key to ask NHA for. `adapter`: `nhcx-build/adapter.config.json` exists with placeholders. `existing`: the wrapper and every gap it closed are listed. +- `nhcx-build/7-modules/7.1.md` is written. diff --git a/plugins/nhcx/skills/nhcx-communication/stages/7-write-code/7.10-communication-and-payment.md b/plugins/nhcx/skills/nhcx-communication/stages/7-write-code/7.10-communication-and-payment.md new file mode 100644 index 000000000..271d56732 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-communication/stages/7-write-code/7.10-communication-and-payment.md @@ -0,0 +1,124 @@ +# Module 7.10: communication and payment + +Purpose: the two legs the payer starts. A CommunicationRequest is classified as a query, a notification or a note and answered accordingly; a PaymentNotice is recorded, matched to its claim, and acknowledged. + +Skills: `nhcx-communication` (classification, the notification acknowledgement, the reply) and `nhcx-payment` (the payment notice and its acknowledgement). Validate rows 1, 3, 4 and 5 are the communication half's; rows 2, 6 and 7 the payment half's; row 8 is both. + +## Depends on + +7.1 to 7.3, 7.7, 7.11 (for the payer's query mode; build 7.11's adapter table first if not yet). + +## Inputs + +- `references/flow-knowledge.md` section 3 (the two payer kinds, the classification rule) and section 1 rows "Payment notice" and "Communication" +- `references/fhir-knowledge.md` sections 9 and 10 +- Pins: `nhcx-package/fhir/B4/communication-request.json` (the payer's message), `B4/communication-response.json` (the reply), `nhcx-package/fhir/B7/payment-notice-ack.json` +- Payer messages: `nhcx-package/fhir/C6/C6-preauth-query-wf24.json` and `C6/C6-claim-query-wf27.json` (generic queries), `C6/C6-notification-wfN02.json` (PMJAY notification), `nhcx-package/fhir/C9/*.json` (payment notices) + +## Build + +### Classification + +`classify_communication(adapter, reason_code, intent) -> kind`, in order: a `resubmit` payer's request is a notification; `intent proposal` is a notification, `order` a query; then `reasonCode`: absent, `additionalinfo`, `questionnaire`, `query` is a query, anything else (`tatquery`, `grievance`, `walletupdate`, `policychange`, `claimarbitration`, with `claimArbitartion` folded in) a notification. A bare `Communication` with no request is a note: recorded, shown, never acted on. + +### Receiving + +`parse_communication_request(bundle)`: the Task's status, intent, reason; the CommunicationRequest's id, `basedOn` (the Claim), one question per `payload[].contentString`; the leg asked about (from the Claim's `use` or the `basedOn` identifier). Store a `claim_query` row keyed on the message's correlation id with `kind`, `stage`, `questions_json`, status `open`. + +### Acknowledging a notification + +`build_acknowledgement_bundle(query_id)`: the payer's own bundle sent back with `Task.status` flipped to `completed`, the reason echoed and the provider Organization first, on `v1/communication/on_request` with the request's correlation id and workflow id echoed in `jwe_headers`. Sent by `acknowledge_notification` from outside the callback (the desk's next request, or a worker). Status `acknowledged`. + +### Answering a query (communication payer) + +`build_communication_bundle(query_id, text, document_ids)`: a TaskBundle with a Task `deliver`, `completed`, including the Communication; the Communication `basedOn` the request (never `inResponseTo`) and `about` the Claim, its text a `contentString`, each document a `contentAttachment` under the document-type extension (its url is participant-defined: read it from configuration; the pin comparison takes the pin's own url); the CommunicationRequest echoed; then the Claim, Patient, provider Organization, payer Organization, Practitioner and Coverage lifted from the queried leg's bundle as sent. This bundle carries `meta.lastUpdated` and `timestamp` (the IG example does). Sent on `v1/communication/on_request` with the request's correlation id and workflow id. Status `answered`. + +For a `resubmit` payer the answer is not here: it is 7.7's query answer on a fresh thread. The inbox item for a PMJAY query is the leg's `query_note`, and its reply box calls `submit_preauth` or `submit_claim` with the reply. + +### Payment notice + +`parse_payment_notice(bundle)`: `PaymentNotice.amount`, `paymentStatus`, `paymentDate`, the `request` reference's identifier (the claim number), `payment` identifier (the UTR when settled), the `PaymentReconciliation` details when present. `record_payment` matches the claim number, dedupes on the correlation id, stores `claim_payment` and `claim_payment_detail`, and stamps the episode `payment`/`noticed` or `paid`. + +### Payment acknowledgement + +`build_payment_ack(payment_id)`: a TaskBundle in the shape of `B7/payment-notice-ack.json`, sent on `v1/paymentnotice/on_request` with the notice's correlation id and, for PMJAY, workflow `17`; for a generic payer the notice's own workflow id echoed (`None` in the adapter table means echo). Sent by `acknowledge_payment` from outside the callback. `ack_status` `sent` or `error`. + +## Rules + +- The reply names the request in `Communication.basedOn`, never `inResponseTo`. +- A `resubmit` payer's CommunicationRequest is always a notification, whatever it says. +- A notification is acknowledged at once and the case is left alone. +- The acknowledgement and the reply are the only two sends that carry `x-hcx-correlation_id` (with the payment acknowledgement). + +## Validate + +- [ ] `B4/communication-response.json` pin: the builder fed the request pin (`B4/communication-request.json`) and the pre-auth pin (`B3/preauth-request.json`) produces the response pin byte for byte (`meta.lastUpdated`, `timestamp` and `authoredOn` excluded). +- [ ] `B7/payment-notice-ack.json` pin comparison passes. +- [ ] Classification: the generic query (`C6/C6-preauth-query-wf24.json`: `intent order`, `additionalinfo`) is a query; the PMJAY notification (`C6/C6-notification-wfN02.json`: `intent proposal`, `information`) is a notification; the same PMJAY bundle under a `communication` adapter with `intent order` is a query; a bare Communication is a note. +- [ ] The reply's `Communication.basedOn` names the request and `inResponseTo` is absent. +- [ ] The acknowledgement and the reply carry `x-hcx-correlation_id` equal to the request's; the workflow id is echoed. +- [ ] Two deliveries of one notice create one `claim_payment` row. +- [ ] The PMJAY acknowledgement carries workflow `17`; the generic one echoes the notice's. +- [ ] No send happens inside the callback (7.1 stub sees zero sends during receipt). + +## Tests + +- The two pin comparisons. +- Classification table as a parametrised test. +- B6, B7, C6, D8, D13 and the notification rows from the matrix. + +## Pseudo code + +Classification, the acknowledgement, the reply and the payment reader: `fhir/FHIR.md` sections 7 and 8. Wiring: + +``` +APPLY["inbound_request"] = function (row, env): + kind = resource_types(env.fhir) + if "PaymentNotice" in kind: record_payment(row, env) + elif "CommunicationRequest" in kind: receive_communication(row, env) + elif "Communication" in kind: record_note(row, env) # a bare Communication: shown, never acted on + +function receive_communication(row, env): + p = fhir.parse_communication_request(env.fhir); adapter = payers.for_claim(row) + kind = fhir.classify_communication(adapter, p.reason, p.intent) + q = insert("claim_query", {claim_id: row.id, correlation_id: env.jwe_headers["x-hcx-correlation_id"], request_id: p.request_id, + workflow_id: env.jwe_headers["x-hcx-workflow_id"], sender_code: env.jwe_headers["x-hcx-sender_code"], + kind, stage: leg_asked_about(row, p), reason_code: p.reason, intent: p.intent, questions_json: p.questions, + request_json: env.fhir, status: "open", received_at: now()}) + if kind == "notification": enqueue(acknowledge_notification, q.id) # sent outside the callback + +function acknowledge_notification(query_id): + q = query(query_id); row = claim(q.claim_id) + bundle = fhir.build_acknowledgement_bundle(q.request_json, settings.facility) + r = transport.send("v1/communication/on_request", bundle, q.sender_code, workflow_id = q.workflow_id, correlation_id = q.correlation_id, claim_no = row.claim_no, usecase = "communication-ack") + update(q, {status: "acknowledged", reply_txn_id: r.txn_id, reply_api_call_id: r.api_call_id, replied_at: now()}) + +function answer_query(query_id, text, document_ids): # communication payer + q = query(query_id); row = claim(q.claim_id) + if payers.for_claim(row).query_mode == "resubmit": return submit_preauth(row.id, reply = text) if q.stage == "preauth" else submit_claim(row.id, reply = text) + sent = (preauth(row.id) if q.stage == "preauth" else submission(row.id)).request_json + bundle = fhir.build_communication_bundle(q, text, [doc_with_bytes(i) for i in document_ids], sent, settings.facility, payer_of(row), now_ist()) + r = transport.send("v1/communication/on_request", bundle, q.sender_code, workflow_id = q.workflow_id, correlation_id = q.correlation_id, claim_no = row.claim_no, usecase = "communication-reply") + update(q, {status: "answered", reply_text: text, reply_document_ids: document_ids, reply_txn_id: r.txn_id, replied_at: now()}); stamp_case(row.id) + +function record_payment(row, env): + p = fhir.parse_payment_notice(env.fhir) + pay = insert_or_ignore("claim_payment", {claim_id: row.id, correlation_id: env.jwe_headers["x-hcx-correlation_id"], workflow_id: env.jwe_headers["x-hcx-workflow_id"], + sender_code: env.jwe_headers["x-hcx-sender_code"], amount: p.amount, payment_status: p.payment_status, payment_date: p.payment_date, + utr: p.utr, notice_json: env.fhir, ack_status: "pending", received_at: now()}) + if not pay: return # the unique constraint caught a redelivery + for d in p.details: insert("claim_payment_detail", {payment_id: pay.id, type: d.type, amount: d.amount}) + enqueue(acknowledge_payment, pay.id) + +function acknowledge_payment(payment_id): + pay = payment(payment_id); row = claim(pay.claim_id); adapter = payers.for_claim(row) + bundle = fhir.payment_ack(submission(row.id).claim_ref or row.claim_no, now_ist(), settings.facility, payer_of(row)) + wf = adapter.workflow_ids.payment_ack or pay.workflow_id # 17 for PMJAY; echo for a generic payer + r = transport.send("v1/paymentnotice/on_request", bundle, pay.sender_code, workflow_id = wf, correlation_id = pay.correlation_id, claim_no = row.claim_no, usecase = "payment-ack") + update(pay, {ack_status: "sent", ack_txn_id: r.txn_id, ack_api_call_id: r.api_call_id, acked_at: now()}); stamp_case(row.id) +``` + +## Done when + +- Validate passes. +- `nhcx-build/7-modules/7.10.md` is written. diff --git a/plugins/nhcx/skills/nhcx-communication/stages/7-write-code/7.11-state-and-payer-adapters.md b/plugins/nhcx/skills/nhcx-communication/stages/7-write-code/7.11-state-and-payer-adapters.md new file mode 100644 index 000000000..94fbfc313 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-communication/stages/7-write-code/7.11-state-and-payer-adapters.md @@ -0,0 +1,145 @@ +# Module 7.11: state and payer adapters + +Purpose: two small tables of truth the whole build reads. The payer adapter says how a payer behaves; the stage machine says where an episode stands and what it waits for. + +Skills: the foundation (`core/FOUNDATION.md`). The first skill builds the payer adapter table whole; each skill adds the `case_stage` branches and the `next_actions` rows for its own legs. + +## Depends on + +7.2. (7.7 to 7.10 call it; build the adapter table as early as 7.4 needs the participant codes.) + +## Inputs + +- `references/flow-knowledge.md` sections 2, 3 and 4, whole +- `nhcx-build/1-idea.md` (the payers in scope) + +## Build + +### The payer adapter + +A table keyed by participant code (normalised: `1518` and `1518@hcx` are one key), each entry holding: + +| Field | PMJAY | Generic | +| --- | --- | --- | +| `query_mode` | `resubmit` | `communication` | +| `workflow_ids` | the PMJAY column of flow-knowledge section 2 | the generic column; `payment_ack` is `None` (echo) | +| `program_code` | `AB-PMJAY` | none | +| `auth_requirements` | asked | asked | +| `status_enquiry` | refused; do not offer | offered | +| `claim_resubmit` | none; reprocess only | `16` | +| `payer_system` | the identifier system for the payer Organization | same | + +`adapter_for(participant_code)` returns the entry or the generic default. `for_claim(row)` reads the episode's payer code. Overrides from configuration (7.1) merge on top, per payer, so a payer that insists on `cancel` as 122 is one config line. + +### Stage and sub-stage + +Stages: `eligibility`, `preauth`, `enhancement`, `claim`, `payment`. Sub-stages: `draft`, `checking`, `eligible`, `not-eligible`, `requested`, `resubmitted`, `answered`, `queried`, `approved`, `partial`, `rejected`, `cancelling`, `cancelled`, `refused`, `noticed`, `paid`. Send kind to sub-stage: `preauth`, `claim`, `enhancement` set `requested`; `*_resubmit` sets `resubmitted`; `*_query_response` and `enhancement_resubmit` set `answered`. `requested`, `answered`, `resubmitted` mean "with the payer". + +`case_stage(row, ...) -> (stage, sub_stage)`: a payment notice wins, then the filed claim, then the pre-auth (stage `enhancement` if the last submission kind was one), then a saved draft, then the eligibility status. An open communication query on a leg that is with the payer flips the sub-stage to `queried`. + +`stamp_case(claim_id)`: recompute and write both onto the episode. Called after every leg write by 7.3, 7.4 to 7.10. + +### Next actions + +The table in `flow/FLOW.md` ("The status line and the actions") and `flow/flow.json` `next_actions` is the specification; the labels are used verbatim. + +`next_actions(claim_id) -> [{label, tab, tone}]`, first is what the case waits for: an unanswered query always leads with "Answer the payer (n)"; the leg's own reply box only for a `resubmit` payer, a `communication` payer is sent to the inbox; a claim refused at the door offers "send again" while `claim_send_kind` still yields a kind, else "Ask for a reprocess"; after a rejection the pre-auth offers a fresh 12; a payer whose adapter refuses status enquiry never gets a "Ask status" action. + +## Rules + +- An unmapped payer is generic. +- The two words are derived, never set by a screen. +- Stamp after every write. A test that checks state after every step is what makes stage 8 possible. + +## Validate + +- [ ] `adapter_for("1518@hcx")` and `adapter_for("1518")` return the PMJAY entry; an unknown code returns generic. +- [ ] The PMJAY `workflow_ids` table equals flow-knowledge section 2's PMJAY column for every kind listed; the generic table has `payment_ack` as echo and `claim_query_response` as `151`. +- [ ] A configuration override for one kind changes only that kind. +- [ ] `case_stage` on each seeded state (draft; checking; eligible; pre-auth submitting; approved; queried by communication; enhancement requested; claim submitting; payment noticed; paid) returns the expected pair (write the table in the test). +- [ ] `next_actions` leads with the query when one is open; offers no status enquiry for PMJAY; offers a fresh 12 after a rejection. +- [ ] For every row of `flow.json` `next_actions`, the seeded state yields that label, character for character. +- [ ] After every leg write in 7.4 to 7.10, `claim.stage` and `sub_stage` equal `case_stage` recomputed. + +## Tests + +- A parametrised table for `case_stage`. +- A parametrised table for `next_actions`. +- The adapter lookups and the override. + +## Pseudo code + +``` +QUERY_MODE_RESUBMIT = "resubmit"; QUERY_MODE_COMMUNICATION = "communication" + +PMJAY = {"name": "PMJAY", "query_mode": QUERY_MODE_RESUBMIT, "program_code": "AB-PMJAY", "auth_requirements": true, + "status_enquiry": false, "payer_system": "https://nhcx.abdm.gov.in", + "workflow_ids": {"preauth": "12", "preauth_resubmit": "121", "preauth_query_response": "19", "enhancement": "13", "enhancement_resubmit": "131", + "cancel": "PC01", "claim": "15", "claim_query_response": "161", "claim_resubmit": null, "payment_ack": "17", "reprocess": "36", "release": "36"}} +GENERIC = {"name": "generic", "query_mode": QUERY_MODE_COMMUNICATION, "program_code": null, "auth_requirements": true, "status_enquiry": true, + "payer_system": "https://nhcx.abdm.gov.in", + "workflow_ids": {... as PMJAY except "claim_query_response": "151", "claim_resubmit": "16", "payment_ack": null}} # null = echo the notice's id +ADAPTERS = {"1518": PMJAY} # keyed without @hcx + +function adapter_for(participant_code): + key = (participant_code or "").split("@")[0] + base = deepcopy(ADAPTERS.get(key, GENERIC)) + for (k, v) in settings.workflow_overrides.get(with_hcx(key), {}): base.workflow_ids[k] = v + return base + +function for_claim(row): return adapter_for(row.payer_code) + +STAGES = ["eligibility", "preauth", "enhancement", "claim", "payment"] +KIND_TO_SUB = {"preauth": "requested", "claim": "requested", "enhancement": "requested", "preauth_resubmit": "resubmitted", "claim_resubmit": "resubmitted", + "preauth_query_response": "answered", "claim_query_response": "answered", "enhancement_resubmit": "answered"} +WITH_PAYER = {"requested", "answered", "resubmitted"} + +function leg_sub_stage(leg): + if leg.status == "submitting": return KIND_TO_SUB.get(leg.submission_kind, "requested") + return {"approved": "approved", "partial": "partial", "queried": "queried", "rejected": "rejected", "error": "refused", + "cancelling": "cancelling", "cancelled": "cancelled", "draft": "draft"}.get(leg.status, leg.status) + +function case_stage(row): + paid = sum(p.amount for p in payments(row.id) if p.payment_status in ("paid", "cleared")) + if payments(row.id): return ("payment", "paid" if paid > 0 else "noticed") + cs = submission(row.id) + if cs and cs.status != "draft": + sub = leg_sub_stage(cs) + if sub in WITH_PAYER and "claim" in open_query_stages(row): sub = "queried" + return ("claim", sub) + pa = preauth(row.id) + if pa and pa.status != "draft": + stage = "enhancement" if pa.submission_kind in ("enhancement", "enhancement_resubmit") else "preauth" + sub = leg_sub_stage(pa) + if sub in WITH_PAYER and "preauth" in open_query_stages(row): sub = "queried" + return (stage, sub) + if pa: return ("preauth", "draft") + return ("eligibility", {"checking": "checking", "eligible": "eligible", "not-eligible": "not-eligible"}.get(row.status, "draft")) + +function stamp_case(claim_id): (s, sub) = case_stage(claim(claim_id)); update(claim(claim_id), {stage: s, sub_stage: sub}) + +function next_actions(claim_id): + row = claim(claim_id); adapter = for_claim(row); out = []; pa = preauth(claim_id); cs = submission(claim_id) + open_q = open_queries(claim_id) + if open_q: out.append({label: f"Answer the payer ({len(open_q)})", tab: "communication" if adapter.query_mode == "communication" else ("claim" if open_q[0].stage == "claim" else "preauth"), tone: "primary"}) + if row.status in ("draft", "not-eligible", "error"): out.append({label: "Check cover", tab: "cover", tone: "primary"}) + elif not row.plan_id: out.append({label: "Fetch the plan", tab: "plan", tone: "primary"}) + elif not pa or pa.status == "draft": out.append({label: "Submit the pre-authorisation", tab: "preauth", tone: "primary"}) + elif pa.status == "queried" and adapter.query_mode == "resubmit": out.append({label: "Answer the query", tab: "preauth", tone: "primary"}) + elif pa.status == "rejected": out.append({label: "Send a fresh pre-authorisation", tab: "preauth", tone: "primary"}) # 12, never 121 + elif pa.status == "error": out.append({label: "Send again", tab: "preauth", tone: "warn"}) + elif pa.status in ("approved", "partial") and (not cs or cs.status == "draft"): + out.append({label: "Discharge and claim", tab: "claim", tone: "primary"}) + if enhancement_lines(claim_id): out.append({label: "Send the enhancement", tab: "lines", tone: "default"}) + out.append({label: "Cancel the pre-authorisation", tab: "preauth", tone: "danger"}) + elif cs and cs.status == "error": out.append({label: "Send again" if claim_send_kind(claim_id) else "Ask for a reprocess", tab: "claim", tone: "warn"}) + elif cs and cs.status == "rejected": out.append({label: "Ask for a reprocess", tab: "claim", tone: "warn"}) + for p in payments(claim_id): if p.ack_status != "sent": out.append({label: "Acknowledge the payment", tab: "payments", tone: "default"}) + if adapter.status_enquiry and (pa or cs): out.append({label: "Ask status", tab: "enquiries", tone: "default"}) + return out +``` + +## Done when + +- Validate passes. +- `nhcx-build/7-modules/7.11.md` is written. diff --git a/plugins/nhcx/skills/nhcx-communication/stages/7-write-code/7.12-screens.md b/plugins/nhcx/skills/nhcx-communication/stages/7-write-code/7.12-screens.md new file mode 100644 index 000000000..130115d38 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-communication/stages/7-write-code/7.12-screens.md @@ -0,0 +1,124 @@ +# Module 7.12: screens + +Purpose: the screens in `screens.json`, built the way the target builds screens, every value derived from a stored message, plus the JSON state address a driver reads. + +Skills: the foundation (`core/FOUNDATION.md`) builds the case screen shell: all eight tabs, the status line, the state address, the page-load polls, the cases list. Each skill fills its own tabs and screens, and adds its legs to the state address. + +## Depends on + +7.1 to 7.11. Screens come last because they render what the readers stored. + +## Inputs + +- `nhcx-build/5-screen-plan.md`, `nhcx-build/screens.json` +- `nhcx-build/3-discovery.md` (screen conventions, helpers, styling) +- `nhcx-package/docs/03-Building a Provider/09-UI Guide.md` +- `ui/UI-GUIDE.md` for the route shape, the state address and the helper vocabulary; two or three route modules of the target for its conventions + +## Build + +### The case screen walks the flow + +Tabs in the order and with the labels of `flow.json` `tabs`; the Pre-authorisation tab appears once the verdict is `eligible`. Above the tabs the status line and the actions from 7.11. Each step F1 to F13 has its control on the tab the flow names, offered only when the step's `holds` hold. The page-load polls run in the order `flow.json` `page_load_polls` gives, bounded, before rendering. + +### Every screen in `screens.json` + +For each screen: the route, the handler, the render. Each value in the screen's `values` list is rendered from the element it names; the empty state is what shows before the message arrived. A decision-bearing value with no message renders as waiting. There is no status control anywhere. + +### The case screen + +The timeline: one row per leg row and per archived message, in time order, with direction, path, workflow id label (7.8's labels), status word, and the payer's words verbatim (`disposition`, item remarks, process notes, `x-hcx-error_details` on a refusal). The actions open now are `next_actions` from 7.11, rendered as buttons that post to the senders; the first action is highlighted. Each pane (cover, plan, lines, forms, documents, pre-auth, communication, claim, payments) shows only when its leg exists. + +### The JSON state address + +`GET /state` returns everything the case screen shows, as JSON, after the same polls the screen runs: stage, sub-stage, next actions, each leg's status and ids, the inbox items, the payments. Stage 10's drivers read this. + +### Polling on the request path + +Where there is no worker, the case screen and the state address run 7.3's poll fallback for any leg that is `submitting` or `checking` before rendering. Bound it: one poll per leg per request, a short timeout, and never a send. + +### Standalone mode + +Also the capture screens from 7.13, in the same style. + +## Rules + +- No screen shows a decision the exchange has not sent. +- Nothing the exchange already knows is typed. Rates, payer names, `preAuthRef`, the approved amount, the UTR and the payer's wording are rendered, never fields. +- An unknown case is a 404, never an invented page. +- Screens answer within two seconds; the poll is bounded. +- Forms post and the page re-renders; no client-side rendering is needed. + +## Validate + +- [ ] The case page's tabs are the eight of `flow.json`, in order, with those labels (string test on the HTML). +- [ ] Every step of `flow.json` with a `routes` entry answers on that route (or the plan's equivalent recorded in `screens.json`). +- [ ] Every route in `screens.json` answers 200 for a seeded case and 404 for an unknown one. +- [ ] A case with a pre-auth `submitting` and no answer renders "waiting" (or the plan's word) and neither "approved" nor "rejected" appears on the page. +- [ ] After a 21 is applied (`nhcx-package/fhir/C5/C5-approved-wf21.json`), the page shows its `preAuthRef` and approved amount verbatim. +- [ ] After a payment notice is applied (`nhcx-package/fhir/C9/C9-notice-wf30.json`), the payments screen shows its UTR verbatim. +- [ ] After a query is applied, the inbox shows the request's `contentString` text verbatim. +- [ ] No `` or `, unless spec.typed +``` + +### Which actions to offer + +``` +function actions(case): + out = [] + q = open_queries(case) + if q: out.append(action("Answer the payer (n)", tab = inbox if payer.query_mode == communication else leg_tab)) + leg = current_leg(case) + if leg.status == "rejected" and leg.kind == "preauth": out.append(action("Send a fresh pre-authorisation", sends = 12)) + if leg.status == "approved" and no_request_in_flight(case) and leg.kind == "preauth": + out.append(action("Enhance", sends = 13)); out.append(action("Cancel", sends = PC01)); out.append(action("Discharge and claim", tab = claim)) + if leg.kind == "claim" and leg.status == "rejected": out.append(action("Ask for a reprocess", sends = 36)) + if payer.status_enquiry: out.append(action("Ask status", sends = task status)) + for notice in unacknowledged_notices(case): out.append(action("Acknowledge payment", sends = 17 or echo)) + return out +``` + +## Component vocabulary (suggested, for a standalone build) + +A suggested set of helpers. Server-rendered HTML from Python functions returning strings, styled by the 0build kit 0.5.4 from jsDelivr. Components: `z-card`, `z-button`, `z-input`, `z-select`, `z-table`, `z-nav`, `z-tab` with `data-z-switcher`, `z-alert`, `z-badge`, `z-breadcrumb`. Utilities take values through custom properties (`class="display-grid gap" style="--gap: 4"`). Helpers a screen needs: `page`, `card`, `stack`, `table`, `grid`, `field`, `text_input`, `select`, `button`, `post_button`, `confirm_form`, `badge`, `when`, `muted`, `dl`, `tabs`, `stat`, `empty_state`. Tables cap at about eight columns; merge facts into a main line with a muted sub-line. Every state-changing action that is not a full form is a `post_button`; destructive ones confirm. + +In `integrate` mode use the HMIS's own components and conventions; the layouts above are the content, not the markup. diff --git a/plugins/nhcx/skills/nhcx-coverage/SKILL.md b/plugins/nhcx/skills/nhcx-coverage/SKILL.md new file mode 100644 index 000000000..7f2baefaa --- /dev/null +++ b/plugins/nhcx/skills/nhcx-coverage/SKILL.md @@ -0,0 +1,92 @@ +--- +name: nhcx-coverage +description: Add NHCX policy search and coverage eligibility (discovery, validation, benefits) to a hospital information system, or build it into a standalone claims desk, held byte for byte to the pinned bundles. Starts by checking whether the app already searches policies and checks cover, then builds, extends or reuses only what is missing. Self-contained; needs no other skill installed. Use for policy search, coverage eligibility checks, "is this patient covered", NHCX use cases A2, B1 and D3, flow steps F1 to F3. +--- + +# NHCX coverage: policy search and coverage eligibility + +This skill finds a beneficiary's policy, opens the claim episode on it, and asks the payer whether the cover is in force. It is the first of the seven NHCX use cases in episode order: the others start from the episode and the verdict it leaves. + +Read `core/LADDER.md` first. It holds the ladder every NHCX skill walks: the definition of compliant, the stages, the workspace, how to run a stage, and the rules. This folder carries everything it needs and runs on its own; the other six NHCX skills are separate folders, and none of them has to be installed. Paths starting `core/`, `stages/`, `references/`, `fhir/`, `flow/`, `ui/`, `templates/` or `scripts/` are relative to this folder. Paths starting `nhcx-package/` are in the NHCX package, which `scripts/fetch-package.sh` fetches into the target project beside `nhcx-build/`; `references/material.md` names the package file of every pin by its label. + +## What this skill covers + +| | | +| --- | --- | +| Flow steps | F1 Policy search, F2 Open the case, F3 Check the cover (`flow/FLOW.md`) | +| Screens and tabs | The "New case" screen; the Eligibility tab (tab 1) with the beneficiary and verdict cards | +| Wire | The participant service's `participant/get/policies` (plain REST, through the transport); `v1/coverageeligibility/check`, purpose `discovery`, `validation` or `benefits`, workflow id = the case number, a new correlation id per check; `on_check` back | +| Next actions | "Check the cover" | +| Use cases | A2 Get policy; B1 and D3 Check coverage eligibility | +| Module | 7.4, whole (`stages/7-write-code/7.4-policy-and-coverage.md`) | +| Pins | `coverage/discovery`, `coverage/validation`, `coverage/benefits`: `nhcx-package/fhir/B1/{discovery,validation,benefits}.json` | +| Payer fixtures | `nhcx-package/fhir/C3/*`: the validation, discovery and benefits answers, generic and PMJAY | +| Tables | `claim`, the episode, with its coverage columns | +| FHIR | `fhir/FHIR.md` section 2; `references/fhir-knowledge.md` section 3 | + +Not here: the `auth-requirements` purpose. It uses this skill's builder with items and belongs to `nhcx-preauth` (F8). + +## Needs and hands on + +Needs from other use cases: nothing. This skill runs first. + +Hands on: an episode (`claim` row) with a claim number, member id, policy code, the payer's and the processor's participant codes, and the raw policy; a verdict `eligible` or `not-eligible` with the payer's demographics, wallet and period. Insurance and pre-authorisation start from an `eligible` episode. Pre-authorisation reuses the coverage builder for auth requirements, so keep it a pure function that takes `items`. + +## Capability check + +Stage 0 (`stages/0-capability-check.md`) gives every capability below a verdict: search for the markers, run the check, record what was observed. + +### Own + +| Id | What | Look for | Present when (observed) | +| --- | --- | --- | --- | +| `coverage.policy-search` | F1: search by `AbhaNumber`, then `MemberId`, then `MobileNo`, and normalise each policy | `participant/get/policies`, `identifiertype`, `processingid`, `AbhaNumber`, `MobileNo`, `NHCX-1016` | Called with a stubbed answer, it returns rows with `member_id` (`memberid`), `policy_code` (`productid`), `payer_code` (`payerid`) and `recipient_code` (`processingid`); a policy with no `processingid` is refused as unaddressable; an NHCX-1016 answer is an empty list, not an error | +| `coverage.episode` | F2: open the case on a chosen policy | an episode table with `member_id`, `policy_code`, `payer_code`, `recipient_code`; a claim number generator | Opening from a policy row stores the member id, policy code, payer code, recipient code and the raw policy, mints a unique claim number and stamps `eligibility / draft` | +| `coverage.request-builder` | `build_coverage_request`, a pure function | `CoverageEligibilityRequest`, `coverageeligibility`, `"purpose"`, `"NONE"` | Fed each pin's own data, it produces the `discovery`, `validation` and `benefits` pins byte for byte in canonical JSON, `created` excluded; every reference resolves; the Patient carries only the two identifiers (7.4 Validate, rows 1 to 4) | +| `coverage.response-reader` | Read `on_check` and settle the verdict | `CoverageEligibilityResponse`, `inforce`, `allowedMoney`, `usedMoney`, `disposition` | Fed every answer in `nhcx-package/fhir/C3`, it yields `inforce`, `outcome` and a non-empty patient name, and settles `eligible` or `not-eligible` (7.4 Validate, rows 5 and 6) | +| `coverage.check-leg` | F3: send the check and keep its thread | a send on `v1/coverageeligibility/check`; `txn_id`, `correlation_id`, `api_call_id` on the episode | With the 7.1 stub: one send, workflow id equal to the claim number, the three ids stored, status `checking`; a ProtocolResponse, or a 404 on `txn/related`, settles `error` and never spins | +| `coverage.screens` | The New case screen and the Eligibility tab | a route like `/claims/new`; the verdict card | On a seeded answer the tab shows sum insured, utilised, wallet balance, disposition verbatim, in force, pre-authorisation required, checked at and correlation, all rendered from the stored answer and none of them an input | + +### Foundation + +All six capabilities in `core/FOUNDATION.md`; `foundation.shell` only in standalone mode. As the first use case, this skill usually finds the foundation absent and builds it. + +### Prerequisites + +None. + +### Host facts + +The stage 3 rows this skill needs: framework and runtime; configuration; inbound route and middleware; background worker; screen conventions; test runner; patient table and key; name, gender, date of birth, phone, ABHA; where a member id and policy code can be stored; facility HFR id, name and participant code. + +## The ladder, for this skill + +| Stage | What is specific here | +| --- | --- | +| 0 | The tables above. | +| 1 | Usually the first skill: write `1-idea.md` whole, every step of the flow with its skill, and ask the user. Own rows: A2, B1, D3. | +| 2 | Risks: validate then discover on a fresh episode (the sandbox's order); the workflow id is the case number, not a code; demographics are the payer's to return; and the foundation rules when the foundation is built here. | +| 3 | The host facts above. | +| 4 | Usually first: the flow table and every table's home. Then the coverage bundle's source map and the `on_check` destinations. Only the member id goes out; the payer returns the rest. | +| 5 | Usually first: the case screen shell. Then the New case screen and the Eligibility tab: values, empty states, actions F1, F2, F3. | +| 6 | 7.4, and every foundation module stage 0 found absent or partial. | +| 7 | The foundation first, then 7.4, each only as far as its verdict says. | +| 8 | 7.4's Validate section whole; the Validate section of every foundation module built or extended here. | +| 9 | Three pin comparisons; a reader test per coverage fixture; matrix rows B1 and D3; the cross-cutting rows on the coverage thread. | +| 10 | Rung 1. The rung 3 driver walks B1 against a generic payer; rung 4 walks D3. | +| 11 | This skill's section. | + +## Rules for these legs + +- Validate, then discover, on a fresh episode; a `benefits` check is optional. +- The workflow id on these legs is the case number. +- The request carries identifiers only: the Patient has the member id typed `PMJAY` and `MB`, and no name. The payer's demographics come back on the answer and are stored on the episode, not written into the HMIS patient unless stage 4 said so. +- `Coverage.identifier` is `NONE` on discovery and the policy code otherwise. +- The policy search answer's shape is not published. Read a real one first and keep the raw JSON on the episode. +- "Check again" is allowed from any settled state. + +## Done when + +- Every gate in this skill's block of `nhcx-build/STATE.md` is closed with evidence, and every foundation row this skill built is closed. +- The three coverage pins pass their comparisons. +- The compliance points in `core/LADDER.md` hold for F1 to F3. diff --git a/plugins/nhcx/skills/nhcx-coverage/core/FOUNDATION.md b/plugins/nhcx/skills/nhcx-coverage/core/FOUNDATION.md new file mode 100644 index 000000000..2037811b9 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-coverage/core/FOUNDATION.md @@ -0,0 +1,65 @@ +# The foundation: what every skill stands on + +Six modules carry every leg, and no one skill owns them. Every skill's stage 0 checks them. The first skill that finds one absent or partial builds or extends it in its own stage 7, and records itself as `Built by` in the Foundation block of `nhcx-build/STATE.md`. Later skills find it present and reuse it. An HMIS that already has one (an NHCX integration, a webhook door, a claims table) has it `existing`. + +| Id | Module | What | Every skill adds | +| --- | --- | --- | --- | +| `foundation.transport` | 7.1 | Settings; the one transport behind `send` (the app's existing NHCX integration, the build's own, or nhcx-adapter when the user asked for it); the policy lookup; the outbound archive | Nothing; it sends through it | +| `foundation.storage` | 7.2 | The episode table with its claim number, payer and recipient codes, stage and sub-stage; the leg tables | The leg tables its `SKILL.md` lists, in its own migration | +| `foundation.callback` | 7.3 | The transport's receiving end and the door: dedupe, archive before apply, match by correlation id then claim number, the door refusal, the poll fallback where there is a ledger | Its readers, wired into the door's dispatch | +| `foundation.state` | 7.11 | The payer adapter table; `case_stage`, `stamp_case`, `next_actions` | The stage branches and next-action rows for its legs, labels verbatim from `flow/flow.json` | +| `foundation.screens` | 7.12 | The case screen shell: the eight tabs in the flow's order, the status line and actions, the JSON state address, the page-load polls, the cases list | Its own tabs and screens | +| `foundation.shell` | 7.13 | Standalone only: patients, admissions, practitioners, diagnoses, documents, settings, the run script | Nothing; `not applicable` in integrate mode | + +## Recognising each one + +For each capability: what to search for, what must be observed for it to be present, and what makes it partial. Search code, dependencies, migrations, configuration and tests. Run every check offline, with the network stubbed. + +### `foundation.transport` (7.1) + +- Look for an NHCX integration of the app's own: `x-hcx-`, `JWEPayload`, `RSA-OAEP-256`, `A256GCM`, a JOSE library among the dependencies, `bearer_auth`, a sessions URL on the ABDM gateway, `participanthcxservice`, `fetch/certs`, `participant/get/policies`, routes ending in `on_submit`, `on_check` or `on_request`, a vendor's NHCX or HCX client, a gateway service the app calls. Look also for nhcx-adapter already in use: `/fhir/out/`, `/out/v1/`, `jwe_headers`, an adapter URL setting, `/ledger/thread/`, `/internal/txn/related`. +- Present when: what was found meets the contract in `references/transport-knowledge.md` section 2, observed through 7.1's Validate rows 1 to 6 (and row 7 for an app that seals its own messages), with the network stubbed and a test key pair for the seal; and `send` is one function a test can replace. +- Partial when: it sends but misses a contract item (no `x-hcx-ben-abha-id`, the `payerid` as the recipient, no ids back to the caller, no archive) or cannot be stubbed. Extend it in place (`references/transport-knowledge.md` section 4). Never add a second transport beside it. +- Absent when: the app has no NHCX integration. The transport is then `own`, built from `references/transport-knowledge.md` section 3, unless the user has asked for nhcx-adapter. +- nhcx-adapter is never the answer to a partial or absent transport unless the user asked for it. Do not suggest it. + +### `foundation.storage` (7.2) + +- Look for: tables or models with `claim_no`, `correlation_id`, `txn_id`, `sub_stage`; migrations that mention claim, preauth or nhcx. +- Present when: observed on a migrated scratch database, or read from the schema file and confirmed by a migration run: the episode table has a unique claim number, member id, policy code, payer code, recipient code, patient and encounter keys, `stage` and `sub_stage`; every leg table this skill needs exists with `txn_id`, `correlation_id`, `api_call_id` and `thread_correlation_id`; the migration runs twice without error; deleting an episode removes its children (7.2 Validate, rows 2, 3, 5 and 6). For `nhcx-communication` and `nhcx-payment`, also row 4: the correlation id on their tables is unique by constraint. +- Partial when: the episode exists but a leg table this skill needs does not, a leg table lacks `thread_correlation_id` or `api_call_id`, or the episode keeps no `recipient_code`. The skill adds its tables and columns in a new migration. + +### `foundation.callback` (7.3) + +- Look for: routes under `/v1/` ending in `on_submit`, `on_check`, `on_request`, `/v1/error`, or a route with `callback` in it; `JWEPayload`, `ProtocolResponse`, `x-hcx-correlation_id`, `x-hcx-api_call_id`, a receipt with `protocol_status`. +- Present when: 7.3 Validate rows 1 to 5, 7 and 8 are observed by calling the receiving end with deliveries of the transport's kind (every inbound path reaches it; an unreadable body is archived and changes nothing; one api call id delivered twice changes state once and is `ignored`; an unknown correlation id is answered and archived under `unmatched`; a delivery is archived even when the apply raises; no outbound call during a delivery; the inbound authentication of the kind). Row 6, the door refusal, is checked by each skill on its own thread. +- Partial when: it receives but routes by path instead of by correlation id, lacks the dedupe, archives after applying, answers the exchange with anything but the 202 receipt (`own`, `existing`), hosts no `/v1/error`, or, with `adapter`, has no poll fallback. Extend it; there is one door. +- A skill whose reader is not wired into the door is partial for its own capability, not for the door. + +### `foundation.state` (7.11) + +- Look for: `query_mode`, `resubmit`, `1518`, a workflow id table (`"12"`, `"PC01"`, `"161"`), `sub_stage`, `next_actions`, a stamp after each write. +- Present when: 7.11 Validate rows 1 to 3 are observed (`adapter_for` with `1518@hcx` and `1518` gives PMJAY and an unknown code gives generic; the PMJAY workflow table equals `references/flow-knowledge.md` section 2; an override changes one kind only), and rows 4 to 7 hold on the seeded states the legs built so far can reach. +- Partial when: the payer table exists and the stage machine does not, or the stage machine lacks this skill's stage branches or labels. Each skill adds its own. + +### `foundation.screens` (7.12) + +- Look for: routes like `/claims`, `/claims/`, `/claims//state`; the tab keys `eligibility`, `plan`, `lines`, `validate`, `preauth`, `communication`, `claim`, `payments`. +- Present when: 7.12 Validate rows 1, 3, 8 and 9 are observed on the shell (the eight tabs in the flow's order with the flow's labels; routes answer 200 for a seeded case and 404 for an unknown one; no input or select named for a rate, a payer name, a `preAuthRef`, a UTR or a status; the state address returns `stage`, `sub_stage`, `next_actions` and `legs`). Rows 4 to 7 belong to the skills whose tabs they test. +- Partial when: the case screen exists without some tabs, without the status line, or without the state address. +- An HMIS with its own screens: the shell may live inside them, for example a panel on the admission screen that opens the case. Present is judged on the eight tabs and the state address, not on the look. + +### `foundation.shell` (7.13, standalone only) + +- Present when: every row of 7.13's Validate section is observed. +- In integrate mode: `not applicable`. The HMIS is the shell; stage 3 finds its patients, admissions, practitioners and documents. + +## Who builds what + +| Verdict at stage 0 | What the running skill does | +| --- | --- | +| `absent` | Builds it in stage 7, before its own modules. 7.1 and 7.3 whole, for the transport chosen at stage 1. 7.2: the episode table and this skill's leg tables. 7.11: the payer adapter table whole, and this skill's stage branches and labels. 7.12: the shell with all eight tabs present in order, its own tabs filled, the others showing their empty state. 7.13 whole, in standalone mode. | +| `partial` | Extends it in the existing code, for the difference stage 0 named, and runs the module's whole Validate section after. | +| `present` | Reuses it. Stage 8 still runs the rows this skill depends on. | + +Record: the Foundation row in `STATE.md` with `Built by` (the skill, or `existing`), and the module record `nhcx-build/7-modules/7.N.md` with a part for each skill that touched it. diff --git a/plugins/nhcx/skills/nhcx-coverage/core/LADDER.md b/plugins/nhcx/skills/nhcx-coverage/core/LADDER.md new file mode 100644 index 000000000..7a6f3f12b --- /dev/null +++ b/plugins/nhcx/skills/nhcx-coverage/core/LADDER.md @@ -0,0 +1,185 @@ +# The NHCX build ladder + +This skill is one of seven NHCX skills, one per use case: `nhcx-coverage`, `nhcx-insurance`, `nhcx-preauth`, `nhcx-claim`, `nhcx-communication`, `nhcx-payment` and `nhcx-reprocess`. Each is a folder of its own and runs on its own: it carries this ladder, the stages, the module files, the references, the flow, the templates and the fetch script. The seven copies of these are the same; only `SKILL.md` differs. This file holds what they share. `SKILL.md` says which flow steps, legs, capabilities, modules, pins and test rows are this skill's own, and what it needs from the use cases before it. + +## Paths + +Paths that start with `core/`, `stages/`, `references/`, `fhir/`, `flow/`, `ui/`, `templates/` or `scripts/` are relative to this skill's folder, the one that holds `SKILL.md`. Paths that start with `nhcx-package/` are in the NHCX package, fetched into the target project beside `nhcx-build/` (below). Paths that start with `nhcx-build/` are the workspace in the target project. + +## Getting the material + +Pins, payer fixtures and docs come from the NHCX package, published at https://github.com/nha-in/nhcx-package. `scripts/fetch-package.sh` downloads the latest release, unpacks it to `nhcx-package/` beside `nhcx-build/` and verifies its MANIFEST (pass a link or a local path to use a different build). `references/material.md` says what the package holds, gives the file of every pin by its label (`preauth/request` is `nhcx-package/fhir/B3/preauth-request.json`), and lists what it does not hold. Read it once, at stage 0. + +## What the skills produce + +Software that raises cashless claims on the National Health Claims Exchange (NHCX) with a private insurer and with PMJAY, in one of two shapes: + +| Mode | You start with | You end with | +| --- | --- | --- | +| `integrate` | A working hospital information system (HMIS, EMR, HIS, billing system) in any language | The same system, with a claims module that speaks NHCX through its transport, kept in sidecar tables and removable | +| `standalone` | Nothing | A self-contained claims desk: its own patients, admissions, documents and screens, speaking NHCX through a transport of its own | + +Every message goes through one transport, chosen at stage 1 from three (`references/transport-knowledge.md` section 1): + +| Transport | When | What the build does | +| --- | --- | --- | +| `existing` | Stage 0 found the app already speaks NHCX: its own client, a vendor gateway, an SDK | Wraps it behind 7.1's `send` and 7.3's door, and closes its gaps; never replaces it | +| `own` | The app has no NHCX integration, and the user has not asked for nhcx-adapter | Builds the protocol into the app from NHA's published chapters: the ABDM session token, the key and certificate, the participant record, the recipient's certificate, the JWE, the callback and its receipt | +| `adapter` | Only when the user asks for nhcx-adapter | Downloads it from https://github.com/nha-in/nhcx-adapter/releases and talks plain FHIR to it (`references/api-knowledge.md`) | + +Never propose nhcx-adapter; use it only when the user asks for it. Whichever the transport, the rest of the build sees the same two things: `send`, and a door that receives `{meta, jwe_headers, fhir}`. + +## The seven skills + +One skill per use case. Together they walk the whole flow in `flow/FLOW.md`; each one alone builds its slice. This folder builds only its own row. The others are named so that a verdict can say which skill owns a missing piece. + +| Skill | Flow steps | Legs | Use cases | Pins | +| --- | --- | --- | --- | --- | +| `nhcx-coverage` | F1, F2, F3 | policy search; `v1/coverageeligibility/check` purpose `discovery`, `validation`, `benefits` | A2, B1, D3 | `coverage/{discovery,validation,benefits}` | +| `nhcx-insurance` | F4, F7 | `v1/insuranceplan/request`; lines quoted from the plan | B2, D1 | `insurance` | +| `nhcx-preauth` | F5, F6, F8, F9, F9a, F9b for a `resubmit` payer, F9c, F9d, F9e | auth requirements; `v1/preauth/submit` 12, 19, 13, 131 and predetermination; cancel PC01 | B3, B8 cancel, B9, D2, D4 to D8 | `coverage/authrequirements`, `preauth/{request,enhancement,queryupdate,cancel}` | +| `nhcx-claim` | F10, F11 | `v1/claim/submit` 15; 161 (PMJAY) or 151 (generic); 16 (generic) | B5, D9, D10 | `claim/{request,queryupdate}` | +| `nhcx-communication` | F9b and the claim query for a `communication` payer, F12b | `v1/communication/request` in; `v1/communication/on_request` out | B4 | `communication/response`, and the `communication/request` reader | +| `nhcx-payment` | F12 | `v1/paymentnotice/request` in; `v1/paymentnotice/on_request` out on 17 or the notice's own id | B7, D13 | `payment/notice-ack` | +| `nhcx-reprocess` | F13 | `v1/task/submit`: reprocess and release on 36, status; 37 and the status Task read | A5, B8 reprocess, D11, D12 | `claim/{reprocess,release}` | + +`flow/flow.json` names the skills of every step in `skills`. Fifteen pins, each owned by exactly one skill, plus the communication request read as the sixteenth comparison. + +### The order they depend on + +The use cases depend on one another in the order the episode happens. A full build runs the seven skills top to bottom. Any one can run alone on an app that already has what it needs; stage 0 establishes whether it does, with the checks in this skill's `SKILL.md` under "Prerequisites". The other skills do not have to be installed for that check. + +| Skill | Needs | Because | +| --- | --- | --- | +| `nhcx-coverage` | nothing | It opens the episode | +| `nhcx-insurance` | coverage: an episode with an `eligible` verdict | The plan is fetched for an eligible episode's policy | +| `nhcx-preauth` | coverage (eligible, and its builder for auth requirements); insurance (plan ready, lines quoted) | Items, prices, documents and forms come from the plan; F9 holds `eligible` | +| `nhcx-claim` | preauth: an approved or partial pre-auth with its `preAuthRef`, the dossier, the Claim builder | The claim goes under the pre-auth's number, built by the same builder | +| `nhcx-communication` | preauth or claim: a leg the payer can ask about, with its bundle as sent | A query names a Claim; the reply lifts entries from the bundle sent | +| `nhcx-payment` | claim: a filed claim | A notice is matched by the claim number | +| `nhcx-reprocess` | claim: a decided claim; payment for a release; preauth for status on a pre-auth | A reprocess reopens a decided claim; a release follows a short payment | + +## The foundation + +Six modules carry every leg and belong to no one skill: 7.1 (the transport), 7.2 (storage), 7.3 (the callback door), 7.11 (state and payer adapters), 7.12 (the case screen shell) and 7.13 (the standalone shell). Every skill's stage 0 checks them. The first skill that finds one absent builds it; a skill that runs later on the same app finds it present and reuses it. `core/FOUNDATION.md` says how to recognise each and what makes it present. + +## What compliant means + +Every skill is held to the same points, for its own legs: + +1. Every hospital-side leg the skill owns (`references/flow-knowledge.md` section 1) is sent with its workflow id, and every payer answer on it is read. +2. Every bundle the skill sends matches its pin in `nhcx-package/fhir` byte for byte, `created` excepted. +3. The callback door answers 2xx fast, dedupes on `x-hcx-api_call_id`, archives before it applies, and matches by correlation id first. +4. No screen shows a decision the exchange has not sent, and nothing the exchange already said is retyped. +5. The offline tests pass, and the report says honestly which rungs of the test pyramid were climbed. +6. The software walks the flow in `flow/FLOW.md`, step for step: the same steps in the same order, the same tabs with the same names, the same guards, the same action labels. The flow is copied, never redesigned. +7. Nothing the app already did is built a second time. Every capability stage 0 found present is reused, and validated and tested like new code. + +## The flow + +An NHCX provider desk walks one path from policy search to settlement, and a build from these skills walks it. `flow/FLOW.md` is that path: thirteen steps with their branches, the case screen's eight tabs in order, the status line, the action labels the desk sees, the guards before every send, and what runs on every page load. `flow/flow.json` is the same, machine-readable, with step ids `F1` to `F13`. Read FLOW.md whole at stage 1; stage 4 copies the steps, stage 5 puts the screens on them, stage 7 implements them by id, stage 8 checks every step has a route. An agent that reorders, merges or renames these steps has left the skill. + +## The ladder + +Twelve stages, 0 to 11. Each has one file under `stages/`, reads the artefacts of the stages before it, writes into `nhcx-build/` in the target project, and ends at a gate. A gate is a list of conditions a reader can check without trusting you. Do not start a stage until the gate before it is closed, and never close a gate by asserting it; close it by pointing at the evidence. + +This skill runs every stage over its own slice. Stage 1 is shared with any other NHCX skill that runs on the same app: the first writes it and later ones confirm it. Parts of stages 3 to 6 are the episode's, not the skill's: the first skill to reach them writes those parts whole, and later skills build on them. + +| Stage | File | Scope | Writes | Gate closes when | +| --- | --- | --- | --- | --- | +| 0 | `stages/0-capability-check.md` | this skill | `nhcx-build/0-capability.md` section, `nhcx-build/capabilities.json` entries | Every own, foundation and prerequisite capability has a verdict with observed evidence | +| 1 | `stages/1-idea.md` | shared | `nhcx-build/1-idea.md` | The mode, the payers, the scope of every step with its skill, and the constraints are written and the user has agreed | +| 2 | `stages/2-planning.md` | this skill | `nhcx-build/2-planning.md` section, this skill's block in `nhcx-build/STATE.md` | Every later stage has a size and a proof; every module has its action from stage 0 | +| 3 | `stages/3-discovery.md` | shared rows; this skill's host facts | `nhcx-build/3-discovery.md` | Every host fact this skill needs is answered with proof, or marked as a gap | +| 4 | `stages/4-flow-and-data-mapping.md` | the flow and table homes episode-wide; this skill's bundles | `nhcx-build/4-flow-data-mapping.md`, `nhcx-build/mapping.json` | Every table has a home, every leg the four ids, every bundle of this skill a source map | +| 5 | `stages/5-screen-plan.md` | the case screen shell episode-wide; this skill's tabs | `nhcx-build/5-screen-plan.md`, `nhcx-build/screens.json` | Every value on this skill's screens names its message; the honesty rules hold | +| 6 | `stages/6-code-plan.md` | this skill's modules; the client and configuration episode-wide | `nhcx-build/6-code-plan.md`, `nhcx-build/modules.json` | Every module this skill touches has files, dependencies, a pin and an action | +| 7 | `stages/7-write-code/README.md` and `7.N-*.md` | what stage 0 found absent or partial | Code, plus `nhcx-build/7-modules/7.N.md` | Each module's "Done when" list is met, in order | +| 8 | `stages/8-validate-modules.md` | every module part this skill owns, reused ones included | `nhcx-build/8-validation.md`, `nhcx-build/8-validation/7.N.json` | Every row passes, or carries a named, accepted exception | +| 9 | `stages/9-write-tests.md` | this skill's pins, readers and matrix rows | Test code, plus `nhcx-build/9-tests.md` | Every row this skill owns has a test, or a written reason it cannot | +| 10 | `stages/10-run-tests.md` | this skill's tests | `nhcx-build/10-test-run.md` and the raw outputs | The offline rung passes; the higher rungs are run only when the user starts the services | +| 11 | `stages/11-build-report.md` | this skill | `nhcx-build/11-report.md` section | The report is written from the artefacts, names every gap, and a stranger could resume from it | + +Stage 7 is a module ladder of its own, 7.1 to 7.13. Each module file carries its own Build, Pseudo code, Validate and Tests sections, and names the skills that build it; stage 8 runs the Validate sections and stage 9 writes the Tests sections, so a module is never validated against a checklist written somewhere else. + +## The workspace + +Everything this skill writes lives in one folder in the target project, so the work can be resumed, reviewed and deleted as a unit. When several NHCX skills work on one app they share that folder, whichever skill folder each runs from: each adds its own section or entries and leaves the others alone. + +``` +nhcx-build/ + STATE.md the gate ledger: the shared rows, the foundation, one block per skill + capabilities.json every capability checked, its verdict and its evidence; read and written by every skill + 0-capability.md one section per skill; scratch checks under 0-capability/ + 1-idea.md shared + 2-planning.md one section per skill + 3-discovery.md shared; each row says which skill answered it + 4-flow-data-mapping.md the flow and table homes, then one section per skill; plus mapping.json + 5-screen-plan.md the case screen shell, then one section per skill; plus screens.json + 6-code-plan.md the client and configuration, then one section per skill; plus modules.json + 7-modules/7.1.md .. 7.13.md one record per module; a shared module has a part per skill + 8-validation.md one section per skill; plus 8-validation/7.N.json, each row tagged with its skill + 9-tests.md one section per skill + 10-test-run.md one section per skill; plus 10-test-run/-*.log + 11-report.md a summary across skills, then one section per skill + NOTES.md every place a skill was silent, ambiguous or wrong +``` + +`templates/` holds the skeleton of each artefact. Copy the skeleton, fill it, keep its headings: later stages find things by heading. + +## How to run a stage + +1. Read `nhcx-build/STATE.md`. If stage 1 in the Shared block is open, and this skill's stage 0 is closed, run stage 1. Otherwise find the first open gate in this skill's block. That is the stage to run; do not skip ahead and do not redo a closed stage unless the user asks. +2. Read the stage file. Read the artefacts it lists under Inputs, and this skill's `SKILL.md` row for the stage. Read the references it names, in the sections it names. +3. Do the work. Write the artefact from its template, in this skill's section. +4. Walk the gate. For each condition, write the evidence into STATE.md: a file path, a line, a command and its output. A condition with no evidence stays open. Every artefact that names a step, a tab or an action uses the ids and words from `flow/flow.json`. +5. If a gate needs the user (stage 0 when a prerequisite is missing; stage 1 always when it is first written; stage 10 rungs 3 and 4 always), stop and ask. Otherwise continue to the next stage. + +Resuming later is step 1 again. Nothing lives in your memory; everything lives in `nhcx-build/`. + +You may be asked to run one stage alone with the earlier artefacts already written. Treat those as closed; do not rewrite them. + +## Rules that hold throughout + +- Reading and offline commands only until stage 10 says otherwise. Never start a service or send live traffic unless the user asks. +- Never edit the files in `nhcx-package/`. They are the truth you are held to. +- Build only what stage 0 found absent or partial. A capability found present is reused through its existing code, never built a second time: two transports or two callback doors break the rule that one module sends and one receives. +- Present means a check was observed passing. Code that looks right is partial until its check has run. +- Never build another skill's capability inside this one. When a prerequisite is missing, stop and say which skill owns it. +- When this skill extends a module another skill built, it re-runs that skill's Validate rows for the module. The rows are in the module file, which every skill folder carries. +- This skill writes its own section of a shared artefact and leaves the other skills' sections alone. +- Never hard-code a document code, a package code or a questionnaire url. Take them from the payer's plan or auth-requirements answer. +- Every outbound leg stores three things from the transport's answer: `txn_id`, `correlation_id` and `api_call_id`. Every message is addressed to the policy's processor (`recipient_code`) and carries the beneficiary's ABHA. Every inbound message is matched by `x-hcx-correlation_id` first and by the claim number inside the bundle second. +- Take the decisions from the module files (Build, Rules, Pseudo code) and `fhir/FHIR.md`, and write them in the target's language and conventions. Never invent a shape the pins do not show. +- Write `nhcx-build/NOTES.md` as you go. A fact the skill does not give you is a gap to record, never a guess to bury in code. +- No em dashes anywhere you write. Short sentences. Tables for anything with more than three columns of fact. +- Do not claim a rung of the test pyramid was climbed when it was not. The report's value is its honesty. + +## Reference map + +| File | Holds | Read at | +| --- | --- | --- | +| `core/FOUNDATION.md` | The six foundation capabilities: how to recognise each, what makes it present, who builds it | Stage 0, stage 7 when building one | +| `references/flow-knowledge.md` | The episode and its legs, every workflow id, the two payer kinds, the classification rule, stage vocabulary, the use-case catalogue, rules no document states | Stages 1, 2, 4, 7.4 to 7.11 | +| `references/transport-knowledge.md` | The three transports and when each applies; the contract `send` and the door rely on; building the protocol yourself from NHA's chapters (token, key and certificate, participant record, policy lookup, recipient certificate, JWE, callback and receipt, status and `/v1/error`); wrapping an existing integration; getting nhcx-adapter when asked | Stages 0, 1, 4, 6, 7.1, 7.3 | +| `references/api-knowledge.md` | The nhcx-adapter contract, read only when the user chose the adapter: config, routes, envelope and answer, delivery, ledger, kit endpoints, curl | 7.1 and 7.3, adapter only | +| `references/fhir-knowledge.md` | Every bundle sent and received, element ids, HPIN, consent questionnaires, supportingInfo, LM100, ONS and DTM, the TaskBundle reply, where the pins live, the validator | Stages 4, 6, 7.4 to 7.10, 8 | +| `references/errors-and-debugging.md` | PAYR and ERR codes with meaning and fix, gateway errors, reading a ledger thread, correlation mistakes, redelivery, sandbox pace | Stages 8, 10, 11 | +| `references/testing-knowledge.md` | The test pyramid, the test-case matrix per use case, a skeleton offline test | Stages 2, 9, 10 | +| `fhir/FHIR.md` | The FHIR guide: every bundle sent and read, entries in pinned order, the code systems, pseudo code for each builder and reader, the refusal each rule guards against | Stages 0, 4, 6, 7.4 to 7.10, 8 | +| `ui/UI-GUIDE.md` | The screens: the two honesty rules, where every value comes from, a layout per screen, the state words, pseudo code for the status line, the timeline and the actions | Stages 5, 7.12, 7.13 | +| `flow/FLOW.md`, `flow/flow.json` | The one path an episode walks: steps F1 to F13 and their skills, the tab order, the action labels, the guards, the page-load polls | Stage 1 whole; stages 4, 5, 7, 8 by step id | +| `references/material.md` | Where the pins, fixtures and docs live: the NHCX package, the pin map, what the package lacks | Stage 0, and whenever a cited file is needed | + +## Keeping the seven copies in step + +Everything in this folder except `SKILL.md` is the same in all seven skill folders. A change to one of these files is made in all seven. `diff -r --exclude=SKILL.md` between any two skill folders prints nothing when they agree. + +## Deliverables + +- This skill's sections of `nhcx-build/`, every gate in its STATE.md block closed with evidence or open with a reason. +- Its verdicts in `capabilities.json`, each with the check that decided it. +- Schema additions for its legs (integrate) or its tables in the whole schema (standalone), under the target's conventions. +- Builders and readers for every leg it owns, each compared with its pin in the offline test. +- Its tabs and screens, deriving every state from received messages. +- Tests covering its rows of the matrix, a run record, and a report section a stranger could act on. diff --git a/plugins/nhcx/skills/nhcx-coverage/fhir/FHIR.md b/plugins/nhcx/skills/nhcx-coverage/fhir/FHIR.md new file mode 100644 index 000000000..90b85cbae --- /dev/null +++ b/plugins/nhcx/skills/nhcx-coverage/fhir/FHIR.md @@ -0,0 +1,658 @@ +# NHCX FHIR: the bundles a hospital sends and reads + +Every bundle here is held to a pin in the NHCX package, under `nhcx-package/fhir/B*`. Read `../references/fhir-knowledge.md` for the why; this file is the how. The pseudo code is language-neutral: a `dict` is a JSON object, a `list` is a JSON array, and `ref(url)` is `{"reference": url}`. + +## 1. Conventions every bundle follows + +"Validator" below is the HL7 FHIR validator with the NRCeS `ndhm.in` IG, run as `../references/fhir-knowledge.md` section 11 describes. + +| Rule | Detail | Refusal if broken | +| --- | --- | --- | +| Bundle | `resourceType Bundle`, `type collection`, `id` fixed per shape, `meta.profile` = the NRCES bundle profile | validator error | +| Entries | Every entry has an absolute `fullUrl` under `https://nhcx.abdm.gov.in/...`; every `reference` resolves to a `fullUrl` in the same bundle | validator error, PAYR-10xx | +| Profiles | Every resource carries `meta.profile` = `https://nrces.in/ndhm/fhir/r4/StructureDefinition/` | validator warning | +| No timestamps on requests | No `meta.versionId`, `meta.lastUpdated`, bundle `timestamp` (the communication reply is the exception) | none, but the pin differs | +| Money | `{"value": n, "currency": "INR"}`; whole numbers as integers, never `3300.0` | pin differs | +| Instants | IST with `+05:30`, seconds precision | PAYR on dates | +| Identifiers | Typed with a `type.coding` from the NDHM identifier-type system or HL7 v2-0203, `system` where the pin has one | PAYR-1083 and kin | + +### Code systems, named once + +``` +NDHM = "https://nrces.in/ndhm/fhir/r4/CodeSystem/" +PROFILE = "https://nrces.in/ndhm/fhir/r4/StructureDefinition/" +BASE = "https://nhcx.abdm.gov.in" +HL7 = "http://terminology.hl7.org/CodeSystem/" +SNOMED = "http://snomed.info/sct" +ICD10 = "http://hl7.org/fhir/sid/icd-10" +HPR = "https://hpr.abdm.gov.in" + +ID_TYPE = NDHM + "ndhm-identifier-type-code" # PMJAY, ABHA, HPID, HPIN, CLN +V2_0203 = HL7 + "v2-0203" # MB, MD, NH, NPI, NIIP +V2_0360 = HL7 + "v2-0360" # qualification degrees +ORG_TYPE = HL7 + "organization-type" # prov, pay +ACT_CODE = HL7 + "v3-ActCode" # HIP +REL = HL7 + "subscriber-relationship" # self +PRIORITY = HL7 + "processpriority" # normal +CARE_ROLE = HL7 + "claimcareteamrole" # primary, assist +DX_TYPE = HL7 + "ex-diagnosistype" # admitting +DX_ONADM = HL7 + "ex-diagnosis-on-admission" # yes +FIN_TASK = HL7 + "financialtaskcode" # poll, cancel, reprocess, release, status +FIN_INPUT = HL7 + "financialtaskinputtype" # include +COMM_CAT = HL7 + "communication-category" # notification + +BENEFIT_CAT = NDHM + "ndhm-benefit-category" # Claim.item.category (specialty) +PROC_CODE = NDHM + "ndhm-procedure-code" # Claim.item.productOrService (package) +PROGRAM = NDHM + "ndhm-program-code" # AB-PMJAY +SI_CATEGORY = NDHM + "ndhm-supportinginfo-category" # INV, ONS, OTH, HDS, DIS, NMI, INF, STG +SI_CODE = NDHM + "ndhm-supportinginfo-code" # ADDD, EDT, PSP, DSDE, DTM, DTH, LAMA, DAMA, CQD, ODN +DOC_CODE = BASE + "/document-code" # the plan's MANDxxxx codes, else ODN +TASK_INPUT = NDHM + "ndhm-task-input-type-code" # policyNumber, providerId, claimNumber, intimationNumber, document +TASK_INPUT_X = BASE + "/task-input-type" # amount +TASK_OUTPUT = NDHM + "ndhm-task-output-type" # status +TASK_OUTVAL = NDHM + "ndhm-task-output-value" # paymentack +TASK_CODES = NDHM + "ndhm-task-codes" # deliver +REASON = NDHM + "ndhm-reason-code" # treatmentplanchanged, claimrejected, partialpayment, rejectiondisputed +CAT_CODE = BASE + "/category-code" # CoverageEligibilityRequest.item.category +PRODUCT_CODE = BASE + "/product-code" # CoverageEligibilityRequest.item.productOrService +PROC_TYPE = BASE + "/procedure-type" # conservative, medical, surgical +DOC_TYPE_EXT = settings.document_type_extension_url # on a Communication attachment; participant-defined (nhcx-package/docs/05-FHIR Reference/17-Communication.md). + # The communication/response pin carries its author's own url: the pin comparison sets this from the pin. +``` + +### Shared helpers + +``` +function cc(system, code, display=null): # CodeableConcept + coding = {"code": code}; if system: coding.system = system; if display: coding.display = display + return {"coding": [coding]} + +function typed_id(type_system, type_code, type_display, value, system=null): + out = {"type": cc(type_system, type_code, type_display), "value": value} + if system: out.system = system # put "system" before "value" as the pins do; canonical JSON sorts anyway + return out + +function entry(url, resource): return {"fullUrl": url, "resource": resource} + +function profile(name): return {"profile": [PROFILE + name]} + +function bundle(id, profile_name, entries): # profile_name: "ClaimBundle", "TaskBundle", "CoverageEligibilityRequestBundle" + return {"resourceType": "Bundle", "id": id, "meta": profile(profile_name), "type": "collection", "entry": entries} + +function organization(role, identifier_code, identifier_display, id_value, name, res_id=null): + o = {"resourceType": "Organization", "meta": profile("Organization"), + "identifier": [typed_id(V2_0203, identifier_code, identifier_display, id_value, BASE)], + "type": [cc(ORG_TYPE, role, "Healthcare Provider" if role == "prov" else "Payer")], "name": name} + if res_id: o.id = res_id + return o + +function provider_org(facility, res_id=null): return organization("prov", "NPI", "National provider identifier", facility.hfr_id, facility.name, res_id) +function payer_org(payer, res_id=null): return organization("pay", "NIIP", "National Insurance Payor Identifier (Payor)", strip_hcx(payer.participant_code), payer.name, res_id) +function strip_hcx(code): return code.split("@")[0] + +function money(v): return {"value": int(v) if v == int(v) else round(v, 2), "currency": "INR"} +``` + +## 2. Coverage eligibility request + +Pins: `coverage/{discovery,validation,benefits,authrequirements}`. Sent on `v1/coverageeligibility/check`, workflow id = the case number. Purposes: `discovery` (who covers this person), `validation` (is the policy in force), `benefits` (balances), `auth-requirements` (rule on the quoted items). + +Entries, in order: CoverageEligibilityRequest, Patient, provider Organization, payer Organization, Location, Coverage, PractitionerRole. + +``` +function build_coverage_request(d): + # d: purpose, member_id, policy_code (null on discovery), facility{hfr_id,name}, payer{participant_code,name}, created, items[] (benefits, auth-requirements only) + U = BASE + cer = {"resourceType": "CoverageEligibilityRequest", "meta": profile("CoverageEligibilityRequest"), + "identifier": [{"system": BASE}], "status": "active", + "priority": cc(PRIORITY, "normal", "Normal"), "purpose": [d.purpose], + "patient": ref(U + "/patient"), "created": d.created, + "enterer": ref(U + "/practitioner-role"), "provider": ref(U + "/provider"), + "insurer": ref(U + "/payer"), "facility": ref(U + "/location"), + "insurance": [{"focal": true, "coverage": ref(U + "/coverage")}]} + if d.purpose in ("benefits", "auth-requirements"): + cer.item = [eligibility_item(i) for i in d.items] + patient = {"resourceType": "Patient", "meta": profile("Patient"), + "identifier": [typed_id(ID_TYPE, "PMJAY", "Pradhan Mantri Jan Aarogya Yojana (PMJAY) ID", d.member_id), + typed_id(V2_0203, "MB", "Member Number", d.member_id)]} # no name, no demographics + coverage = {"resourceType": "Coverage", "meta": profile("Coverage"), + "identifier": [typed_id(V2_0203, "NH", "National Health Plan Identifier", d.policy_code or "NONE")], + "status": "active", "type": cc(ACT_CODE, "HIP", "health insurance plan policy"), + "subscriber": ref(U + "/patient"), "subscriberId": d.member_id, "beneficiary": ref(U + "/patient"), + "relationship": cc(REL, "self"), "payor": [ref(U + "/payer")]} + location = {"resourceType": "Location", "name": d.facility.name, "managingOrganization": ref(U + "/provider")} + role = {"resourceType": "PractitionerRole", "meta": profile("PractitionerRole"), + "code": [cc(SNOMED, "307988006", "Medical technician")]} + return bundle("coverage-" + d.purpose.replace("-", "") + "-request-generic", "CoverageEligibilityRequestBundle", [ + entry(U + "/coverage-eligibility/request", cer), entry(U + "/patient", patient), + entry(U + "/provider", provider_org(d.facility)), entry(U + "/payer", payer_org(d.payer)), + entry(U + "/location", location), entry(U + "/coverage", coverage), entry(U + "/practitioner-role", role)]) + +function eligibility_item(i): + # i: category{code,display}, code, display, quantity (integer), tiers[] {code, display} + out = {"category": cc(CAT_CODE, i.category.code, i.category.display), + "productOrService": cc(PRODUCT_CODE, i.code, i.display), + "quantity": {"value": int(i.quantity)}} + if i.tiers: out.modifier = [cc(null, t.code, t.display) for t in i.tiers] # no system on a tier + return out +``` + +Bundle ids: `coverage-discovery-request-generic`, `coverage-validation-request-generic`, `coverage-benefits-request-generic`, `coverage-authrequirements-request-generic`. + +### Reader: CoverageEligibilityResponse + +The payer echoes the request's entries and appends its own; take the last of each type. + +``` +function parse_validation_bundle(b): + resp = last(b, "CoverageEligibilityResponse"); pat = last(b, "Patient"); cov = last(b, "Coverage") + out = {"outcome": resp.outcome, "disposition": resp.disposition, "inforce": resp.insurance[0].inforce, + "auth_required": any(item.authorizationRequired for item in resp.insurance[0].item or []), + "allowed": null, "used": null} + for item in resp.insurance[0].item or []: + for ben in item.benefit or []: + if ben.allowedMoney and (out.allowed is null or ben.allowedMoney.value > out.allowed): + out.allowed = ben.allowedMoney.value; out.used = (ben.usedMoney or {}).value or 0 + out.patient = {"name": pat.name[0].text, "gender": pat.gender, "birthDate": pat.birthDate, + "abha": first_identifier(pat, "ABHA"), "photo": pat.photo[0].data if pat.photo else null} + out.coverage = {"class": cov.class[0].name if cov.class else null, "period": cov.period} + return out +# status: eligible if inforce else not-eligible; balance shown = allowed - used +``` + +### Reader: the auth-requirements ruling + +``` +function parse_auth_bundle(b): + resp = last(b, "CoverageEligibilityResponse"); items = []; requirements = [] + for item in resp.insurance[0].item or []: + items.append({"code": item.productOrService.coding[0].code, "authorised": item.authorizationRequired, + "excluded": item.excluded, "benefit": item.benefit[0] if item.benefit else null}) + for sup in item.authorizationSupporting or []: + text = sup.text or "" # the scheme overloads free text + r = {"line": item.productOrService.coding[0].code, "code": sup.coding[0].code if sup.coding else null, + "display": sup.coding[0].display if sup.coding else text} + if "fullUrl:" in text: r.kind = "form"; r.url = after("fullUrl:", text).strip(); r.stage = "pre" + else: r.kind = "document"; r.stage = "post" if "Type: post" in text else "pre" + r.at_preauth = (r.kind == "form") or (r.stage == "pre") + requirements.append(r) + return {"items": items, "requirements": requirements} +``` + +## 3. Insurance plan request + +Pin: `insurance`. Sent on `v1/insuranceplan/request`, workflow id = the case number. One entry. + +``` +function build_plan_request(policy_code, provider_id): + task = {"resourceType": "Task", "meta": profile("Task"), "status": "requested", "intent": "order", + "code": cc(FIN_TASK, "poll"), + "input": [{"type": cc(TASK_INPUT, "policyNumber"), "valueString": policy_code}, + {"type": cc(TASK_INPUT, "providerId"), "valueString": provider_id}]} + return bundle("insurance-request-generic", "TaskBundle", [entry(BASE + "/insurance/request", task)]) +# no id, no authoredOn, no requester; at least one input is mandatory +``` + +### Reader: the plan + +``` +function parse_plan_bundle(b): + plan = first(b, "InsurancePlan"); forms = {q.url: q for q in all(b, "Questionnaire")} + benefits = {} # keyed by package code + for p in plan.plan or []: # shape 1: package-based + for sc in p.specificCost or []: + specialty = sc.category.coding[0] + for ben in sc.benefit or []: + code = ben.type.coding[0].code; row = benefits.setdefault(code, new_benefit(code, ben.type.coding[0].display, specialty)) + for cost in ben.cost or []: + kind = cost.type.coding[0].code # Procedure | Implant | Stratification + if kind == "Procedure": row.rate = cost.value.value; row.kind = "Procedure" + else: row.extras.append({"kind": kind, "code": cost.qualifiers[0].coding[0].code, "display": cost.qualifiers[0].coding[0].display, "amount": cost.value.value}) + row.conditions.update(read_conditions(ben.extension)); row.requirements += read_requirements(ben.extension) + for cov in plan.coverage or []: # shape 2: coverage-based + for ben in cov.benefit or []: + code = ben.type.coding[0].code; row = benefits.setdefault(code, new_benefit(code, ben.type.coding[0].display, cov.type.coding[0])) + for lim in ben.limit or []: + if lim.code.coding[0].code == code: row.rate = lim.value.value + else: row.extras.append({"kind": "Stratification", "code": lim.code.coding[0].code, "display": lim.code.coding[0].display, "amount": lim.value.value}) + row.conditions.update(read_conditions(ben.extension)); row.requirements += read_requirements(ben.extension) + policy_requirements = read_requirements(plan.extension) # policy-wide: identity proof, consent forms + return {"plan": {"id": plan.id, "name": plan.name}, "benefits": list(benefits.values()), + "policy_requirements": policy_requirements, + "forms": [{"url": u, "title": q.title, "kind": "stg" if "/stgquestionnaire/" in u else "policy", + "questions": [{"linkId": it.linkId, "text": it.prefix or it.text, "type": it.type, + "options": [o.valueString or o.valueCoding.display for o in it.answerOption or []], + "default": first_selected(it)} for it in q.item]} for u, q in forms.items()]} + +function read_conditions(exts): # extension url family "...Claim-Condition": children named by their url tail + out = {} + for e in exts or []: + if "Claim-Condition" in e.url: + for child in e.extension or []: out[tail(child.url)] = child.valueString or child.valueBoolean or child.valueCodeableConcept.coding[0].code + return out + +function read_requirements(exts): # "...Claim-SupportingInfoRequirement": one nested requirement per document + out = [] + for e in exts or []: + if "Claim-SupportingInfoRequirement" in e.url: + for req in e.extension or []: + r = {} + for f in req.extension or []: + if tail(f.url) == "category": r.category = f.valueCodeableConcept.coding[0].code + if tail(f.url) == "code": r.code = f.valueCodeableConcept.coding[0].code; r.display = f.valueCodeableConcept.coding[0].display + if tail(f.url) == "documentationUrl": r.url = f.valueUri or f.valueString + out.append(r) + return out +``` + +## 4. The Claim bundle + +Pins: `preauth/request`, `preauth/enhancement`, `preauth/queryupdate`, `claim/request`, `claim/queryupdate`. One builder, three switches: `leg` (`preauth`, `claim`, `predetermination`), `flow` (`request`, `enhancement`, `queryupdate`), `use` (`preauthorization`, `claim`, `predetermination`). + +Entries, in order: Claim, Patient, provider Organization (id 1), payer Organization (id 2), Coverage (id 1), Practitioner (one per care team member), Procedure (one per package line), QuestionnaireResponse (one per answered form). + +``` +function claim_bundle(leg, use, d): + # d: flow, claim_no, created, admission{admitted_at, discharged_at, surgery_at, death_at, mode, stage}, + # patient{member_id, abha, name, phone, gender, birthDate}, facility, payer, policy_code, + # care_team[] {hpid, licence, hpin, name, qualification_code, qualification_display, specialty_snomed, specialty_display}, + # diagnoses[] {code, display}, lines[] (procedures and implants, each with tiers[]), documents[] {code, category, content_type, bytes, title}, + # forms[] {url, answers[] {linkId, type, value}}, program_code (AB-PMJAY or null), factor_rule (pmjay or null), + # preauth_ref (claim leg), summary{code, content_type, bytes, title} (claim leg), query_reply (queryupdate) + U = BASE; anchor = U + "/" + leg + "/" + d.flow + practitioners = [practitioner_resource(m, n + 1) for n, m in enumerate(d.care_team)] + procedures = [procedure_resource(line, n + 1, completed = (leg == "claim"), when = d.admission.surgery_at or d.admission.admitted_at) for n, line in enumerate(package_lines(d.lines))] + (qrs, form_refs) = questionnaire_responses(d.forms, d.created) + (si, si_refs) = supporting_info(d, leg, form_refs) + claim = {"resourceType": "Claim", "id": d.claim_no, "meta": profile("Claim"), + "identifier": [typed_id(ID_TYPE, "CLN", "Claim number", d.claim_no, BASE)], + "status": "active", "type": cc(SNOMED, "737481003", "Inpatient care management (procedure)"), "use": use, + "patient": ref(U + "/patient"), + "billablePeriod": {"start": d.admission.admitted_at, "end": d.admission.discharged_at or planned_end(d)}, + "created": d.created, "insurer": ref(U + "/payer"), "provider": ref(U + "/provider"), + "priority": cc(PRIORITY, "normal", "Normal"), + "careTeam": [{"sequence": n + 1, "provider": ref(practitioner_url(n)), + "role": cc(CARE_ROLE, "primary" if n == 0 else "assist", "Primary provider" if n == 0 else "Assisting Provider"), + "qualification": cc(SNOMED, m.specialty_snomed, m.specialty_display)} for n, m in enumerate(d.care_team)], + "supportingInfo": si, + "diagnosis": [{"sequence": n + 1, "diagnosisCodeableConcept": cc(ICD10, dx.code, dx.display), + "type": [cc(DX_TYPE, "admitting", "Admitting Diagnosis")], "onAdmission": cc(DX_ONADM, "yes", "Yes")} for n, dx in enumerate(d.diagnoses)], + "procedure": [{"id": "Procedure/" + str(n + 1), "sequence": n + 1, + "type": [cc(PROC_TYPE, line.procedure_type.lower(), line.procedure_type)], # from the plan's ProcedureType condition + "date": d.admission.surgery_at or d.admission.admitted_at, + "procedureReference": {"reference": U + "/procedure/" + str(n + 1), "display": line.display}} for n, line in enumerate(package_lines(d.lines))], + "insurance": [{"sequence": 1, "focal": true, "coverage": ref(U + "/coverage")}], + "item": claim_items(d, si_refs), + "total": money(sum(item.net.value for item in items))} + if leg == "claim": claim.insurance[0].preAuthRef = [d.preauth_ref] # the payer's ClaimResponse.preAuthRef + entries = [entry(anchor, claim), entry(U + "/patient", patient_resource(d.patient)), + entry(U + "/provider", provider_org(d.facility, "1")), entry(U + "/payer", payer_org(d.payer, "2")), + entry(U + "/coverage", coverage_resource(d.policy_code, d.patient.member_id))] + entries += [entry(practitioner_url(n), p) for n, p in enumerate(practitioners)] + entries += [entry(U + "/procedure/" + str(n + 1), p) for n, p in enumerate(procedures)] + entries += [entry(U + "/questionnaireresponse/" + str(n + 1), q) for n, q in enumerate(qrs)] + return bundle(leg + "-" + d.flow + "-request-generic", "ClaimBundle", entries) + # preauth-request-generic, preauth-enhancement-request-generic, preauth-queryupdate-request-generic, claim-request-generic, claim-queryupdate-request-generic + +function practitioner_url(n): return BASE + "/practitioner" + ("" if n == 0 else "/" + str(n + 1)) + +function patient_resource(p): + ids = [typed_id(ID_TYPE, "PMJAY", "Pradhan Mantri Jan Aarogya Yojana (PMJAY) ID", p.member_id)] + if p.abha: ids.append(typed_id(ID_TYPE, "ABHA", "Ayushman Bharat Health Account (ABHA) ID", p.abha)) + ids.append(typed_id(V2_0203, "MB", "Member Number", p.member_id)) + return {"resourceType": "Patient", "id": "1", "meta": profile("Patient"), "identifier": ids, + "name": [{"text": p.name}], "telecom": [{"system": "phone", "value": p.phone}], "gender": p.gender, "birthDate": p.birthDate} + +function practitioner_resource(m, n): + ids = [typed_id(ID_TYPE, "HPID", "Healthcare Professional ID (HPID)", m.hpid or m.hpin, BASE)] + if m.licence: ids.append(typed_id(V2_0203, "MD", "Medical License number", m.licence, BASE)) + ids.append(typed_id(ID_TYPE, "HPIN", "Health Practitioner ID issued by NDHM", m.hpin, HPR)) # PAYR-1083 without it + return {"resourceType": "Practitioner", "id": str(n), "meta": profile("Practitioner"), "identifier": ids, + "name": [{"text": m.name}], "qualification": [{"code": cc(V2_0360, m.qualification_code, m.qualification_display)}]} + +function coverage_resource(policy_code, member_id): + return {"resourceType": "Coverage", "id": "1", "meta": profile("Coverage"), + "identifier": [typed_id(V2_0203, "NH", "National Health Plan Identifier", policy_code)], + "status": "active", "type": cc(ACT_CODE, "HIP", "health insurance plan policy"), + "subscriber": ref(BASE + "/patient"), "subscriberId": member_id, "beneficiary": ref(BASE + "/patient"), + "relationship": cc(REL, "self"), "payor": [ref(BASE + "/payer")]} + +function procedure_resource(line, n, completed, when): + return {"resourceType": "Procedure", "id": str(n), "meta": profile("Procedure"), + "status": "completed" if completed else "preparation", + "code": {"coding": [{"system": SNOMED, "code": "71388002", "display": "Procedure"}], "text": line.display}, + "subject": ref(BASE + "/patient"), "performedDateTime": when} +``` + +### Items: one per procedure or implant, never per tier + +``` +function package_lines(lines): return [l for l in lines if l.kind in ("procedure", "implant")] # tiers ride on their parent + +function claim_items(d, si_refs): + groups = package_lines(d.lines); factors = procedure_factors(groups, d.factor_rule) + items = [] + for n, line in enumerate(groups): + tiers = [t for t in d.lines if t.kind == "tier" and t.parent_code == line.code] + net = line.amount + sum(t.amount for t in tiers) + item = {"id": "Item/" + str(n + 1), "sequence": n + 1, "careTeamSequence": [1], "diagnosisSequence": [1], + "procedureSequence": [n + 1], "informationSequence": si_refs, # every supportingInfo sequence + "category": cc(BENEFIT_CAT, line.category.code, line.category.display), + "productOrService": cc(PROC_CODE, line.code, line.display)} + if tiers: item.modifier = [cc(null, t.code, t.display) for t in tiers] + if d.program_code: item.programCode = [cc(PROGRAM, d.program_code, "Ayushman Bharat Pradhan Mantri Jan Arogya Yojana (AB-PMJAY)")] + item.servicedPeriod = {"start": day(d.admission.admitted_at), "end": day(d.admission.discharged_at or planned_end(d))} + item.quantity = {"value": int(line.quantity)} + item.unitPrice = money(net / line.quantity) + if factors: item.factor = factors[n] + item.net = money(net) + items.append(item) + return items + +function procedure_factors(groups, rule): + # PMJAY multiple-procedure rule: by cost rank, 1, 0.5, 0.25; a generic payer sends no factor + if rule != "pmjay" or len(groups) < 2: return null # the single-item pins carry factor 0.5 (their own contradiction); compare without it + ranked = sorted(range(len(groups)), key = lambda i: -groups[i].amount) + return {i: [1, 0.5, 0.25][min(rank, 2)] for rank, i in enumerate(ranked)} +``` + +### supportingInfo: the table, then the numbering + +``` +function supporting_info(d, leg, form_refs): + si = [] + for doc in d.documents: # one per attached file; never drop one + si.append({"category": cc(SI_CATEGORY, doc.category or "INV", display_for(doc.category or "INV")), + "code": cc(DOC_CODE, doc.code or "ODN", doc.title), # the plan's code, else ODN + "valueAttachment": {"contentType": doc.content_type, "data": base64(doc.bytes), "title": doc.title}}) + if leg == "claim": + si.append({"category": cc(SI_CATEGORY, "HDS", "Discharge summary"), "code": cc(DOC_CODE, d.summary.code or "HDS", d.summary.title), + "valueAttachment": {"contentType": d.summary.content_type, "data": base64(d.summary.bytes), "title": d.summary.title}}) + si.append(scalar("ONS", "ADDD", "Admission date -Discharge date", d.admission.admitted_at)) + si.append(scalar("OTH", "EDT", "EncounterDateTime", d.admission.admitted_at)) + if leg == "claim": + if d.admission.surgery_at: si.append(scalar("ONS", "PSP", "Procedure start", d.admission.surgery_at)) + si.append(scalar("ONS", "DSDE", "Discharge date", d.admission.death_at or d.admission.discharged_at)) + if d.admission.mode == "death": si.append(scalar("ONS", "DTM", "Date and time of death", d.admission.death_at)) # PAYR-1096 without it + code = {"normal": "DTH", "lama": "LAMA", "dama": "DAMA", "death": "DTM"}[d.admission.mode] + si.append(scalar("DIS", code, display_for(code), stage_words(d.admission.stage))) # "Before Surgery" | "During Surgery" | "After Surgery" + if d.flow == "queryupdate": + si.append(scalar("NMI", "CQD", "Claim query detail", d.query_reply)) # the desk's words; PMJAY reads its answer from here + for (form, url) in form_refs: # one per answered form + cat = "STG" if form.kind == "stg" else "INF"; code = "STG" if form.kind == "stg" else "ODN" + si.append({"category": cc(SI_CATEGORY, cat, display_for(cat)), "code": cc(SI_CODE, code, display_for(code)), "valueReference": ref(url)}) + for n, s in enumerate(si): # number once, after assembly: PAYR-1019 without sequence + s.id = "SupportingInformation/" + str(n + 1); s.sequence = n + 1 + reorder(s, ["id", "sequence", "category", "code", "value*"]) + return (si, [s.sequence for s in si]) + +function scalar(cat, code, display, value): + return {"category": cc(SI_CATEGORY, cat, display_for(cat)), "code": cc(SI_CODE, code, display), "valueString": value} +``` + +### Questionnaire responses + +``` +function questionnaire_responses(forms, authored): + qrs = []; refs = [] + for n, form in enumerate(forms): + url = BASE + "/questionnaireresponse/" + str(n + 1) + qr = {"resourceType": "QuestionnaireResponse", "id": str(n + 1), "meta": profile("QuestionnaireResponse"), + "questionnaire": form.url, "status": "completed", "subject": ref(BASE + "/patient"), "authored": authored, + "item": [{"linkId": a.linkId, "answer": [typed_answer(a)]} for a in form.answers]} + qrs.append(qr); refs.append((form, url)) + return (qrs, refs) + +function typed_answer(a): + switch a.type: + "string", "text", "choice": return {"valueString": a.value} + "date", "dateTime": return {"valueDateTime": a.value} + "boolean": return {"valueBoolean": a.value} + "integer": return {"valueInteger": int(a.value)} + "decimal": return {"valueDecimal": a.value} + "attachment": return {"valueAttachment": {"contentType": a.content_type, "data": base64(a.bytes), "title": a.title}} +``` + +### Which forms and documents ride + +``` +function required_forms(case, stage): # stage: preauth | claim + if case.ruling: forms = [r for r in case.ruling.requirements if r.kind == "form" and (stage == "preauth" or r.stage != "pre")] + else: forms = plan_stg_forms(case.plan, case.lines) if stage == "preauth" else [] + return forms + policy_forms(case.plan) # consent every leg: PAYR-1256 / PAYR-1363; STG: PAYR-1254 / PAYR-1365 + +function required_documents(case, stage): + if case.ruling: return [r for r in case.ruling.requirements if r.kind == "document" and (r.stage == "pre") == (stage == "preauth")] + wanted = plan_documents(case.plan, case.lines) + return wanted if stage == "preauth" else [w for w in wanted if not attached_at_preauth(case, w.code)] +``` + +### The legs, and the LAMA collapse + +``` +function lines_for(case, leg): + if leg == "claim" and case.admission.mode in ("lama", "dama") and case.admission.stage in ("before", "during"): + return [{"kind": "procedure", "code": "LM100", "display": "Left against medical advice", "quantity": 1, + "amount": plan_rate(case.plan, "LM100") or 0, "category": lm100_category(case.plan)}] # PAYR-1362 if the package stays + return case.lines # LM100 never on a pre-auth: PAYR-1270 +``` + +| Leg | flow | use | Procedure status | Workflow | Extra | +| --- | --- | --- | --- | --- | --- | +| Pre-auth | `request` | `preauthorization` | `preparation` | 12 | fresh 12 after a rejection too (PAYR-1214 on 121) | +| Enhancement | `enhancement` | `preauthorization` | `preparation` | 13 | every line, old and new, same claim number; factors 1 and 0.5 | +| Query answer | `queryupdate` | `preauthorization` | `preparation` | 19 (131 after an enhancement query) | `NMI/CQD`; new correlation id | +| Claim | `request` | `claim` | `completed` | 15 | discharge scalars, `HDS`, `preAuthRef`, under the pre-auth's number (ERR-PYR-CLM-007) | +| Claim query answer | `queryupdate` | `claim` | `completed` | 161 (PMJAY), 151 (generic) | as the claim plus `NMI/CQD` | +| Predetermination | `request` | `predetermination` | `preparation` | 12 on `v1/preauth/submit` | no state effects | + +## 5. Reader: ClaimResponse + +Fed by every answer on a pre-auth, enhancement, claim or predetermination thread. Entries: ClaimResponse, Patient, two Organizations, Coverage. + +``` +function parse_claim_response(b): + r = first(b, "ClaimResponse") + status_adj = first(a for a in r.adjudication or [] if a.category.coding[0].code == "status") + out = {"use": r.use, "outcome": r.outcome, "disposition": r.disposition, + "status_reason": status_adj.reason.coding[0].code.lower() if status_adj else null, # submitted|approved|queried|rejected|cancelled + "preauth_ref": r.preAuthRef if is_string(r.preAuthRef) else (r.preAuthRef[0] if r.preAuthRef else null), + "claim_no": r.identifier[0].value if r.identifier else null, + "totals": {t.category.coding[0].code: t.amount.value for t in r.total or []}, # by category, never by position + "items": [], "notes": [n.text for n in r.processNote or []]} + for it in r.item or []: + adj = {a.category.coding[0].code: a for a in it.adjudication or []} + out.items.append({"sequence": it.itemSequence, + "status": adj.status.reason.coding[0].code.lower() if adj.status else null, + "eligible": adj.eligible.amount.value if adj.eligible else null, + "submitted": adj.submitted.amount.value if adj.submitted else null, + "reason": adj.reason.reason.coding[0].display if adj.reason else "", # verbatim, pipe-delimited USER~datetime~type~comment~trust + "eligpercent": adj.eligpercent.value if adj.eligpercent else null, + "deductible": adj.deductible.amount.value if adj.deductible else null}) + return out + +function verdict_status(p): # copy exactly; never read outcome alone + if p.outcome == "queued" or p.status_reason == "submitted": return "submitting" + if p.status_reason == "cancelled": return "rejected" + if p.status_reason == "queried": return "queried" + if p.outcome == "error": return "rejected" + if p.outcome == "partial": return "partial" if p.status_reason == "approved" else "queried" + if p.outcome == "complete": return "approved" if p.status_reason in ("approved", null) else "queried" + return "queried" + +function apply_claim_response(leg, p, envelope): + leg.status = verdict_status(p) + if p.preauth_ref: leg.preauth_ref = p.preauth_ref # never overwrite a value with an empty one + leg.eligible_amount = p.totals.get("eligible") or p.totals.get("benefit") + leg.submitted_amount = p.totals.get("submitted") + leg.approved_amount = p.totals.get("benefit") # what the screen shows as the decision + leg.items_json = p.items; leg.query_note = join(p.notes + [i.reason for i in p.items if i.reason]) + leg.thread_correlation_id = envelope.jwe_headers["x-hcx-correlation_id"] + leg.answered_at = now() if leg.status != "submitting" else leg.answered_at +``` + +Payer workflow ids are labels for the timeline only: 20 received, 21 approved, 22 enhancement approved, 23 rejected, 24 queried, 25 claim received, 26 approved, 27 queried, 291 rejected. The bundle decides the state. + +## 6. Task bundles the hospital sends + +Pins: `preauth/cancel`, `claim/reprocess`, `claim/release`, `payment/notice-ack`. Sent on `v1/task/submit` (the payment acknowledgement on `v1/paymentnotice/on_request`). Entries: Task, provider Organization, payer Organization. + +``` +function task_bundle(id, anchor, task, facility, payer): + return bundle(id, "TaskBundle", [entry(BASE + anchor, task), entry(BASE + "/provider", provider_org(facility)), entry(BASE + "/payer", payer_org(payer))]) + +function base_task(code, status, authored_on, description): + return {"resourceType": "Task", "meta": profile("Task"), "status": status, "intent": "order", + "code": cc(FIN_TASK, code), "description": description, "authoredOn": authored_on, + "requester": ref(BASE + "/provider"), "owner": ref(BASE + "/payer")} + +function task_input(code, display, value): return {"type": cc(TASK_INPUT, code, display), "valueString": value} +function based_on(claim_no): return [{"identifier": typed_id(ID_TYPE, "CLN", "Claim number", claim_no, BASE), "display": "Claim " + claim_no}] + +function cancel_task(claim_no, reason, authored_on, facility, payer): # workflow PC01 + t = base_task("cancel", "requested", authored_on, "Cancel the preauthorization " + claim_no) + t.reasonCode = cc(REASON, reason.code, reason.display) # treatmentplanchanged, ... + t.input = [task_input("claimNumber", "ClaimNumber", claim_no), task_input("intimationNumber", "IntimationNumber", claim_no)] + return task_bundle("preauth-cancel-request-generic", "/preauth/cancel", t, facility, payer) + +function reprocess_task(claim_no, member_id, reason, description, documents, authored_on, facility, payer): # workflow 36 + t = base_task("reprocess", "requested", authored_on, description) + t.reasonCode = cc(REASON, reason.code, reason.display) # claimrejected | partialpayment | rejectiondisputed + t.basedOn = based_on(claim_no) + t.input = [task_input("claimNumber", "ClaimNumber", claim_no), task_input("intimationNumber", "IntimationNumber", claim_no)] + t.input += [{"type": cc(TASK_INPUT, "document", "Document"), "valueAttachment": {"contentType": d.content_type, "data": base64(d.bytes), "title": d.title}} for d in documents] + t.for = {"identifier": typed_id(ID_TYPE, "PMJAY", "Pradhan Mantri Jan Aarogya Yojana (PMJAY) ID", member_id)} # MB on a generic payer + return task_bundle("claim-reprocess-request-generic", "/claim/reprocess", t, facility, payer) + +function release_task(claim_no, amount, authored_on, facility, payer): # workflow 36 + t = base_task("release", "requested", authored_on, "Release the balance amount for claim " + claim_no) + t.reasonCode = cc(REASON, "partialpayment", "Reprocess request due to partial payment by payer") + t.basedOn = based_on(claim_no) + t.input = [task_input("claimNumber", "ClaimNumber", claim_no), {"type": cc(TASK_INPUT_X, "amount", "Amount"), "valueMoney": money(amount)}] + return task_bundle("claim-release-request-generic", "/claim/release", t, facility, payer) + +function status_task(claim_no, authored_on, facility, payer): # workflow = the leg's correlation id; PMJAY refuses (PAYR-1018) + t = base_task("status", "requested", authored_on, "Status of " + claim_no) + t.input = [task_input("claimNumber", "ClaimNumber", claim_no)] + return task_bundle("claim-status-request-generic", "/claim/status", t, facility, payer) + +function payment_ack(claim_no, authored_on, facility, payer): # workflow 17 (PMJAY) or the notice's own id; x-hcx-correlation_id = the notice's + t = base_task("status", "completed", authored_on, "Received the payment for claim " + claim_no) + t.output = [{"type": cc(TASK_OUTPUT, "status", "Status"), "valueCodeableConcept": cc(TASK_OUTVAL, "paymentack", "Payment is acknowledged")}, + {"type": cc(TASK_INPUT, "claimNumber", "ClaimNumber"), "valueString": claim_no}] + return task_bundle("payment-notice-ack-generic", "/payment/notice-ack", t, facility, payer) +``` + +The pins and the build both carry `intimationNumber`, so the offline comparison diffs the pins unchanged. + +### Readers: PC02, 37, status + +``` +function parse_task_answer(b): + t = first(b, "Task"); cr = first(b, "ClaimResponse") # a 37 may carry a ClaimResponse queued + outputs = {o.type.coding[0].code: o for o in t.output or []} + return {"status": t.status, "code": t.code.coding[0].code, + "claim_status": (outputs.get("claimStatus") or outputs.get("status") or {}).valueCodeableConcept.coding[0].code if outputs else null, + "description": t.description, "queued": cr is not null and cr.outcome == "queued"} +# PC02: pre-auth -> cancelled, episode gets a fresh claim number, the withdrawn one stays on the leg +# 37: enquiry row -> answered; a fresh verdict follows on the claim's own thread +``` + +## 7. Communication + +Pins: `communication/request` (the payer's TaskBundle, the reader's input) and `communication/response` (the hospital's reply). On `v1/communication/request` in, `v1/communication/on_request` out, with the request's correlation id and workflow id echoed. + +``` +function parse_communication_request(b): + t = first(b, "Task"); cr = first(b, "CommunicationRequest") + return {"task_status": t.status, "intent": t.intent, "reason": t.reasonCode.coding[0].code.lower() if t.reasonCode else null, + "request_id": cr.id, "request_url": fullurl_of(b, cr), + "questions": [p.contentString for p in cr.payload or [] if p.contentString], + "about_claim": (cr.basedOn or [{}])[0].display, "claim_no": claim_no_in(b)} + +function classify_communication(adapter, reason, intent): + if adapter.query_mode == "resubmit": return "notification" + if intent == "proposal": return "notification" + if intent == "order": return "query" + if reason in (null, "additionalinfo", "questionnaire", "query"): return "query" + return "notification" # tatquery, grievance, walletupdate, policychange, claimarbitration + +function build_acknowledgement_bundle(request_bundle, facility): # a notification, sent back at once + b = deepcopy(request_bundle); t = first(b, "Task"); t.status = "completed" + move_first(b, "Organization", where = provider) # provider Organization first + return b + +function build_communication_bundle(q, text, documents, sent_leg_bundle, facility, payer, now): + # q: the parsed request; sent_leg_bundle: the pre-auth or claim bundle as sent (its Claim, Patient, Organizations, Practitioner, Coverage are lifted) + task_id = uuid(); comm_id = uuid() + comm = {"resourceType": "Communication", "id": comm_id, "meta": profile("Communication"), + "identifier": [{"value": q.request_identifier}], "basedOn": [{"reference": q.request_url, "display": "CommunicationRequest"}], # never inResponseTo + "status": "completed", "category": [cc(COMM_CAT, "notification")], "priority": "routine", + "about": [{"reference": claim_anchor(sent_leg_bundle), "display": "Claim " + claim_no}], + "sender": {"reference": BASE + "/provider", "display": "Organization"}, "recipient": [{"reference": BASE + "/payer", "display": "Organization"}], + "payload": [{"contentString": text}] + [{"contentAttachment": {"contentType": d.content_type, "data": base64(d.bytes), "title": d.title}, + "extension": [{"url": DOC_TYPE_EXT, "valueString": d.code}]} for d in documents]} + task = {"resourceType": "Task", "id": task_id, "meta": profile("Task"), "status": "completed", "intent": "order", + "code": cc(TASK_CODES, "deliver"), "reasonCode": cc(null, q.reason or "additionalinfo", "Additional information requested"), + "authoredOn": now, "requester": {"reference": BASE + "/provider", "display": "Organization"}, "owner": {"reference": BASE + "/payer", "display": "Organization"}, + "input": [{"type": cc(FIN_INPUT, "include"), "valueReference": {"reference": "urn:uuid:" + comm_id, "display": "Communication"}}]} + entries = [entry("urn:uuid:" + task_id, task), entry("urn:uuid:" + comm_id, comm), entry(q.request_url, q.request_resource)] + entries += [entry(e.fullUrl, e.resource) for e in sent_leg_bundle.entry if e.resource.resourceType in ("Claim", "Patient", "Organization", "Practitioner", "Coverage")] + b = bundle("communication-response-generic", "TaskBundle", entries) + b.meta.lastUpdated = now; b.timestamp = now # the IG example carries both; the only request that does + return b +``` + +Excluded from the byte comparison of the reply: `meta.lastUpdated`, `timestamp`, `authoredOn`, the two generated uuids. + +## 8. Payment notice + +Read on `v1/paymentnotice/request`. Entries: Task, PaymentNotice, PaymentReconciliation, two Organizations. + +``` +function parse_payment_notice(b): + pn = first(b, "PaymentNotice"); pr = first(b, "PaymentReconciliation"); t = first(b, "Task") + out = {"claim_no": pn.identifier[0].value if pn.identifier else claim_no_in(b), + "amount": pn.amount.value, "payment_status": pn.paymentStatus.coding[0].code, # paid | cleared | ... + "payment_date": pn.paymentDate, "utr": null, "details": []} + if pr: + out.utr = pr.paymentIdentifier.value if pr.paymentIdentifier else null + out.gross = pr.paymentAmount.value if pr.paymentAmount else null + out.details = [{"type": d.type.coding[0].code, "amount": d.amount.value if d.amount else null} for d in pr.detail or []] # deductions, TDS + if not out.utr and pn.payment and pn.payment.identifier: out.utr = pn.payment.identifier.value + return out +# record: one claim_payment row keyed on the message's correlation id (unique), matched by claim_no; then acknowledge with payment_ack() +``` + +## 9. Validate before you send + +``` +function validate_bundle(b, pin): # the offline gate, module 7.7 Validate + assert canonical(strip(b, ["created"])) == canonical(strip(pin, ["created"])) # plus the per-shape exclusions above + urls = {e.fullUrl for e in b.entry} + for r in all_references(b): assert r in urls or r.startswith("urn:uuid:") + c = first(b, "Claim") + if c: + for it in c.item: assert it.id and it.sequence + for p in c.procedure: assert p.id and p.sequence + for n, s in enumerate(c.supportingInfo): assert s.id and s.sequence == n + 1 + for pr in all(b, "Practitioner"): assert any(i.type.coding[0].code == "HPIN" and i.system == HPR for i in pr.identifier) + assert c.total.value == sum(it.net.value for it in c.item) + assert not any(it.productOrService.coding[0].code == "LM100" for it in c.item) or c.use == "claim" + assert no literal in the builder matches r"MAND\d+|MG\d+|/questionnaire/" +``` + +| Symptom | Refusal | +| --- | --- | +| an item without `id` | PAYR-1027 | +| a supportingInfo without `sequence` | PAYR-1019 | +| a Practitioner without `HPIN` | PAYR-1083 | +| a death claim without `ONS/DTM` | PAYR-1096, PAYR-1503 | +| a LAMA claim before surgery still carrying the package | PAYR-1362 | +| `LM100` on a pre-auth | PAYR-1270 | +| the consent form unanswered | PAYR-1256 (pre-auth), PAYR-1363 (claim) | +| a package's STG form unanswered | PAYR-1254, PAYR-1365 | +| a claim under its own number | ERR-PYR-CLM-007 | +| 121 after a rejection | PAYR-1214 | +| 151, 19 or 16 on `v1/claim/submit` to PMJAY | PAYR-1321 | +| a document outside pdf, jpg, jpeg, png; a Task the sandbox does not take; a misspelt intimation input on a reprocess | PAYR-1008 | diff --git a/plugins/nhcx/skills/nhcx-coverage/flow/FLOW.md b/plugins/nhcx/skills/nhcx-coverage/flow/FLOW.md new file mode 100644 index 000000000..312668e67 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-coverage/flow/FLOW.md @@ -0,0 +1,228 @@ +# The flow: the one path a claim episode walks + +This is the reference flow for an NHCX provider desk: these steps, in this order, with these guards and these words. A build from this skill walks the same path. It does not redesign it, reorder it, merge steps, or invent screens the path does not have. Stage 4 copies it, stage 5 puts screens on it, stage 7 implements it step by step, stage 8 checks every step exists, and test drivers check the same through `flow.json`. + +## The shape + +One episode is one case (`claim` row). It has one list screen, one "new case" screen and one case screen. The case screen has tabs in the order the episode happens, and above the tabs one status line and the actions the case is waiting for. Everything else (inbox, payments across cases) is a view over the same rows. + +Tabs on the case screen, in this order and with these names: + +| # | Tab key | Tab label | Opens when | +| --- | --- | --- | --- | +| 1 | `eligibility` | Eligibility | always | +| 2 | `plan` | Insurance plan | always (empty until the plan is fetched) | +| 3 | `lines` | Line items | always (quoting refused until the plan is `ready`) | +| 4 | `validate` | Validate | always (the ruling on the quoted set) | +| 5 | `preauth` | Pre-authorisation | once the coverage verdict is `eligible` | +| 6 | `communication` | Communication | always (the payer's questions on both legs) | +| 7 | `claim` | Claim | always; its submit opens once a pre-auth is approved or partial | +| 8 | `payments` | Payments | always | + +The episode may also render on one page, with the same sections in the same order. Either shape is fine; the order and the gating are not negotiable. + +## Which skill builds which step + +Seven skills build this flow, one slice each (`core/LADDER.md`). `flow.json` names them per step in `skills`, the first named being the one that owns the step. + +| Steps | Skill | +| --- | --- | +| F1, F2, F3 | `nhcx-coverage` | +| F4, F7 | `nhcx-insurance` | +| F5, F6, F8, F9, F9a, F9c, F9d, F9e; F9b for a `resubmit` payer (19, 131) | `nhcx-preauth` | +| F10, F11; the claim query answer for a `resubmit` payer (161) | `nhcx-claim` | +| F9b and the claim query for a `communication` payer; F12b | `nhcx-communication` | +| F12 | `nhcx-payment` | +| F13 | `nhcx-reprocess` | + +The case screen, its tabs, the status line and actions, and the page-load polls are the foundation's (`core/FOUNDATION.md`): the first skill lays them out whole, and each skill fills its own tabs. + +## The status line and the actions + +Above the tabs: `stage / sub-stage` from `case_stage` (module 7.11) and the list from `next_actions`, first item highlighted. The labels are these, verbatim: + +| Stage | Sub-stage | Action offered (label, tab) | +| --- | --- | --- | +| any | an open query exists | "Answer the payer (n)", `communication` (leads every list) | +| `eligibility` | `draft`, `error`, `not-eligible` | "Check the cover", `eligibility` | +| `eligibility` | `eligible`, no plan `ready` | "Fetch the package master", `plan` | +| `eligibility` | plan ready, no lines | "Quote the treatment", `lines` | +| `eligibility` | lines quoted | "Send the pre-authorisation", `preauth` | +| `preauth` or `enhancement` | `queried` | "Answer the query", `preauth` (resubmit payer) or "Answer the payer's query", `communication` (communication payer) | +| `preauth` | `draft`, `refused` | "Send the pre-authorisation", `preauth` | +| `preauth` | `rejected` | "Send a fresh pre-authorisation", `preauth` | +| `preauth` | `approved`, `partial`, lines added since | "Send the enhancement (n added)", `preauth` | +| `preauth` | `approved`, `partial`, not discharged | "Record the discharge", `claim` | +| `preauth` | `approved`, `partial`, discharged | "File the claim", `claim` | +| `preauth` | `requested`, `answered`, `resubmitted` | "With the payer; ask where it stands", `preauth` | +| `claim` | `queried` | "Answer the claim query", `claim` or "Answer the payer's query", `communication` | +| `claim` | `rejected`, `partial` | "Ask for a reprocess", `claim` | +| `claim` | `requested`, `answered`, `resubmitted` | "With the payer; ask where it stands", `claim` | +| `claim` | `refused` | "Send the claim again", `claim` (while a send kind remains) else "Ask for a reprocess" | +| `claim` | `approved` | "Await the payment notice", `payments` | +| `payment` | a notice unacknowledged | "Acknowledge the payment notice", `payments` | +| `payment` | all acknowledged | "Settled", `payments` | + +## The steps + +Each step: where it happens, what must hold, what the user does, what the system does (module in brackets), what goes on the wire, what is stored, where the case stands afterwards, and what the screen shows next. Ids are `F1` to `F13` with letters for branches; `flow.json` carries the same ids. + +### F1. Policy search + +- Screen: Cases list, "New case", `GET /claims/new`. +- Holds: nothing. +- User: picks an identifier type (`MemberId`, `AbhaNumber`, `MobileNo`) and a value, presses "Search policies". +- System [7.4]: `search_policies` through the transport: the participant service's `participant/get/policies`; normalises each row (`member_id`, `policy_code` from `productid`, `payer_code` from `payerid`, `recipient_code` from `processingid`, `product_name`). NHCX-1016 (nothing linked) is an empty list, not an error. +- Screen: a table, one row per policy: beneficiary, product and policy, payer, ABHA, mobile, a "Select" button. No name and no photo yet; the payer returns those at F3. + +### F2. Open the case + +- Screen: the same, "Select" on a row; `POST /claims`. +- System [7.4, 7.2]: `create_claim` snapshots the policy (`member_id`, `policy_code`, `payer_code`, `recipient_code`, `policy_json`), mints the claim number, stamps `eligibility / draft`. +- Redirect: the case screen, Eligibility tab, "Claim opened." +- Next action: "Check the cover". + +### F3. Check the cover (coverage eligibility) + +- Screen: Eligibility tab, card "Coverage eligibility check": purpose select (`validation` default, `benefits`, `discovery`), policy code and member id shown from the snapshot, "Send to payer". +- Holds: member id; policy code for `validation` and `benefits`. +- System [7.4]: `run_check(purpose)`, workflow id = the claim number, status `checking`; the page shows "Awaiting payer" and refreshes; the answer arrives by callback [7.3] or poll. +- Wire: `v1/coverageeligibility/check`; `on_check` back. +- Stored: `txn_id`, `correlation_id`, `api_call_id`; on the answer `inforce`, `outcome`, `disposition`, allowed and used amounts, the payer's `Patient` (name, gender, DOB, address, ABHA, photo), `Coverage` class and period. +- After: `eligibility / eligible` or `not-eligible` (or `error` with the payer's words). A `ProtocolResponse` or a 404 on `txn/related` settles as `error`, never spins. +- Screen: card "Payer verdict": Sum insured, Utilised, Wallet balance (allowed less used), Disposition verbatim, In force, Pre-authorisation required, Checked at, Correlation. Beneficiary card fills with the payer's demographics. "Check again" allowed from any settled state. +- Next action: "Fetch the package master". + +### F4. Fetch the package master (insurance plan) + +- Screen: Insurance plan tab, "Fetch the plan" (or "Refresh"). +- Holds: `eligible`. +- System [7.5]: `reuse_plan` first (same policy, provider, payer, status `ready`: zero sends); else `request_plan`, status `fetching`, workflow id = the claim number. +- Wire: `v1/insuranceplan/request`; `on_request` back with the InsurancePlan and Questionnaires. +- Stored: `claim_plan` (`ready`, `empty` or `error`), `claim_plan_benefit` per package, `claim_plan_form` per url. Both published shapes merged on package code. +- Screen: a search over the master (name or code, specialty filter, procedure or implant), one row per package with rate, kind, "View"; a package view with rate, implants approved, tiers, conditions, documents wanted, the forms those point at as questions; an "All forms" page. Policy-wide requirements shown above the table. +- Next action: "Quote the treatment". + +### F5. Link the admission (integrate) or capture it (standalone) + +- Screen: Pre-authorisation tab, card "Link the admission" (opens once `eligible`). +- Holds: `eligible`. +- Integrate: list every current inpatient stay of the patient whose ABHA matches the payer's (digits only); "Link" stores `patient_id` and `encounter_id`, defaults the admission date from the encounter. Linking before `eligible` and to a stay that is not a current IPD admission is refused. "Unlink" keeps the draft. +- Standalone [7.13]: register the patient (from the payer's demographics) and admit them here; the same two keys are stored. +- Screen after: card "Linked admission" with ward, bed, admitted at, consultant. + +### F6. The dossier (pre-auth capture) + +- Screen: Pre-authorisation tab, once linked: the form, saved in one transaction by `save_preauth` [7.7 inputs]. +- Captured: admission date (required) and provisional discharge date (not before admission); ICD-10 diagnoses (at least one; read off the admission when it recorded them, else a picker); the treating doctor (the admission's consultant, else a picker; must have an HPIN); package case or non-package case toggle; documents (pdf, jpg, jpeg, png, each recorded against the payer requirement code it answers, else `ODN`). +- Estimated amount: always recomputed server-side from the lines (F7), never from the form. +- Guards: saving a package case with no line quoted is refused. + +### F7. Quote the treatment (lines from the plan) + +- Screen: Line items tab, "Choose line items", `GET /claims//lines`. Three parts: what is quoted (editable quantities, running total, "remove"); what the payer says goes with it (implants approved for the quoted procedures, the tiers each offers; anything already quoted drops out); the whole master to search. +- Holds: plan `ready`. Quoting anything before that is refused. +- System [7.5]: `add_line(kind, code, parent_code)`; price read from the plan at add time; `amount = rate x quantity` server-side; a tier is added through the procedure that offers it and carries `parent_code`. Refused: a code the plan lacks, a tier the procedure does not offer, a duplicate, a zero quantity. +- Forms: the chosen lines pull in the questionnaires the plan attaches (STG per package, policy forms always); they render on the Pre-authorisation tab and are answered there (`save_answers`, one row per question, file answers upload a document). +- Next action: "Send the pre-authorisation". + +### F8. Validate the set (auth requirements) + +- Screen: Validate tab, "Ask the payer" (also run silently before F9). +- Holds: at least one line. +- System [7.6]: `ensure_auth_requirements`: fingerprint the quoted set; send only when the fingerprint is new; never wait for the answer. +- Wire: `v1/coverageeligibility/check` with purpose `auth-requirements` and the items; `on_check` back (the PMJAY sandbox rarely answers). +- Stored: `claim_auth` (`checking` then `ready`), items authorised or excluded, requirements (document or form, code, url, stage `pre` or `post`, `at_preauth`). +- Screen: the ruling per line, the documents and forms it wants for each leg; the pre-auth and claim tabs read it to build their document and form cards. Without a ruling they fall back to the plan's list. + +### F9. Send the pre-authorisation + +- Screen: Pre-authorisation tab, card "Submit": what will be sent (lines, forms answered, documents attached, the total), "Send to payer". +- Holds (all before any HTTP call): `eligible`; an admission linked; an admission date; at least one diagnosis; at least one care team member with an HPIN; at least one line; every required form answered; every document the ruling or plan asks for at pre-auth attached. +- System [7.7]: `submit_preauth`: `preauth_send_kind` picks `preauth` (12); builds the Claim bundle (`preauth`, `request`); status `submitting`, `submission_kind`, `workflow_id`; stores the three ids; `thread_correlation_id` untouched until the payer answers. +- Wire: `v1/preauth/submit`, workflow 12. +- After: `preauth / requested`. +- Screen: "Awaiting payer", the timeline row for the send, Refresh. Next action: "With the payer; ask where it stands". + +#### F9a. The payer answers + +- Callback [7.3] or poll: first the acknowledgement (workflow 20, `outcome queued`, reason `submitted`): recorded, `preauth_ref` kept, the leg stays `submitting`. Then the decision on the same correlation id: `verdict_status` [7.8]. +- After: `approved` (21), `partial` (approved for less), `queried` (24), `rejected` (23). Never read `outcome` alone. +- Screen: Decision, Payer reference (`preAuthRef`), Approved amount (`total[benefit]`), Eligible amount, the item verdicts table (eligible, status, reason verbatim, eligible %, quantity), process notes verbatim. A door refusal shows as a flag with the payer's code and text, the thread restored. +- Next action per the table above. + +#### F9b. Answer a query + +- Resubmit payer (PMJAY): the query is inside the ClaimResponse (`query_note`). Screen: Pre-authorisation tab, the payer's words, a reply box, "Submit again". System: `submit_preauth(reply)` with kind `preauth_query_response` (19; 131 after an enhancement query), flow `queryupdate`, `NMI/CQD` = the reply, a new correlation id. After: `answered`, then the decision. +- Communication payer (generic): the query is a CommunicationRequest on a new thread, filed in `claim_query` (F12 inbox). Screen: Communication tab, the questions verbatim, a reply box, documents to attach (existing or new, each under the payer's code else `ODN`), "Send the reply". System [7.10]: `answer_query`: the TaskBundle reply on `v1/communication/on_request` with the request's correlation id and workflow id. The leg stays `queried` until the decision arrives on its own thread. An empty reply is refused before any HTTP call. + +#### F9c. Enhancement + +- Screen: Line items tab, add a line after a decision; the Pre-authorisation card shows "enhancement pending (n added)"; "Submit enhancement". +- Holds: `approved` or `partial`; no request in flight. +- System: `submit_preauth` with kind `enhancement` (13; `enhancement_resubmit` 131 on a query): the whole bundle again, every line old and new, same claim number, factors 1 and 0.5. After: `enhancement / requested`, then 22 (or 21 from the SHA), 231, 241. + +#### F9d. Cancel + +- Screen: Pre-authorisation tab, "Withdraw": a reason picker (the seven documented reasons) and a note, required for Other. Hidden once a claim has been raised; refused on a `rejected` pre-auth and twice. +- System [7.9]: `cancel_preauth`: Task `cancel`, workflow PC01, on its own thread (`cancel_correlation_id`), `cancelling`. +- After PC02: `cancelled`; the episode gets a fresh claim number, the withdrawn one stays on the leg. + +#### F9e. Predetermination (a quote) + +- Screen: Pre-authorisation tab, "Ask for a quote". +- System [7.7]: the very bundle F9 would send with `use predetermination`, on `v1/preauth/submit`, workflow 12, its own row (`asking` then `answered`). Nothing on the pre-auth changes. + +### F10. Record the discharge + +- Screen: Claim tab, card "Discharge": mode (Normal, LAMA, DAMA, Death), stage (Before, During, After surgery), discharge date and time, surgery date and time, death date and time (death only). +- Holds: a pre-auth `approved` or `partial`. +- Stored: on `claim_submission` (`draft`) or the encounter. +- Screen after: the claim card opens; for LAMA or DAMA before or during surgery it says the approved packages are voided and the claim will carry `LM100` only. +- Next action: "File the claim". + +### F11. File the claim + +- Screen: Claim tab, cards "Documents for the claim" (what the ruling deferred to this stage, plus the discharge summary, always), "Forms for the claim" (the consent again, and what the ruling deferred), "Everything attached for the claim" (any further pdf or image), "Submit the claim". +- Holds: discharge recorded; the discharge summary attached; every claim-stage form answered; amount not above the approved amount. +- System [7.7]: `submit_claim`: `claim_send_kind` (`claim` 15; `claim_query_response` 161 PMJAY or 151 generic; `claim_resubmit` 16 generic only); the Claim bundle (`claim`, `request`) under the pre-auth's claim number with `preAuthRef`, procedures `completed`, discharge scalars, `HDS`, `DIS`; `LM100` collapse when it applies. +- Wire: `v1/claim/submit`. +- After: `claim / requested`; then 25 (ack), 26 `approved`, 27 `queried`, 291 `rejected`, read as F9a. +- Screen: as the pre-auth card: decision, amounts, item verdicts with `deductible`, notes verbatim. + +#### F11, continued: claim query and reprocess + +- Query: as F9b, on the claim (161 or the Communication reply). +- Rejected or partial: "Ask for a reprocess" (F13). There is no claim resubmit on PMJAY. + +### F12. Payments + +- The payer starts it: `v1/paymentnotice/request` arrives on a new thread, matched by the claim number inside (a `CLN` identifier, then any untyped identifier on the notice, the reconciliation, the Task; never the bundle id), looked up against `claim_no` and every leg's `claim_ref`. +- System [7.10]: `record_payment`: one `claim_payment` row per notice, deduped on the notice's correlation id; details from the PaymentReconciliation; a payer that reuses the notice id updates the row. Then, at once and automatically, `acknowledge_payment`: Task `status` `completed`, output `paymentack`, to the notice's own sender, its correlation id echoed, workflow 17 (PMJAY) or the notice's own (generic). A failed acknowledgement is kept on the row; the notice is still recorded and the callback still answered 2xx. +- After: `payment / noticed` or `paid`. Paid is counted once per UTR, newest notice winning; an initiated notice without a UTR shows "Initiated, UTR awaited" and is not money received. +- Screen: Payments tab, one card per notice: status, amount, UTR as text, the breakdown, "Acknowledged at" or "Send the acknowledgement again". Across cases: the payments view. +- Next action: "Acknowledge the payment notice" while one is pending, else "Settled". + +### F12b. The inbox + +- Every CommunicationRequest is classified [7.10]: query, notification or note. Notifications are acknowledged at once (the payer's bundle back, Task `completed`) and the case left alone. Queries are filed `open` and lead every action list until answered (F9b). Notes are shown, never acted on. +- Screen: Communication tab on the case; the inbox view across cases, by kind and reason. + +### F13. The small exchanges + +- Status: "Ask where it stands" on the pre-auth and claim cards, while awaiting and after a decision; Task `status`, workflow = the leg's correlation id (fallback 13); not offered to a payer whose adapter refuses it (PMJAY, PAYR-1018). The answer fills the enquiry row; the leg is unchanged. +- Reprocess: on a decided claim not paid in full, "Send reprocess request" with a coded reason (`claimrejected`, `partialpayment`, `rejectiondisputed`), words, and documents; Task `reprocess`, workflow 36. The payer's `completed` Task (37) reopens the claim: the submission goes back to `requested` and the new verdict lands on the claim's own thread. +- Release: once part of an approved claim is paid, "Ask for the balance" with the amount owed; Task `release`, reason `partialpayment`, `valueMoney`, workflow 36. +- Each ask is its own `claim_enquiry` row on its own thread, shown on the card it belongs to, newest first. + +## What runs on every page load of the case + +In this order, before rendering, each bounded to one poll and a short timeout, never a send: coverage (`checking`), plan (`fetching`), ruling (`checking`), claim (`submitting`), predeterminations (`asking`), pre-auth (`submitting` or `cancelling`), enquiries (`asking`). Then the beneficiary card, the policy card, the verdict card, the status line and actions, the tabs. A "Refresh" button reloads the same tab. + +## What is not in the flow + +- No status control anywhere. Stage and sub-stage are derived. +- No manual acknowledgement of a payment notice as the only path; it goes automatically and the screen shows that it went. +- No "chase" button without the status exchange behind it. +- No separate discharge submission on PMJAY; the discharge rides on the claim. +- No claim resubmit on PMJAY; a decided claim is reprocessed. diff --git a/plugins/nhcx/skills/nhcx-coverage/flow/flow.json b/plugins/nhcx/skills/nhcx-coverage/flow/flow.json new file mode 100644 index 000000000..315d1a4b8 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-coverage/flow/flow.json @@ -0,0 +1,818 @@ +{ + "source": "flow/FLOW.md", + "tabs": [ + { + "key": "eligibility", + "label": "Eligibility", + "opens": "always" + }, + { + "key": "plan", + "label": "Insurance plan", + "opens": "always" + }, + { + "key": "lines", + "label": "Line items", + "opens": "always; quoting refused until the plan is ready" + }, + { + "key": "validate", + "label": "Validate", + "opens": "always" + }, + { + "key": "preauth", + "label": "Pre-authorisation", + "opens": "coverage verdict eligible" + }, + { + "key": "communication", + "label": "Communication", + "opens": "always" + }, + { + "key": "claim", + "label": "Claim", + "opens": "always; submit once the pre-auth is approved or partial" + }, + { + "key": "payments", + "label": "Payments", + "opens": "always" + } + ], + "stages": [ + "eligibility", + "preauth", + "enhancement", + "claim", + "payment" + ], + "sub_stages": [ + "draft", + "checking", + "eligible", + "not-eligible", + "requested", + "resubmitted", + "answered", + "queried", + "approved", + "partial", + "rejected", + "cancelling", + "cancelled", + "refused", + "noticed", + "paid" + ], + "next_actions": [ + { + "when": "an open query exists", + "label": "Answer the payer (n)", + "tab": "communication", + "leads": true + }, + { + "stage": "eligibility", + "sub_stage": [ + "draft", + "error", + "not-eligible" + ], + "label": "Check the cover", + "tab": "eligibility" + }, + { + "stage": "eligibility", + "when": "no plan ready", + "label": "Fetch the package master", + "tab": "plan" + }, + { + "stage": "eligibility", + "when": "no lines", + "label": "Quote the treatment", + "tab": "lines" + }, + { + "stage": "eligibility", + "when": "lines quoted", + "label": "Send the pre-authorisation", + "tab": "preauth" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "queried" + ], + "label": "Answer the query", + "tab": "preauth", + "payer": "resubmit" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "queried" + ], + "label": "Answer the payer's query", + "tab": "communication", + "payer": "communication" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "draft", + "refused" + ], + "label": "Send the pre-authorisation", + "tab": "preauth" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "rejected" + ], + "label": "Send a fresh pre-authorisation", + "tab": "preauth" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "approved", + "partial" + ], + "when": "lines added since", + "label": "Send the enhancement (n added)", + "tab": "preauth" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "approved", + "partial" + ], + "when": "not discharged", + "label": "Record the discharge", + "tab": "claim" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "approved", + "partial" + ], + "when": "discharged", + "label": "File the claim", + "tab": "claim" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "requested", + "answered", + "resubmitted" + ], + "label": "With the payer; ask where it stands", + "tab": "preauth" + }, + { + "stage": "claim", + "sub_stage": [ + "queried" + ], + "label": "Answer the claim query", + "tab": "claim", + "payer": "resubmit" + }, + { + "stage": "claim", + "sub_stage": [ + "queried" + ], + "label": "Answer the payer's query", + "tab": "communication", + "payer": "communication" + }, + { + "stage": "claim", + "sub_stage": [ + "rejected", + "partial" + ], + "label": "Ask for a reprocess", + "tab": "claim" + }, + { + "stage": "claim", + "sub_stage": [ + "requested", + "answered", + "resubmitted" + ], + "label": "With the payer; ask where it stands", + "tab": "claim" + }, + { + "stage": "claim", + "sub_stage": [ + "refused" + ], + "label": "Send the claim again", + "tab": "claim", + "when": "a send kind remains, else Ask for a reprocess" + }, + { + "stage": "claim", + "sub_stage": [ + "approved" + ], + "label": "Await the payment notice", + "tab": "payments" + }, + { + "stage": "payment", + "when": "a notice unacknowledged", + "label": "Acknowledge the payment notice", + "tab": "payments" + }, + { + "stage": "payment", + "when": "all acknowledged", + "label": "Settled", + "tab": "payments" + } + ], + "steps": [ + { + "id": "F1", + "name": "Policy search", + "screen": "new case", + "tab": null, + "routes": [ + "GET /claims/new" + ], + "module": "7.4", + "skills": ["nhcx-coverage"], + "holds": [], + "user": "Search policies", + "sends": { + "path": "participant/get/policies", + "kind": "registry REST" + }, + "stores": [], + "after": null, + "shows": "one row per policy with Select" + }, + { + "id": "F2", + "name": "Open the case", + "screen": "new case", + "tab": null, + "routes": [ + "POST /claims" + ], + "module": "7.4", + "skills": ["nhcx-coverage"], + "holds": [], + "user": "Select", + "sends": null, + "stores": [ + "claim: member_id, policy_code, payer_code, recipient_code, policy_json, claim_no" + ], + "after": { + "stage": "eligibility", + "sub_stage": "draft" + }, + "next_action": "Check the cover" + }, + { + "id": "F3", + "name": "Check the cover", + "screen": "case", + "tab": "eligibility", + "routes": [ + "POST /claims//check" + ], + "module": "7.4", + "skills": ["nhcx-coverage"], + "holds": [ + "member id", + "policy code for validation and benefits" + ], + "user": "purpose, Send to payer", + "sends": { + "path": "v1/coverageeligibility/check", + "workflow": "", + "reply": "on_check" + }, + "stores": [ + "txn_id", + "correlation_id", + "api_call_id", + "inforce", + "outcome", + "disposition", + "allowed_amount", + "used_amount", + "patient demographics", + "coverage class and period" + ], + "after": { + "stage": "eligibility", + "sub_stage": "eligible|not-eligible|error" + }, + "shows": "Payer verdict: sum insured, utilised, wallet balance, disposition verbatim", + "next_action": "Fetch the package master" + }, + { + "id": "F4", + "name": "Fetch the package master", + "screen": "case", + "tab": "plan", + "routes": [ + "POST /claims//plan", + "GET /claims//plan/", + "GET /claims//plan/forms" + ], + "module": "7.5", + "skills": ["nhcx-insurance"], + "holds": [ + "eligible" + ], + "user": "Fetch the plan (reuse first)", + "sends": { + "path": "v1/insuranceplan/request", + "workflow": "", + "reply": "on_request" + }, + "stores": [ + "claim_plan", + "claim_plan_benefit", + "claim_plan_form" + ], + "after": { + "plan": "ready|empty|error" + }, + "shows": "searchable master, package view, all forms", + "next_action": "Quote the treatment" + }, + { + "id": "F5", + "name": "Link or capture the admission", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//link", + "POST /claims//unlink" + ], + "module": "7.13 or the HMIS", + "skills": ["nhcx-preauth"], + "holds": [ + "eligible" + ], + "user": "Link the admission", + "sends": null, + "stores": [ + "claim.patient_id", + "claim.encounter_id", + "admission date default" + ], + "after": null + }, + { + "id": "F6", + "name": "The dossier", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//preauth", + "POST /claims//documents", + "POST /claims//documents/required" + ], + "module": "7.7 inputs", + "skills": ["nhcx-preauth"], + "holds": [ + "linked" + ], + "user": "Save the dossier", + "sends": null, + "stores": [ + "claim_diagnosis", + "claim_care_team", + "claim_document (code, stage)", + "claim_item" + ], + "guards": [ + "admission date required", + "at least one diagnosis", + "doctor with HPIN", + "package case needs a line" + ] + }, + { + "id": "F7", + "name": "Quote the treatment", + "screen": "lines", + "tab": "lines", + "routes": [ + "GET /claims//lines", + "POST /claims//lines", + "POST /claims//lines/quantities", + "POST /claims//lines//delete", + "POST /claims//forms" + ], + "module": "7.5", + "skills": ["nhcx-insurance"], + "holds": [ + "plan ready" + ], + "user": "add procedure, implant or tier; quantities; answer the forms the lines pull in", + "sends": null, + "stores": [ + "claim_line (rate from the plan, parent_code on a tier)", + "claim_form_answer" + ], + "guards": [ + "code not in plan", + "tier not offered by the procedure", + "duplicate", + "zero quantity" + ], + "next_action": "Send the pre-authorisation" + }, + { + "id": "F8", + "name": "Validate the set", + "screen": "case", + "tab": "validate", + "routes": [ + "POST /claims//auth" + ], + "module": "7.6", + "skills": ["nhcx-preauth"], + "holds": [ + "at least one line" + ], + "user": "Ask the payer (validate)", + "sends": { + "path": "v1/coverageeligibility/check", + "purpose": "auth-requirements", + "workflow": "", + "reply": "on_check", + "awaited": false + }, + "stores": [ + "claim_auth (fingerprint)", + "claim_auth_item", + "claim_auth_requirement" + ], + "after": { + "auth": "checking|ready" + } + }, + { + "id": "F9", + "name": "Send the pre-authorisation", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//submit" + ], + "module": "7.7", + "skills": ["nhcx-preauth"], + "holds": [ + "eligible", + "linked", + "admission date", + "diagnosis", + "care team with HPIN", + "a line", + "required forms answered", + "required documents attached" + ], + "user": "Send to payer", + "sends": { + "path": "v1/preauth/submit", + "workflow": "12", + "kind": "preauth", + "reply": "on_submit 20 then 21|23|24" + }, + "stores": [ + "claim_preauth: submitting, submission_kind, workflow_id, txn_id, correlation_id, api_call_id, request_json" + ], + "after": { + "stage": "preauth", + "sub_stage": "requested" + }, + "next_action": "With the payer; ask where it stands" + }, + { + "id": "F9a", + "name": "The payer answers", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /nhcx/callback/v1/preauth/on_submit" + ], + "module": "7.8", + "skills": ["nhcx-preauth"], + "holds": [], + "user": null, + "reads": "20 queued (stay submitting, keep preauth_ref) then the decision via verdict_status", + "stores": [ + "status", + "preauth_ref", + "approved_amount", + "eligible_amount", + "items_json", + "query_note", + "thread_correlation_id" + ], + "after": { + "stage": "preauth", + "sub_stage": "approved|partial|queried|rejected" + }, + "shows": "decision, payer reference, approved amount, item verdicts, notes verbatim; door refusal as a flag" + }, + { + "id": "F9b", + "name": "Answer a query", + "screen": "case", + "tab": "preauth or communication", + "routes": [ + "POST /claims//submit (reply)", + "POST /claims//queries//reply" + ], + "module": "7.7 or 7.10", + "skills": ["nhcx-preauth", "nhcx-communication"], + "holds": [ + "queried" + ], + "user": "reply text and documents", + "sends": { + "resubmit": { + "path": "v1/preauth/submit", + "workflow": "19 or 131", + "flow": "queryupdate", + "new_thread": true + }, + "communication": { + "path": "v1/communication/on_request", + "workflow": "", + "correlation_id": "" + } + }, + "after": { + "stage": "preauth", + "sub_stage": "answered (resubmit) or queried until the decision (communication)" + } + }, + { + "id": "F9c", + "name": "Enhancement", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//submit" + ], + "module": "7.7", + "skills": ["nhcx-preauth"], + "holds": [ + "approved or partial", + "lines added", + "no request in flight" + ], + "user": "Submit enhancement", + "sends": { + "path": "v1/preauth/submit", + "workflow": "13 or 131", + "flow": "enhancement", + "whole_bundle": true + }, + "after": { + "stage": "enhancement", + "sub_stage": "requested" + } + }, + { + "id": "F9d", + "name": "Cancel", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//cancel" + ], + "module": "7.9", + "skills": ["nhcx-preauth"], + "holds": [ + "not rejected", + "not cancelled", + "no claim raised" + ], + "user": "Withdraw the pre-authorisation", + "sends": { + "path": "v1/task/submit", + "workflow": "PC01", + "task": "cancel", + "own_thread": true + }, + "after": { + "stage": "preauth", + "sub_stage": "cancelling then cancelled; fresh claim number" + } + }, + { + "id": "F9e", + "name": "Predetermination", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//predetermination" + ], + "module": "7.7", + "skills": ["nhcx-preauth"], + "holds": [ + "as F9" + ], + "user": "Ask for a quote", + "sends": { + "path": "v1/preauth/submit", + "workflow": "12", + "use": "predetermination" + }, + "after": { + "predetermination": "asking then answered; the pre-auth unchanged" + } + }, + { + "id": "F10", + "name": "Record the discharge", + "screen": "case", + "tab": "claim", + "routes": [ + "POST /claims//discharge" + ], + "module": "7.7 inputs", + "skills": ["nhcx-claim"], + "holds": [ + "approved or partial" + ], + "user": "mode (normal, lama, dama, death), stage, discharge, surgery and death times", + "sends": null, + "stores": [ + "claim_submission draft: discharge_mode, discharge_stage, dates" + ], + "next_action": "File the claim" + }, + { + "id": "F11", + "name": "File the claim", + "screen": "case", + "tab": "claim", + "routes": [ + "POST /claims//claim", + "POST /claims//claim/documents" + ], + "module": "7.7", + "skills": ["nhcx-claim", "nhcx-communication"], + "holds": [ + "discharge recorded", + "discharge summary attached", + "claim-stage forms answered", + "amount not above approved" + ], + "user": "Submit the claim", + "sends": { + "path": "v1/claim/submit", + "workflow": "15 (161 or 151 query answer; 16 generic resubmit)", + "kind": "claim", + "under": "the pre-auth's claim number", + "reply": "on_submit 25 then 26|27|291" + }, + "after": { + "stage": "claim", + "sub_stage": "requested then approved|queried|rejected|partial" + } + }, + { + "id": "F12", + "name": "Payments", + "screen": "case", + "tab": "payments", + "routes": [ + "POST /nhcx/callback/v1/paymentnotice/request", + "POST /claims//payments//ack", + "GET /claims/payments" + ], + "module": "7.10", + "skills": ["nhcx-payment"], + "holds": [], + "user": null, + "reads": "PaymentNotice matched by claim number; deduped on its correlation id", + "sends": { + "path": "v1/paymentnotice/on_request", + "workflow": "17 (PMJAY) or the notice's own", + "correlation_id": "", + "to": "the notice's sender", + "automatic": true + }, + "after": { + "stage": "payment", + "sub_stage": "noticed|paid" + }, + "next_action": "Acknowledge the payment notice, then Settled" + }, + { + "id": "F12b", + "name": "The inbox", + "screen": "inbox", + "tab": "communication", + "routes": [ + "POST /nhcx/callback/v1/communication/request", + "GET /claims/inbox", + "POST /claims//queries//acknowledge" + ], + "module": "7.10", + "skills": ["nhcx-communication"], + "holds": [], + "reads": "classify: query | notification | note", + "sends": { + "notification": { + "path": "v1/communication/on_request", + "automatic": true + } + }, + "after": { + "query": "open, leads every action list" + } + }, + { + "id": "F13", + "name": "Status, reprocess, release", + "screen": "case", + "tab": "preauth or claim", + "routes": [ + "POST /claims//status", + "POST /claims//reprocess", + "POST /claims//release" + ], + "module": "7.9", + "skills": ["nhcx-reprocess"], + "holds": [ + "status: payer allows it", + "reprocess: claim decided and not paid in full", + "release: part paid" + ], + "sends": { + "path": "v1/task/submit", + "workflow": "leg correlation id (status) or 36", + "own_thread": true + }, + "after": { + "enquiry": "asking then answered|error; a reprocess reopens the claim to requested" + } + } + ], + "page_load_polls": [ + "coverage checking", + "plan fetching", + "ruling checking", + "claim submitting", + "predeterminations asking", + "preauth submitting or cancelling", + "enquiries asking" + ], + "not_in_the_flow": [ + "a status control", + "a manual-only payment acknowledgement", + "a chase button without the status exchange", + "a separate discharge submission on PMJAY", + "a claim resubmit on PMJAY" + ] +} \ No newline at end of file diff --git a/plugins/nhcx/skills/nhcx-coverage/references/api-knowledge.md b/plugins/nhcx/skills/nhcx-coverage/references/api-knowledge.md new file mode 100644 index 000000000..3b07e901d --- /dev/null +++ b/plugins/nhcx/skills/nhcx-coverage/references/api-knowledge.md @@ -0,0 +1,400 @@ +# API knowledge: the nhcx-adapter contract (optional transport) and the HMIS endpoints that face it + +Read this file only when the transport is nhcx-adapter, and use nhcx-adapter only when the user has asked for it (`references/transport-knowledge.md` section 1). Otherwise the build reaches NHCX through the app's existing integration or its own transport, and `references/transport-knowledge.md` sections 3 and 4 replace everything here. + +This file describes nhcx-adapter (https://github.com/nha-in/nhcx-adapter) as its release ships it, and the HMIS side a build needs to face it. A release carries the binary, `config.sample.json`, `serve.sh`, `stop.sh`, `update.sh` and `README.md`. `nhcx-package/docs/02-Getting Started/10-NHCX Adapter.md` covers the same adapter. When a detail matters, check the release README and `config.sample.json` for the version you run. + +## 1. What the adapter is + +One binary, one `config.json`, no database. You POST plain FHIR to it. It mints the protocol ids, fetches the recipient's certificate, encrypts a compact JWE, posts to the NHCX gateway, and records the exchange in a file ledger. NHCX callbacks reach it encrypted; it decrypts them and POSTs plain FHIR to your HMIS. Both directions are synchronous; there is no queue (release README, "How it works"). + +The same binary can front several participants at once. Inbound, `x-hcx-recipient_code` picks the profile whose key decrypts and whose callback receives. Outbound, `x-hcx-sender_code` picks who sends (release README, "Hosting several participants"). Encrypting for a code the same adapter holds is allowed. So one adapter can host a hospital and a test payer together, and a test between them needs no second gateway. + +## 2. Configuration + +File: `config.sample.json` in the release. `${NAME}` reads an environment variable; `@file` reads a file next to the config. Unknown keys are rejected. + +| Key | Default | What it does | +| --- | --- | --- | +| `env` | `sandbox` | `sandbox` or `production`. Picks the gateway (`https://apisbx.abdm.gov.in/hcx/v1` or `https://apis.abdm.gov.in/hcx/v1`), registry, session endpoint and `X-CM-ID` (`sbx` or `abdm`). | +| `listen` | `127.0.0.1:8090` | The HTTP listener. | +| `publicUrl` | empty | How NHCX reaches the adapter. Register `/in` as the participant's `endpoint_url`. | +| `apiKey` | `${NHCX_ADAPTER_API_KEY}` | The key your HMIS presents on `/out`, `/fhir/out`, `/ledger*`, `/token`. Demanded in production, honoured but not demanded in sandbox. `requireApiKey: true` closes a sandbox adapter. | +| `participant.participantId` | none; the sample carries an example code | Your registry code. `@hcx` is added if missing. | +| `participant.clientId`, `clientSecret` | `${NHCX_CLIENT_ID}`, `${NHCX_CLIENT_SECRET}` | ABDM credentials that mint the session token. | +| `participant.privateKey` | `@private_key.pem` | The RSA key of your registered certificate. | +| `participants[]` | `[]` | Further hosted identities. Each needs only `participantId` and `callback`; the rest is inherited. | +| `callback.url` | `http://127.0.0.1:8765/nhcx/callback` in the sample | Where decrypted messages are POSTed. | +| `callback.appendPath` | `true` | Appends the NHCX path: `.../callback` receives `v1/preauth/on_submit` at `.../callback/v1/preauth/on_submit`. | +| `callback.timeoutSeconds` | `20` | One delivery. NHCX wants its 202 within 30 seconds. | +| `callback.apiKey` | empty | Sent to your HMIS as `Authorization: Bearer `. | +| `callback.routes` | `{}` | Per-path overrides, used exactly as written: `{"v1/preauth/on_submit": "http://preauth-svc/hook"}`. | +| `callback.also` | absent | Extra targets for the same delivery (two systems behind one participant code). Every target must accept or NHCX redelivers to all. | +| `ledger.enabled`, `ledger.dir`, `ledger.retentionDays`, `ledger.storeBodies` | `true`, `data/ledger`, `30`, `true` | The traffic ledger. A hand-written config that leaves out `retentionDays` keeps every day. | +| `maxBodyBytes` | 8 MiB in the v1.0.1 README | Caps request bodies on both surfaces. A PMJAY package master is far larger: set 100 MiB (`104857600`) explicitly. | +| `panel.password`, `panel.path` | empty, `/panel` | The browser console; off until a password is set. | +| `auth.mode`, `auth.tokenTtlSeconds` | `sessions`, `1200` | How the ABDM token is obtained. | + +Minimal working config for one hospital: + +```json +{ + "env": "sandbox", + "listen": "127.0.0.1:8090", + "publicUrl": "https:///in", + "apiKey": "${NHCX_ADAPTER_API_KEY}", + "participant": { + "participantId": "@hcx", + "clientId": "${NHCX_CLIENT_ID}", + "clientSecret": "${NHCX_CLIENT_SECRET}", + "privateKey": "@private_key.pem" + }, + "callback": { "url": "http://127.0.0.1:/nhcx/callback", "appendPath": true, "apiKey": "" } +} +``` + +Start it with `./nhcx-adapter serve`, or `./serve.sh` from the release archive; `./stop.sh` stops a background server. It checks token, participant record, certificate and registered endpoint first and offers to fix each in a terminal (release README, "Startup checks"). `./nhcx-adapter check --no-tui` is the same as a health gate. `serve --no-tui --skip-checks` starts it with no prompts and no checks, for a script that has already checked. + +## 3. Routes + +| Route | Auth | Does | +| --- | --- | --- | +| `POST /out/{path...}` | API key | Send. `path` is the NHCX API path, `v1/preauth/submit`. | +| `POST /fhir/out/{path...}` | API key | Same handler, hcxkit's prefix. The client in section 11 sends here. | +| `POST /in/{path...}` | none | NHCX delivers here. Register `/in`. | +| `POST /v1/{path...}` | none | Alias of `/in` for a registry `endpoint_url` of `/`. | +| `GET /ledger` | API key | Newest first. Filters: `direction, entity, kind, status, sender, recipient, participant, correlation_id, workflow_id, since, until, before, limit` (1 to 500). `since` and `until` take RFC 3339, a date, or a duration such as `24h`. | +| `GET /ledger/stats` | API key | Counts by direction, status, entity. | +| `GET /ledger/thread/{cid}` | API key | Every message on one correlation id plus the derived state. | +| `GET /ledger/{id}` | API key | One message in full, bundle included. | +| `GET /token`, `POST /token/refresh` | API key | The ABDM session token, for calls the adapter does not make (registry, PMJAY payer service). `?participant=` for a hosted identity. | +| `GET /healthz`, `GET /readyz` | none | Liveness; readiness is 503 until a token is held. | +| `GET /panel` | its own password | Operator console: Live, Ledger, Send, Lookup, Setup. | +| `/internal/*` | none | hcxkit-compatible console API, section 8. | + +API key check: `Authorization: Bearer ` first, then `X-Api-Key: `. Constant-time compare. A miss answers `401 {"ok":false,"error":{"code":"UNAUTHORIZED","message":"missing or invalid API key"}}`. + +## 4. The outbound envelope + +The body must be a JSON object. Header precedence, lowest to highest: + +1. HTTP request headers named `x-hcx-*`. +2. The `jwe_headers` object (hcxkit spelling). +3. Top-level `x-hcx-*` keys. +4. Top-level short aliases: `sender`, `recipient`, `correlation_id`, `request_id`, `api_call_id`, `workflow_id`, `status`. + +The payload is `fhir`, else `payload`, else the body itself when it carries `resourceType`. Otherwise `400 INVALID_ENVELOPE`. + +The protected header names: + +``` +x-hcx-api_call_id x-hcx-request_id x-hcx-correlation_id x-hcx-timestamp +x-hcx-status x-hcx-sender_code x-hcx-recipient_code x-hcx-workflow_id +``` + +Completion rules: + +- Sender and recipient codes get `@hcx` appended if missing. +- `api_call_id`, `request_id`, `correlation_id` are kept only when they are plain 8-4-4-4-12 UUIDs; anything else is replaced with a fresh UUID. So a response must carry the request's `correlation_id` as a UUID or the thread is lost. +- `x-hcx-status` defaults to `request.initiated`, or `response.complete` when the last path segment starts with `on_`. +- `x-hcx-timestamp` defaults to now as `YYYY-MM-DDThh:mm:ss±hhmm`. The zone has no colon: `+0530`, not `+05:30`. +- An empty `x-hcx-workflow_id` is dropped, not sent. +- On an `on_` path with no usable correlation id, the adapter threads the message to the newest inbound request of that entity from that recipient. Do not rely on it; send the id. + +What a hospital sends on a normal leg: + +```json +{ + "jwe_headers": { + "x-hcx-sender_code": "@hcx", + "x-hcx-recipient_code": "@hcx", + "x-hcx-workflow_id": "12" + }, + "fhir": { "resourceType": "Bundle", "type": "collection", "...": "..." } +} +``` + +Add `"x-hcx-correlation_id": ""` only on the two reply legs: the communication reply on `v1/communication/on_request` and the payment acknowledgement on `v1/paymentnotice/on_request`. + +## 5. The outbound answer + +The HTTP status is the NHCX gateway's own. Body: + +```json +{ + "ok": true, + "path": "v1/preauth/submit", + "url": "https://apisbx.abdm.gov.in/hcx/v1/preauth/submit", + "headers": { "x-hcx-correlation_id": "...", "x-hcx-api_call_id": "...", "x-hcx-request_id": "...", "x-hcx-workflow_id": "12", "x-hcx-status": "request.initiated", "x-hcx-timestamp": "...", "x-hcx-sender_code": "...", "x-hcx-recipient_code": "..." }, + "gateway_status": 202, + "response": { "...": "the NHCX 202 body" }, + "duration_ms": 412, + "ledger_id": "7UMV0007", + "txn_id": "7UMV0007", + "correlation_id": "...", + "request_id": "..." +} +``` + +Store three things on the leg: `txn_id` (the ledger id), `correlation_id` (the thread), and `headers["x-hcx-api_call_id"]`. Store them on every send. + +Local failures come back as `{"ok": false, "error": {"code", "message", "retryable"}, "request_id", "upstream_status", "upstream_body"}` with these statuses: `400` for `INVALID_ENVELOPE`, `INVALID_PAYLOAD`, `INVALID_BODY`, `INVALID_JWE`, `NO_PATH`, `NO_RECIPIENT`, `WRONG_RECIPIENT`, `BODY_READ`; `401` for the API key; `413` `BODY_TOO_LARGE`; `422` for `DECRYPT_FAILED`, `CERT_NOT_FOUND`, `SELF_ENCRYPTION_KEY`; `502` for any code starting `CALLBACK_`, `GATEWAY_`, `CERT_FETCH_`, `TOKEN_`; `501` `LEDGER_DISABLED`. A gateway refusal is recorded in the ledger as `rejected` with `GATEWAY_HTTP_`. + +## 6. The inbound callback your HMIS receives + +The adapter POSTs to `callback.url` plus the NHCX path. Body: + +```json +{ + "meta": { + "type": "in", + "payloadType": "fhir", + "path": "v1/preauth/on_submit", + "ip": "1.2.3.4", + "time": "", + "redelivery": false, + "participant": "@hcx" + }, + "jwe_headers": { + "alg": "RSA-OAEP-256", "enc": "A256GCM", + "x-hcx-api_call_id": "...", "x-hcx-correlation_id": "...", "x-hcx-request_id": "...", + "x-hcx-sender_code": "@hcx", "x-hcx-recipient_code": "@hcx", + "x-hcx-status": "response.partial", "x-hcx-timestamp": "...", "x-hcx-workflow_id": "20" + }, + "fhir": { "resourceType": "Bundle", "...": "..." } +} +``` + +`payloadType` is `fhir` for a bundle and `protocol` for a ProtocolResponse. A ProtocolResponse is a refusal. Then `fhir` is the plain JSON body with `type: "ProtocolResponse"`, `x-hcx-status: response.error` and `x-hcx-error_details` at its top level. + +HTTP headers on the delivery: + +| Header | Value | +| --- | --- | +| `X-Nhcx-Path` | `v1/preauth/on_submit` | +| `X-Nhcx-Payload-Kind` | `fhir` or `protocol` | +| `X-Nhcx-Correlation-Id` | the thread | +| `X-Nhcx-Api-Call-Id` | this delivery's id, stable across redeliveries | +| `X-Nhcx-Redelivery` | `true` when the ledger already holds this api_call_id (absent otherwise) | +| `X-Nhcx-Participant` | the hosted identity it was addressed to | +| `X-Hcxkit-Txn-Id` | equals `x-hcx-api_call_id` (what a kit-style backend dedupes on) | +| `X-Hcxkit-Type` | entity: `coverage`, `insurance`, `preauth`, `claim`, `task`, `payment`, `communication`, `status` | +| `X-Hcxkit-Flow` | `request` for an arriving response, `on_request` for an arriving request (inverted on purpose) | +| `X-Hcxkit-Payload-Kind` | same as `X-Nhcx-Payload-Kind` | +| `Authorization` | `Bearer ` when configured | + +Contract: answer any 2xx quickly. The adapter then answers NHCX with the 202 acceptance body and an `X-Nhcx-Ledger-Id` header: + +```json +{ + "timestamp": "11/09/2026 10:00:00:123", + "api_call_id": "...", "correlation_id": "...", + "result": { "sender_code": "...", "recipient_code": "...", "entity_type": "preauth", "protocol_status": "request.queued" }, + "error": { "code": "", "message": "" } +} +``` + +A non-2xx from your HMIS becomes `CALLBACK_HTTP_` and NHCX redelivers. NHCX makes five attempts, then drops the correlation id. Your handler must therefore be idempotent on `x-hcx-api_call_id`. Do not do slow work inside the callback: store the envelope, answer 200, apply it after. Apply a delivery on a context detached from the incoming request, so a gateway that hangs up cannot roll the write back. + +The HMIS callback handler: + +- Routes `POST /callback`, `POST /callback/` and `POST /nhcx/callback`. +- Takes an optional shared secret on the query string (`?token=`). +- Reads `X-Hcxkit-Type`, `X-Hcxkit-Flow` and `X-Hcxkit-Payload-Kind`. +- Archives the envelope before applying it. +- Answers `400` for an unreadable body, because redelivery cannot help. Anything unexpected becomes a 500, so the adapter retries. +- Returns `{"status": "settled" | "unmatched" | "ignored"}`. +- Routes by correlation id, never by path. + +## 7. The ledger + +Layout: `ledger.dir//.json`, one file per message, plus `/index.jsonl` with one summary line per message. Ids are eight base32 characters (alphabet `0-9A-V`), a day prefix and a counter that restarts each day: `7UMV0001` is the first message of its day. Pruned hourly by `retentionDays`. + +Entry fields: `id, direction (out|in), created_at, path, entity, action, kind (request|response), format (fhir|protocol|json), sender, recipient, correlation_id, api_call_id, request_id, workflow_id, hcx_status, status, error{code,message}, redelivery, duration_ms, peer{url,status_code,response}, also[], headers{}, fhir{}, fhir_summary{resource_type,bundle_type,entries,resource_types,focus,identifier,patient,outcome}`. + +`status` values: outbound `accepted`, `rejected`, `failed`; inbound `delivered`, `delivery_failed`, `rejected`. + +Thread: `{correlation_id, entity, workflow_id, counterparty, role (initiator|responder), state, started, updated, messages[]}`. `state` is derived by walking the messages in order: + +- `awaiting_response`: you sent a request. +- `awaiting_our_response`: a request reached you. +- `partial`: a `response.partial` arrived. +- `completed`: a response closed it. +- `error`: a rejection, a failed send or delivery, a protocol message, or an `error` status. +- `unknown`. + +Two ledger behaviours you rely on. An outbound `on_` response with no `correlation_id` is threaded to the newest matching inbound request. An inbound whose `api_call_id` was seen before is flagged `redelivery: true`. + +CLI, same data, no server needed for `follow`: + +```sh +nhcx-adapter ledger list --since 24h --entity preauth --status rejected +nhcx-adapter ledger follow --direction in +nhcx-adapter ledger show 7UMV0007 +nhcx-adapter ledger thread +nhcx-adapter ledger stats +nhcx-adapter decrypt --file body.json +nhcx-adapter cert +nhcx-adapter send --path v1/preauth/submit --recipient --file bundle.json +``` + +## 8. hcxkit-compatible endpoints + +A client written against hcxkit polls the adapter for the other side's answer instead of only waiting for its callback. The adapter serves the sliver of hcxkit's `/internal` API that such a client needs. None of these need the API key. Keep the adapter's port off any network you do not control (`nhcx-package/docs/02-Getting Started/10-NHCX Adapter.md`, "Before you expose it"). + +| Route | Body | Answers | +| --- | --- | --- | +| `GET /internal/config/get` | none | `{participant{participantId,name,callbackUrl}, participants[], CMID, env, urls{nhcx,participant,sessions}}` | +| `POST /internal/participants/search` | `{"participant_code": ""}` | `{participants:[registry record + participant_code, participant_name, endpoint_url, status, roles]}`; an unknown code is `{participants: []}` | +| `POST /internal/txn/related` | `{"txnId": ""}` | every ledger row on the same correlation id, both directions, as `{id, direction, status, sender, recipient, correlation_id, api_call_id, type, flow, created_at}`; `404 TXN_NOT_FOUND` when the ledger no longer holds it | +| `POST /internal/txn/fhir` | `{"txnId": ""}` | `{meta{type,payloadType,path,time}, jwe_headers, fhir}`, the same envelope shape a delivery carries | +| `POST /internal/txn/dispatch` | `{"txnId": ""}` | `{txnId, status}` with `dispatch_failed` for a failed or rejected send, `dispatched` for accepted or delivered, plus `errorCode`, `errorMessage` | +| `GET /internal/txn/list?limit=200` | none | the recent ledger, newest first, same row shape | +| `POST /internal/policies/search` | `{"identifiertype": "MemberId", "MobileNo" or "AbhaNumber", "identifiervalue": "..."}` (also `mobile`, `abhaNo`) | the ABDM registry's `participant/get/policies` answer, status passed through; "No policies found" is an error the caller reads as empty | +| `POST /internal/policies/abha/link`, `.../delink` | forwarded verbatim | registry answer | +| `POST /internal/participants/list` | forwarded verbatim | registry roster | +| `POST /internal/participants/certs` | `{"participantid": ""}` | `{participant_code, encryption_cert}` | +| `GET /internal/participants/saved` | none | the configured profiles | + +The polling pattern: + +1. After a send, call `/internal/txn/related` with the stored `txn_id`. +2. Take the inbound rows on the thread that were not sent by you. Keep only rows addressed to the participant the send came from. +3. Fetch each with `/internal/txn/fhir`, newest first. +4. Take the first whose bundle carries the resource the reply is made of (ClaimResponse, CoverageEligibilityResponse, InsurancePlan, Task). +5. Apply it through the same code path the callback uses. Dedupe on `x-hcx-api_call_id`. + +A `404` from `txn/related` means the ledger was reset. Settle the leg as an error instead of spinning. + +## 9. curl examples + +Set these once. The address is the adapter's default `listen`: + +```sh +export ADAPTER=http://127.0.0.1:8090 +export KEY= +export ME=@hcx +export PAYER=@hcx +``` + +Liveness and readiness: + +```sh +curl -s $ADAPTER/healthz +curl -s $ADAPTER/readyz +``` + +Send a coverage eligibility check. Write the envelope to a file first. The bundle is the package's validation request, `nhcx-package/fhir/B1/validation.json`, with your own identifiers substituted. Run this from the project root that holds `nhcx-package/`: + +```sh +python3 - <<'EOF' +import json, os +bundle = json.load(open("nhcx-package/fhir/B1/validation.json")) +env = {"jwe_headers": {"x-hcx-sender_code": os.environ["ME"], + "x-hcx-recipient_code": os.environ["PAYER"], + "x-hcx-workflow_id": ""}, + "fhir": bundle} +json.dump(env, open("/tmp/coverage-out.json", "w")) +EOF +curl -s $ADAPTER/fhir/out/v1/coverageeligibility/check \ + -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \ + --data-binary @/tmp/coverage-out.json +``` + +Read the answer back from the ledger with the `correlation_id` from that response: + +```sh +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger/thread/" +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger?direction=in&entity=coverageeligibility&since=1h" +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger/" +``` + +Same thread through the kit endpoints (no key): + +```sh +curl -s $ADAPTER/internal/txn/related -H 'Content-Type: application/json' -d '{"txnId":""}' +curl -s $ADAPTER/internal/txn/fhir -H 'Content-Type: application/json' -d '{"txnId":""}' +``` + +A session token for the PMJAY payer service or a registry call: + +```sh +curl -s -H "Authorization: Bearer $KEY" $ADAPTER/token +``` + +Simulate a delivery to your own callback while the adapter is not involved (useful for the callback handler's unit test). This is the exact shape the adapter posts. Wrap the package's bare payer bundle, here the pre-auth approval `nhcx-package/fhir/C5/C5-approved-wf21.json`, as `{"meta":{...},"jwe_headers":{...},"fhir":}` first: + +```sh +python3 - <<'EOF' +import json +bundle = json.load(open("nhcx-package/fhir/C5/C5-approved-wf21.json")) +env = {"meta": {"type": "in", "payloadType": "fhir", "path": "v1/preauth/on_submit"}, + "jwe_headers": {"x-hcx-correlation_id": "", "x-hcx-api_call_id": "", + "x-hcx-sender_code": "@hcx", + "x-hcx-recipient_code": "@hcx", + "x-hcx-status": "response.complete", "x-hcx-workflow_id": "21"}, + "fhir": bundle} +json.dump(env, open("/tmp/delivery.json", "w")) +EOF +curl -s -X POST "http://127.0.0.1:/nhcx/callback/v1/preauth/on_submit" \ + -H 'Content-Type: application/json' -H 'X-Nhcx-Path: v1/preauth/on_submit' \ + -H 'X-Nhcx-Payload-Kind: fhir' -H 'X-Nhcx-Correlation-Id: ' -H 'X-Nhcx-Api-Call-Id: ' \ + -H 'X-Hcxkit-Txn-Id: ' -H 'X-Hcxkit-Type: preauth' -H 'X-Hcxkit-Flow: request' -H 'X-Hcxkit-Payload-Kind: fhir' \ + -H 'Authorization: Bearer ' \ + --data-binary @/tmp/delivery.json +``` + +## 10. The HMIS-side endpoints a build exposes + +Use these as the model for what your HMIS needs. `` is the claim episode id. + +| Method | Path | Purpose | Leg | +| --- | --- | --- | --- | +| GET | `/claims`, `/claims/new`, `/claims/` | list, policy search, detail | none | +| POST | `/claims` | open an episode from a chosen policy | none | +| GET | `/claims//state` | the whole episode as JSON after the page-load polls | none | +| POST | `/claims//check` | coverage eligibility (validation, benefits, discovery) | `v1/coverageeligibility/check` | +| POST | `/claims//plan` | fetch or refresh the package master | `v1/insuranceplan/request` | +| GET | `/claims//plan/forms`, `.../forms/`, `.../plan/` | questionnaires and one package | none | +| POST | `/claims//link`, `/unlink` | attach or detach the admission | none | +| POST | `/claims//preauth` | save the dossier draft | none | +| GET, POST | `/claims//lines`, `.../lines/quantities`, `.../lines//delete` | procedure, implant and tier lines | none | +| POST | `/claims//forms` | save questionnaire answers | none | +| POST | `/claims//auth` | auth-requirements ruling | `v1/coverageeligibility/check` | +| POST | `/claims//submit` | pre-auth 12, query answer 19, enhancement 13, enhancement answer 131 | `v1/preauth/submit` | +| POST | `/claims//predetermination` | a quote | `v1/preauth/submit` | +| POST | `/claims//cancel` | cancel Task PC01 | `v1/task/submit` | +| POST | `/claims//status` | status enquiry Task | `v1/task/submit` | +| POST | `/claims//reprocess`, `/release` | reprocess or balance release, 36 | `v1/task/submit` | +| POST | `/claims//queries//reply`, `.../acknowledge` | communication reply or notification acknowledgement | `v1/communication/on_request` | +| POST | `/claims//discharge` | record how the stay ended | none | +| POST | `/claims//claim` | claim 15, query answer 161 or 151, resubmit 16 | `v1/claim/submit` | +| POST | `/claims//claim/documents`, `/documents`, `/documents/required`, `.../delete` | attachments | none | +| GET | `/claims//documents/` | view an attachment | none | +| POST | `/claims//payments//ack` | resend a payment acknowledgement | `v1/paymentnotice/on_request` | +| POST | `/v1/` under the registered `endpoint_url` (own transport), or `/callback`, `/callback/`, `/nhcx/callback` (nhcx-adapter) | a delivery | inbound | + +The HMIS configuration a build needs: + +- The transport's settings: for nhcx-adapter, its base URL (it listens on `127.0.0.1:8090` by default) and API key; for your own transport, the ABDM client id and secret, the private key, and the sessions, NHCX and registry addresses (`references/transport-knowledge.md` section 3). +- The payer's participant code (`1518@hcx` for the PMJAY SHA Himachal Pradesh sandbox) and the payer's name. +- The callback shared secret. +- A workflow-id override table, JSON, that overrides the per-payer table key by key, for example `cancel=122`. +- A map from payer code to payer adapter, for example `1518=pmjay,=generic`. +- The archive folder for cases, and a switch to turn the archive off. + +The sender code is not an environment variable. It is the facility's participant code, held in the HMIS's own settings. + +## 11. What the adapter client looks like in code + +The whole client is one function, `_api(path, payload, timeout, method, claim_id, use_case)`. It builds the URL from the base, adds `Authorization: Bearer` when a key is set, POSTs JSON, raises `GatewayError(message, status)` on any non-2xx or network failure, decodes JSON, and archives the envelope beside the case when `claim_id` is given. Every send in the module goes through it, which is what lets a test replace it with a stub: + +```python +posted = {} +def _ack(path, payload=None, **kw): + posted["path"], posted["payload"] = path, payload + return {"txn_id": "01PLAN", "correlation_id": "corr-plan-1"} +claims._api = _ack +``` + +Give your HMIS the same single door. diff --git a/plugins/nhcx/skills/nhcx-coverage/references/errors-and-debugging.md b/plugins/nhcx/skills/nhcx-coverage/references/errors-and-debugging.md new file mode 100644 index 000000000..9be844d82 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-coverage/references/errors-and-debugging.md @@ -0,0 +1,167 @@ +# Errors and debugging + +Sources: + +- `nhcx-package/nhcx-error.yaml`: every NHCX, PAYR and ERR-PYR code, with the standard and reference payer readings side by side. +- `nhcx-package/docs/06-Reference/01-Error Codes.md`: the same codes as tables. +- `nhcx-package/docs/01-Overview/04-JWE, Status and Errors.md`, "Codes met live". +- `nhcx-package/docs/03-Building a Provider/11-PMJAY Sandbox Run.md`: one full case run, refusal by refusal. +- `nhcx-package/docs/06-Reference/02-Troubleshooting.md`. +- The nhcx-adapter release README, "Troubleshooting". + +The live readings are from runs against the PMJAY SHA Himachal Pradesh sandbox payer (`1518@hcx`). + +## 1. Where an error comes from + +Three places refuse a message, and the family of the code says which (`nhcx-error.yaml`, `spaces`): + +| Family | Who refused | How you hear it | +| --- | --- | --- | +| Gateway answers to your own send (`400`, `401`) | the exchange, before the message goes further | the HTTP answer to your POST on `/v1/...`; a `401` is an expired token or a missing `Bearer` | +| A delivery your key cannot open (own transport) | your receiving end | the JWE will not decrypt: the certificate on your participant record is not the key you hold | +| Adapter codes (`INVALID_ENVELOPE`, `CERT_NOT_FOUND`, `CALLBACK_HTTP_500`), nhcx-adapter only | nhcx-adapter, before or after the wire | the HTTP answer to your `/fhir/out` call, `{"ok": false, "error": {...}}` | +| `NHCX-*` | the exchange; the message never reached the payer | the HTTP answer to your call (`gateway_status` 4xx with `upstream_body`), or a `ProtocolResponse` delivered to your callback later | +| `PAYR-*`, `ERR-PYR-*` | the payer; the message reached it | a `ProtocolResponse` on your callback with `x-hcx-status: response.error` and `x-hcx-error_details {code, message}`, on the request's correlation id | + +A `ProtocolResponse` is plain JSON, not a bundle. The exchange delivers it with `type: ProtocolResponse` and the `x-hcx-` fields in the clear; nhcx-adapter passes it on with `X-Nhcx-Payload-Kind: protocol` and `fhir` set to the body. Read `fhir.type == "ProtocolResponse"` and `fhir["x-hcx-error_details"]`. Settle the leg as refused at the door with the payer's words, and keep the thread the payer last answered on. + +PAYR numbers are not globally unique. The same number means different things on different sheets (`nhcx-error.yaml` lists them under `collisions`), and the live sandbox reuses several with a meaning the published sheet does not give. Match on the message text and log both. + +## 2. PAYR and ERR codes met live + +The published text is from `nhcx-package/nhcx-error.yaml`. Where the standard and reference payer sheets collide, both readings are given. The live text and the fix are from the sandbox runs. + +| Code | Published text | Live text | What it means | Fix | +| --- | --- | --- | --- | --- | +| PAYR-1008 | Invalid FHIR bundle received (reference payer); Eligible coverage amount is insufficient (standard) | "Invalid content type" or "Invalid input, code and reason code" or "Invalid Base64" | Three faults on one code: a document outside pdf, jpg, jpeg, png and fhir+json; a Task code paired with a reason the scheme does not accept (every `status`, `reprocess`, `release` Task on the sandbox, and a reprocess with the intimation input misspelt); an attachment it will not decode | Check the content type. For a Task, the sandbox takes only one financial task code, `cancel` (`11-PMJAY Sandbox Run.md`, "What the sandbox will not take"). Spell the reprocess input `intimationNumber` | +| PAYR-1018 | Time limit for submission expired (standard); No task reason code received (reference payer) | asks for a `Task.reasonCode` on a status enquiry | The status Task is refused as incomplete; with a reason it is refused with PAYR-1008 | Do not offer a status enquiry on PMJAY; switch it off in the PMJAY payer adapter | +| PAYR-1019 | Requested additional information was not received in time (standard); Invalid sequence received in supporting info element (reference payer) | "Invalid sequence received in supporting info element" | A `supportingInfo` entry with no `sequence` | Number the whole list once it is assembled | +| PAYR-1027 | (item error family) | "Invalid item id found for item in claim component" | `Claim.item` has no element `id` (`Item/1`). Nothing to do with the package code | Put `id` on every item, procedure and supportingInfo | +| PAYR-1083 | (practitioner family) | "No HPR details found for the practitioner ... category code as HPIN" | The Practitioner carries no identifier typed `HPIN` | Add the `HPIN` identifier under `https://hpr.abdm.gov.in` | +| PAYR-1096, PAYR-1503 | (supporting-info value-type family) | the death date is missing | A death claim without the `ONS`/`DTM` entry | Add `ONS`/`DTM` with the death instant and answer the plan's death forms | +| PAYR-1214 | No previous preauthorization approved record found for the resubmission request | same | A 121 after a rejection | Send a fresh 12 | +| PAYR-1238 | Beneficiary is having an active preauthorization request at this hospital with reference number ... | same; the reference ends in the SHA's case id | Scheme rule, not a bundle fault: one live pre-auth per beneficiary per hospital. Perversely the first sign the bundle is right, because validation runs first | Cancel the other case (PC01) or let it be rejected; sweep before a run | +| PAYR-1245 | Rule failure | "Only one conservative procedure can be booked for a case" | The master's `ProcedureType`; an enhancement on a conservative case must add a medical package | Pick a package whose `ProcedureType` is medical | +| PAYR-1254, PAYR-1365 | Response for STG Questionnaire id ... is mandatory for procedure code ... | same | A package's treatment-guideline questionnaire unanswered | Answer every `/stgquestionnaire/` form the plan attaches to the quoted packages | +| PAYR-1256, PAYR-1363 | Response for Authentication Consent Questionnaire is missing | same | The plan's consent questionnaire unanswered where no biometric token was taken; 1256 on the pre-auth, 1363 on the claim | Answer the policy-level consent form on both legs | +| PAYR-1270 | Item LM100 is not applicable for preauthorization request | same | `LM100` on a pre-auth | Only a LAMA or DAMA claim before or during surgery carries it | +| PAYR-1321 | Error occurred while processing the request due to invalid workflow id | same | 151, 19 or 16 on `v1/claim/submit` | Answer a claim query on 161; never resubmit a decided claim, reprocess it | +| PAYR-1322 | No active case found for the given case number | "Active instance found for case number" | A request is already open on that case; the scheme takes one at a time | Wait about 30 seconds after a decision, then send again; up to three tries | +| PAYR-1362 | No procedure with code LM100 received with 'Requested' status | same | A LAMA or DAMA claim before or during surgery that still carries the package | Collapse the claim to one `LM100` line | +| PAYR-1367, PAYR-1368 | No biometric records found ... / units of cycle information received | same | A cyclic package (dialysis) claimed without a biometric record per cycle and cycle information | Do not claim a cyclic package unless the HMIS can produce both | +| PAYR-1401 | policy not allowed for the hospital | same | The plan was asked for under a policy the hospital is not empanelled under | Ask under the beneficiary's own policy code from the policy search | +| PAYR-1406 | Existing request with correlation id ... is in progress | same | A second plan request while one is still being served | Wait 15 to 60 minutes; reuse the master you hold | +| ERR-PYR-CLM-007 | on none of the published sheets; `nhcx-error.yaml` lists it as observed live | "No prior preauthorization or claim record found for case number" | The claim was sent under a number of its own instead of the pre-auth's | Send the claim under the pre-auth's claim number | + +Refusals arrive in order: the SHA validates the bundle first and applies the scheme's rules only to a bundle that passed. A refusal in the `PAYR-102x` block is structural, so check ids and sequences before values. + +## 3. Gateway protocol errors + +From `nhcx-package/nhcx-error.yaml` (the gateway space) and the live notes: + +| Code | Message | When you meet it | Fix | +| --- | --- | --- | --- | +| NHCX-1006 | Duplicate request. Request with same correlation id already exist | A request sent again on a correlation id the exchange already holds | Mint a fresh correlation id for every request; only a response echoes one | +| NHCX-1010 | No Data with given Correlation id for call back request | A response sent on a thread the exchange has retired: the request was redelivered five times without a 2xx, or the id was never a request | Acknowledge inbound requests at once; a payer that decides minutes later sends `outcome queued` first | +| NHCX-1012 | No records found with the requested api caller id | The sandbox's own `v1/status` route, whatever id you pass | Ask status as a Task on `v1/task/submit` | +| NHCX-1015 | Invalid response received from receiver (published); the registry answers "You are not authorized to update/modify details" | Updating a participant's endpoint or certificate with a client id that did not create it | Use the creator's credentials or the NHCX participant portal (nhcx-adapter release README, "Troubleshooting") | +| NHCX-1016 | Invalid Api Action / no policies found (the registry, on a policy search) | A policy search that finds nothing | Read it as an empty result | +| NHCX-1018 | Invalid ABHA number received | An ABHA not in `XX-XXXX-XXXX-XXXX` form on the envelope | Format it, or omit the header | + +With nhcx-adapter as the transport, its local codes and their HTTP statuses are in `api-knowledge.md` section 5. The ones you will meet first: + +- `CERT_NOT_FOUND`: the recipient has no certificate on the registry; nothing to fix locally. +- `SELF_ENCRYPTION_KEY`: the registry handed out your own certificate for another code; run `nhcx-adapter cert --refresh`. +- `DECRYPT_FAILED` on `/in`: your registered certificate is not the key you hold; run `nhcx-adapter check`. +- `WRONG_RECIPIENT` on `/in`: a message for a participant this adapter does not hold. +- `CALLBACK_HTTP_` and `CALLBACK_UNREACHABLE`: your HMIS refused or was down; NHCX will redeliver up to five times. +- `TOKEN_HTTP_401`: wrong `clientId` or `clientSecret`, or sandbox credentials against production. + +## 4. Reading a ledger thread + +The per-case archive is the first place to look, with any transport: every message sent and received, by correlation id, in `//transactions.txt` (step 4). With nhcx-adapter as the transport, its ledger also holds what reached it but not your HMIS; the commands below read it. + +Step 1. Find the thread. From the leg row's `correlation_id`, or from the case number in a summary: + +```sh +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger/thread/" | python3 -m json.tool +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger?since=2h&direction=in&limit=100" | python3 -c 'import json,sys; [print(r["id"], r["created_at"][11:19], r["direction"], r["path"], r["workflow_id"], r["hcx_status"], r["status"], r.get("fhir_summary",{}).get("outcome")) for r in json.load(sys.stdin)["items"]]' +nhcx-adapter ledger thread # no server needed +``` + +Step 2. Read the derived `state`: + +| state | Meaning | What to do | +| --- | --- | --- | +| `awaiting_response` | You sent a request and nothing came back | Wait; on the SHA a decision needs the desk. Check `peer.status_code` on the outbound row is 202 | +| `partial` | A `response.partial` arrived (20, 25, or the SHA's 37) | The payer has it. The decision comes on the same thread | +| `completed` | A `response.complete` arrived | The leg should be settled in the HMIS. If it is not, the callback failed or the reader misread it | +| `awaiting_our_response` | A request reached you (a CommunicationRequest, a payment notice) | Your reply is due on this correlation id | +| `error` | A rejection, a failed send or delivery, or a protocol message | Open the message with `error` or `format: protocol` | + +Step 3. Read one message in full, bundle included: + +```sh +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger/" | python3 -m json.tool | less +``` + +On an inbound row, `peer.status_code` is what your callback answered and `peer.response` is its body. A `delivery_failed` row with a 500 is your handler raising. On an outbound row, `peer.status_code` is the gateway's answer and `peer.response` its body. A `rejected` row carries `GATEWAY_HTTP_` and the NHCX error in `peer.response`. + +Step 4. Compare with the HMIS's own archive for the case, `//transactions.txt`. Each line names the workflow id, correlation id, api call id, ledger id and file. + +- A message in the ledger and not in the archive is a callback that failed. +- A message in the archive marked `outcome=unmatched` is one the HMIS could not tie to a case: the correlation id is on no leg row, and the bundle names no claim number the HMIS knows. +- A message in neither is a send that never left; look at the HMIS's error on the leg row. + +Files, when the server is down: `//.json`, and `index.jsonl` in the same folder for the summaries. `ledger.dir` is `data/ledger` by default. + +## 5. Correlation mistakes + +Each of these was made once in a real build. + +- Answering on the wrong thread. A communication reply or a payment acknowledgement must carry the request's `x-hcx-correlation_id`; every other leg must not carry one. A PMJAY query answer (19, 131, 161) goes on a new correlation id; a same-thread answer is swallowed without a refusal. +- Sending a non-UUID correlation id. nhcx-adapter replaces anything that is not an 8-4-4-4-12 UUID with a fresh one, so the thread is silently lost; store what the transport returned, not what you sent. With your own transport, a request's correlation id is its own `api_call_id` and an answer echoes the request's. +- Matching by path or by header type. Route an inbound message by its correlation id first, then by the claim number inside the bundle. With nhcx-adapter, the `X-Hcxkit-Flow` header is inverted on purpose and must not be a filter. +- Closing a thread on the first reply. The acknowledgement and the decision share one correlation id; a settled-status guard throws the approval away. +- Losing the thread after a refusal at the door. A send refused with a ProtocolResponse went out under a correlation id the payer never took in. The case still lives on the thread the payer last answered; keep it as `thread_correlation_id`. +- Reusing a correlation id after an error. The exchange retires it; the next attempt needs a fresh one. +- Forgetting the workflow id on a reply. Some payers match the payment acknowledgement on the notice's own workflow id; PMJAY wants 17. + +## 6. Redelivery and deduplication + +NHCX redelivers an unacknowledged message up to five times and then drops the correlation id. The SHA redelivers a large plan answer on its own, two or three times about a minute apart, under the same `x-hcx-api_call_id`. A case archive showed it as three lines on one api call id. With `callback.also` configured, one delivery reaches every target, and a refusal by any one of them makes NHCX redeliver to all. + +So: + +- Dedupe on `x-hcx-api_call_id` (with nhcx-adapter, `X-Hcxkit-Txn-Id` carries the same value). Either store the last applied `api_call_id` on the leg row and ignore a repeat, or keep an inbound ledger keyed on it and answer `duplicate`. A payer that omits the id is deduped on identical outcome and adjudication. +- Dedupe payment notices and communication requests on their correlation id, with a unique index on each table. +- Answer 2xx before doing slow work. The exchange allows 30 seconds for the 202 receipt (nhcx-adapter gives your HMIS 20 of them, `callback.timeoutSeconds`); anything slower is a failed delivery. +- Un-record a delivery whose application failed for a passing reason (database away), so the redelivery is not waved off as a duplicate. +- With nhcx-adapter, treat `X-Nhcx-Redelivery: true` as a hint, not a rule: the ledger flag is per adapter process and is lost on a ledger reset. + +## 7. A send reported as failed can still have landed + +Seen live on the sandbox three times in one night. A pre-authorisation went out through nhcx-adapter, the connection dropped after the request had been written, and it answered the hospital `GATEWAY_UNREACHABLE` with HTTP 502. NHCX had taken the message: the SHA acknowledged it four seconds later on the correlation the adapter had minted. A hospital that treats that 502 as "not sent" sends again. The scheme refuses the duplicate (ERR-PYR-PRE-030 "Active instance found for case number", PAYR-1238 for a fresh pre-auth), and a live case stands at the payer that the hospital has no record of. + +So: + +- nhcx-adapter's failure body names the ids the message went out under: `ledger_id`, `txn_id`, `correlation_id`, `api_call_id`, `request_id` and the `headers` map. Keep them. With your own transport the ids are the ones you minted before sealing: store them before the POST, so a failed POST still has a thread to look for. +- Record the failed leg under that correlation, not as nothing. Carry the ids on the client's error and write them onto the leg row. +- When an answer arrives on a failed leg's correlation, revive it: the leg becomes a sent leg, the record moves from draft to with-the-payer, and the desk is not offered a second send. A protocol error answer revives nothing. +- Anything that creates a record before it sends must name that record in the refusal, or the record is orphaned where nobody can see it. An enhancement handler returns the child it raised alongside the gateway's words. + +## 8. Sandbox pace rules + +What the SHA Himachal Pradesh sandbox (`1518@hcx`) did across the runs. `nhcx-package/docs/03-Building a Provider/11-PMJAY Sandbox Run.md` records one such run in order. + +- One live pre-authorisation per beneficiary per hospital (PAYR-1238). Every HMIS that shares the facility's participant code shares the limit, so sweep before a run: withdraw every approved case without a claim, then wait ten seconds. +- One request at a time per case (PAYR-1322). About 30 seconds between a decision and the next leg; an enhancement refused with "Active instance" is resent up to three times. +- Decisions are taken on the NHCX Payer Service desk, not on the exchange (`nhcx-package/docs/03-Building a Provider/12-PMJAY Adjudication APIs.md`). A case has to be driven through roles: PPD-Trust decides a pre-auth; a claim walks CEX-Trust, CPD-Trust, the Medical Audit Committee, ACO-Trust, SHA-Trust and the Claim Review Committee. The desk answers "Event Meta Log not found" or "Case not found" until the exchange has delivered the request; retry every six seconds, up to 150 seconds. A decision the desk accepts is sometimes never sent; taken again a minute later it is answered in seconds, so decide up to four rounds of 90 seconds. +- An enhancement's query has to be taken a minute after the acknowledgement. +- A claim episode with a query answered and the roles walked takes about ten minutes. Run cases one at a time and allow 20 minutes per case. +- The plan answer arrives in pieces over a minute and is redelivered; expect the same api call id three times. +- The beneficiary registry behind the ABDM session refuses a search now and then while a token refreshes. Retry the search up to four times, 30 seconds apart. +- The sandbox approves a claim query answer at zero with "No query response comments received" when the `CQD` reply is missing, and sometimes even when it is present. Report it; do not assert on the amount. +- The status Task is refused on this sandbox: without a `Task.reasonCode` it answers PAYR-1018, with any reason code PAYR-1008. PMJAY decides on its own desk and answers no status enquiry, so do not offer one for it. Record the refusal on the enquiry row and move on. +- The reprocess Task is taken only under the standard's spelling, `intimationNumber`. Use that spelling on every Task (cancel included); the package's bundles carry it too. The SHA answers workflow 37, "Arbitration claim submission process completed successfully". +- A test payer you run yourself has none of these limits; six use cases ran in under four minutes against one. diff --git a/plugins/nhcx/skills/nhcx-coverage/references/fhir-knowledge.md b/plugins/nhcx/skills/nhcx-coverage/references/fhir-knowledge.md new file mode 100644 index 000000000..08ffbb6c6 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-coverage/references/fhir-knowledge.md @@ -0,0 +1,206 @@ +# FHIR knowledge: every bundle sent and received + +Sources: the bundles under `nhcx-package/fhir` (the hospital pins in `B1` to `B9`, the payer answers in `C3` to `C11`, the live PMJAY hospital captures in `D1` to `D13`) and the chapters under `nhcx-package/docs/05-FHIR Reference`. Get the package as `references/material.md` says. + +## 1. Where the examples live + +| Set | Path | What it is | +| --- | --- | --- | +| Pinned hospital bundles | `nhcx-package/fhir/B1` to `B9`, the lower-case files (`B3/preauth-request.json`) | One bundle per message a hospital sends, written to the specification with placeholders. A build is held to these byte for byte. The pin map is in `references/material.md`. | +| Payer answers | `nhcx-package/fhir/C3` to `C11` | One file per message the payer sends: the generic answer and, where one exists, its `-pmjay` twin. Feed these into your readers. | +| Live hospital captures | `nhcx-package/fhir/D1` to `D13` (PMJAY) and the capitalised B files such as `B3/B3-request.json` (generic) | Bundles taken from the sandbox wire, with the beneficiary's identifiers replaced | +| The catalogue | `nhcx-package/fhir/index.yaml` | For each file: direction, side, scheme (`generic` or `pmjay`), workflow id, focal resource, origin. Origin `example` means placeholders, not a payload; `wire` means a capture. | +| The NRCeS IG's own example | `nhcx-package/fhir/B4/communication-request.json` | The communication TaskBundle for the payer's request comes from the IG | +| Your build's archive | `//NNN--.json` and `transactions.txt` (modules 7.1 and 7.3) | Every envelope one episode sent and received, in order | +| Chapters | `nhcx-package/docs/05-FHIR Reference/*.md` | Element by element: `08-Preauthorisation Request.md`, `12-Claim Request.md`, `13-Claim Response.md`, `17-Communication.md`, `15-Cancel, Reprocess and Shortfall.md`, `16-Payment Notice and Acknowledgement.md`, `06-Insurance Plan Response, Package-Based.md`, `19-Codes and Value Sets.md` | + +Pins, by leg. Paths are under `nhcx-package/fhir/`. + +| Leg | Provider pin | Payer answer or capture | +| --- | --- | --- | +| Coverage eligibility | `B1/discovery.json`, `B1/validation.json`, `B1/benefits.json`, `B1/auth-requirements.json` | `C3/validation-response.json`, `C3/discovery-response.json`, `C3/benefits-response.json`, `C3/C3-response-generic.json`; PMJAY `C3/coverage-eligibility.json`, `C3/C3-benefits-pmjay.json`, `C3/C3-response-pmjay.json` | +| Insurance plan | `B2/insurance-plan-request.json` | `C4/C4-response-pmjay.json` (package-based, abridged), `C4/C4-response-generic.json` (coverage-based) | +| Pre-auth 12, enhancement 13, query answer 19 or 131 | `B3/preauth-request.json`, `B3/preauth-enhancement.json`, `B3/preauth-queryupdate.json` | `C5/C5-received-wf20.json`, `C5/C5-approved-wf21.json`, `C5/preauth-queried.json`, `C5/C5-rejected-wf23.json`, `C5/C5-enhancement-approved-wf22.json`; PMJAY the `-pmjay` twins and `C5/C5-queried-wf24.json` | +| Cancel PC01 | `B3/preauth-cancel.json` | `C10/C10-cancelled-wfPC02.json`, `C10/C10-cancelled-wfPC02-pmjay.json` | +| Claim 15, query answer 161 | `B5/claim-request.json`, `B5/claim-queryupdate.json` | `C7/C7-received-wf25.json`, `C7/C7-approved-wf26.json`, `C7/claim-queried.json`, `C7/C7-rejected-wf291.json`; PMJAY the `-pmjay` twins, `C7/C7-approved-deduction-wf26-pmjay.json` and `C7/C7-queried-wf27.json` | +| Reprocess 36, release 36 | `B5/claim-reprocess.json`, `B5/claim-release.json` | `C10/C10-arbitration-wf37.json`, `C10/C10-arbitration-wf37-pmjay.json` | +| Payment acknowledgement | `B7/payment-notice-ack.json` | The notice you answer: `C9/C9-notice-wf30.json`; PMJAY `C9/payment-notice.json`, `C9/C9-notice-tds-wf30-pmjay.json` | +| Communication reply | `B4/communication-response.json` | `B4/communication-request.json` (the query you answer; the IG's example), `C6/C6-preauth-query-wf24.json` and `C6/C6-claim-query-wf27.json` (live, generic), `C6/C6-notification-wfN02.json` (PMJAY) | +| Status enquiry | None. The published call carries no bundle (`nhcx-package/docs/05-FHIR Reference/18-Predetermination, Status and Search.md`). | None captured | + +## 2. Conventions every hospital bundle follows + +From `nhcx-package/docs/05-FHIR Reference/01-Bundles and Conventions.md` and the pins: + +- `Bundle.type` is `collection`; `Bundle.meta.profile` names the NRCES bundle profile (`ClaimBundle`, `TaskBundle`, `CoverageEligibilityRequestBundle`); every resource names its own profile under `https://nrces.in/ndhm/fhir/r4/StructureDefinition/`. +- Every entry has an absolute `fullUrl` under one base, `https://nhcx.abdm.gov.in/...`, and every reference resolves to another entry. A thing that is genuinely not in the bundle is named by identifier, not by a URL. The chapter's rule 3 also accepts `urn:uuid:` references; parse both. +- `Bundle.id` is fixed per shape: `coverage-validation-request-generic`, `preauth-request-generic`, `preauth-enhancement-request-generic`, `claim-queryupdate-request-generic`, `preauth-cancel-request-generic`. +- No `meta.versionId`, no `meta.lastUpdated`, no bundle `timestamp` on a request. The communication reply and acknowledgement are the exception: the IG example carries `meta.lastUpdated` and `timestamp`, and the build writes them. +- Money carries `currency: INR`; the total equals the sum of the item nets; whole numbers are written as integers. +- Instants are IST with `+05:30`. The four coverage pins in `B1` stamp `created` at `+05:00`, so leave `created` out of the byte comparison. + +## 3. Coverage eligibility request + +Builder: `build_coverage_request`. Seven entries, in this order and at these urls: + +1. `CoverageEligibilityRequest` at `/coverage-eligibility/request`: `identifier: [{system: https://nhcx.abdm.gov.in}]`, `status active`, `priority normal`, `purpose: []`, `patient`, `created`, `enterer` (the PractitionerRole), `provider`, `insurer`, `facility` (the Location), `insurance: [{focal: true, coverage}]`, and `item[]` on `benefits` and `auth-requirements`. +2. `Patient` at `/patient`: identifiers typed `PMJAY` (NDHM identifier-type system) and `MB` (v2-0203), both the member id. Nothing else; demographics are the payer's to return. +3. `Organization` provider at `/provider`: identifier `NPI` under `https://nhcx.abdm.gov.in` = the facility's registry id (HFR id); `type prov`; `name`. +4. `Organization` payer at `/payer`: identifier `NIIP` = the participant code without `@hcx` (`1518`); `type pay`. +5. `Location` at `/location`: `name`, `managingOrganization` the provider. +6. `Coverage` at `/coverage`: identifier `NH` = the policy code, or `NONE` on a discovery; `status active`; `type HIP`; `subscriber`, `beneficiary`, `subscriberId` = member id; `relationship self`; `payor`. +7. `PractitionerRole` at `/practitioner-role`: `code` SNOMED `307988006` Medical technician. + +Items (`eligibility_item`): `category` under `https://nhcx.abdm.gov.in/category-code` (the specialty), `productOrService` under `https://nhcx.abdm.gov.in/product-code` (the package), `quantity.value` as an integer, and each ward tier quoted through the package as a `modifier` coding with code and display and no system. No money, no diagnosis, no sequence. + +The four purposes differ only in `purpose`, the Coverage identifier and whether `item` is present. + +Reader (`parse_validation_bundle`): the payer echoes the request's entries and appends its own, so take the last `CoverageEligibilityResponse`, `Patient` and `Coverage`. Read `insurance[0].inforce`, `outcome`, `disposition`, `item[].authorizationRequired`, the largest `benefit[].allowedMoney` with its `usedMoney`, the Patient's name, gender, birth date, address, `ABHA` identifier and photo, the Coverage's `class[0].name` and `period`. The SHA answers on workflow id `5` (`nhcx-package/fhir/C3/C3-response-pmjay.json`). + +Auth-requirements reader (`parse_auth_bundle`, with `supporting_entry`; examples `C3/C3-response-generic.json` and `C3/C3-response-pmjay.json`): one `insurance[0].item` per line quoted, each with `authorizationRequired`, `excluded`, `benefit[0]` and `authorizationSupporting[]`. Each supporting entry is a CodeableConcept whose `text` is free text the scheme overloads: `fullUrl: ` marks a form to answer; `Type: pre` or `Type: post` says which leg a document is due at; `Procedure Code: X` says for which line. The space after the colon is sometimes missing; match both. A form is always wanted at pre-auth; a document only when its stage is `pre`. + +## 4. Insurance plan request and the plan + +Request (`build_plan_request`): a `TaskBundle` with one entry, a `Task` at `https://nhcx.abdm.gov.in/insurance/request`: `status requested`, `intent order`, `code poll` on the HL7 financial task code system, inputs typed `policyNumber` and `providerId` under the NDHM task-input code system. No id, no timestamp, no requester. At least one input is mandatory. Bundle id `insurance-request-generic`. + +Answer: an `InsurancePlanBundle` with one `InsurancePlan`, an `Organization`, and one `Questionnaire` per form the plan names (the same form repeated once per benefit that needs it; collect by `url`). The parser (`parse_plan_bundle`) reads both published shapes and merges them on package code: + +- `plan[].specificCost[].category` (the specialty) then `benefit[].type` (the package) then `cost[]`: the cost typed `Procedure` is the package rate; `Stratification` and `Implant` costs are money paid over the rate, named by their `qualifiers[0]`. +- `coverage[].benefit[].limit[]`: the limit whose code is the package's own is the rate; the rest (STRAT codes, implants) are tiers. +- Extensions on the plan, the coverage and each benefit, matched by a squashed url family: `Claim-Condition` children name conditions (`ProcedureType`, `IsDayCare`, and so on); `Claim-SupportingInfoRequirement` children are one nested requirement per document, each with `category`, `code` (`MAND0409` and the like) and `documentationUrl` pointing at a Questionnaire. Requirements on the `InsurancePlan` resource itself are policy-wide (proof of identity, the consent forms). +- A `Questionnaire` under `/questionnaire/` is a policy form; under `/stgquestionnaire/` a treatment-guideline checklist. Questions live on `item.prefix` far more often than `item.text`; answer options are plain strings; `initialSelected` is the payer's default. + +Store it once per facility and policy and copy it onto later episodes (`reuse_plan`). The PMJAY master runs to tens of megabytes; the validator cannot check it whole. + +## 5. The Claim bundle: pre-authorisation, enhancement, query answer, claim, predetermination + +One document for every leg (`claim_bundle`). Entries, in order and at these urls: + +1. `Claim` at `https://nhcx.abdm.gov.in//`: leg `preauth`, `claim` or `predetermination`; flow `request`, `enhancement` or `queryupdate`. +2. `Patient` at `/patient`, `id 1`: identifiers `PMJAY` (member id), `ABHA` (when known), `MB` (member id); `name.text`, `telecom`, `gender`, `birthDate`. +3. `Organization` provider at `/provider`, `id 1`; `Organization` payer at `/payer`, `id 2` (as in section 3). +4. `Coverage` at `/coverage`, `id 1`: `NH` identifier = policy code, `subscriberId` = member id. +5. `Practitioner` at `/practitioner` (the second and later at `/practitioner/2` and so on), `id n`: identifiers `HPID` under `https://nhcx.abdm.gov.in`, `MD` (licence) when known, and `HPIN` under `https://hpr.abdm.gov.in`. PMJAY looks the practitioner up by the `HPIN` typed identifier and refuses a bundle without one with PAYR-1083. `qualification.code` under HL7 v2-0360 with the table's own display (`degree_coding`). +6. `Procedure` at `/procedure/n`, `id n`, one per package: `status preparation` before treatment, `completed` on the claim; `code` SNOMED `71388002` with `text` = the package display; `performedDateTime`. +7. `QuestionnaireResponse` at `/questionnaireresponse/n`, one per answered form: `questionnaire` = the plan's Questionnaire url, `status completed`, `subject` the Patient, `authored`, `item[].answer[]` typed by the question (`valueString`, `valueDateTime`, `valueBoolean`, `valueInteger`, `valueDecimal`, `valueAttachment`). + +The Claim itself: + +- `id` = the claim number; `identifier[0]` typed `CLN` under `https://nhcx.abdm.gov.in` = the claim number. Element ids on every list the payer indexes: `item[].id = Item/n`, `procedure[].id = Procedure/n`, `supportingInfo[].id = SupportingInformation/n`. PAYR-1027 is an item without one. +- `status active`, `type` SNOMED `737481003` inpatient care, `use` = `preauthorization`, `claim` or `predetermination`, `billablePeriod`, `created`, `insurer`, `provider`, `priority normal`. +- `careTeam[]`: sequence, provider reference, role `primary` for the first and `assist` after, `qualification` SNOMED specialty. +- `diagnosis[]`: ICD-10 under `http://hl7.org/fhir/sid/icd-10`, type `admitting`, `onAdmission yes`. +- `procedure[]`: sequence, `type` under `https://nhcx.abdm.gov.in/procedure-type` = the plan's `ProcedureType` condition lower-cased (`conservative`, `medical`, `surgical`), `date`, `procedureReference` with the package display. +- `insurance[0]`: `sequence 1`, `focal true`, `coverage`; on the claim `preAuthRef: [""]`. The pin carries the pre-auth's own claim number there (`B5/claim-request.json` quotes `B3/preauth-request.json`'s claim id). The build carries the payer's `ClaimResponse.preAuthRef`, which the live capture `nhcx-package/fhir/D9/D9-request.json` shows as `2026091110000810`. +- `item[]` (`claim_items`): one per procedure or implant, never per tier. `sequence`, `careTeamSequence`, `diagnosisSequence`, `procedureSequence` (its own Procedure), `informationSequence` (every supportingInfo), `category` under `ndhm-benefit-category` (the specialty), `productOrService` under `ndhm-procedure-code` (the package), `modifier[]` one coding per ward tier with code and display and no system, `programCode` `AB-PMJAY` under `ndhm-program-code` for PMJAY and none for a generic payer, `servicedPeriod` as dates, `quantity`, `unitPrice` = net divided by quantity, `factor` from the scheme's multiple-procedure rule (1, 0.5, 0.25 by cost rank; PMJAY only), `net` = the line plus its tiers. +- `total` = the sum of the nets. + +supportingInfo (`supporting_info`), every entry numbered once the list is assembled (PAYR-1019 is an entry without `sequence`): + +| When | category | code | value | +| --- | --- | --- | --- | +| every leg, one per attached document | `INV` (or the document's own category) under `ndhm-supportinginfo-category` | the plan's requirement code (`MAND0408`) under `https://nhcx.abdm.gov.in/document-code`, else `ODN` | `valueAttachment {contentType, data, title}` | +| every leg | `ONS` | `ADDD` | `valueString` admission instant | +| every leg | `OTH` | `EDT` | `valueString` admission instant | +| claim | `HDS` | the plan's summary code (`MAND0006` in the pin) else `HDS` | `valueAttachment` the discharge summary | +| claim, when a surgery time is known | `ONS` | `PSP` | `valueString` surgery instant | +| claim | `ONS` | `DSDE` | `valueString` discharge instant, or the death instant | +| claim, death only | `ONS` | `DTM` | `valueString` death instant (PAYR-1096 and PAYR-1503 without it) | +| claim | `DIS` | `DTH`, `LAMA`, `DAMA` or `DTM` | `valueString` the stage: `Before Surgery`, `During Surgery`, `After Surgery` | +| query answer (flow `queryupdate`) | `NMI` | `CQD` | `valueString` the desk's reply. The SHA reads its query response comments from here; an answer without one is decided as if none was given | +| every leg, one per answered form | `INF` (or `STG` for a treatment guideline) | `ODN` (or `STG`) | `valueReference` to the QuestionnaireResponse entry | + +Which forms ride (`required_forms`): with an auth-requirements ruling, the forms it named for the leg; without one, at pre-auth every guideline form the plan attaches to the quoted packages; and on both legs every policy-level form. The scheme refuses a pre-auth that answers neither biometrically nor with its Authentication Consent questionnaire (PAYR-1256, PAYR-1271), a claim without the consent answered again at discharge (PAYR-1363, PAYR-1364), and a package without its STG questionnaire (PAYR-1254, PAYR-1365). The live D4 capture carries two policy questionnaires; the live D9 claim carries four, including the Discharge Consent (`nhcx-package/fhir/D9/D9-request.json`). + +Which documents ride (`required_documents`, `preauth_documents`): the ruling's list for the leg, else the plan's list for the quoted packages at pre-auth and whatever was not attached there at the claim. A file attached against a requirement carries that requirement's code; a file nobody asked for carries `ODN`. Never drop one. Content types the scheme takes: pdf, jpg, jpeg, png (PAYR-1008 otherwise). + +The legs differ in these ways only: + +| Leg | flow | use | Procedure status | Extra | +| --- | --- | --- | --- | --- | +| Pre-auth 12 | `request` | `preauthorization` | `preparation` | | +| Enhancement 13 | `enhancement` | `preauthorization` | `preparation` | every line, old and new, under the same claim number; the costlier package at factor 1 and the other at 0.5 (the live capture `nhcx-package/fhir/D6/D6-enhancement.json` carries the two lines at 1 and 0.5) | +| Query answer 19 or 131 | `queryupdate` | `preauthorization` | `preparation` | the `NMI`/`CQD` reply | +| Claim 15 | `request` | `claim` | `completed` | discharge scalars, summary, `preAuthRef`, the claim under the pre-auth's number (ERR-PYR-CLM-007) | +| Claim query answer 161 | `queryupdate` | `claim` | `completed` | as the claim, plus `NMI`/`CQD` | +| Predetermination | `request` | `predetermination` | `preparation` | sent on `v1/preauth/submit` with workflow 12 | + +LAMA and DAMA before or during surgery (`claim_lines`): the claim carries one item, procedure `LM100` at the plan's rate (the sandbox prices it at zero), no tier, and the payer disqualifies every approved item (PAYR-1362 if the package is still there). After surgery the package stands and `LM100` is not used. PAYR-1270 is `LM100` on a pre-auth. + +## 6. The ClaimResponse you read + +Shape (`nhcx-package/docs/01-Overview/07-Payer Flexibility.md`, "Answer detail"): `ClaimResponse`, `Patient`, the two `Organization` entries, `Coverage`, in that order. Fields to read (`parse_claim_response`): + +- `use`: `preauthorization` or `claim`; a bundle with none is whatever you sent on that thread. +- `outcome`: `queued` (acknowledgement), `partial` (queried, or approved for less), `complete`, `error` (rejected). +- `adjudication[]` at claim level: the entry whose `category` is `status` carries `reason.coding.code`: `submitted`, `approved`, `queried`, `rejected`, `cancelled`. +- `preAuthRef`: the payer's case number; see `flow-knowledge.md` section 3 for which answers carry it. +- `identifier[0].value`: your claim number, echoed on every answer. +- `total[]`: a repeating list by `category`, never positional: `benefit` (granted this round), `eligible` (what the case stands at), `submitted`; PMJAY adds `tax` and `incentive`. +- `item[].adjudication[]` by category: `eligible` (amount), `status` (reason `Approved`, `Queried`, `Rejected`), `reason` (the desk's remark, pipe-delimited `USER~datetime~type~comment~trust`, kept verbatim), `eligpercent`, `eligquant`, `deductible` with its reason after a claim. +- `processNote[].text`. +- `type` is present only on the pre-auth acknowledgement (SNOMED `737481003`). + +The status rule (`verdict_status`): `queued` or reason `submitted` is still `submitting`; reason `cancelled` is `rejected`; reason `queried` is `queried`; outcome `error` is `rejected`; outcome `partial` is `partial` only with reason `approved`, else `queried`; outcome `complete` is `approved` with reason `approved` or none, else `queried`. Never read `outcome` alone. + +## 7. Task bundles the hospital sends + +A `TaskBundle` with the `Task` at `https://nhcx.abdm.gov.in//` followed by the provider and payer Organizations. The Task: `status requested` (`completed` on an acknowledgement), `intent order`, `code` on the HL7 financial task code system with no display, `description`, `authoredOn`, `requester` the provider, `owner` the payer. + +| Task | code | reasonCode (NDHM reason code system) | inputs | Other | +| --- | --- | --- | --- | --- | +| Cancel PC01 | `cancel` | one of `treatmentplanchanged`, `patientrequest`, `financialconstraints`, `alternativetreatment`, `duplicateclaim`, `administrativeerror`, `other` (with `other` the description is the only justification) | `claimNumber`, `intimationNumber` (both typed under `ndhm-task-input-type-code`) | anchor `/preauth/cancel` | +| Reprocess 36 | `reprocess` | `claimrejected`, `partialpayment` or `rejectiondisputed` with the reference's displays | `claimNumber`, `intimationNumber` (the standard's spelling), one `document` input per attachment as `valueAttachment` | `basedOn[0].identifier` typed `CLN`; `for.identifier` typed `PMJAY` on the scheme, `MB` elsewhere; anchor `/claim/reprocess` | +| Release 36 | `release` | `partialpayment` | `claimNumber`, `amount` as `valueMoney` under `https://nhcx.abdm.gov.in/task-input-type` | `basedOn` as above; anchor `/claim/release` | +| Status | `status` | none | `claimNumber` | anchor `//status`; not in the package, whose status call carries no bundle (`18-Predetermination, Status and Search.md`); refused by PMJAY | +| Payment acknowledgement 17 | `status`, `status completed` | none | none; `output[]`: `status` = `paymentack` under the NDHM task-output systems, and `claimNumber` | anchor `/payment/notice-ack` | + +The spelling rule: the input is `intimationNumber`, the standard's spelling, on every Task. A reprocess under any other spelling is refused with PAYR-1008 (proven live; `nhcx-package/docs/01-Overview/07-Payer Flexibility.md`, "One spelling on the Task"). The pinned cancel and reprocess Tasks carry the same spelling, so the offline comparison diffs them unchanged. + +## 8. Task answers you read + +`parse_task_response`: find the `Task`, then follow each `output[].valueReference` to the entry it names; when that is a `ClaimResponse`, read it with the same parser as a verdict. + +- PC02 (`nhcx-package/fhir/C10/C10-cancelled-wfPC02.json`): Task `completed`, code `approve`, `output[0]` an `include` reference to a `ClaimResponse` with adjudication reason `cancelled`, `use preauthorization`. Accept the cancel when the Task status is `completed` or `accepted` and the outcome is not `error`. Retire the claim number after an accepted cancel. +- 37 (`nhcx-package/fhir/C10/C10-arbitration-wf37.json`): Task `accepted`, code `approve`, a `ClaimResponse` with outcome `queued`, `use claim`. Put the claim leg back to `submitting`; the new verdict comes on the claim's own thread. +- A status answer: none captured in the package. A generic payer that answers a status Task sends a Task `completed`, code `status`, `output[]` with `claimNumber` and a `claimStatus` string; PMJAY refuses the enquiry instead. + +## 9. The communication loop + +The query, generic payer (`nhcx-package/fhir/C6/C6-preauth-query-wf24.json`; the IG's example at `nhcx-package/fhir/B4/communication-request.json`): a `TaskBundle` with a `Task` `poll`, `requested`, `intent order`, `reasonCode additionalinfo`, one `include` input pointing at the `CommunicationRequest`; the request with `identifier` (the claim number), `basedOn` the Claim, `payload[].contentString` one per ask, `reasonCode[].text` repeating them; then the Claim, Patient, the two Organizations, Practitioner and Coverage. It arrives on `v1/communication/request` on a new correlation id, with the queried leg's correlation id in `x-hcx-workflow_id` when the payer sends one. + +The notification, PMJAY (`nhcx-package/fhir/C6/C6-notification-wfN02.json`): a Task `poll`, `completed`, `intent proposal`, reason `information` under `http://terminology.hl7.org/CodeSystem/communication-category`, a `CommunicationRequest` with one `contentString`, and the two Organizations. + +Reader (`parse_communication_request`): the first `CommunicationRequest`; the claim numbers it names in `about[]`, `basedOn[]` and `identifier[]`; the asks from `payload[].contentString`, else `reasonCode[].text`, else the Task's `description`; the Task's `intent` and `reasonCode`. Match the claim by those numbers first, then by a request id already held, then by the correlation id of one of your sends, then by the workflow id as a thread. + +The reply (`build_communication_bundle`; pin `nhcx-package/fhir/B4/communication-response.json`): a `TaskBundle` with `meta.lastUpdated`, `identifier` under the payer system, `timestamp`, and entries in this order: + +1. `Task` at `urn:uuid:`: `status completed`, `intent order`, `code deliver` under `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-codes`, `authoredOn`, `requester` the provider, `owner` the payer, one `input` typed `include` (HL7 financialtaskinputtype) pointing at the Communication, `reasonCode` echoed from the request's Task when it carried one. +2. `Communication` at `urn:uuid:`: `identifier` echoed from the request, `basedOn: [{reference: }]`, `about: [{reference: }]`, `status completed`, `category notification`, `priority routine`, `recipient` the payer, `sender` the provider, `payload[]`: a `contentString` for the text, then one `contentAttachment {contentType, title, creation, data}` per document, each with an `extension` carrying the document code. The extension url is participant-defined (`17-Communication.md`): write it under your own system and keep one url. `inResponseTo` is never set: FHIR allows only a Communication there and the validator refuses a request. +3. The `CommunicationRequest` echoed as it arrived. +4. The case as the payer holds it, lifted from the queried leg's own bundle: `Claim`, `Patient`, provider `Organization`, payer `Organization`, `Practitioner`, `Coverage`. + +Envelope for the reply: `x-hcx-correlation_id` = the request's, `x-hcx-workflow_id` = the request's, else the queried leg's correlation id, else the claim number; sender and recipient swapped. + +The acknowledgement of a notification: the payer's own bundle sent back with `Task.status` set to `completed`, its intent and reason as sent, the provider Organization ahead of the payer's, a fresh `timestamp`. A request that came without a Task gets one built round it, coded `poll`, intent `proposal`, pointing at the request. The package's `B4/communication-acknowledgement.json` is a different shape: a `status` Task, `completed`, with a `status` output and the two Organizations, and no CommunicationRequest. + +## 10. The payment notice you read and the acknowledgement you send + +Notice (`nhcx-package/fhir/C9/C9-notice-wf30.json`; PMJAY `C9/payment-notice.json` and `C9/C9-notice-tds-wf30-pmjay.json`): a Task `deliver`, `requested`, with a `status` input; a `PaymentNotice` with a `CLN` identifier (the claim number), `amount`, `paymentStatus paid`; a `PaymentReconciliation` with the same identifier, `disposition`, `paymentDate`, `paymentAmount`, `paymentIdentifier` typed `UTR`, and `detail[]` lines (`RF` and `Payment` in `payment-notice.json`; `TDS` and `Payment` in the other two); the two Organizations. It arrives on `v1/paymentnotice/request` on a new thread, workflow 30, 31 or 33. + +Reader (`parse_payment_notice`): the claim number from the `CLN` identifier on the notice, the reconciliation, the Task, or the first entry's untyped identifier, never from the bundle identifier; the amount from the notice or `paymentAmount`; the UTR; the details. Dedupe on the notice's correlation id; a second notice with the same `PaymentNotice.id` updates the first (`record_payment`). Count money once per UTR (`paid_total`). + +Acknowledgement: the Task in section 7, sent on `v1/paymentnotice/on_request` to whoever sent the notice (not always the claim's payer), with `x-hcx-correlation_id` = the notice's and `x-hcx-workflow_id` = `17` for PMJAY or the notice's own id for a generic payer. + +## 11. Validating a bundle + +The package ships no validator. Use the HL7 FHIR validator (`validator_cli.jar`, from HL7) with the NRCeS IG package `ndhm.in`, version 6.5.0. A bundle refused with PAYR-1004 or PAYR-1008 goes through the validator before anything else (`nhcx-package/docs/06-Reference/02-Troubleshooting.md`). The rules it checks against are in `nhcx-package/docs/05-FHIR Reference/01-Bundles and Conventions.md`. + +```sh +java -Xmx4g -jar validator_cli.jar \ + -version 4.0.1 -ig -tx n/a -output result.json +``` + +Pass every file in one call; starting the JVM is the slow part. `-tx n/a` keeps the terminology checks offline; drop it to add them. A bundle passes when the output holds no issue of severity error or fatal. + +The provider pins carry 0 to 13 errors each and the SHA accepted every one as it stands. An error that says "a code the profile does not define" is the scheme's own vocabulary, not a fault to fix. A warning is advice. diff --git a/plugins/nhcx/skills/nhcx-coverage/references/flow-knowledge.md b/plugins/nhcx/skills/nhcx-coverage/references/flow-knowledge.md new file mode 100644 index 000000000..098cd9dbc --- /dev/null +++ b/plugins/nhcx/skills/nhcx-coverage/references/flow-knowledge.md @@ -0,0 +1,206 @@ +# Flow knowledge: the claim episode, its workflow ids, the two payer kinds, the use cases + +Sources: the NHCX package, fetched by `scripts/fetch-package.sh` into `nhcx-package/` beside `nhcx-build/`. That means the overview chapters under `nhcx-package/docs/01-Overview`, the workflow sheet `nhcx-package/workflow.yaml`, the use-case catalogue `nhcx-package/usecases.yaml`, and the payer bundles under `nhcx-package/fhir/C3` to `nhcx-package/fhir/C11`. The published chapters live under `nhcx-package/docs/01-Overview`, `nhcx-package/docs/05-FHIR Reference` and `nhcx-package/docs/03-Building a Provider`. Everything else here was learnt live on the NHCX sandbox. + +## 1. The episode + +One hospital admission that an insurer pays for is one claim episode. Store it as one record with a claim number. Any number works if it is unique per hospital, short, sortable, and fits the payer's `CLN` identifier. The episode has these legs, each a separate exchange with its own correlation id: + +| Order | Leg | You send | Payer answers | Thread | +| --- | --- | --- | --- | --- | +| 1 | Policy lookup | The participant service's `participant/get/policies`, through the transport; the recipient of every later leg is the policy's `processingid` | synchronous JSON | none, plain REST | +| 2 | Coverage eligibility | `v1/coverageeligibility/check`, purpose `discovery`, `validation` or `benefits` | `on_check` | new per check | +| 3 | Insurance plan (package master) | `v1/insuranceplan/request` | `on_request` | new; one plan per facility and policy | +| 4 | Auth requirements | `v1/coverageeligibility/check`, purpose `auth-requirements`, with items | `on_check` (the PMJAY sandbox rarely answers; `nhcx-package/fhir/C3/C3-response-pmjay.json` is an SHA ruling, `C3/C3-response-generic.json` a generic one) | new per procedure set | +| 5 | Pre-authorisation | `v1/preauth/submit` wf 12 | `on_submit` 20 first, then 21, 23 or 24 | new; the acknowledgement comes first on the same thread | +| 5a | Pre-auth query answer | `v1/preauth/submit` wf 19 (PMJAY) or `v1/communication/on_request` (generic) | 21 or 23 | new (PMJAY) or the request's (generic) | +| 5b | Enhancement | `v1/preauth/submit` wf 13, the whole pre-auth again with the added line | 20 then 22, 231 or 241 (the SHA sandbox has also answered with 21) | new | +| 5c | Enhancement query answer | `v1/preauth/submit` wf 131 | 22 or 231 | new | +| 5d | Cancel | `v1/task/submit` wf PC01 | `task/on_submit` PC02 | new | +| 5e | Predetermination | `v1/preauth/submit`, `Claim.use = predetermination`, wf 12 | `on_submit` | new | +| 6 | Claim | `v1/claim/submit` wf 15, `Claim.use = claim`, under the pre-auth's number | 25 then 26, 27 or 291 | new | +| 6a | Claim query answer | `v1/claim/submit` wf 161 (PMJAY) or `v1/communication/on_request` (generic) | 26 or 291 | new (PMJAY) or the request's (generic) | +| 6b | Reprocess or release | `v1/task/submit` wf 36 | `task/on_submit` 37, then a fresh verdict on the claim's thread | new | +| 7 | Payment notice | the payer sends `v1/paymentnotice/request` wf 30 (31, 33) | you answer `v1/paymentnotice/on_request` wf 17 (PMJAY) or the notice's own id (generic) | the notice's | +| any | Status enquiry | `v1/task/submit`, Task code `status` | `task/on_submit` (generic); PMJAY refuses it | new | +| any | Communication | the payer sends `v1/communication/request` | you answer `v1/communication/on_request` | the request's | + +The payer's acknowledgement is `x-hcx-status: response.partial` and the decision is `response.complete`, on the same correlation id (`nhcx-package/docs/01-Overview/07-Payer Flexibility.md`, "Answer detail"). Read the acknowledgement as "the payer has it", never as a decision. Map `ClaimResponse.outcome` `queued`, or an adjudication reason `submitted`, to leg status `submitting` (`verdict_status`). + +## 2. Every workflow id + +The hospital's table. PMJAY and a generic payer differ in three rows: `claim_query_response`, `claim_resubmit` and `payment_ack`. + +| Kind | PMJAY | Generic | Path | Note | +| --- | --- | --- | --- | --- | +| `preauth` | `12` | `12` | `v1/preauth/submit` | A new pre-auth. Also a fresh request after a rejection: PMJAY refuses 121 there with PAYR-1214. | +| `preauth_resubmit` | `121` | `121` | `v1/preauth/submit` | Kept in the table. `preauth_send_kind` never picks it after a rejection. | +| `preauth_query_response` | `19` | `19` | `v1/preauth/submit` | The answer to a 24. A generic payer asks by communication instead, so this is a PMJAY leg. | +| `enhancement` | `13` | `13` | `v1/preauth/submit` | The whole pre-auth again under the parent's number, plus the added line. | +| `enhancement_resubmit` | `131` | `131` | `v1/preauth/submit` | The answer to a 241. | +| `cancel` | `PC01` | `PC01` | `v1/task/submit` | Task code `cancel`. The handbook's section 8.6 says 122 (`nhcx-package/docs/01-Overview/06-Workflow Codes.md`, "Reconciled Discrepancies and Authority Rules", takes PC01). If a payer insists on 122, override it per payer in configuration. | +| `claim` | `15` | `15` | `v1/claim/submit` | The final bill. | +| `claim_query_response` | `161` | `151` | `v1/claim/submit` | PMJAY refuses 151, 19 and 16 with PAYR-1321; 161 is taken. | +| `claim_resubmit` | none | `16` | `v1/claim/submit` | PMJAY has no claim resubmit. A decided claim goes back only as a reprocess. | +| `payment_ack` | `17` | none (echo the notice's own id) | `v1/paymentnotice/on_request` | `None` in the table means "echo". | +| `reprocess` | `36` | `36` | `v1/task/submit` | Task code `reprocess`; acknowledged on 37. | +| `release` | `36` | `36` | `v1/task/submit` | Task code `release`, reason `partialpayment`, an `amount` input. | +| status enquiry | the leg's correlation id, fallback `13` | same | `v1/task/submit` | The fallback id is `13`. The NHCX sandbox refuses `v1/status` with NHCX-1012. | +| coverage, plan, auth requirements | your case number | your case number | see section 1 | The sheet lists no code. Send the episode's case number. | + +The payer's ids you must branch on (`nhcx-package/workflow.yaml`, `nhcx-package/docs/01-Overview/06-Workflow Codes.md`), with what the sandbox actually sent: + +| Id | Meaning | Status word | +| --- | --- | --- | +| `20` | Pre-auth or enhancement received | `response.partial` | +| `21` | Pre-auth approved | `response.complete` | +| `22` | Enhancement approved. A generic payer sends 22. The SHA sandbox has answered an enhancement with 21, and `nhcx-package/fhir/C5/C5-enhancement-approved-wf22-pmjay.json` is an SHA answer on 22. Accept both. | `response.complete` | +| `23` | Pre-auth rejected | `response.complete` | +| `231` | Enhancement denied | `response.complete` | +| `24` | Pre-auth queried | the sheet says `request.initiated`; the SHA sent `response.complete` | +| `241` | Enhancement queried | as 24 | +| `25` | Claim received | `response.partial` | +| `26` | Claim approved | `response.complete` | +| `27` | Claim queried | as 24 | +| `28`, `29` | Claim in process, forwarded | `response.partial` | +| `291` | Claim rejected | `response.complete` | +| `251`, `252`, `253`, `254` | Reprocess received, approved, rejected, queried | listed; both live payers answer a 36 with 37 instead | +| `37` | Arbitration acknowledged (the reprocess taken) | `response.complete` (the SHA sent `response.partial`) | +| `PC02` | Cancellation done | `response.complete` | +| `30`, `31`, `33` | Payment initiated, processed, settled with UTR | `request.initiated`, new thread | +| `5` | The SHA's coverage eligibility and plan answers | `response.complete` (`nhcx-package/fhir/index.yaml` gives 5 for `C3/C3-response-pmjay.json` and `C4/C4-response-pmjay.json`) | +| `N02` | Notification to a provider (a PMJAY CommunicationRequest) | `request.initiated` | + +Other codes exist (10, 11, 14, 141, 18, 45 to 47, 181, 491, 34, 35, 38, 39, G11 to G13, RP1 to RP3, DC01, DC02, N01, N03, N04, the R-series). A hospital build sends none of them. See `nhcx-package/docs/01-Overview/06-Workflow Codes.md` for the full sheet and the seven codes the handbook and the sheet publish differently. + +## 3. Two kinds of payer + +Read `nhcx-package/docs/01-Overview/07-Payer Flexibility.md` in full. A generic payer is any payer on the exchange, IRDAI-regulated insurers and TPAs included (`nhcx-package/fhir/README.md`). The rule, as coded: + +| | PMJAY (`query_mode: resubmit`) | Generic (`query_mode: communication`) | +| --- | --- | --- | +| The query arrives as | a `ClaimResponse` on the case's own thread, `outcome: partial`, item status `Queried`, wf 24, 241 or 27 | a `CommunicationRequest` TaskBundle on `v1/communication/request`, on a new thread, wf 24, 241 or 27 | +| The answer | the whole bundle again on `v1/preauth/submit` or `v1/claim/submit`, wf 19, 131 or 161, a new correlation id, the reply text on the `NMI`/`CQD` supportingInfo entry | a Communication TaskBundle on `v1/communication/on_request`, the request's correlation id and workflow id echoed | +| A `CommunicationRequest` from this payer | always a notification: acknowledge and leave the case alone | classified (below) | + +Where the payer's case number arrives. The package files are under `nhcx-package/fhir/`; the rule is in `07-Payer Flexibility.md`, "When the case number arrives". + +| Answer | PMJAY | Generic | +| --- | --- | --- | +| 20 on a fresh pre-auth | The package says none, and `C5/C5-received-wf20-pmjay.json` carries none. A live SHA 20 has also carried the path form, `PMJAY/HP/S/2024/R2/`. Handle both. | present (`C5/C5-received-wf20.json`) | +| 20 on an enhancement | none; keep the parent's | present | +| 21, 23, 24 | the bare number (`C5/C5-approved-wf21-pmjay.json`, `C5/C5-rejected-wf23-pmjay.json`, `C5/C5-queried-wf24.json`) | present (`C5/C5-approved-wf21.json`, `C5/C5-rejected-wf23.json`) | +| 25 | the path form (`C7/C7-received-wf25-pmjay.json`) | present (`C7/C7-received-wf25.json`) | +| 26, 27, 291, PC02, 37 | none | none | + +So the brief's rule holds with care. A generic payer's `response.partial` acknowledgement carries the payer's case number. PMJAY's 25 carries it; its 20 may not. Read `ClaimResponse.preAuthRef` on every answer. Keep a value and never overwrite it with an empty one (`apply_preauth`). The bare number is what the payer service desk wants; the path form ends in it. + +`query_mode` lives on the payer adapter. Choose the adapter by the payer's participant code through configuration: `1518@hcx` is PMJAY, and an unmapped code is generic. + +### The classification rule + +`classify_communication(adapter, reason, intent)` applies these, in order: + +1. If the payer's `query_mode` is `resubmit`: notification. +2. Else if `Task.intent` is `proposal`: notification. If `order`: query. +3. Else look at `Task.reasonCode`: absent, `additionalinfo`, `questionnaire` or `query` is a query; anything else (`tatquery`, `grievance`, `walletupdate`, `policychange`, `claimarbitration`) is a notification. Fold `claimArbitartion` into `claimarbitration`. +4. A bare `Communication` with no `CommunicationRequest` is a note: recorded, shown, never acted on. + +Acknowledge a notification at once. Send the payer's own bundle back with `Task.status` flipped to `completed`, the reason echoed and the provider Organization first. File a query open for the desk, and answer it later with the TaskBundle reply (see `fhir-knowledge.md`). The reply names the request in `Communication.basedOn`, never `inResponseTo`. + +The live shapes. A generic payer's query (`nhcx-package/fhir/C6/C6-preauth-query-wf24.json`) carries a Task `poll`, `requested`, `intent order`, reason `additionalinfo`, and a CommunicationRequest with one `contentString` per ask and `basedOn` the Claim. PMJAY's notification (`nhcx-package/fhir/C6/C6-notification-wfN02.json`) carries a Task `poll`, `completed`, `intent proposal`, reason `information` under the HL7 communication-category system. + +## 4. Stage, sub-stage, next actions + +Stamp two words onto the episode after every leg write (`stamp_case`), and compute a next-action list from them. Copy the vocabulary; it is what a desk needs to see. + +Stages: `eligibility`, `preauth`, `enhancement`, `claim`, `payment`. + +Sub-stages: `draft`, `checking`, `eligible`, `not-eligible`, `requested`, `resubmitted`, `answered`, `queried`, `approved`, `partial`, `rejected`, `cancelling`, `cancelled`, `refused`, `noticed`, `paid`. + +How a send kind maps to a sub-stage: `preauth`, `claim`, `enhancement` set `requested`; `*_resubmit` sets `resubmitted`; `*_query_response` and `enhancement_resubmit` set `answered`. `requested`, `answered` and `resubmitted` mean "with the payer". + +Derivation (`case_stage`): a payment notice wins, then the filed claim, then the pre-auth (stage `enhancement` if the last submission kind was an enhancement), then a saved draft, then the eligibility status. An open communication query on a leg that is with the payer flips the sub-stage to `queried`, because a generic payer's query never touches the leg row. + +Next actions (`next_actions`) are `{label, tab, tone}`; the first is what the case waits for. Rules worth copying: + +- An unanswered query always leads with "Answer the payer (n)". +- The leg's own reply box is offered only for a `resubmit` payer. A `communication` payer's desk is sent to the communication tab. +- A claim refused at the door offers "send again" while `claim_send_kind` still yields a kind, else "Ask for a reprocess". +- After a rejection the pre-auth offers a fresh 12, not 121. + +## 5. Rules the exchange enforces that no document states + +Each was found live on the sandbox. + +- Acknowledge or lose the thread. NHCX redelivers an unanswered submission, then drops it and retires the correlation id; a verdict sent later is refused with NHCX-1010. Both live payers answer twice on one correlation: `outcome: queued` first, the decision after. Your reader must not close a thread on the first reply. +- One message is taken once. The SHA redelivers the same `api_call_id` two or three times, about a minute apart, and a transport can fan one delivery out to several receivers (nhcx-adapter's `callback.also`). Dedupe on `x-hcx-api_call_id`. +- One live pre-auth per beneficiary per hospital (PAYR-1238). Clear it with PC01 or a rejection (`nhcx-package/docs/03-Building a Provider/11-PMJAY Sandbox Run.md`, "PAYR-1238 An active preauthorisation exists"). Sweep live pre-auths before a test run. +- One request at a time per case (PAYR-1322, "Active instance found"). Wait about 30 seconds after a decision before the next leg. When a refusal says "Active instance", wait and resend, up to three times. +- One plan per facility and policy. Key it on policy code, provider id and payer. Copy the held master onto a new episode instead of asking again (`reuse_plan`). A PMJAY master runs to tens of megabytes; one fetched live was 56 MB. +- Never drop a document. A file nobody asked for by name goes under `ODN`, "other document". A file attached against a requirement carries that requirement's code (`attach_required_document`). Take the code list from the plan, not from a constant. +- Ask the auth-requirements check, never await it (`ensure_auth_requirements`). Fingerprint the quoted set (`procedure_set`) so an unchanged set is not asked twice. Send the quantity as a whole number. +- Tiers are modifiers, not lines. A ward or ICU tier rides on `Claim.item.modifier` under its procedure, and that item's `net` carries both. +- The claim goes under the pre-auth's number (ERR-PYR-CLM-007), and PMJAY bills the package alone at the whole amount (`11-PMJAY Sandbox Run.md`, "ERR-PYR-CLM-007" and "What the package master decides"). +- Answers to a PMJAY query go on a new correlation id (`07-Payer Flexibility.md`, "On the claim thread"). A same-thread answer is swallowed: no acknowledgement, no refusal, and the desk dies on the old id. +- Cancel retires the number. Give the episode a fresh claim number after an accepted PC01, and keep the withdrawn one on the leg. +- A send refused at the door keeps the case on the thread the payer last answered. An enhancement refused at the door leaves the pre-auth approved. + +## 6. The use-case catalogue + +Codes and titles are quoted from `nhcx-package/usecases.yaml`, rendered as `nhcx-package/docs/01-Overview/05-NHCX Use Cases.md`. "Proves" is what a test run must show for each one. "Package file" is the provider bundle the package holds for it, under `nhcx-package/fhir/`. + +### A: shared + +| Code | Title | What it proves | +| --- | --- | --- | +| A1 | Get participant list | You can find the payer's code in the registry (the participant service's `fetch/participants/list`). | +| A2 | Get policy | You can find a beneficiary's policy and the processor code that becomes `x-hcx-recipient_code` (the participant service's `participant/get/policies`). | +| A3 | Get public key | The transport fetches the recipient's certificate (`fetch/certs`) and caches it. | +| A4 | Get auth token | The transport holds an ABDM session token (the gateway's sessions call) and refreshes it. | +| A5 | Get status | A status Task on `v1/task/submit` gets a Task back (generic), or a PAYR-1018 then PAYR-1008 refusal (PMJAY). The package holds no bundle for A5 (`nhcx-package/fhir/README.md`). | +| A6 | Receive errors | Your callback accepts a `ProtocolResponse` on any path and answers 2xx. | + +### B: hospital on the generic network + +| Code | Title | Workflow | Proves | Package file | +| --- | --- | --- | --- | --- | +| B1 | Check coverage eligibility | none | The check goes out; `inforce` and the wallet come back. | `B1/B1-check.json` | +| B2 | Request insurance plan | none | The package master lands and is stored once per policy. | `B2/B2-request.json` | +| B3 | Submit pre-authorisation | 12, 13 | Sent, acknowledged on 20, decided on 21 or 23; an enhancement on 13 decided on 22. | `B3/B3-request.json`, `B3/B3-enhancement.json` | +| B4 | Respond to a communication | 24, 27 echoed | A CommunicationRequest is classified and the TaskBundle reply goes on the request's thread. | `B4/B4-preauth-query-answer.json`, `B4/B4-claim-query-answer.json` | +| B5 | Submit claim | 15 | The claim under the pre-auth's number, acknowledged 25, decided 26 or 291. | `B5/B5-request.json` | +| B6 | Search claims | none | Not built by these skills. | `B6/claim-search.json` (example) | +| B7 | Acknowledge payment notice | 30 echoed | The notice is filed by claim number, deduped by correlation id, acknowledged on `on_request`. | `B7/B7-acknowledgement.json` | +| B8 | Reprocess or cancel | 36, PC01 | A decided claim is reopened (37 then a new verdict); a live pre-auth is withdrawn (PC02). | `B8/B8-reprocess.json`, `B8/B8-cancel.json` | +| B9 | Submit predetermination | 12 | A quote comes back as a ClaimResponse; nothing else changes. | `B9/predetermination-request.json` (example); the answer is `C11/predetermination-response.json` | + +### C: payer answering (for reference; you build the reader, not the sender) + +C3 coverage answer, C4 plan answer, C5 pre-auth answers (20, 21, 22, 23, 24, 231, 241), C6 communication (24, 241, 27, N02), C7 claim answers (25, 26, 27, 28, 29, 291), C9 payment notice (30, 31, 33), C10 Task answers (PC02, 37, 251 to 254), C11 predetermination. Reader inputs: `nhcx-package/fhir/C3` to `nhcx-package/fhir/C11`. The files ending `-pmjay` are the SHA's own; the rest are the generic payer's. `nhcx-package/fhir/index.yaml` gives each file's scheme, workflow id and origin. The PMJAY captures have the beneficiary's identifiers replaced. + +### D: hospital on PMJAY + +| Code | Title | Workflow | Proves | Package file | +| --- | --- | --- | --- | --- | +| D1 | Fetch the insurance plan | none | The scheme's master, both `coverage[]` and `specificCost[]`, nested document requirements, questionnaires. | `D1/D1-request.json` | +| D2 | Authenticate the beneficiary | not NHCX | Biometric token or the consent questionnaire fallback. | none | +| D3 | Check coverage eligibility | none | The wallet answer on wf 5. | `D3/D3-check.json` | +| D4 | Submit pre-authorisation | 12 | Element ids, HPIN, consent QuestionnaireResponse, documents from the master; acknowledged 20, decided 21 or 23 with `preAuthRef`. | `D4/D4-request.json` | +| D5 | Resubmit pre-authorisation | 121 | Not reachable on the sandbox after a rejection (PAYR-1214); send a fresh 12. | none | +| D6 | Raise an enhancement | 13, 131 | A second package (medical, not conservative: PAYR-1245) under the parent's number; a 241 answered on 131. | `D6/D6-enhancement.json`, `D6/D6-enhancement-query-answer.json` | +| D7 | Answer a pre-authorisation query | 19 | The 24 answered as a fresh submit with `CQD` reply text, new correlation id, then 21. | `D7/D7-query-answer.json` | +| D8 | Cancel pre-authorisation | PC01 | Task `cancel` with `claimNumber` and `intimationNumber`; PC02 back. | `D8/D8-cancel.json` | +| D9 | Submit claim | 15 | Under the pre-auth's number, the package alone, discharge scalars, Discharge Consent answered, PDF documents; 25 then 26. | `D9/D9-request.json` | +| D10 | Answer a claim query | 161 | The 27 answered on 161 with a written reply; the sandbox approves at zero. | `D10/D10-query-answer.json` | +| D11 | Reprocess a rejected claim | 36 | Task `reprocess`, reason `claimrejected`, second input spelled `intimationNumber` on every Task (a reprocess under any other spelling is refused PAYR-1008). The SHA answers 37, "Arbitration claim submission process completed successfully", and reopens the case; a generic payer answers 37 too. | `D11/D11-reprocess.json` | +| D12 | Claim a shortfall | 36 | Task `reprocess` with `partialpayment` after a settled payment. Out of reach on the sandbox: its finance side issues the notice on its own schedule, and the combination is refused before notice 33 is acknowledged (`11-PMJAY Sandbox Run.md`, "What the sandbox will not take"). | none | +| D13 | Acknowledge the payment notice | 17 | Notice 30 filed and acknowledged on `on_request` with 17. | `D13/D13-acknowledgement.json` | + +Discharge variants the D9 claim must cover, each proven on the sandbox: normal after surgery; LAMA and DAMA before, during and after surgery; death before, during and after surgery. Before or during surgery, LAMA and DAMA collapse the claim to one `LM100` line; a death carries `ONS`/`DTM`. `nhcx-package/docs/03-Building a Provider/08-PMJAY Provider.md` states the LAMA and DAMA rule. + +## 7. What each payer sends back, in order + +A pre-authorisation on the SHA sandbox: 20 (`queued`, `response.partial`, `ClaimResponse.type` present only here, as in `nhcx-package/fhir/C5/C5-received-wf20-pmjay.json`), then 24 (query) or 21 or 23. A claim: 25, then 27 or 26 or 291. A cancel: PC02 as a Task `completed`, code `approve`, `output[0]` an `include` reference to a ClaimResponse whose adjudication reason is `cancelled` (`C10/C10-cancelled-wfPC02-pmjay.json`). A reprocess: 37 as a Task `accepted` with a `queued` ClaimResponse (`C10/C10-arbitration-wf37-pmjay.json`), then 26 or 291 on the claim's thread. A payment: 30 on a new thread with a Task `deliver`, a `PaymentNotice` and a `PaymentReconciliation` (`C9/payment-notice.json`). + +A generic payer sends the same ids with the generic differences: 22 for an enhancement, `preAuthRef` on every acknowledgement and every pre-auth decision, queries as CommunicationRequests, `response.complete` on 37. Its files are the ones without `-pmjay` under `nhcx-package/fhir/C5`, `C6`, `C7`, `C9` and `C10`. diff --git a/plugins/nhcx/skills/nhcx-coverage/references/material.md b/plugins/nhcx/skills/nhcx-coverage/references/material.md new file mode 100644 index 000000000..d8882931d --- /dev/null +++ b/plugins/nhcx/skills/nhcx-coverage/references/material.md @@ -0,0 +1,120 @@ +# Material: where the pins, fixtures and docs live + +The stage and module files cite pins, payer fixtures and chapters. All of them come from one source, the NHCX package. This file says how to get it, what it holds, and which package file each citation means. + +## The package + +| Source | Has | Get it | +| --- | --- | --- | +| The NHCX package (`nhcx-package/`) | The docs, every API as a request, the FHIR bundles (the fifteen hospital pins, the payer answers, the live PMJAY captures with identifiers replaced), the field mappings per use case, `workflow.yaml`, `usecases.yaml`, `nhcx-error.yaml`, `baseurl.yaml`, a `MANIFEST` with a sha256 per file | `scripts/fetch-package.sh`, or by hand (below) | +| nhcx-adapter (optional: only when the user asks for it) | The binary, `config.sample.json`, `serve.sh`, `README.md` | The latest release of https://github.com/nha-in/nhcx-adapter, downloaded only when the user chose it (`references/transport-knowledge.md` section 5). Its contract is in `references/api-knowledge.md`. | + +By default `scripts/fetch-package.sh` takes the build attached to the latest GitHub release of `nha-in/nhcx-package`. It checks the download against the sha256 the release records. To use a different build, pass a link or a local path: `scripts/fetch-package.sh `. + +By hand: download the `nhcx-package-v.zip` asset from https://github.com/nha-in/nhcx-package/releases/latest. Unzip it beside `nhcx-build/`. It unpacks to `nhcx-package/`. + +Where the web is off, copy the package in. Do not try to fetch it. + +After unpacking, check it. `nhcx-package/MANIFEST` names the version and lists every file with its size and sha256. Verify at least the pins you will be held to. + +What the package holds: + +| Path | What it is | +| --- | --- | +| `nhcx-package/fhir/B1` to `B9` | Hospital bundles. Lower-case files (`preauth-request.json`) are the pins, written to the specification with placeholders. Capitalised files (`B3-request.json`) are live captures. | +| `nhcx-package/fhir/C3` to `C11` | Payer answers. A generic file and, where one exists, its `-pmjay` twin. | +| `nhcx-package/fhir/D1` to `D13` | Live PMJAY hospital captures, identifiers replaced | +| `nhcx-package/fhir/index.yaml` | The catalogue: for each file its direction, side, scheme (`generic` or `pmjay`), workflow id, focal resource, origin (`wire` or `example`) | +| `nhcx-package/docs/` | The chapters, `01-Overview` to `07-Go Live` | +| `nhcx-package/mappings/.yaml` | Field mappings per bundle; `A1.yaml` is the master dictionary | +| `nhcx-package/apis/` | Every API as a request (a Bruno collection) | +| `nhcx-package/workflow.yaml`, `usecases.yaml`, `nhcx-error.yaml`, `baseurl.yaml` | Workflow ids, use cases, error codes, base URLs | +| `nhcx-package/MANIFEST` | Version, and a size and sha256 per file | + +## The pin map + +Every hospital-side pin, and its file in the package. The fifteen hospital-built pins are the bytes a build is held to (canonical JSON). The last row is a payer's message, the reader's input. + +| Pin | Package | Module | +| --- | --- | --- | +| `coverage/discovery` | `nhcx-package/fhir/B1/discovery.json` | 7.4 | +| `coverage/validation` | `nhcx-package/fhir/B1/validation.json` | 7.4 | +| `coverage/benefits` | `nhcx-package/fhir/B1/benefits.json` | 7.4 | +| `coverage/authrequirements` | `nhcx-package/fhir/B1/auth-requirements.json` | 7.6 | +| `insurance` | `nhcx-package/fhir/B2/insurance-plan-request.json` | 7.5 | +| `preauth/request` | `nhcx-package/fhir/B3/preauth-request.json` | 7.7 | +| `preauth/enhancement` | `nhcx-package/fhir/B3/preauth-enhancement.json` | 7.7 | +| `preauth/queryupdate` | `nhcx-package/fhir/B3/preauth-queryupdate.json` | 7.7 | +| `preauth/cancel` | `nhcx-package/fhir/B3/preauth-cancel.json` | 7.9 | +| `claim/request` | `nhcx-package/fhir/B5/claim-request.json` | 7.7 | +| `claim/queryupdate` | `nhcx-package/fhir/B5/claim-queryupdate.json` | 7.7 | +| `claim/reprocess` | `nhcx-package/fhir/B5/claim-reprocess.json` | 7.9 | +| `claim/release` | `nhcx-package/fhir/B5/claim-release.json` | 7.9 | +| `communication/response` | `nhcx-package/fhir/B4/communication-response.json` | 7.10 | +| `payment/notice-ack` | `nhcx-package/fhir/B7/payment-notice-ack.json` | 7.10 | +| `communication/request` (a payer's message, the reader's input) | `nhcx-package/fhir/B4/communication-request.json`. It is the NRCeS IG's own example, with the Patient's name, identifier, birth date and phone replaced. | 7.10 | + +## The payer fixtures + +What the readers are fed. `generic` is what any payer on the exchange sends, IRDAI-regulated insurers and TPAs included. `pmjay` is the SHA's own message, a live capture with the beneficiary's identifiers replaced. Some identifiers are absent from the PMJAY files: `C5-received-wf20-pmjay.json` carries no `preAuthRef`. Read a value from the file before you assert it. Paths are under `nhcx-package/fhir/`. + +| Answer | Generic | PMJAY | Reader | +| --- | --- | --- | --- | +| Coverage, validation | `C3/validation-response.json` | `C3/coverage-eligibility.json` | 7.4 | +| Coverage, discovery | `C3/discovery-response.json` | none | 7.4 | +| Coverage, benefits | `C3/benefits-response.json` | `C3/C3-benefits-pmjay.json` | 7.4 | +| Coverage, auth-requirements | `C3/C3-response-generic.json` | `C3/C3-response-pmjay.json` (workflow 5) | 7.6 | +| Insurance plan | `C4/C4-response-generic.json` (coverage-based) | `C4/C4-response-pmjay.json` (package-based) | 7.5 | +| Pre-auth received 20 | `C5/C5-received-wf20.json` | `C5/C5-received-wf20-pmjay.json` | 7.8 | +| Pre-auth approved 21 | `C5/C5-approved-wf21.json` | `C5/C5-approved-wf21-pmjay.json` | 7.8 | +| Enhancement approved 22 | `C5/C5-enhancement-approved-wf22.json` | `C5/C5-enhancement-approved-wf22-pmjay.json` | 7.8 | +| Pre-auth rejected 23 | `C5/C5-rejected-wf23.json` | `C5/C5-rejected-wf23-pmjay.json` | 7.8 | +| Pre-auth queried 24 | `C5/preauth-queried.json` | `C5/C5-queried-wf24.json` | 7.8 | +| Claim received 25 | `C7/C7-received-wf25.json` | `C7/C7-received-wf25-pmjay.json` | 7.8 | +| Claim approved 26 | `C7/C7-approved-wf26.json` | `C7/C7-approved-wf26-pmjay.json`, `C7/C7-approved-deduction-wf26-pmjay.json` | 7.8 | +| Claim queried 27 | `C7/claim-queried.json` | `C7/C7-queried-wf27.json` | 7.8 | +| Claim rejected 291 | `C7/C7-rejected-wf291.json` | `C7/C7-rejected-wf291-pmjay.json` | 7.8 | +| Cancellation done PC02 | `C10/C10-cancelled-wfPC02.json` | `C10/C10-cancelled-wfPC02-pmjay.json` | 7.9 | +| Arbitration acknowledged 37 | `C10/C10-arbitration-wf37.json` | `C10/C10-arbitration-wf37-pmjay.json` | 7.9 | +| Query on the communication API, 24 and 27 | `C6/C6-preauth-query-wf24.json`, `C6/C6-claim-query-wf27.json` | none | 7.10 | +| Notification N02 | none | `C6/C6-notification-wfN02.json` | 7.10 | +| The query the reply answers | `B4/communication-request.json` (the IG's example) | none | 7.10 | +| Payment notice 30 | `C9/C9-notice-wf30.json` | `C9/payment-notice.json`, `C9/C9-notice-tds-wf30-pmjay.json` | 7.10 | +| Predetermination | `B9/predetermination-request.json` (the request), `C11/predetermination-response.json` | none | 7.7, 7.8 | + +`nhcx-package/fhir/index.yaml` catalogues every file: direction, side, scheme, workflow id, focal resource, origin (`wire` or `example`). An `example` file is placeholders written to the specification, not a payload. + +## The live hospital captures + +What a hospital actually sent, as the payer accepted it. The module files quote these shapes. Paths are under `nhcx-package/fhir/`. + +| Scheme | Files | +| --- | --- | +| PMJAY | `D1/D1-request.json` (plan), `D3/D3-check.json` (auth-requirements), `D4/D4-request.json` (pre-auth 12), `D6/D6-enhancement.json` (13), `D6/D6-enhancement-query-answer.json` (131), `D7/D7-query-answer.json` (19), `D8/D8-cancel.json` (PC01), `D9/D9-request.json` (claim 15), `D10/D10-query-answer.json` (161), `D11/D11-reprocess.json` (36), `D13/D13-acknowledgement.json` (17) | +| Generic | `B1/B1-check.json`, `B2/B2-request.json`, `B3/B3-request.json`, `B3/B3-enhancement.json`, `B4/B4-preauth-query-answer.json`, `B4/B4-claim-query-answer.json`, `B5/B5-request.json`, `B7/B7-acknowledgement.json`, `B8/B8-cancel.json`, `B8/B8-reprocess.json` | + +## The docs and the data files + +| Cited | Package | +| --- | --- | +| a chapter | `nhcx-package/docs/`, from `01-Overview` to `07-Go Live` | +| workflow ids (`references/flow-knowledge.md` section 2) | `nhcx-package/workflow.yaml`, the maintained source; rendered as `nhcx-package/docs/01-Overview/06-Workflow Codes.md` | +| use cases (`flow-knowledge.md` section 6) | `nhcx-package/usecases.yaml`; rendered as `nhcx-package/docs/01-Overview/05-NHCX Use Cases.md` | +| PAYR and ERR codes (`references/errors-and-debugging.md`) | `nhcx-package/nhcx-error.yaml` | +| field mappings per bundle (stage 4) | `nhcx-package/mappings/.yaml`; `A1.yaml` is the master dictionary | +| base URLs, sandbox and production | `nhcx-package/baseurl.yaml` | +| every API as a request | `nhcx-package/apis/` (a Bruno collection) | +| the bundle catalogue | `nhcx-package/fhir/index.yaml` | + +## What the package does not hold + +| Missing | Without it | +| --- | --- | +| A status-enquiry answer | None captured. The published status call carries no bundle either way (`nhcx-package/docs/05-FHIR Reference/18-Predetermination, Status and Search.md`). | +| A validator wrapper | Run the HL7 FHIR validator directly, as `references/fhir-knowledge.md` section 11 describes | +| Reference application source | The decisions are written into the module files and the references. Build from them. Record in `NOTES.md` where you would have wanted more. | +| End-to-end drivers and checkers | Write the stage 10 driver against your own build's state address | + +## Which is newer + +Where the references and the package disagree, the package is newer for the published facts (workflow ids, error text, base URLs). The references are newer for what was seen live (which ids a payer actually sent, which refusals mean what). Say which you followed in `NOTES.md`. diff --git a/plugins/nhcx/skills/nhcx-coverage/references/testing-knowledge.md b/plugins/nhcx/skills/nhcx-coverage/references/testing-knowledge.md new file mode 100644 index 000000000..4a24d7946 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-coverage/references/testing-knowledge.md @@ -0,0 +1,405 @@ +# Testing knowledge + +Sources: the NHCX package, fetched by `scripts/fetch-package.sh` into `nhcx-package/` beside `nhcx-build/`. That means the pins and payer fixtures under `nhcx-package/fhir` (catalogued in `nhcx-package/fhir/index.yaml`), the use-case catalogue `nhcx-package/usecases.yaml`, and the chapters named below. Also what live runs on the NHCX sandbox taught. + +## 1. The pyramid + +| Rung | What it proves | Needs | How | +| --- | --- | --- | --- | +| 1. Offline | Every builder equals its pin (`created` excepted); every reader settles the right state from a payer fixture; the state machine refuses what it should | nothing running; a throwaway database; the transport's send stubbed; `nhcx-package/` | one suite in one process (sections 2 to 4) | +| 2. Validator | Every built bundle validates against the NRCeS profiles with no error you cannot explain | Java, the HL7 FHIR validator, the bundles your tests wrote | section 5 | +| 3. A generic payer on the sandbox | Every leg over the real exchange with a payer whose desk you can drive; queries as CommunicationRequests; payment released | the transport on the sandbox (your app's own, or nhcx-adapter when the user chose it), a generic payer you can drive, the sandbox reaching your callback | section 6 | +| 4. Live PMJAY sandbox | `1518@hcx`: the scheme's own refusals and rules, decisions taken on the payer service desk | the sandbox, a real beneficiary, patience | section 6 | + +Climb in order. Rungs 1 and 2 need no service and no consent. Rungs 3 and 4 put traffic on the live NHCX sandbox, and only the user starts them. + +## 2. Writing rung 1 for a new HMIS + +Build one suite with this shape, whatever the language: + +- One process, one seeded database under a temporary path, sections in the order the episode runs. `section(name)` starts a group; `check(label, condition, detail)` records one assertion and never raises. The run exits non-zero at the end if anything failed. +- The transport's `send` is one function, and the test replaces it. Every send goes through it; the test assigns a stub that records the path, recipient, workflow id, correlation id and bundle, and returns `{"txn_id": ..., "correlation_id": ..., "api_call_id": ...}`. Restore the real one in `finally`. The receiving end is tested apart from the door: for your own transport, seal a payer bundle with a test key pair, POST it, and check the 202 receipt and the envelope the door receives. +- Call the callback handler directly with an envelope, not over HTTP: `receive({"jwe_headers": {...}, "fhir": bundle}, "", "", "fhir")`. The return value is one of `settled`, `unmatched`, `ignored`. Feed it the payer bundles under `nhcx-package/fhir/C3` to `nhcx-package/fhir/C11`, both the generic files and the `-pmjay` ones. The auth-requirements rulings are `C3/C3-response-generic.json` (one line, 10 supporting entries) and `C3/C3-response-pmjay.json` (two lines, 22 entries). +- The pin comparison builds each bundle from the pin's own data and compares canonical JSON (`json.dumps(bundle, sort_keys=True)`) against the pin. The data is all in `nhcx-package/fhir/B3/preauth-request.json`: member `MD5SLS4X5`, policy `PMJAY/HP/S/G`, provider `IN1910000151`, payer `1518@hcx`, package `MG0111A` with tier `STRAT006b`, the four `MAND` documents. Drop from both sides only `created`. The bundle id and every entry's `fullUrl` are fixed strings in the pins (`preauth-request-generic`, `https://nhcx.abdm.gov.in/preauth/request`), and the build produces them as they are. +- The single-item pins carry `factor 0.5`. That contradicts the rule their own enhancement follows (`nhcx-package/fhir/B3/preauth-enhancement.json`: the costlier line 1, the next 0.5), so compare those with `factor` removed. Compare the cancel and reprocess pins as they are; they carry `intimationNumber`, the spelling the build sends. +- Read every expected value in a reader check from the fixture you feed: `preAuthRef`, amounts, claim numbers, the UTR. The PMJAY captures have the beneficiary's identifiers replaced, and some fields are absent (`C5/C5-received-wf20-pmjay.json` carries no `preAuthRef`). A typed literal tests your memory, not the reader. +- Negative checks are half the value. A code the plan does not carry is refused. A send while the leg is with the payer is refused. A redelivered api call id is ignored. A claim refused at the door goes back to `queried` with the question restored. A cancel while the payer holds the case is accepted, and a cancel of a rejected one is refused. +- Put the regression sections near the bottom. Each is a defect that reached working code, named after what went wrong. Add one each time the sandbox teaches you something. + +In a language whose JSON encoder does not sort keys, decode into a map and encode again before comparing, so key order cannot fail a check. Where a byte comparison is too strict, as with the wire captures, compare element by element. + +## 3. The test-case matrix + +One row per hospital-side use case. Preconditions are the state the HMIS must be in. The action is what the desk or the test does. The expected wire is what must go out and come back; the per-case archive shows it (and the adapter's ledger, when it is the transport). The expected state is what the HMIS must hold afterwards. Codes are those of `nhcx-package/usecases.yaml`. Workflow ids are the PMJAY table unless the row says generic. + +| Use case | Preconditions | Action | Expected wire | Expected state | +| --- | --- | --- | --- | --- | +| A5 Get status (generic) | A pre-auth or claim leg with the payer; a generic payer | Ask status for the leg | `v1/task/submit`, Task `status` with `claimNumber`, workflow = the leg's correlation id; a Task back with `claimStatus` | An enquiry row `answered` with the status word; the leg unchanged | +| A5 Get status (PMJAY) | as above; PMJAY | Ask status | the same Task; a ProtocolResponse PAYR-1018 (no reason) or PAYR-1008 (with one) | The enquiry row `error` with the payer's words; nothing else changes | +| B1 Check coverage eligibility | A patient with a member id and policy from the policy search; facility HFR id and participant code set | Validate, then discover | `v1/coverageeligibility/check` twice, new correlation each, workflow = the case number; `on_check` with the request echoed and a `CoverageEligibilityResponse` | `claim.status eligible`, `inforce 1`, allowed and used amounts, the payer's Patient demographics | +| B2 Request insurance plan | Eligible; no master held for this facility and policy | Fetch the plan | `v1/insuranceplan/request`, a Task `poll` with `policyNumber` and `providerId`; `on_request` with the InsurancePlan and Questionnaires | `claim_plan.status ready`, benefits with rates, tiers, requirements, forms by url; a second episode on the same policy copies it without a send | +| B3 Submit pre-authorisation | Plan ready; lines quoted from it; dossier saved; admission linked; documents and forms for the pre-auth stage attached | Submit | `v1/coverageeligibility/check` purpose `auth-requirements` first (sent, not awaited), then `v1/preauth/submit` workflow 12 equal to the pin but for identifiers; `on_submit` 20 (`queued`, `response.partial`) then 21 | `claim_preauth.status submitting` after the 20 with `preauth_ref` kept, `approved` after the 21 with `approved_amount`; stage `preauth`, sub-stage `approved` | +| B3 Auth-requirements ruling | The check sent with the pre-auth; the payer answers it | Nothing; read on arrival | inbound `on_check`, a CoverageEligibilityResponse with purpose `auth-requirements`, one `insurance[0].item` per quoted line with `authorizationRequired`, `excluded` and `authorizationSupporting[]` (`C3/C3-response-generic.json`, `C3/C3-response-pmjay.json`) | each quoted line holds its ruling and what is due at pre-auth (a form always, a document only when its `Type` is `pre`); the pre-auth leg unchanged | +| B3 Enhancement | Approved; a line added since (`enhancement_lines` non-empty) | Submit again | `v1/preauth/submit` workflow 13, every line old and new, factors 1 and 0.5; 20 then 22 (generic); the SHA has answered 21 or 22 | `submission_kind enhancement`, `enhancement_no 1`, `preauth_ref` kept, then `approved`; stage `enhancement` | +| B4 Respond to a communication (generic) | A pre-auth or claim with the payer; the payer sends a CommunicationRequest on a new thread | The desk replies with text and a document | inbound `v1/communication/request` with Task `poll`, reason `additionalinfo`; outbound `v1/communication/on_request` with the request's correlation id and workflow id, a TaskBundle: Task `deliver`, Communication `basedOn` the request, the request echoed, the case entries | `claim_query` row `kind query`, `status open` then `answered` with `reply_json`; the leg row untouched; sub-stage `queried` while open | +| B4 Notification | Any leg; the payer sends a CommunicationRequest with intent `proposal` or reason `tatquery` | Nothing; it is acknowledged on arrival | outbound `v1/communication/on_request` at once, the payer's bundle with `Task.status completed`, provider Organization first | `claim_query` row `kind notification`, `status acknowledged`; the case's stage unchanged | +| B5 Submit claim | Approved pre-auth; discharge recorded with mode and stage; claim-stage documents and forms attached | Submit the claim | `v1/claim/submit` workflow 15, `use claim`, `preAuthRef`, the discharge scalars, the summary; 25 (`queued`) then 26 | `claim_submission.status submitting` then `approved` with amounts and item verdicts; stage `claim` | +| B7 Acknowledge payment notice (generic) | An approved claim; the payer's desk releases payment | Nothing; acknowledged on arrival | inbound `v1/paymentnotice/request` workflow 30 on a new thread; outbound `v1/paymentnotice/on_request` with the notice's correlation id and its own workflow id echoed, Task `status completed` with `paymentack` | `claim_payment` row with amount, UTR, `ack_status sent`; stage `payment`, sub-stage `paid`; a redelivery of the notice is `ignored` | +| B8 Cancel | A pre-auth `submitting`, `approved`, `partial` or `queried` | Cancel with a reason | `v1/task/submit` workflow PC01, Task `cancel`, inputs `claimNumber` and `intimationNumber`; `task/on_submit` PC02 with a ClaimResponse adjudicated `cancelled` | `claim_preauth.status cancelling` then `cancelled`; the episode gets a fresh claim number, the old one stays on `claim_ref`; a cancel of a `rejected` pre-auth is refused before sending | +| B8 Reprocess (generic) | A claim `rejected` or `partial` | Reprocess with reason `claimrejected` and a document | `v1/task/submit` workflow 36, Task `reprocess`, `intimationNumber`, `basedOn` CLN, `document` inputs, `for` the member; 37 (Task `accepted`, ClaimResponse `queued`); then 26 on the claim's thread | The enquiry row `answered` with `reopened`; `claim_submission` back to `submitting`, then `approved` | +| B9 Submit predetermination | Eligible; dossier saved | Ask for a quote | `v1/preauth/submit` workflow 12 with `use predetermination`; a ClaimResponse back | A `claim_predetermination` row `answered` with `allowed_amount`; the pre-auth row untouched | +| D1 Fetch the insurance plan | Eligible on PMJAY | Fetch | as B2; the answer on workflow 5, both `specificCost[]` and `coverage[]`, nested document requirements, `/questionnaire/` and `/stgquestionnaire/` forms | as B2, with `ProcedureType` conditions and the consent forms among the policy documents | +| D2 Authenticate the beneficiary | A policy from the BIS | Not NHCX; take the consent questionnaire path | none | The consent form answered for the pre-auth stage | +| D3 Check coverage eligibility | as B1 with member `MD5SLS4X5` style ids | Validate | as B1; the answer on workflow 5 with the wallet | as B1 | +| D4 Submit pre-authorisation | as B3, plus: HPIN on the doctor, `Item/n` ids, consent and STG forms answered, documents under the plan's `MAND` codes | Submit | `v1/preauth/submit` workflow 12; 20 with the path-form `preAuthRef` or none (flow-knowledge.md section 3), then 21 with the bare number | as B3; `preauth_ref` = the bare case number after the 21 | +| D5 Resubmit pre-authorisation | A pre-auth `rejected` | Submit again | a fresh 12, never 121 | a new `submitting` round; 121 would be PAYR-1214 | +| D6 Raise an enhancement | Approved; a medical package added (not conservative) | Submit | workflow 13; 20 without `preAuthRef` (keep the parent's); 241 arrives as a ClaimResponse `partial` on the case thread; the desk answers on 131 with a `CQD` reply; then approved | `enhancement_no 1`; `queried` then `answered` then `approved`; a second conservative package would be PAYR-1245 | +| D7 Answer a pre-authorisation query | The 24 arrived as a ClaimResponse `partial`, item status `Queried` | The desk writes a reply and submits again | `v1/preauth/submit` workflow 19, flow `queryupdate`, `NMI`/`CQD` carrying the words, a new correlation id; 20 then 21 | `submission_kind preauth_query_response`, `query_note` holding the payer's question, then `approved`; an empty reply is refused before sending | +| D8 Cancel pre-authorisation | as B8 on PMJAY | Cancel | as B8 | as B8 | +| D9 Submit claim | as B5, plus: the claim under the pre-auth's claim number, the package alone at the whole amount, Discharge Consent answered, PDF documents | Submit | `v1/claim/submit` workflow 15; 25 with `preAuthRef` as a path; then 26 | as B5; item verdicts with `eligible`, `status Approved` | +| D9 LAMA or DAMA before or during surgery | Discharge mode `lama` or `dama`, stage `Before Surgery` or `During Surgery` | Submit the claim | one item `LM100`, no tier, `DIS` = `LAMA` or `DAMA` with the stage | approved; the package would be PAYR-1362 | +| D9 Death | Discharge mode `death` with a date and time | Submit the claim | `ONS`/`DTM` and `DSDE` with the death instant, `DIS`/`DTM`, the death forms | approved; without `DTM` PAYR-1096 | +| D10 Answer a claim query | The 27 arrived as a ClaimResponse `partial` | The desk writes a reply and submits again | `v1/claim/submit` workflow 161, `NMI`/`CQD`, a new correlation id; 25 then 26 | `submission_kind claim_query_response`, then `approved`, possibly at zero | +| D11 Reprocess a rejected claim | A claim `rejected` | Reprocess | as B8 reprocess; on the sandbox a ProtocolResponse PAYR-1008 | the enquiry row `error` with the refusal; on a generic payer as B8 | +| D12 Claim a shortfall | A settled payment short of the approved amount | Release with `partialpayment` and the amount | `v1/task/submit` workflow 36, Task `release`, `valueMoney` | an enquiry row; out of reach on the sandbox | +| D13 Acknowledge the payment notice | An approved claim; the SHA's finance side sends 30 | Nothing; acknowledged on arrival | outbound `v1/paymentnotice/on_request` with workflow 17, the notice's correlation id, to the notice's sender | as B7 | + +Cross-cutting rows every matrix needs: + +| Case | Action | Expected | +| --- | --- | --- | +| Redelivery | Deliver the same envelope twice | the second returns `ignored`; state unchanged | +| Unmatched | Deliver an answer on an unknown correlation id | `unmatched`; archived under `unmatched`; nothing changes | +| Refusal at the door | Deliver a ProtocolResponse on a leg's thread | the leg `error` (or `queried` restored for a query answer, `approved` restored for an enhancement) with the payer's words; `correlation_id` restored to `thread_correlation_id` | +| Ledger reset (nhcx-adapter only) | The adapter answers 404 on `txn/related` | the leg `error` with "send again"; no spinning | +| Stage after every write | Any of the above | `stage` and `sub_stage` on the episode agree with `case_stage` recomputed from the legs | + +## 4. A skeleton offline test + +Replace the placeholders marked `` with your HMIS's own. Every pin and payer answer is loaded from the package. + +```python +#!/usr/bin/env python3 +"""Offline NHCX checks for : builders against the package pins, readers against the payer fixtures. + + NHCX_PACKAGE=nhcx-package python3 nhcx_offline_test.py # exit 0 when every check passes +""" +from __future__ import annotations + +import copy +import json +import os +import tempfile + +PKG = os.environ.get("NHCX_PACKAGE", "nhcx-package") +GENERIC_PAYER = "" + +os.environ[""] = os.path.join(tempfile.mkdtemp(prefix="nhcx-test-"), "t.db") + +import as nhcx # noqa: E402 the module that owns transport, build_*, receive + +failures = 0 +current = "general" +tally: dict[str, list[int]] = {} + + +def section(name: str) -> None: + global current + current = name + tally.setdefault(name, [0, 0]) + print(f"\n-- {name} " + "-" * max(3, 60 - len(name))) + + +def check(label: str, condition: bool, detail: str = "") -> None: + global failures + tally.setdefault(current, [0, 0]) + tally[current][0 if condition else 1] += 1 + if not condition: + failures += 1 + print(f"[{' ok ' if condition else ' FAIL '}] {label}" + (f" ({detail})" if detail else "")) + + +def pin(rel: str) -> dict: + """A bundle from the package by its path under fhir/, e.g. pin("B3/preauth-request.json").""" + with open(os.path.join(PKG, "fhir", rel), encoding="utf-8") as fh: + return json.load(fh) + + +def resource(bundle: dict, kind: str) -> dict: + return next(e["resource"] for e in bundle["entry"] if e["resource"]["resourceType"] == kind) + + +def task_input(task: dict, code: str): + return next(i.get("valueString") for i in task.get("input", []) if i["type"]["coding"][0]["code"] == code) + + +def total(claim_response: dict, category: str): + return next((t["amount"].get("value") for t in claim_response.get("total", []) + if t["category"]["coding"][0]["code"] == category), None) + + +def normalised(bundle: dict, factor: bool = True) -> dict: + """Drop only `created`, which a builder stamps when it sends; with factor=False, the Claim items' factor too.""" + out = copy.deepcopy(bundle) + + def walk(node): + if isinstance(node, dict): + node.pop("created", None) + for value in node.values(): + walk(value) + elif isinstance(node, list): + for value in node: + walk(value) + + walk(out) + if not factor: + for entry in out["entry"]: + if entry["resource"]["resourceType"] == "Claim": + for item in entry["resource"].get("item", []): + item.pop("factor", None) + return out + + +def canonical(bundle: dict, factor: bool = True) -> str: + return json.dumps(normalised(bundle, factor), sort_keys=True, ensure_ascii=False) + + +def same(label: str, ours: dict, want: dict, factor: bool = True) -> None: + a, b = canonical(ours, factor), canonical(want, factor) + check(label, a == b, "" if a == b else a[:300]) + + +# The package pins' own data: nhcx-package/fhir/B3/preauth-request.json and B1/*.json. +# Every builder is fed this and must produce the pin. +REF = { + "claim_no": "VB26AA2600001", "member_id": "MD5SLS4X5", "policy": "PMJAY/HP/S/G", + "provider": {"id": "IN1910000151", "name": "Facility Name"}, + "payer": {"code": "1518@hcx", "id": "1518", "name": "Insurance Company"}, + "patient": {"name": "Patient Name", "gender": "male", "dob": "2004-09-18", + "phone": "9999999999", "abha": "91718280654077", "member_id": "MD5SLS4X5"}, + "practitioner": {"name": "Practitioner Name", "hpr_id": "982374978-2343", "license_no": "MCI-12345", + "qualification": "Doctor of Medicine", "qualification_code": "MD", + "specialty": "General medicine", "specialty_code": "394802001"}, + "diagnosis": {"code": "A97", "display": "Dengue"}, + "item": {"code": "MG0111A", "display": "Pleural Effusion", "category_code": "MG", + "category_display": "General Medicine", "quantity": 1, "unit_price": 3300, "net": 3300, + "kind": "Procedure", "procedure_type": "conservative"}, + "tier": {"code": "STRAT006b", "display": "HDU", "kind": "Stratification", "parent_code": "MG0111A"}, + # The benefits and auth-requirements pins quote a different package. + "coverage_item": {"code": "MG004C", "display": "Dengue shock syndrome (Dengue fever)", + "category_code": "MG", "category_display": "General Medicine", "quantity": 1, + "tier": {"code": "STRAT006c", "display": "ICU - Without Ventilator"}}, +} + + +def main() -> int: + section("coverage eligibility: ours is the pin") + for purpose, rel in (("discovery", "B1/discovery.json"), ("validation", "B1/validation.json"), + ("benefits", "B1/benefits.json"), ("auth-requirements", "B1/auth-requirements.json")): + want = pin(rel) + ours = nhcx.build_coverage_request((purpose, want)) + same(f"coverage {purpose}", ours, want) + + section("insurance plan request: ours is the pin") + same("plan request", nhcx.build_plan_request(REF["policy"], REF["provider"]["id"]), + pin("B2/insurance-plan-request.json")) + + section("claim bundles: ours is the pin") + ref_pa = pin("B3/preauth-request.json") + ref_pdf = next(si["valueAttachment"]["data"] for si in resource(ref_pa, "Claim")["supportingInfo"] + if "valueAttachment" in si) + dossier = (REF, ref_pdf, ref_pa) + same("preauth request", nhcx.build_preauth_bundle(dossier, flow="request"), ref_pa, factor=False) + ref_qu = pin("B3/preauth-queryupdate.json") + reply = next(si["valueString"] for si in resource(ref_qu, "Claim")["supportingInfo"] + if si["category"]["coding"][0]["code"] == "NMI") + same("preauth query update", + nhcx.build_preauth_bundle(dossier, flow="queryupdate", query_response=reply), + ref_qu, factor=False) + ref_cancel = pin("B3/preauth-cancel.json") + cancel = resource(ref_cancel, "Task") + reason = cancel["reasonCode"]["coding"][0] + same("preauth cancel", + nhcx.build_cancel_task(task_input(cancel, "claimNumber"), (reason["code"], reason["display"]), + cancel["authoredOn"], REF["provider"], REF["payer"]), + ref_cancel) + ref_ack = pin("B7/payment-notice-ack.json") + ack = resource(ref_ack, "Task") + acked_claim = next(o["valueString"] for o in ack["output"] if "valueString" in o) + same("payment acknowledgement", + nhcx.build_payment_ack(acked_claim, ack["authoredOn"], REF["provider"], REF["payer"]), + ref_ack) + + section("the transport is the one door, and it can be stubbed") + posted: list[dict] = [] + real_send = nhcx.transport.send + + def submitted(payer: str, corr: str): + def _send(path, bundle, recipient, workflow_id, correlation_id=None, **kw): + posted.append({"path": path, "recipient": recipient, "workflow_id": workflow_id, + "correlation_id": correlation_id, "bundle": bundle}) + return {"txn_id": "01TEST", "correlation_id": corr, "api_call_id": "acid-" + corr} + + seeded = (payer) # eligible, plan ready, lines quoted, dossier saved + nhcx.transport.send = _send + try: + nhcx.submit_preauth(seeded) + finally: + nhcx.transport.send = real_send + return seeded + + episode = submitted(REF["payer"]["code"], "corr-preauth-1") + sent = posted[-1] + leg = nhcx.preauth(episode) + check("the pre-auth goes out on the preauth route under workflow 12", + sent["path"] == "v1/preauth/submit" and str(sent["workflow_id"]) == "12") + check("no correlation id is passed on a request", sent["correlation_id"] is None) + check("the leg waits with the transport's ids", + leg["status"] == "submitting" and leg["txn_id"] == "01TEST" and leg["correlation_id"] == "corr-preauth-1") + + section("readers: the payer answers settle the right state") + + def deliver(bundle: dict, acid: str, workflow: str, status: str = "response.complete", + corr: str = "corr-preauth-1", sender: str = "1518@hcx") -> str: + return nhcx.receive({"jwe_headers": {"x-hcx-correlation_id": corr, + "x-hcx-api_call_id": acid, + "x-hcx-sender_code": sender, + "x-hcx-status": status, "x-hcx-workflow_id": workflow}, + "fhir": bundle}, "preauth", "request", "fhir") + + received = pin("C5/C5-received-wf20-pmjay.json") + before = nhcx.preauth(episode)["preauth_ref"] + check("the PMJAY acknowledgement leaves the leg waiting", + deliver(received, "acid-20", "20", "response.partial") == "settled" + and nhcx.preauth(episode)["status"] == "submitting") + check("an acknowledgement without preAuthRef overwrites nothing", + not resource(received, "ClaimResponse").get("preAuthRef") + and nhcx.preauth(episode)["preauth_ref"] == before) + check("the same api call id delivered again is ignored", + deliver(received, "acid-20", "20", "response.partial") == "ignored") + approval = pin("C5/C5-approved-wf21-pmjay.json") + approved = resource(approval, "ClaimResponse") + check("the approval settles the leg on the same thread with the payer's case number", + deliver(approval, "acid-21", "21") == "settled" + and nhcx.preauth(episode)["status"] == "approved" + and nhcx.preauth(episode)["approved_amount"] == total(approved, "benefit") + and nhcx.preauth(episode)["preauth_ref"] == approved["preAuthRef"]) + stage, sub_stage = nhcx.case_stage(episode) + check("the episode is stamped preauth / approved", (stage, sub_stage) == ("preauth", "approved")) + + other = submitted(GENERIC_PAYER, "corr-preauth-2") + generic = pin("C5/C5-received-wf20.json") + check("a generic payer's acknowledgement carries the case number, and it is kept", + deliver(generic, "acid-20g", "20", "response.partial", corr="corr-preauth-2", + sender=GENERIC_PAYER) == "settled" + and nhcx.preauth(other)["status"] == "submitting" + and nhcx.preauth(other)["preauth_ref"] == resource(generic, "ClaimResponse")["preAuthRef"]) + + section("auth requirements: the payer's ruling is read line by line") + for rel in ("C3/C3-response-generic.json", "C3/C3-response-pmjay.json"): + ruling = pin(rel) + answer = [e["resource"] for e in ruling["entry"] + if e["resource"]["resourceType"] == "CoverageEligibilityResponse"][-1] + want = {i["productOrService"]["coding"][0]["code"]: i.get("authorizationRequired") + for i in answer["insurance"][0]["item"]} + got = nhcx.parse_auth_bundle(ruling) # {procedure code: {"required": bool, "supporting": [...]}} + check(f"{rel}: one ruling per quoted line, required as the payer says", + {code: line["required"] for code, line in got.items()} == want) + + section("the query loop") + queried = pin("C5/C5-queried-wf24.json") + check("a PMJAY query is the leg queried, with the payer's words and case number kept", + deliver(queried, "acid-24", "24") == "settled" + and nhcx.preauth(episode)["status"] == "queried" + and bool(nhcx.preauth(episode)["query_note"]) + and nhcx.preauth(episode)["preauth_ref"] == resource(queried, "ClaimResponse")["preAuthRef"]) + try: + nhcx.submit_preauth(episode, reply="") + check("an empty reply is refused before sending", False) + except ValueError: + check("an empty reply is refused before sending", True) + check("a generic payer's CommunicationRequest is classified a query", + nhcx.classify_communication(nhcx.GENERIC_ADAPTER, "additionalinfo", "order") == "query" + and nhcx.classify_communication(nhcx.PMJAY_ADAPTER, "additionalinfo", "order") == "notification" + and nhcx.classify_communication(nhcx.GENERIC_ADAPTER, "tatquery", None) == "notification") + + section("refusal at the door") + refusal = {"type": "ProtocolResponse", "x-hcx-status": "response.error", + "x-hcx-correlation_id": "corr-preauth-1", + "x-hcx-error_details": {"code": "PAYR-1238", "message": "Beneficiary is having an active preauthorization request"}} + (episode) + check("a ProtocolResponse settles the leg as refused with the payer's words", + nhcx.receive({"jwe_headers": {"x-hcx-correlation_id": "corr-preauth-1"}, "fhir": refusal}, + "preauth", "request", "protocol") == "settled" + and nhcx.preauth(episode)["status"] == "error" + and "PAYR-1238" in (nhcx.preauth(episode)["error_message"] or "")) + + section("tasks and payment") + cancelled = pin("C10/C10-cancelled-wfPC02-pmjay.json") + verdict = resource(cancelled, "ClaimResponse")["adjudication"][0]["reason"]["coding"][0]["code"] + check("PC02 is read as an accepted cancellation", + nhcx.parse_task_response(cancelled)["adjudication"] == verdict == "cancelled") + arbitration = pin("C10/C10-arbitration-wf37-pmjay.json") + check("37 is read as the reprocess taken", + nhcx.parse_task_response(arbitration)["task_status"] == resource(arbitration, "Task")["status"]) + paid = pin("C9/payment-notice.json") + pn, pr = resource(paid, "PaymentNotice"), resource(paid, "PaymentReconciliation") + notice = nhcx.parse_payment_notice(paid) + check("the payment notice names the claim, the amount and the UTR", + notice["claim_ref"] == pn["identifier"][0]["value"] + and notice["amount"] == pn["amount"]["value"] + and notice["utr"] == pr["paymentIdentifier"]["value"]) + + print("\n" + "=" * 64) + total_checks = sum(ok + bad for ok, bad in tally.values()) + for name, (ok, bad) in tally.items(): + print(f" {name:44s} {ok:3d} passed {bad:2d} failed [{'FAIL' if bad else 'ok'}]") + print("=" * 64) + if failures: + print(f"{failures} of {total_checks} check(s) FAILED") + return 1 + print(f"all {total_checks} checks passed") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) +``` + +What each placeholder must do: + +- `` names the variable your HMIS reads its database path from, so the suite runs on a throwaway file. +- `` is the module that owns `transport`, the builders and `receive`. +- `` is the participant code of a generic payer (``) that your configuration maps to `query_mode: communication`. +- `` returns the dict your coverage builder takes, filled from `REF`. The discovery pin carries policy `NONE`. The benefits and auth-requirements pins quote `REF["coverage_item"]`. Copy the Location and PractitionerRole from the pin it is given. +- `` returns whatever your claim builder takes. That is the claim number, the item, the tier, the program `AB-PMJAY` and factors `(1, 0.5, 0.25)`. Add the four `MAND` documents (`MAND0408`, `MAND0455`, `MAND0409`, `MAND0570`, each with the pin's PDF), and copy the stay and procedure dates from the pin it is given. +- `` takes a payer code and inserts an eligible episode for that payer, with the plan and lines seeded straight into the database. +- `` puts the pre-auth row back to `submitting` on `corr-preauth-1`. + +Run the suite from the folder that holds `nhcx-package/`, or set `NHCX_PACKAGE` to its path. + +## 5. Running rung 2 + +Have your tests and live runs write every bundle they build into one archive folder. The package ships no validator. Run the HL7 FHIR validator with the NRCeS IG `ndhm.in` on the whole folder in one call, with the command and flags in `references/fhir-knowledge.md` section 11. + +Read the results in three piles. "A code the profile does not define" is the scheme's vocabulary, and it is expected. "A required element is missing" and "an id or value the base rules refuse" are yours to fix. Warnings are advice; the sandbox accepted every pin as it stands. Skip the package master; it exhausts the validator's memory. A live PAYR-1004 or PAYR-1008 is the first reason to run this rung again (`nhcx-package/docs/06-Reference/02-Troubleshooting.md`). + +## 6. Running rungs 3 and 4 + +Only the user runs these. Prepare what they start and the driver, then stop and ask. + +What the user starts: + +1. The transport. Your own or the app's existing one needs a participant record carrying its certificate and a public HTTPS `endpoint_url` the exchange can reach (`references/transport-knowledge.md` section 3). nhcx-adapter, only when the user chose it, comes from its release: `config.sample.json` filled in, started with `serve.sh`. +2. Your HMIS, reachable by the exchange through that transport. +3. For rung 3, a generic payer on the sandbox whose desk you can drive (``), mapped to `query_mode: communication`. For rung 4, nothing more: the PMJAY payer is `1518@hcx`, and its decisions are taken on the payer service desk. + +The driver is a script or a browser spec. It walks the matrix rows through the app's JSON state address or its own screens, one episode per test, in series, with a 20 minute timeout per episode. + +- Before a PMJAY run, sweep every live pre-auth for the beneficiaries the tests use. Cancel it on PC01, or have the desk reject it. Otherwise the first pre-auth is refused with PAYR-1238. +- One request at a time per case. Wait about 30 seconds after a decision before the next leg. On "Active instance found" (PAYR-1322), wait and resend, up to three times. +- Wait on the case's own state, never on a fixed sleep or a checklist. +- Log every verdict the sandbox gives, with its workflow id and words, so a refusal is a finding, not a mystery. +- Expect about four minutes for the rung 3 matrix and about ten minutes per episode on PMJAY. + +After the run, package its bundles by correlation id from the per-case archive: every message sent and received, filed under its case. With nhcx-adapter as the transport, `nhcx-adapter ledger thread ` gives the same conversation, with bodies only while `ledger.storeBodies` is true (`nhcx-package/docs/02-Getting Started/10-NHCX Adapter.md`). File each thread under its use case. diff --git a/plugins/nhcx/skills/nhcx-coverage/references/transport-knowledge.md b/plugins/nhcx/skills/nhcx-coverage/references/transport-knowledge.md new file mode 100644 index 000000000..a0838b9cd --- /dev/null +++ b/plugins/nhcx/skills/nhcx-coverage/references/transport-knowledge.md @@ -0,0 +1,283 @@ +# Transport knowledge: how the build reaches NHCX + +Every NHCX message is a FHIR bundle sealed in a JWE, sent with an ABDM session token, and answered later on the sender's own callback. Something has to do that work. This file says which of three things does it for a build, what the rest of the build expects from it, and how to build it yourself. + +Section 3 is drawn from NHA's published chapters: `nhcx-package/docs/02-Getting Started` (01 to 09, and 11), `nhcx-package/docs/01-Overview/04-JWE, Status and Errors.md` and `nhcx-package/docs/06-Reference/03-Envelope Fields.md`. Open them when a detail matters. Where they and this summary differ, they win. + +## 1. Three transports + +| Transport | Choose it when | The build | +| --- | --- | --- | +| `existing` | Stage 0 found the app already speaks NHCX: its own client that seals and posts JWEs, a vendor gateway or middleware, an HCX SDK, callbacks under `/v1/...` | Keeps it. Wraps it behind the contract in section 2 and closes the gaps section 4 lists. Never replaces a working one. | +| `own` | The app has no NHCX integration, and the user has not asked for nhcx-adapter. This is the default. | Builds the protocol into the app (section 3): the session token, the key and certificate, the participant record, the recipient's certificate, sealing and sending, the callback and its receipt. | +| `adapter` | Only when the user asks for nhcx-adapter, by name or by asking for "the adapter" | Downloads it (section 5) and talks plain FHIR to it. `references/api-knowledge.md` is its contract. | + +The rules: + +- Never propose nhcx-adapter, and never choose it because it is easier. Use it only when the user has asked for it, and write their words into `nhcx-build/1-idea.md`. +- An app with an NHCX integration of its own keeps it, even when it is partial. Extend it; never put a second transport beside it. +- The choice is made once per app, at stage 1, from stage 0's verdict on `foundation.transport`. Every skill after the first reads it from `1-idea.md`. + +## 2. The contract every transport meets + +The rest of the build (modules 7.2 to 7.13) never sees the transport, only these functions: + +| Function | Takes | Gives | Notes | +| --- | --- | --- | --- | +| `send(path, bundle, recipient, workflow_id, correlation_id = null, ben_abha_id = null, claim_no, usecase)` | The NHCX path (`v1/preauth/submit`), the bundle, the recipient's participant code, the workflow id; a correlation id only when answering (the communication reply, the payment acknowledgement); the beneficiary's ABHA, else the episode's by `claim_no` | `{txn_id, correlation_id, api_call_id, raw}` | Raises `TransportError(code, message, protocol_response, retryable)` on a refusal. Archives the outbound message. Every leg stores the three ids. | +| The receiving end | A delivery from the exchange (`own`, `existing`) or from nhcx-adapter | Calls 7.3's `receive(envelope)` with `{meta: {path, payloadType, redelivery}, jwe_headers: {every x-hcx- field}, fhir: }`; `payloadType` is `fhir`, `protocol` or `error` | Answers the sender as its transport requires (section 3.9 for `own`). The door does the rest. | +| `policies(id_type, value)` | `AbhaNumber`, `MemberId` or `MobileNo`, and the value | The participant service's answer, raw | Module 7.4 normalises it (section 3.6). | +| `participants(role)` | `PAYER`, `PROVIDER` or `TPA` | The registry's list | Cached for the day. | +| `token()` | nothing | The ABDM session token | For calls the transport does not make itself, such as the PMJAY payer service. | +| `thread(correlation_id)`, `fetch_missed(txn_id)` | | The messages on one thread; a missed answer | Only nhcx-adapter keeps a ledger to answer these. With `own` and `existing`, `thread` reads the per-case archive and `fetch_missed` answers `unavailable`; a lost answer surfaces through `/v1/error` and the status exchange instead (section 3.10). | + +Two values every transport needs from the build, both from the policy lookup (section 3.6). The recipient is the policy's `processingid`, kept on the episode as `recipient_code`. The insurer is its `payerid`, kept as `payer_code`: it goes inside the bundle and chooses the payer adapter (module 7.11). And every message carries the beneficiary's ABHA number in `x-hcx-ben-abha-id`. + +A test replaces `send` with a stub of the same signature (stage 9). Nothing else in the build changes for a test. + +## 3. Building it yourself (`own`) + +Seven things, in this order (`01-The Base Framework.md`): a token, a key and certificate, a participant record, the payer and policy lookups, the recipient's certificate, sealing and sending, and the callback. The last two are the ones every message uses. + +### 3.1 Before you start + +| Need | Why | +| --- | --- | +| The facility's HFR id | The registry that vouches for a hospital | +| ABDM sandbox client id and secret, Milestone 1 completed | NHCX uses the same credentials; there is no separate login | +| A public HTTPS server in India with a domain name | The exchange calls your callback; it will not call an IP address or a port number | +| `openssl` where the private key will live | The key pair | +| A JOSE library | RSA-OAEP-256 with A256GCM: `jose` on Node, `jwcrypto` on Python, Nimbus on Java, `jose-jwt` on .NET | + +Ask the user for the credentials. Never write them, the token or the private key into code, a log or `nhcx-build/`. + +### 3.2 Addresses and headers + +From `nhcx-package/baseurl.yaml`: + +| Service | Sandbox | Production | +| --- | --- | --- | +| ABDM session token | `https://dev.abdm.gov.in/api/hiecm/gateway/v3/sessions` | `https://apis.abdm.gov.in` plus the same path; confirm it in the onboarding letter | +| NHCX exchange, every use-case call under `/v1` | `https://apisbx.abdm.gov.in/hcx` | Shared by NHA after sandbox exit | +| Participant service | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice` | `https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice` | + +Keep every address in configuration. Every call to the participant service and the use-case endpoints carries `Accept: application/json`, `Content-Type: application/json` and `bearer_auth: Bearer `. The header is `bearer_auth`, not `Authorization`; some NHA pages write `Authorization`, so send both with the same value. + +### 3.3 The session token + +`POST` to the sessions address with three headers, none optional: `REQUEST-ID` (a fresh UUID on every call), `TIMESTAMP` (UTC with milliseconds and a trailing `Z`, from the system clock) and `X-CM-ID` (`sbx` on the sandbox, `abdm` in production). The body is `{"clientId", "clientSecret", "grantType": "client_credentials"}`. The answer carries `accessToken` and `expiresIn`. + +- NHA's documents give its life as 300, 1200 and 6000 seconds. Rely on none: keep the token and when you got it, and fetch a new one when it is a few minutes old. +- On any `401`, get a new token and retry that call once. Never retry with the same token. +- Put `Bearer` and a space before the token. Without it, `401`. + +`03-Session Token.md` also shows the two timestamp shapes in ten languages: the gateway's UTC `...975Z`, the exchange's `+05:30`. + +### 3.4 Your key and certificate + +```bash +openssl genpkey -algorithm RSA -out private.key -pkeyopt rsa_keygen_bits:2048 +openssl req -new -key private.key -out request.csr +openssl x509 -req -in request.csr -signkey private.key -out certificate.crt -days 365 +base64 -w 0 certificate.crt > certificate.b64 # macOS: base64 -i certificate.crt -o certificate.b64 +``` + +`private.key` never leaves the server that receives callbacks. `certificate.b64` goes on the participant record as `encryption_cert`. Note the expiry: a lapsed certificate stops every sender. Replace it yearly (`04-Your Certificate.md`). + +### 3.5 The participant record + +On the sandbox, `POST /participant/create` with: + +| Field | Value | +| --- | --- | +| `linked_registry_codes` | `["10001"]` (HFR) | +| `registryid` | Your ABDM client id on the sandbox; the HFR id in production | +| `roles` | `["10001"]` (provider) | +| `participant_name`, `scheme_code`, `state`, `district`, `primaryEmail`, `phone`, `primaryMobile` | The facility's | +| `encryption_cert` | The base64 certificate | +| `endpoint_url` | The base of your callback server | + +The answer is your `participant_code`: the `x-hcx-sender_code` on everything you send. `participant/update` changes the certificate or the address. Production takes four steps with a passcode to the mobile on the HFR record (`v2/participant/create`, `validate`, `v2/participant/update`, `update/validate`), and `v2/update/cert` rotates only the certificate (`05-Creating and Updating a Participant.md`). + +The exchange appends the use-case path to `endpoint_url`: a pre-auth decision arrives at `/v1/preauth/on_submit`. Only the client id that created the record may change it; any other gets NHCX-1015. + +This is the user's onboarding, not the build's. The build writes the script or the settings screen; the user runs it with their credentials. Check it worked by fetching your own certificate back (section 3.7). + +### 3.6 The payer and the policy + +- Payers: `POST /fetch/participants/list` with `role` (`PAYER`, `PROVIDER`, `TPA`), `fromdate` and `todate` (`dd/MM/yyyy`), and optionally `entitytype` (`Gov`). There is no server-side search by name: fetch, filter locally, and cache for the day. +- Policies: `POST /participant/get/policies` with `identifiertype` and `identifiervalue`. Try `AbhaNumber` (no hyphens), then `MemberId`, then `MobileNo`, and stop at the first that returns a policy. Each policy carries `payerid`, `processingid`, `memberid`, `productid` and `productname`. The published answer is a sketch: read a real one before writing the parser, and keep it raw on the episode. +- Send to the processor. `processingid` is the envelope's recipient and whose certificate seals the message; `payerid` is the insurer named inside the bundle. They are the same when the insurer processes its own claims and differ when a TPA does. Addressing the `payerid` is the portal's seventh most common mistake. A policy with no `processingid` cannot be addressed: stop and say so (`06-Finding Participants and Policies.md`). + +### 3.7 The recipient's certificate + +`POST /fetch/certs` with `{"participantid": ""}`. The answer is PEM text: usually an X.509 certificate, sometimes a bare SPKI public key (anything under about 400 bytes). Load it as a certificate and take its key; if that fails, load it as a key. NHA does not publish the JSON envelope around it, so read one real answer first. Cache by participant code for 24 hours, and refresh early when the other side stops being able to open your messages (`07-Fetching a Recipient Certificate.md`). + +### 3.8 Sealing and sending + +The protected header (`08-Building and Sending a JWE.md`, `06-Reference/03-Envelope Fields.md`): + +| Field | Value | +| --- | --- | +| `alg`, `enc` | `RSA-OAEP-256`, `A256GCM`; not `RSA-OAEP` | +| `x-hcx-sender_code` | Your participant code | +| `x-hcx-recipient_code` | The policy's `processingid` on a request; the request's sender on an answer | +| `x-hcx-api_call_id` | A fresh UUID on every message, answers included | +| `x-hcx-request_id` | A UUID per request; optional, send it | +| `x-hcx-correlation_id` | On a request, this message's own `api_call_id`. On an answer, the request's `correlation_id`, so the two ids differ on an answer | +| `x-hcx-workflow_id` | The step code (`references/flow-knowledge.md` section 2). Optional in the specification, but payers key on it: send it wherever the sheet gives one | +| `x-hcx-timestamp` | ISO 8601 with `+05:30`, no milliseconds, from the system clock | +| `x-hcx-status` | `request.initiated` on a request; `response.complete` on an answer (an `on_` path) | +| `x-hcx-ben-abha-id` | The beneficiary's ABHA number without hyphens. Mandatory on every exchange | +| `x-hcx-use_case` | Optional: `New`, `Enhancement` or `Resubmit` on a pre-auth; `New` or `Resubmit` on a claim | + +Seal with the JOSE library: the bundle as plaintext, the recipient's public key, the header above as the protected header, compact serialisation (five parts, four dots). POST `{"payload": ""}` to `/v1/` with the headers of section 3.2. The sandbox collection also repeats the `x-hcx-` fields as HTTP headers; send them both ways. + +What comes back: + +| Answer | Means | The build | +| --- | --- | --- | +| `202` with a receipt (`protocol_status: request.queued`) | The envelope was valid and is queued. It is not the decision | Store `api_call_id` and `correlation_id`, and the archive id as `txn_id`; the leg waits | +| `400` | The envelope failed validation | Raise with the gateway's body; nothing went to the payer | +| `401` | The token expired, or `Bearer` is missing | New token, retry once | +| A connection dropped after the request was written | Unknown: it may have landed | Do not resend at once (`references/errors-and-debugging.md` section 7) | + +A correlation id that failed at the gateway is retired. The next attempt needs a fresh `api_call_id` and a fresh `correlation_id` (`01-Overview/04-JWE, Status and Errors.md`). + +### 3.9 Receiving + +Host these under `endpoint_url` (`09-Receiving a Callback.md`): `/v1/coverageeligibility/on_check`, `/v1/insuranceplan/on_request`, `/v1/preauth/on_submit`, `/v1/claim/on_submit`, `/v1/predetermination/on_submit`, `/v1/search/on_submit`, `/v1/communication/request`, `/v1/paymentnotice/request`, `/v1/task/on_submit`, `/v1/on_status` and `/v1/error`. Build one handler. The path gives the receipt's `entity_type`; the correlation id routes everything else (module 7.3). + +- The address: a domain over HTTPS with TLS 1.2 or newer, hosted in India, reachable from the exchange's outbound addresses `3.109.99.210`, `13.126.152.0` and `13.200.129.223`. +- The body: `{"type": "JWEPayload", "payload": ""}`; or, when the recipient refused your message, `{"type": "ProtocolResponse", "x-hcx-...": ..., "x-hcx-status": "response.error", "x-hcx-error_details": {code, message, trace}}` with the fields in the clear. `/v1/error` carries neither: it is a plain report of a request the exchange gave up on after five attempts. Store it whole and do not parse it against a fixed schema. +- Open a `JWEPayload` with your private key: the protected header comes out in the clear and the bundle is the plaintext. A failure to decrypt means the message was sealed for a certificate that is not the one on your participant record. +- Answer every delivery with `202` and the receipt within 30 seconds, `/v1/error` and unrecognised messages included. Not `200`, and not an empty body: + + ```json + {"timestamp": "dd/MM/yyyy HH:mm:ss:SSS", "api_call_id": "", "correlation_id": "", + "result": {"sender_code": "", "recipient_code": "", "entity_type": "preauth", "protocol_status": "request.queued"}, + "error": {"code": "", "message": ""}} + ``` + + `entity_type` is the path's second-to-last segment, or the last where that is `v1`, with `on_` stripped. +- Hand the door `{meta: {path, payloadType, redelivery}, jwe_headers, fhir}`: `payloadType` `fhir` with the bundle, `protocol` with the ProtocolResponse body as `fhir`, `error` with the `/v1/error` report. The door dedupes on `x-hcx-api_call_id`, archives, matches and applies, fast and with no outbound calls, so the receipt still goes inside the 30 seconds. +- The exchange signs its calls to you with a JWT (RS256; claims `jti`, `iss`, `sub`, `iat`, `exp`). No published source gives the NHCX public key or the header the token arrives in. Build the check with the key in configuration. While no key is configured, log that at every start, accept calls only from the three addresses above, and ask NHA for the key at onboarding. Never leave the check off silently. + +### 3.10 Status and the error endpoint + +- `/v1/status` asks the exchange what became of a message you sent. The payload is empty; `x-hcx-correlation_id` is that message's `api_call_id`. The answer arrives on `/v1/on_status` with `request.queued`, `request.dispatched` or `request.stopped` (redelivery exhausted; the correlation is retired). Call it when a case has been quiet longer than the payer's turnaround, never on a timer (`11-Status and Search.md`). `references/flow-knowledge.md` section 2 records what the sandbox did with it; keep the path configurable. This is not the claim's status Task of module 7.9. +- `/v1/error` is how you learn a request died. Without it a lost message is silent. + +With no ledger to poll, these two, the per-case archive and the receipts are what an `own` transport has. A leg with no answer stays waiting; it never turns into an error on a timer. + +### 3.11 Proving it + +The sandbox's dummy payer answers when you trigger it. Send it a bundle, then `POST https://apisbx.abdm.gov.in/pmjay/sbxhcx/dummyhcxpayer/process/request` with `{"action": "Approve" | "Reject" | "Query", "method": "Preauth" | "Claim", "correlationId": ""}`. Its answer reaching your `/v1/preauth/on_submit`, sealed or as a ProtocolResponse, proves the token, the participant record, the address, the sealing and the opening together (`09-Receiving a Callback.md`, "Closing the loop"). This is live traffic: stage 10, rung 3, started by the user. + +### 3.12 Pseudo code + +``` +settings.nhcx = {sessions, base, registry, cm_id, client_id, client_secret, # from configuration, never from code + private_key, signing_key} # signing_key empty until onboarding gives it + +function token(): + if cache.token and age(cache.at) < 240s: return cache.token + r = http_post(settings.nhcx.sessions, json = {clientId: settings.nhcx.client_id, clientSecret: settings.nhcx.client_secret, + grantType: "client_credentials"}, + headers = {"REQUEST-ID": uuid4(), "TIMESTAMP": utc_millis_z(), "X-CM-ID": settings.nhcx.cm_id}) + cache = {token: r.json().accessToken, at: now()} + return cache.token + +function authed_post(url, body, extra_headers = {}): + for attempt in (1, 2): + t = token() + r = http_post(url, json = body, timeout = 90, + headers = {"Accept": "application/json", "Content-Type": "application/json", + "bearer_auth": "Bearer " + t, "Authorization": "Bearer " + t} + extra_headers) + if r.status != 401: return r + cache.token = null # one retry, with a fresh token + return r + +function registry(path, body): return authed_post(settings.nhcx.registry + "/" + path, body) + +function recipient_key(code): # cached for 24 hours + if certs[code] and age(certs[code].at) < 24h: return certs[code].key + pem = pem_in(registry("fetch/certs", {participantid: code}).json()) # read one real answer first + key = try_certificate(pem).public_key() or load_public_key(pem) # X.509 first, bare SPKI second + certs[code] = {key, at: now()} + return key + +function send(path, bundle, recipient, workflow_id, correlation_id = null, ben_abha_id = null, claim_no = null, usecase = ""): + abha = digits(ben_abha_id or ben_abha(claim_no)) + if not recipient or not workflow_id or not abha: raise ValueError("recipient, workflow id and beneficiary ABHA are required") + answer = path.split("/")[-1].startswith("on_") + api_call_id = uuid4() + header = {"alg": "RSA-OAEP-256", "enc": "A256GCM", + "x-hcx-sender_code": with_hcx(settings.participant_code), "x-hcx-recipient_code": with_hcx(recipient), + "x-hcx-api_call_id": api_call_id, "x-hcx-request_id": uuid4(), + "x-hcx-correlation_id": correlation_id if answer else api_call_id, + "x-hcx-workflow_id": str(workflow_id), "x-hcx-timestamp": now_ist_seconds(), + "x-hcx-status": "response.complete" if answer else "request.initiated", + "x-hcx-ben-abha-id": abha} + jwe = jose_encrypt_compact(to_json(bundle), recipient_key(with_hcx(recipient)), protected = header) + r = authed_post(settings.nhcx.base + "/" + path, {"payload": jwe}, extra_headers = without(header, "alg", "enc")) + txn = archive.record(claim_no, usecase, "out", {path, header, bundle, status: r.status, response: r.text}) + if r.status >= 300: + raise TransportError(code = "GATEWAY_HTTP_" + r.status, message = r.text, retryable = r.status >= 500) + return {txn_id: txn, correlation_id: header["x-hcx-correlation_id"], api_call_id: api_call_id, raw: r.json()} + +route POST /v1/ # under endpoint_url; exempt from session auth and CSRF; the exchange's addresses only +function inbound(request, path): + verify_nhcx_jwt(request, settings.nhcx.signing_key) # when the key is configured; else logged at start, never silent + body = parse_json_or_null(request.body) + if path == "error": + env = {meta: {path: "v1/error", payloadType: "error"}, jwe_headers: {}, fhir: body} + elif body and body.type == "ProtocolResponse": + env = {meta: {path: "v1/" + path, payloadType: "protocol"}, jwe_headers: x_hcx_fields(body), fhir: body} + else: + try: header, plaintext = jose_decrypt_compact(body.payload, settings.nhcx.private_key) + except: archive.record(null, "undecryptable", "in", request.body); return 202, receipt({}, path, error = "DECRYPT_FAILED") + env = {meta: {path: "v1/" + path, payloadType: "fhir"}, jwe_headers: header, fhir: parse_json(plaintext)} + receive(env) # module 7.3: dedupe, archive, match, apply; fast, no sends + return 202, receipt(env.jwe_headers, path) # within 30 seconds + +function receipt(h, path, error = ""): + return {"timestamp": now_ist("dd/MM/yyyy HH:mm:ss:SSS"), + "api_call_id": h["x-hcx-api_call_id"], "correlation_id": h["x-hcx-correlation_id"], + "result": {"sender_code": h["x-hcx-sender_code"], "recipient_code": h["x-hcx-recipient_code"], + "entity_type": entity_type(path), "protocol_status": "request.queued"}, + "error": {"code": error, "message": ""}} + +function entity_type(path): # "v1/preauth/on_submit" -> "preauth"; "v1/on_status" -> "status" + parts = ("v1/" + path).split("/"); seg = parts[-2] if parts[-2] != "v1" else parts[-1] + return seg.removeprefix("on_") +``` + +## 4. Using an existing integration (`existing`) + +How stage 0 recognises one: `x-hcx-`, `JWEPayload`, `RSA-OAEP-256`, `A256GCM`, a JOSE library among the dependencies, `bearer_auth`, a sessions URL on the ABDM gateway, `participanthcxservice`, `fetch/certs`, `participant/get/policies`, routes ending in `on_submit`, `on_check` or `on_request`, a vendor's NHCX or HCX client library, a separate gateway service the app calls. + +What it must do, checked by running it offline with the network stubbed and a test key pair for the seal: + +| Contract item (section 2) | Look at | Common gap | +| --- | --- | --- | +| `send` emits the protected header of section 3.8 | What it seals or posts | No `x-hcx-ben-abha-id`; a request correlation id that is not its own `api_call_id`; UTC timestamps; `RSA-OAEP` | +| The recipient | Who it addresses | The `payerid` instead of the `processingid` | +| The three ids back to the caller | Its return value | Only a success flag; the ids stay inside it | +| Receiving: a `202` receipt within 30 seconds on every path, `/v1/error` included | Its callback handler | `200` or an empty body; no `/v1/error`; slow work before answering | +| Handing on the header and the bundle | What it gives the app | The bundle without the header; no ProtocolResponse path | +| Dedupe on `x-hcx-api_call_id` | Its store | None | +| A record of every message | Its logs | Bodies not kept | + +The build wraps it. 7.1's `send` calls the existing client and returns the three ids. The existing callback handler, after its receipt, calls 7.3's `receive` with the envelope of section 2. Each gap is closed in the existing code, in its style (stage 7, action `extend`). The existing transport is not rewritten, and no second one is added beside it. If it cannot be made to hand on the ids or the header, record `partial` and ask the user whether to extend it further or, with their agreement, build `own` in its place. + +## 5. nhcx-adapter, only when asked + +nhcx-adapter is NHA's optional single binary that does section 3 for you (`nhcx-package/docs/02-Getting Started/10-NHCX Adapter.md`, titled "Optional"). Use it only when the user has asked for it. Then: + +1. Get it, with the user's go-ahead, from https://github.com/nha-in/nhcx-adapter/releases (the latest). Each release carries one archive per platform, `nhcx-adapter___.tar.gz` (darwin, linux, windows, freebsd; amd64, arm64, 386), holding the binary, `config.sample.json`, `serve.sh`, `stop.sh`, `update.sh` and `README.md`. Put it in a folder of the user's, not in the skill. +2. Its contract is `references/api-knowledge.md`: configuration (section 2), routes (3), the outbound envelope and answer (4, 5), the delivery your HMIS receives (6), the ledger (7), the kit endpoints (8). +3. Onboarding is sections 3.1 to 3.5 again: credentials, a key, a participant record, a public address. The adapter can generate and register the key itself (`config init`, `cert generate`, its startup checks). +4. It does not queue or retry, does not build or validate bundles, and does not verify who sent an inbound message beyond decrypting it. Its `/internal/*` routes have no authentication: bind it to loopback. + +How it maps onto section 2: `send` POSTs `{jwe_headers, fhir}` to `/fhir/out/`; the receiving end is the HMIS route the adapter posts to (`api-knowledge.md` section 6); `policies` is `/internal/policies/search`; `thread` and `fetch_missed` are its ledger and `/internal/txn/*`. diff --git a/plugins/nhcx/skills/nhcx-coverage/scripts/fetch-package.sh b/plugins/nhcx/skills/nhcx-coverage/scripts/fetch-package.sh new file mode 100755 index 000000000..efbafa50b --- /dev/null +++ b/plugins/nhcx/skills/nhcx-coverage/scripts/fetch-package.sh @@ -0,0 +1,122 @@ +#!/usr/bin/env bash +# Fetch the NHCX package and unpack it beside nhcx-build/ as nhcx-package/. +# +# scripts/fetch-package.sh [url-or-path] [target-dir] +# +# With no [url-or-path] (or "latest"), the zip is the build attached to the latest +# release of https://github.com/nha-in/nhcx-package (the nhcx-package-v.zip +# asset); its sha256 is checked against the digest GitHub records for the asset. +# Otherwise [url-or-path] is a link to the zip or a local path to it. +# [target-dir] defaults to the current directory. The zip unpacks to /nhcx-package/. +# +# Afterwards MANIFEST is checked: every file it lists must exist with the sha256 +# it records. Nothing is deleted; an existing nhcx-package/ is replaced. +set -euo pipefail + +repo="nha-in/nhcx-package" +src="${1:-latest}" +target="${2:-.}" +if [[ "$src" == "-h" || "$src" == "--help" ]]; then + echo "usage: $0 [latest|url-or-path-to-package.zip] [target-dir]" >&2 + exit 2 +fi + +download() { # + if command -v curl >/dev/null 2>&1; then + curl -fsSL -o "$2" "$1" + elif command -v wget >/dev/null 2>&1; then + wget -qO "$2" "$1" + else + echo "neither curl nor wget is available" >&2 + exit 1 + fi +} + +mkdir -p "$target" +tmp="$(mktemp -d)" +zip="$tmp/package.zip" +want_sha="" + +if [[ "$src" == "latest" ]]; then + # Ask the releases API for the latest release's zip asset and its digest. + api="https://api.github.com/repos/$repo/releases/latest" + if download "$api" "$tmp/release.json" 2>/dev/null; then + read -r tag url want_sha < <(python3 - "$tmp/release.json" <<'PY' +import json, sys +rel = json.load(open(sys.argv[1], encoding="utf-8")) +assets = [a for a in rel.get("assets", []) + if a["name"].startswith("nhcx-package") and a["name"].endswith(".zip")] +if not assets: + sys.exit(f"release {rel.get('tag_name')} has no nhcx-package*.zip asset") +a = assets[0] +digest = a.get("digest") or "" +print(rel["tag_name"], a["browser_download_url"], + digest.split(":", 1)[1] if digest.startswith("sha256:") else "") +PY + ) + else + # API unreachable or rate limited: read the tag off the releases/latest redirect + # and build the asset name from it. No digest to check in this case. + tag="$(curl -fsSIL -o /dev/null -w '%{url_effective}' "https://github.com/$repo/releases/latest")" + tag="${tag##*/}" + if [[ -z "$tag" || "$tag" == "latest" ]]; then + echo "could not resolve the latest release of $repo" >&2 + exit 1 + fi + url="https://github.com/$repo/releases/download/$tag/nhcx-package-v$tag.zip" + fi + echo "fetching $repo release $tag: $url" + download "$url" "$zip" + if [[ -n "$want_sha" ]]; then + got_sha="$(python3 -c 'import hashlib,sys; print(hashlib.sha256(open(sys.argv[1],"rb").read()).hexdigest())' "$zip")" + if [[ "$got_sha" != "$want_sha" ]]; then + echo "sha256 mismatch for $url: got $got_sha, release says $want_sha" >&2 + exit 1 + fi + fi +elif [[ -f "$src" ]]; then + cp "$src" "$zip" +else + download "$src" "$zip" +fi + +rm -rf "$target/nhcx-package" +unzip -q "$zip" -d "$target" +if [[ ! -f "$target/nhcx-package/MANIFEST" ]]; then + echo "unpacked, but $target/nhcx-package/MANIFEST is missing; is this the NHCX package?" >&2 + exit 1 +fi + +# Verify every file the MANIFEST lists. The MANIFEST is YAML; its file entries +# carry path, bytes and sha256 on separate lines. +python3 - "$target/nhcx-package" <<'PY' +import hashlib, os, re, sys +root = sys.argv[1] +text = open(os.path.join(root, "MANIFEST"), encoding="utf-8").read() +# Only the `files:` section lists a sha256 per path; the `contents:` summary above it +# lists directories. Parse entry by entry so a directory entry never borrows the next +# file's hash. +files_section = text.split("\nfiles:\n", 1)[1] if "\nfiles:\n" in text else "" +entries = [] +for chunk in re.split(r"\n\s*-\s+path:\s*", "\n" + files_section)[1:]: + path = chunk.split("\n", 1)[0].strip() + m = re.search(r"^\s+sha256:\s*([0-9a-f]{64})", chunk, re.M) + if path and m: + entries.append((path, m.group(1))) +bad = [] +for path, want in entries: + p = os.path.join(root, path) + if not os.path.isfile(p): + bad.append(f"missing {path}") + continue + got = hashlib.sha256(open(p, "rb").read()).hexdigest() + if got != want: + bad.append(f"sha256 mismatch {path}") +print(f"nhcx-package: {len(entries)} file(s) listed, {len(bad)} problem(s)") +for b in bad[:20]: + print(" " + b) +sys.exit(1 if bad else 0) +PY + +rm -rf "$tmp" +echo "ready: $target/nhcx-package (see references/material.md for the path map)" diff --git a/plugins/nhcx/skills/nhcx-coverage/stages/0-capability-check.md b/plugins/nhcx/skills/nhcx-coverage/stages/0-capability-check.md new file mode 100644 index 000000000..8186c3288 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-coverage/stages/0-capability-check.md @@ -0,0 +1,92 @@ +# Stage 0: capability check + +Purpose: before anything is planned, find out what the app already does. For this skill's own capabilities, for the foundation it stands on, and for what it needs from the use cases before it, write one verdict each with the evidence that decides it. The verdicts decide what the later stages reuse, extend, build or wait for. Nothing is built twice, and nothing is reused on faith. + +## Inputs + +- This skill's `SKILL.md`, section "Capability check": its own capabilities (what to look for, what makes each present), and its prerequisites with the check that proves each present. The skills that own the prerequisites do not need to be installed; their checks are in this skill's `SKILL.md`. +- `core/FOUNDATION.md`: the six foundation capabilities. +- `nhcx-build/capabilities.json` and `nhcx-build/0-capability.md`, if another NHCX skill already ran on this app. +- The target: the codebase (integrate), or the folder where the standalone app lives or will live. +- The pins and payer fixtures each check names, in `nhcx-package/`. If it is not beside `nhcx-build/`, fetch it now (`scripts/fetch-package.sh`); `references/material.md` names each pin's file. + +## The verdicts + +| Verdict | Means | What happens next | +| --- | --- | --- | +| `present` | Located, and its check was run and observed passing | Reuse. Stage 7 builds nothing for it. Stage 8 still runs its Validate rows; stage 9 still tests it. | +| `partial` | Located, but its check fails; or it covers some legs or branches and not others; or it was located and could not be run | Extend. Stage 7 builds the difference, in the existing code. | +| `absent` | Searched for as the skill says and not found | Build. Stage 7 builds it. | +| `unknown` | Could not be searched: no code is reachable | Planned as absent; stage 0 runs again when the code is reachable. | +| `not applicable` | The mode or the scope excludes it: 7.13 in integrate mode, a leg the user marked out | Nothing. | + +For a prerequisite, a verdict of `absent` or `unknown` is a stop: see step 5. + +Present is a claim about behaviour. Code that looks right is `partial` until its check has run. + +## Do + +### 1. Find the target + +Integrate: the codebase root, its language and framework, enough to search and to run code offline (stage 3 does the full survey). Standalone: the app folder. If it is empty and no other NHCX skill has built anything there, every capability is `absent` and this stage is short. Write which in one line. + +If `nhcx-build/capabilities.json` exists, read it. A verdict another skill recorded is a lead, not a result. If the code changed since its date (the version control log says), run its check again; otherwise carry it forward with its evidence and date. + +### 2. Locate + +For each capability in the three lists (own, foundation, prerequisites), search for the markers: NHCX paths such as `v1/preauth/submit`, resource names such as `CoverageEligibilityRequest`, workflow ids as strings, table and column names. `SKILL.md` lists them for its own capabilities; for a prerequisite, the marker is what its check names. Record every hit as `path:line`. A hit in a comment, a dead branch or a test fixture is not the capability; say so. + +Look also for the same job done another way: a pre-auth sent to a TPA portal, an eligibility check recorded from a phone call, a payment keyed in from a bank statement. That is a host capability that stages 3 and 4 may link to. The NHCX capability is still `absent`. + +### 3. Check + +For every capability located, run the check `SKILL.md` names, offline: + +- a builder: feed it the pin's own data and compare its output with the pin (canonical JSON, `created` excluded, and only the exclusions the module names); +- a reader: feed it the payer fixture and read the state it settles; +- a sender: call it with the 7.1 stub, or a stub of the app's own client, and read what it posted; +- the door: call the handler with an envelope; +- a screen: render it on a seeded state and read the text. + +Use the app's own test runner where it can host the check, else a one-off script under `nhcx-build/0-capability/`. Nothing leaves the machine. + +Where the existing code cannot be called without the network or a running service, record `partial` with `not run: `. Never `present`. + +### 4. Decide + +One verdict per capability, with where (the paths), how (the command), observed (the output, or the first lines of the diff), and the action: reuse, extend, build or wait. For `partial`, name the difference: which pin fails and at which element, which branch is missing (a PMJAY query answer on 19 but none on 131), which column is missing. + +### 5. When a prerequisite is missing + +A prerequisite is a capability another skill owns that this skill's legs cannot run without. `SKILL.md` lists them with their checks. If one is `absent` or `unknown`: + +1. Stop and tell the user which capability is missing, which skill owns it, and what this skill cannot do without it. +2. Offer the two ways on: run the owning skill first (installing it if it is not beside this one; it is the default); or continue with this skill's offline work only (builders, readers and tests against seeded rows), with the live legs marked `later` in stage 1 and the dependency written in `NOTES.md`. +3. Never build another skill's capability inside this one. It would be built without that skill's checks. + +A `partial` prerequisite does not stop the skill. Its gap goes into stage 2's risk table. + +## Write + +- `nhcx-build/capabilities.json` from `templates/capabilities.json`: one entry per capability, keyed by id, with `skill`, `module`, `verdict`, `located`, `how`, `observed`, `action`, `checked_by` and `date`. Update the entries this skill checked; leave the others. +- `nhcx-build/0-capability.md` from `templates/0-capability.md`: a section headed with this skill's name, holding the three tables (own, foundation, prerequisites) and the summary line. +- The scratch checks under `nhcx-build/0-capability/`, kept: stage 8 runs them again. +- This skill's block in `nhcx-build/STATE.md` (create the file from `templates/STATE.md` if it does not exist), with stage 0's row closed and its evidence. + +## Gate + +- [ ] Every capability in this skill's list, every foundation capability, and every prerequisite has a verdict. +- [ ] Every `present` names the command run and its observed output. None rests on reading alone. +- [ ] Every `partial` names the difference. +- [ ] Every `absent` names what was searched for, so a reader can repeat the search. +- [ ] A missing prerequisite was put to the user, and the answer is recorded. +- [ ] `capabilities.json` parses and holds this skill's entries. + +## Common mistakes + +- Marking a capability present because its endpoint name appears in the code. The pin decides. +- Rebuilding a working NHCX transport or callback door because this skill did not write it. An app that already seals, sends and receives NHCX messages keeps its own; the verdict says reuse. +- Proposing nhcx-adapter for an app that lacks a transport. The transport is then `own`; the adapter is used only when the user asks for it. +- Treating a legacy TPA workflow as the NHCX capability. It is a host capability; the NHCX one is absent. +- Checking against the live sandbox. Stage 0 is offline; the live rungs are stage 10's, and the user's. +- Carrying another skill's verdict forward after the code changed. diff --git a/plugins/nhcx/skills/nhcx-coverage/stages/1-idea.md b/plugins/nhcx/skills/nhcx-coverage/stages/1-idea.md new file mode 100644 index 000000000..b9f391316 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-coverage/stages/1-idea.md @@ -0,0 +1,80 @@ +# Stage 1: the idea + +Purpose: agree with the user what is being built before anything is designed. One page, shared by the seven skills. Wrong answers here cost the most later, so this is the one stage that always ends with a question to the user when it is first written. + +The first skill to reach this stage writes `1-idea.md` whole: the mode, the payers, the constraints, and a scope row for every step of the flow, each naming the skill that owns it. A later skill reads the page, confirms that the mode and the payers still hold, and marks its own rows. It asks the user only when it would change a row or an answer. + +## Inputs + +- This skill's section of `nhcx-build/0-capability.md`: what the app already does. A leg found present is still in scope: it is validated and tested, not rebuilt. Say so in the scope table's reason column. A prerequisite the user chose to wait for makes this skill's live legs `later`. +- `flow/FLOW.md`, whole. The build walks this path; the scope table below marks its steps in, later or out, and nothing else. `flow/flow.json` names the skills of each step in `skills`. +- What the user said. If they pasted a brief, quote it in the artefact. +- `references/flow-knowledge.md` sections 1, 3 and 6: the legs, the two payer kinds, the use-case catalogue. Read them so the scope table below uses the catalogue's codes. + +## Do + +Decide five things, in this order. A later skill confirms the first two and the fourth, and does the third for its own rows. + +### 1. Mode + +| Signal | Mode | +| --- | --- | +| A codebase, a database, a running system is named | `integrate` | +| "from scratch", "standalone", "a claims app", no existing system | `standalone` | +| Unclear | Ask. Do not guess; the two modes diverge at stage 3. | + +### 2. Payers + +Which participant codes the software will talk to, and which kind each is: + +| Payer | Participant code | Kind | Query mode | +| --- | --- | --- | --- | +| PMJAY (SHA Himachal Pradesh, sandbox) | `1518@hcx` | scheme | `resubmit` | +| A generic sandbox payer you can drive, for testing | from the participant registry | generic | `communication` | +| Any other insurer | from the registry | generic unless told otherwise | `communication` | + +Both kinds are in scope by default. A build that targets only one still keeps the payer adapter switch (module 7.11), because the second is one config line away. + +### 3. Scope of legs + +Copy the steps of `flow/flow.json` (F1 to F13 with their branches) into a scope table, with the skill that owns each (`skills`), and mark each `in`, `later` or `out`, with a reason; add the catalogue code from `flow-knowledge.md` section 6 beside each. The default scope for a first release is every hospital-side leg in `flow-knowledge.md` section 1. Cutting a leg is the user's call; propose it, do not decide it. Legs that are commonly `later`: predetermination, status enquiry (PMJAY refuses it), release of a shortfall (out of reach on the sandbox). + +A later skill changes only its own rows. + +### 4. Constraints + +Ask the codebase, not the user, where you can: + +- Language and framework (integrate: whatever the HMIS uses; standalone: Python standard library unless the user names another, because the module files' pseudo code maps onto it directly). +- The transport (`references/transport-knowledge.md` section 1): `existing` when stage 0 found the app already speaks NHCX; else `own`, built into the app from NHA's protocol; `adapter` (nhcx-adapter) only when the user has asked for it, their words quoted. Never propose the adapter. +- The inbound path. For `own`: a public HTTPS domain in India, registered as the participant's `endpoint_url` and reachable from the exchange. For `existing`: the app's own callback. For `adapter`: whether the app can receive the adapter's POST; if not, polling the adapter's ledger is the only inbound path. Write it down now. +- What onboarding needs from the user: the ABDM sandbox client id and secret (Milestone 1), the facility's HFR id, and a participant record carrying the build's certificate and callback address. +- Document storage: blob, filesystem, object store. +- Whether a background worker exists. Without one, polls happen on the request path. +- Anything the user forbids: new dependencies, schema changes to existing tables, a build step. + +### 5. Definition of done + +Write the compliance points from `core/LADDER.md` as they apply to this build, and the highest rung of the test pyramid the user wants climbed before handover (`references/testing-knowledge.md` section 1). The offline rung is never optional. + +## Write + +`nhcx-build/1-idea.md` from `templates/1-idea.md`. Keep the headings. Under two pages. A later skill edits only its scope rows and adds a line under "Agreed". + +## Gate + +- [ ] Mode is `integrate` or `standalone`, and the reason is one sentence. +- [ ] Every payer has a participant code and a query mode. +- [ ] The scope table has every step of the flow and every catalogue row, each with its skill, marked in, later or out. +- [ ] Constraints name the language, the transport (existing, own, or nhcx-adapter because the user asked for it), the inbound path and the document store. +- [ ] Definition of done names the target rung. +- [ ] The user has read the page and agreed, or a written brief stands in for the user. A later skill that changed nothing records that it confirmed the page. + +Record the gate in the Shared block of `nhcx-build/STATE.md`. + +## Common mistakes + +- Choosing `standalone` because the HMIS is unfamiliar. Unfamiliar is what stage 3 is for. +- Leaving PMJAY out because the user only named an insurer. PMJAY is the payer that refuses most; a build that handles it handles the rest. +- Dropping a leg from scope because stage 0 found it present. It stays in: present capabilities are validated and tested. +- Writing design here. Tables, screens and modules belong to stages 4 to 6. diff --git a/plugins/nhcx/skills/nhcx-coverage/stages/10-run-tests.md b/plugins/nhcx/skills/nhcx-coverage/stages/10-run-tests.md new file mode 100644 index 000000000..e7e5d8d32 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-coverage/stages/10-run-tests.md @@ -0,0 +1,59 @@ +# Stage 10: run the tests + +Purpose: climb the pyramid as far as the user asked in stage 1, for this skill's rows, and record every rung honestly. Rung 1 you run yourself. Rungs 2 to 4 need services or live payers, and only the user starts those. + +## Inputs + +- `nhcx-build/1-idea.md` (the target rung), `nhcx-build/9-tests.md` (the run command, this skill's rows) +- This skill's `SKILL.md`: its stage 10 row (which matrix rows each rung walks) +- `references/testing-knowledge.md` sections 1, 5 and 6 +- `references/errors-and-debugging.md` sections 4 to 8 (reading the ledger, sandbox pace) + +## The rungs + +| Rung | What | Who starts it | Record | +| --- | --- | --- | --- | +| 1 Offline | The suite from stage 9, against the pins and fixtures, no network | you | the full output | +| 2 Validator | The HL7 FHIR validator on every bundle this skill builds, run as `references/fhir-knowledge.md` section 11 says | you, if Java and the validator are installed | one table: bundle, errors, warnings | +| 3 Generic payer | The transport on the sandbox (the app's own, or nhcx-adapter when the user chose it) and a generic sandbox payer whose desk you can drive; this skill's legs, every query as a CommunicationRequest, payment from its desk | the user | the ledger thread per leg, the state address after each | +| 4 PMJAY sandbox | SHA Himachal Pradesh, `1518@hcx`; sweep live pre-auths first; one request at a time per case, 30 seconds between; decisions on the payer service desk | the user | the ledger, the archive folder, every refusal verbatim | + +## Do + +### Rung 1 + +Run the command from `nhcx-build/9-tests.md`: the whole suite, not only this skill's tests, because a skill that extended a shared module can break another skill's test. Save the whole output to `nhcx-build/10-test-run/-rung1.log`. In `integrate` mode also run the HMIS's own suite and save it. A failure goes back to stage 7 (the module) or stage 9 (the test); record the fix and the re-run. Do not edit a test to make it pass unless the test was wrong, and say so. + +### Rung 2 + +If the validator runs, validate every bundle this skill's tests built (write them to a folder from the tests). Warnings are advice; the sandbox accepted every pin as it stands. Errors are findings. If it does not run, write `not run` and why. + +### Rungs 3 and 4 + +Prepare, do not run: + +1. The commands the user runs: the HMIS with its public callback (`own` or `existing`), nhcx-adapter with its filled config only when the user chose it, and the payer (rung 3). For `own`, the sandbox's dummy payer proves the loop first (`references/transport-knowledge.md` section 3.11). Write them into this skill's section of `nhcx-build/10-test-run.md` under "Runbook". +2. The driver: a script or a spec that walks this skill's matrix rows through the JSON state address, waiting on the case's own state and never on a fixed sleep, logging every verdict the payer gives. The earlier legs a row needs (an eligible case, an approved pre-auth) are reached by the earlier skills' drivers or through the app's own screens. +3. The sweep for rung 4: cancel or let expire every live pre-auth for the beneficiaries the tests use (PAYR-1238 otherwise). +4. Then stop and ask the user to start the services. When they have, run the driver, save its log, and package the run's bundles by correlation id from the per-case archive (or the adapter's ledger, when it is the transport). + +While a live run is going: one request at a time per case; wait about 30 seconds after a decision; on "Active instance found" wait and resend up to three times; on a refusal read the ledger thread before touching the code. + +## Write + +This skill's section of `nhcx-build/10-test-run.md` from `templates/10-test-run.md`: per rung, `passed`, `failed`, `not run` with the reason, the log path, and the findings (each a line: what, where, the PAYR or rule, the fix or the open question). The raw logs under `nhcx-build/10-test-run/`, named for the skill. + +## Gate + +- [ ] This skill's rung 1 log exists and shows every test in the suite passing, or the failures are listed as findings with a stage to return to. +- [ ] In `integrate` mode the HMIS's own suite log exists and passes. +- [ ] Rung 2 has a table or `not run` with a reason. +- [ ] Rungs 3 and 4 have a runbook and a driver for this skill's rows, and either a log or `not run: user has not started the services`. +- [ ] No rung is marked passed without a log. + +## Common mistakes + +- Starting a service yourself: the app's public callback, or nhcx-adapter. Only the user does. +- Running only this skill's tests at rung 1. A shared module may have broken another skill's. +- Sleeping a fixed time in a driver. Wait on the state address. +- Reading a refusal as a code bug before reading the ledger thread. Half of them are scheme rules (flow-knowledge section 5). diff --git a/plugins/nhcx/skills/nhcx-coverage/stages/11-build-report.md b/plugins/nhcx/skills/nhcx-coverage/stages/11-build-report.md new file mode 100644 index 000000000..4ea8a0806 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-coverage/stages/11-build-report.md @@ -0,0 +1,64 @@ +# Stage 11: the report + +Purpose: one document a stranger can pick up to know what was built, what was found already there, what was proven, what was not, and what to do next. Written from the artefacts in `nhcx-build/`, not from memory. Its value is its honesty. + +`11-report.md` has a summary across the skills at the top and one section per skill below it. This skill writes its section and updates its row of the summary. + +## Inputs + +- Everything in `nhcx-build/`, `STATE.md` first, `NOTES.md` last +- This skill's sections of `0-capability.md`, `8-validation.md` and `10-test-run.md` + +## Do + +### 1. Read STATE.md + +Every gate row in this skill's block, and the foundation rows it built, with their evidence. A gate without evidence is reported as open, whatever you remember. + +### 2. Write this skill's section + +From `templates/11-report.md`, in this order: + +| Section | Holds | +| --- | --- | +| Capabilities | Every capability in this skill's section of `0-capability.md`: its verdict at stage 0, what was done (reused, extended, built), and its evidence after stage 8 | +| What was built | Each module part this skill built or extended, with its files and its record (`7-modules/7.N.md`) | +| Compliance | The seven points from `core/LADDER.md` for this skill's legs, each with the evidence path (the pin comparisons, the door tests, the screen tests, the rung logs) | +| The test pyramid | Per rung: passed, failed, not run, the log | +| Findings | Every failure from stages 8 and 10 with its resolution or its open state | +| Gaps | This skill's entries in `NOTES.md` folded in: what the skills did not say, what the docs did not say, what the sandbox did that no document states | +| Exceptions | Every accepted exception from stage 8 and the user's agreement | +| Runbook | How to start it, how to run the suite, how to run rungs 3 and 4, what to sweep first, where the archive and the ledger are | +| Next | The `later` legs from stage 1, the open gates, the rungs not climbed, and the skill to run next in the order `core/LADDER.md` gives | + +Then update this skill's row in the summary table: stages closed, rung reached, what it reused, extended and built, what is open. Mode, payers and "today a user can" are for the whole build; bring them up to date. + +### 3. Check the report against the rules + +- Every claim of "passes" has a log or a record path beside it. +- Every rung not run says so. +- Every capability reported as reused has its stage 8 evidence, not only stage 0's. +- No em dashes, short sentences, tables for facts. +- A stranger with this report and the target project could resume at the first open gate. + +## Write + +This skill's section of `nhcx-build/11-report.md`, and its summary row. Update `STATE.md` with the final gate. + +## Gate + +- [ ] Every section in the template is present in this skill's section. +- [ ] Every capability in this skill's section of `0-capability.md` appears under Capabilities. +- [ ] Every module part this skill touched appears in "What was built" or, if reused, under Capabilities. +- [ ] Every compliance point names evidence. +- [ ] The pyramid table matches this skill's section of `10-test-run.md`. +- [ ] This skill's entries in `NOTES.md` are folded into "Gaps" in full. +- [ ] The runbook has the start commands, the test command and the sweep. +- [ ] The summary table has this skill's row. + +## Common mistakes + +- Reporting the rung the user asked for as reached because the offline rung passed. +- Reporting a reused capability as working on the strength of stage 0 alone. +- Dropping a finding that was fixed. Fixed findings are the most useful part of the report for the next build. +- Writing the report before stage 10's logs exist. diff --git a/plugins/nhcx/skills/nhcx-coverage/stages/2-planning.md b/plugins/nhcx/skills/nhcx-coverage/stages/2-planning.md new file mode 100644 index 000000000..06c405cdc --- /dev/null +++ b/plugins/nhcx/skills/nhcx-coverage/stages/2-planning.md @@ -0,0 +1,67 @@ +# Stage 2: planning + +Purpose: turn the idea and the capability check into this skill's schedule of gates, and add its block to the ledger every later stage writes to. This is bookkeeping, and it is short. + +## Inputs + +- `nhcx-build/1-idea.md` +- This skill's section of `nhcx-build/0-capability.md`: the verdict of every capability it owns or stands on +- `core/LADDER.md`, "The ladder"; this skill's `SKILL.md`, "The ladder, for this skill" +- `references/testing-knowledge.md` section 1 (the pyramid) and section 3 (the matrix), so the acceptance tests below are the matrix's rows and not invented ones + +## Do + +### 1. Size each stage + +For every stage 3 to 11, write one row for this skill: what it produces for this build, how big it is (small, medium, large), and what proves it done. "What proves it done" is the stage's gate, restated for this skill. + +For stage 7, list the modules this skill's `SKILL.md` names and the foundation modules, each with its verdict from stage 0 turned into an action: + +| Verdict | Action in stage 7 | +| --- | --- | +| `present` | reuse: nothing built; validated in stage 8, tested in stage 9 | +| `partial` | extend: the difference, in the existing code | +| `absent`, `unknown` | build | +| `not applicable` | nothing | + +Module 7.13 depends on the mode: + +| Module | integrate | standalone | +| --- | --- | --- | +| 7.1 to 7.12 | yes | yes | +| 7.13 standalone shell | no | yes | + +Module 7.12 (screens) is smaller in `integrate` mode when the HMIS already has patients, admissions and documents; the plan says which existing screens gain a panel and which are new. + +### 2. Order and dependencies + +The ladder is sequential by stage. Inside stage 7, foundation modules come first, then this skill's modules in the order of `stages/7-write-code/README.md`; the plan may not reorder them, because each module's validation assumes the ones before it exist. + +### 3. Risks + +Copy into a risk table the rules from `references/flow-knowledge.md` section 5 that touch this skill's legs; its `SKILL.md` names them in its stage 2 row. Each rule is a way the build fails live even when the offline tests pass. When this skill builds or extends a foundation module, add the foundation's rules too: acknowledge or lose the thread; one message is taken once (dedupe on `x-hcx-api_call_id`). Add every `partial` prerequisite from stage 0, and the build's own risks: a missing HPIN on the practitioner table, no inbound route to the HMIS, a plan master too large for the database column, a callback behind auth middleware. + +### 4. What the user must do + +List every point where the ladder stops for the user: agreeing stage 1, running an owning skill first when a prerequisite is missing, supplying participant credentials (the ABDM client id and secret), registering the participant's certificate and callback address, starting the services for stage 10 rungs 3 and 4 (the app's public callback, or nhcx-adapter when the user chose it), sweeping live pre-auths before a PMJAY run. + +## Write + +- This skill's section of `nhcx-build/2-planning.md`, from `templates/2-planning.md`. +- This skill's block in `nhcx-build/STATE.md` (created at stage 0 from `templates/STATE.md`), with a row per stage and a row per module part, each module row carrying its action. +- `nhcx-build/NOTES.md`, empty but for its heading, if it does not exist. + +## Gate + +- [ ] Every stage 3 to 11 has a row with a size and a proof, for this skill. +- [ ] Every module this skill touches, and every foundation module, has its verdict and its action; 7.13 is marked by mode. +- [ ] The risk table holds every rule this skill's `SKILL.md` names for stage 2, and the foundation's rules when this skill builds or extends a foundation module. +- [ ] The user-action list names the credentials and the service starts. +- [ ] STATE.md has this skill's block with a row per stage and per module part. + +## Common mistakes + +- Estimating in days. Estimate in size; the user turns size into time. +- Planning to skip stage 8 or 9 "for the first pass". They are what makes the report true. +- Planning to rebuild a capability stage 0 found present. +- Reordering modules so screens come first. Screens derive from messages; without readers there is nothing to derive from. diff --git a/plugins/nhcx/skills/nhcx-coverage/stages/3-discovery.md b/plugins/nhcx/skills/nhcx-coverage/stages/3-discovery.md new file mode 100644 index 000000000..9feb26eca --- /dev/null +++ b/plugins/nhcx/skills/nhcx-coverage/stages/3-discovery.md @@ -0,0 +1,97 @@ +# Stage 3: discovery + +Purpose: find the surface you will build on. In `integrate` mode that is the HMIS; in `standalone` mode it is the runtime, the storage and the deployment target the user has chosen. Every answer names the file, table or endpoint that proves it. An answer without proof is a gap. + +`3-discovery.md` is shared by the seven skills: one row per concern, each naming the skill that answered it. This skill answers the rows its `SKILL.md` lists under "Host facts", and the framework and runtime rows if no skill has. A row an earlier skill answered with proof is reused; check it again only if the code changed since. + +Stage 0 looked for NHCX capabilities. This stage looks at the host: where patients, admissions, doctors, documents and bills live. + +## Inputs + +- `nhcx-build/1-idea.md`, `nhcx-build/2-planning.md`, this skill's section of `nhcx-build/0-capability.md` +- This skill's `SKILL.md`, "Host facts" +- The target codebase (integrate) or the chosen runtime (standalone) +- `stages/7-write-code/7.2-storage.md` (the claim tables) and `stages/7-write-code/7.13-standalone-shell.md` (patient, encounter, practitioner, document), as the shape to compare against + +## Do + +Answer in writing every question below that this skill's host facts name, plus the framework and runtime questions when they are not yet answered. Reading only; change nothing. + +### Framework and runtime + +| Question | Why it matters | +| --- | --- | +| Language, web framework, ORM, database engine, migration tool | Where a new table goes and how it is created | +| How configuration is read (env, file, database) | Where the transport's settings live: the participant code, and the client id and secret and the private key (`own`), or the adapter URL and key (`adapter`) | +| How the app exposes an HTTP endpoint an outside process can POST to; which auth middleware must be exempted | The callback door, module 7.3 | +| Background worker or scheduler, or none | Whether polls run on the request path or in a worker | +| How the app serves a page and what the screen conventions are | Module 7.12 must match them | +| How tests are run and where they live | Stage 9 must match them | + +### Patients + +| Question | Why it matters | +| --- | --- | +| The patient table, its primary key, the unique identifier (MRN) | `claim.patient_id` | +| Where name, gender, date of birth, phone, ABHA number live | The Patient resource in every bundle | +| Where a scheme member id (PMJAY id) and a policy code can be stored, per patient or per visit | The Coverage resource; the policy search result | + +### Admissions and encounters + +| Question | Why it matters | +| --- | --- | +| The inpatient encounter table: admission time, discharge time, ward or bed, admitting doctor, status | `billablePeriod`, `ONS/ADDD`, the care team | +| How discharge is recorded, and whether it can carry a mode (normal, LAMA, DAMA, death) and a stage (before, during, after surgery) | `DIS` and `DSDE` on the claim; the LM100 collapse | +| Diagnoses: SNOMED, ICD-10 or free text | The payer needs ICD-10 with a display | +| Procedures or surgeries, and whether a surgery time is recorded | `ONS/PSP` | + +### Billing + +| Question | Why it matters | +| --- | --- | +| Billing lines: code, quantity, unit price, net; which charge master | Lines are quoted from the payer's plan, not the HMIS master, but the two must be reconcilable | +| Whether a line can be tagged with a payer package code and a category | `claim_line` | +| Invoices and receipts: where a settlement amount and a UTR go | Payment notices, module 7.10 | + +### Documents + +| Question | Why it matters | +| --- | --- | +| Where PDFs and images live (blob column, filesystem, object store) | `valueAttachment` needs the bytes and the content type | +| Whether a file can be tagged with a payer document code and a stage (pre-auth or claim) | The plan's requirement codes; never `ODN` for a file that was asked for by name | +| Accepted content types | The scheme takes pdf, jpg, jpeg, png only (PAYR-1008) | + +### Doctors + +| Question | Why it matters | +| --- | --- | +| The practitioner table; an HPR id (HPIN); a licence number; a qualification string | PMJAY refuses a pre-auth without an HPIN typed identifier (PAYR-1083) | + +### Facility + +| Question | Why it matters | +| --- | --- | +| The facility's HFR id, name, phone; its NHCX participant code | The provider Organization; the sender code | + +### Standalone mode + +The same questions, answered for the runtime the user chose. Where the answer is "nothing exists yet", write what module 7.13 will create: `patient`, `encounter`, `practitioner`, `document`, `settings`. A standalone app still has to hold every fact the questions ask for; it simply has to capture it itself. + +## Write + +`nhcx-build/3-discovery.md` from `templates/3-discovery.md`: one table, concern by concern, columns `Concern | Where it lives (proof) | Gap | Answered by`. A gap is what stage 4 fills. Add rows; do not rewrite another skill's rows. + +## Gate + +- [ ] Every host fact this skill's `SKILL.md` names has a row, and so does every framework and runtime question. +- [ ] Every row that is not a gap names a file path, a table, or an endpoint. +- [ ] When this skill builds or extends the callback door, the callback route is answered: which URL, which middleware to exempt, or "no inbound route, poll only". +- [ ] When this skill's bundles carry a Practitioner, the HPIN question is answered; if the practitioner table has no HPR id, the gap says so. +- [ ] When this skill attaches documents, the document store is answered with content-type handling. + +## Common mistakes + +- Answering from the framework's documentation instead of the codebase. The proof column is the codebase. +- Skipping the discharge-mode question. A death claim without `DTM` is refused (PAYR-1096); the HMIS must be able to say the patient died and when. +- Treating "no background worker" as a blocker. Without one, polls run on the request path; it is a design input, not a stop. +- Answering every concern for every skill. Answer the ones this skill needs; the next skill adds its own. diff --git a/plugins/nhcx/skills/nhcx-coverage/stages/4-flow-and-data-mapping.md b/plugins/nhcx/skills/nhcx-coverage/stages/4-flow-and-data-mapping.md new file mode 100644 index 000000000..bf51c7991 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-coverage/stages/4-flow-and-data-mapping.md @@ -0,0 +1,92 @@ +# Stage 4: flow and data mapping + +Purpose: decide where every fact the exchange needs comes from and where every fact the exchange returns goes, leg by leg. This is the design stage with the most rows; get it right and stages 6 and 7 are transcription. + +Two parts of this stage belong to the episode, not to one skill: the flow table (section 1) and the home of every table (section 2), with the matching order (section 4). The first skill to run this stage writes them whole, so every later skill builds on one design; a later skill checks them and adds only what its gaps need. The field mapping (section 3) is this skill's own bundles only. + +## Inputs + +- `nhcx-build/1-idea.md` (scope), `nhcx-build/3-discovery.md` (the surface and its gaps), this skill's section of `nhcx-build/0-capability.md` (what exists already) +- This skill's `SKILL.md`: its steps, legs, bundles and tables +- `flow/FLOW.md` and `flow/flow.json`: the steps this build implements. They are copied, not redesigned. +- `references/flow-knowledge.md` sections 1, 2, 4 and 5 +- `references/transport-knowledge.md` section 2 (what a send returns, what arrives at the door) +- `references/fhir-knowledge.md` sections 3 to 10 (what each bundle needs); `fhir/FHIR.md` for the exact elements, as the builders' data dictionaries name them +- `stages/7-write-code/7.2-storage.md`: the claim tables and the columns each must hold + +## Do + +### 1. The flow, for this build + +The first skill copies every step of `flow/flow.json` into the flow table, in order, with its id and its skills, and adds two columns for this build: the HMIS event it hangs off (admission, discharge, a desk action) and the mark from stage 1 (`in`, `later`, `out`). The steps, their order, their tabs, their guards and their action labels are the flow's; this build adds where each fact comes from, nothing else. Then note the payer branches as the flow has them (F9b, F11, F12: `19`/`131`/`161` resubmits against a Communication reply; `17` against an echoed id). The stage and sub-stage vocabulary is copied as is; do not rename it. + +Write the step ids into `mapping.json` under `flow.steps` and the eight tabs, in order and with their labels, under `flow.tabs`. + +A later skill checks its own steps' rows and fills their HMIS event where the first skill left it open. + +### 2. The episode tables + +The first skill gives every table below a home, not only its own. The home is one decision for the episode (sidecar tables, or columns on the HMIS's tables), and a skill that chose differently later would split the design. It writes the columns each table must hold, and the legs' columns under `legs`. Later skills read the homes and add only the columns their gaps need. + +For each table below, decide one of three homes and write it down: + +| Home | When | +| --- | --- | +| A new sidecar table keyed on the HMIS's own ids | Default. Keeps the HMIS schema untouched and the integration removable. | +| Columns added to an existing HMIS table | Only for a scalar the HMIS already half-holds (a member id on the visit, an HPIN on the doctor) | +| An existing table used as is (`existing`) | Only when it already holds every column named below. This is the home of a capability stage 0 found present: record its real name and its columns, and a gap for each column it lacks | + +| Table | Why it exists | Must hold | +| --- | --- | --- | +| `claim` | The episode: beneficiary, policy, payer, eligibility verdict, link to the admission, pre-auth draft, stage and sub-stage | claim number, member id, policy code, payer participant code, patient and encounter keys, `txn_id`, `correlation_id`, `stage`, `sub_stage` | +| `claim_plan`, `claim_plan_benefit`, `claim_plan_form` | The payer's package master, flattened; one per facility and policy, copied onto later episodes | packages with rate, kind, conditions, extras (tiers, implants), document requirements; questionnaires by url | +| `claim_auth`, `claim_auth_item`, `claim_auth_requirement` | The auth-requirements ruling on the quoted set | per line: authorised, excluded; per requirement: kind (document or form), code, url, stage | +| `claim_line` | What is quoted: procedures, implants, ward tiers with a parent procedure | code, kind, quantity, unit price, amount, parent code | +| `claim_form_answer` | Answers to the plan's questionnaires | url, linkId, answer, stage | +| `claim_preauth` | The pre-auth leg, one row rewritten each round (12, 19, 13, 131) | status, `txn_id`, `correlation_id`, `thread_correlation_id`, `api_call_id`, `preauth_ref`, `submission_kind`, `workflow_id`, request and response json, cancel fields | +| `claim_submission` | The claim leg plus the discharge | discharge mode, stage, dates; the same exchange columns as the pre-auth | +| `claim_query` | Every CommunicationRequest or Communication from the payer, classified | `correlation_id` (unique), request id, kind, reason code, status, reply fields | +| `claim_payment`, `claim_payment_detail` | Payment notices, matched by claim number, deduped by correlation id | amount, UTR, payment status, ack fields | +| `claim_enquiry` | Status, reprocess and release Tasks, one row per ask | kind, `correlation_id`, answer | +| `claim_predetermination` | A quote, one row per ask | as a pre-auth, without state effects | +| `claim_document` | Attachments with the payer's code, category and stage | bytes or a pointer, content type, code, stage | +| `claim_diagnosis`, `claim_care_team`, `claim_item` | ICD-10 codes, doctors, non-package items | as named | + +The rule that never bends: every leg row holds `txn_id`, `correlation_id` and `api_call_id` from the transport's answer, and `thread_correlation_id` separately, because a send refused at the door must not lose the thread the payer last answered on. + +### 3. Field mapping, per bundle + +For each bundle this skill sends (its `SKILL.md` lists them; `fhir-knowledge.md` sections 3, 4, 5, 7, 9, 10), one table: `FHIR element | Source (table.column or constant or payer answer) | Transform | Gap`. Do not fill values; name sources. The elements that are always mapped from a payer answer and never from the HMIS: package codes and rates (the plan), document codes and questionnaire urls (the plan or the ruling), `preAuthRef` (the ClaimResponse), the payer's own case number. + +For each bundle this skill reads (sections 6, 8, 9, 10 and the coverage answer in section 3), one table: `FHIR element | Destination | Rule`. The status rule for a ClaimResponse is `verdict_status`, copied verbatim; never read `outcome` alone. + +Where stage 0 found a builder or reader present, map what it does today, and name each element where it differs from the pin as a gap. + +### 4. Inbound matching + +Written once, by the first skill. Write the matching order as a numbered list: `x-hcx-correlation_id` against every leg table; then the claim number inside the bundle; then unmatched, archived, 2xx returned. Write the dedupe key: `x-hcx-api_call_id`. Write the archive path: `//NNN--.json` plus `transactions.txt`. A later skill adds its leg tables to the correlation order. + +## Write + +- `nhcx-build/4-flow-data-mapping.md` from `templates/4-flow-data-mapping.md`. The first skill writes the flow table, the table homes and the matching order at the top; each skill writes a section headed with its name holding its field mappings. +- `nhcx-build/mapping.json` in the shape of `templates/mapping.json`. The first skill writes `flow`, `episode`, `tables`, `legs` and `inbound` whole; every skill adds its bundles under `bundles`, each entry with `"skill"`. Stage 6 reads it. + +## Gate + +- [ ] The flow table has every step of `flow/flow.json`, in its order, with its id, its skills and an in/later/out mark; `mapping.json` `flow.steps` lists every id and `flow.tabs` the eight tabs verbatim. +- [ ] Every table above has a home in `mapping.json` under `tables`. +- [ ] Every leg table's columns in `mapping.json` include `txn_id`, `correlation_id`, `api_call_id` and `thread_correlation_id`. +- [ ] `mapping.json` `episode.columns` includes `stage` and `sub_stage`. +- [ ] Every bundle this skill sends has a source table; every element with no source is listed as a gap, not omitted. +- [ ] Where this skill's bundles carry a Practitioner, the HPIN element's source is named (or its gap is). +- [ ] Every capability stage 0 found present is mapped to what exists, with its differences from the pin as gaps. +- [ ] The matching order, the dedupe key and the archive path are written. + +## Common mistakes + +- Redesigning the flow: merging tabs, adding a "status" step, moving the discharge out of the claim tab. The flow is the reference flow; copy it. +- Giving homes only to this skill's tables when it is the first to run the stage. The next skill would choose differently. +- Mapping package rates to the HMIS charge master. Prices come from the plan; the master is for reconciliation. +- One `correlation_id` column on the episode instead of one per leg. Each leg is its own thread. +- Forgetting `thread_correlation_id`. It is the difference between a recoverable door refusal and a dead case. +- Mapping `Patient` demographics on the coverage request. Only the member id goes out; the payer returns the rest. diff --git a/plugins/nhcx/skills/nhcx-coverage/stages/5-screen-plan.md b/plugins/nhcx/skills/nhcx-coverage/stages/5-screen-plan.md new file mode 100644 index 000000000..9ec0d8bc2 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-coverage/stages/5-screen-plan.md @@ -0,0 +1,74 @@ +# Stage 5: screen plan + +Purpose: decide the screens, and for every value on every screen, the received message it is derived from. The two honesty rules are the whole point of this stage, and a reviewer tests them before anything else. + +The case screen is the episode's (`foundation.screens`): its eight tabs, the status line and actions, the JSON state address and the cases list. The first skill to run this stage lays them out whole, every tab present with its opening condition. Each skill then plans the values and actions of its own tabs and screens, which its `SKILL.md` lists. + +## Inputs + +- `nhcx-build/1-idea.md`, `nhcx-build/3-discovery.md` (screen conventions), `nhcx-build/4-flow-data-mapping.md` +- This skill's `SKILL.md`: its tabs, its screens, its next actions +- `flow/FLOW.md` ("The shape", "The status line and the actions", every step's Screen line) and `flow/flow.json`: the screens are put on these steps, not invented. +- `references/flow-knowledge.md` section 4 (stage, sub-stage, next actions) +- `ui/UI-GUIDE.md`: the screens, a layout per screen, where every value comes from, the state words. Read it whole before planning. +- `nhcx-package/docs/03-Building a Provider/09-UI Guide.md` (the published source of the guide) + +## The two rules + +1. No screen shows a decision the exchange has not sent. Every state on every screen is derived from a stored message. A case with a request sent and no answer back reads as waiting, never approved, never rejected. That case exists only because module 7.3 kept a record of what was sent, so the screen must be able to render a leg with a request and no response. +2. Nothing the exchange already knows is typed. Payer names, policies, balances, package rates, the payer's own wording, `preAuthRef`, the approved amount, the UTR are rendered from the message that carried them. A package rate is never an editable field. + +## Do + +### 1. The screen list + +The case screen carries the eight tabs of `flow.json` `tabs`, in that order, with those labels, opening under those conditions. The status line and the action list above the tabs use the labels of `flow.json` `next_actions` verbatim. Then, minimum, once every skill has run: + +| Screen | Who | Shows | Derived from | Planned by | +| --- | --- | --- | --- | --- | +| Cases list | billing clerk | every episode, its stage and sub-stage, what it waits for | `claim.stage`, `sub_stage`, `next_actions` | the first skill | +| Case | everyone | the timeline of legs, the payer's answer verbatim, the actions open now | every leg row and its archived messages | the first skill; each skill its tabs | +| Inbox | desk | payer messages routed by kind: query, notification, note | `claim_query` | `nhcx-communication` | +| Payments | accounts | notices, deductions, UTR, reconciliation | `claim_payment`, `claim_payment_detail` | `nhcx-payment` | +| Find and cover | registration clerk | policy search, eligibility verdict, register or link | the policy search answer and the `on_check` bundle | `nhcx-coverage` | +| Plan | doctor | specialty, package, add-ons, tiers, the documents and forms the plan wants | `claim_plan_*`, `claim_auth_*` | `nhcx-insurance`, with the ruling from `nhcx-preauth` | + +`integrate` mode adds a panel to the HMIS's own admission screen linking the admission to its episode. `standalone` mode adds the capture screens module 7.13 describes (patient, admission, discharge, documents, settings). + +Where stage 0 found a screen present, plan what it shows today against the rules, and list every value that breaks one as a gap. + +### 2. Per screen, per value + +For every value on this skill's screens, one row: `Value | Message and element | Empty state`. The empty state is what the screen shows before the message arrives (for a decision: "waiting"; for a rate: nothing, the field does not exist yet). A value whose source is "the user types it" is allowed only for things the exchange cannot know: the discharge mode and dates, the desk's reply to a query, the documents, the questionnaire answers, the chosen lines. + +### 3. Actions + +Every action is one step of `flow.json` and carries its id in `step`. For every action this skill's screens offer, the leg it sends, the sub-stage that must hold for it to be offered, and the sub-stage it moves to. Take the offered-when rules from `next_actions` in flow-knowledge section 4: an unanswered query always leads; the reply box is offered only to a `resubmit` payer; after a rejection the pre-auth offers a fresh 12, not 121. + +### 4. Addresses and conventions + +Write the route for each screen in the HMIS's own style (from stage 3). The state of a case must also be readable as JSON at one address, because stage 10 drives the screens through it (for example `GET /claims//state`). Each skill adds its legs to what the address returns. + +## Write + +- `nhcx-build/5-screen-plan.md` from `templates/5-screen-plan.md`: the shell at the top (first skill), then a section per skill. +- `nhcx-build/screens.json` in the shape of `templates/screens.json`: the first skill writes `rules`, `tabs`, `state_address`, the cases list and the case screen; each skill adds its screens and actions. + +## Gate + +- [ ] `screens.json` `tabs` lists the eight tabs of `flow.json` in order with the same keys and labels. +- [ ] Every user-driven step this skill owns (its steps among F1 to F13, except F9a, F12 and F12b, which the payer starts) appears as an action with its `step` id, and every action's `label` is one of `flow.json` `next_actions` or the step's own button. +- [ ] `screens.json` holds the cases list, the case screen, and every screen this skill plans, each with a route (plus 7.13's in standalone mode). +- [ ] Every screen this skill plans has a `values` list and every value names a message element or is marked `typed` with a reason from the allowed list. +- [ ] Every decision-bearing value has an empty state of waiting. +- [ ] No `values` entry marks a rate, a payer name, a `preAuthRef` or a UTR as typed. +- [ ] Every action names its leg, its offered-when sub-stage and its resulting sub-stage. +- [ ] A JSON state address exists for a case. + +## Common mistakes + +- A status dropdown on the case. Status is derived; there is no dropdown. +- Showing `preAuthRef` from the pre-auth's own claim number. It comes from the ClaimResponse. +- Designing the desk's reply box for a `communication` payer on the leg. It belongs on the inbox item. +- Laying out only this skill's tab when it is the first to run the stage. The shell has all eight. +- Screens that need JavaScript. Forms post and the page re-renders; that is enough. diff --git a/plugins/nhcx/skills/nhcx-coverage/stages/6-code-plan.md b/plugins/nhcx/skills/nhcx-coverage/stages/6-code-plan.md new file mode 100644 index 000000000..2167000f1 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-coverage/stages/6-code-plan.md @@ -0,0 +1,68 @@ +# Stage 6: code plan + +Purpose: turn the mapping, the screen plan and the capability verdicts into a list of modules with files, dependencies, the pin each is held to, and what this skill does to each. Stage 7 builds this list in order; stage 8 validates it in order. + +The transport's shape, the configuration, the archive and the test placement (sections 2 to 5) are the episode's: the first skill to run this stage writes them, and later skills use them. + +## Inputs + +- `nhcx-build/3-discovery.md`, `nhcx-build/4-flow-data-mapping.md`, `mapping.json`, `nhcx-build/5-screen-plan.md`, `screens.json` +- This skill's section of `nhcx-build/0-capability.md` and `nhcx-build/2-planning.md` (the action per module) +- `stages/7-write-code/README.md` and every `7.N-*.md` this skill touches: the module ladder is fixed; the plan decides the files +- `references/fhir-knowledge.md` section 1: where the pins live +- `fhir/FHIR.md`: the builders and readers the modules 7.4 to 7.10 implement, so the plan names them + +## Do + +### 1. Place each module + +For each module this skill touches (its `SKILL.md` lists them) and each foundation module it builds or extends, write: + +| Field | Meaning | +| --- | --- | +| `skills` | A map from skill to action: `build`, `extend` or `reuse`. A module another skill already placed keeps its entry; add this skill and its action | +| `files` | The files it creates or changes, in the target's layout and naming (from stage 3). For a reused or extended module, the files that exist | +| `depends_on` | The modules that must exist first; the ladder's order is the floor, the plan may add more | +| `held_to` | The pin in `nhcx-package/fhir` (its file, from `references/material.md`), the payer fixture, or the rule (for modules with no bundle) | +| `copy_from` | What the module follows: its own Pseudo code section and the `fhir/FHIR.md` section it names | +| `tables` | The tables from `mapping.json` it reads and writes | +| `screens` | The screens from `screens.json` it serves (7.12 and 7.13 only) | + +`modules.json` holds one entry per module, in ladder order (7.1 to 7.13), whichever skill adds it. + +### 2. The transport's shape + +Decide once, and every module uses it: the transport kind from stage 1, and the functions of the contract in `references/transport-knowledge.md` section 2: `send`, the receiving end that hands the door a normalised envelope, `policies`, `participants`, `token`, and `thread` and `fetch_missed` where the kind has them. Name them here so 7.4 to 7.10 call the same thing. A stub of `send`, recording the path, recipient, workflow id, correlation id and bundle and returning `{"txn_id", "correlation_id", "api_call_id"}`, is what stage 9 injects. When stage 0 found an existing transport, name its functions and what wraps them. + +### 3. Configuration + +List every setting and where it lives (from stage 3): the transport kind, participant code, facility HFR id and name, cases directory, per-payer overrides for workflow ids, and the transport's own. For `own`: the ABDM client id and secret, the private key, the sessions, NHCX and registry addresses, and the NHCX signing key once onboarding gives it. For `adapter`: its URL, API key and callback secret. For `existing`: whatever its client reads. Name the environment variables or config keys in the target's convention. + +### 4. The archive + +The per-case archive path from stage 4, and which module writes it (7.3 for inbound, 7.1 for outbound). + +### 5. Test placement + +Where the offline test lives (from stage 3's "how tests are run"), and how the pin comparison is wired: canonical JSON, `created` excluded, one comparison per pin. + +## Write + +- `nhcx-build/6-code-plan.md` from `templates/6-code-plan.md`: the episode sections once, the modules table, and this skill's section. +- `nhcx-build/modules.json` in the shape of `templates/modules.json`. + +## Gate + +- [ ] `modules.json` has an entry, in ladder order, for every module this skill touches and every foundation module (7.13 in standalone mode). +- [ ] Every entry this skill touches has non-empty `files`, `depends_on` (7.1 may be empty), `held_to` and `copy_from`, and this skill in `skills` with its action. +- [ ] Every pin this skill owns appears in some module's `held_to`. +- [ ] The transport kind and its functions are named. +- [ ] The configuration list includes the transport kind, the participant code, the cases directory, and every setting the chosen transport needs. +- [ ] The test file's location and the pin comparison rule are written. + +## Common mistakes + +- Splitting the claim bundle builder across modules by leg, or by skill. One builder, one `leg` and `flow` argument, is what the pins expect; `nhcx-claim` extends what `nhcx-preauth` built. +- Planning a second transport for the reply legs. Same function; the reply legs add `x-hcx-correlation_id` to the headers. +- Planning new files for a module stage 0 found present. +- Planning the screens before the readers exist in the dependency list. diff --git a/plugins/nhcx/skills/nhcx-coverage/stages/7-write-code/7.1-config-and-transport.md b/plugins/nhcx/skills/nhcx-coverage/stages/7-write-code/7.1-config-and-transport.md new file mode 100644 index 000000000..2ad046569 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-coverage/stages/7-write-code/7.1-config-and-transport.md @@ -0,0 +1,131 @@ +# Module 7.1: configuration and the NHCX transport + +Purpose: the one path every message leaves by, whichever transport carries it. The settings, the transport chosen at stage 1 behind one `send`, the policy lookup, and the outbound half of the per-case archive. + +Skills: the foundation (`core/FOUNDATION.md`). Built whole by the first skill whose stage 0 finds it absent; every skill sends through it. + +## Depends on + +Nothing. First module. + +## Inputs + +- `nhcx-build/1-idea.md`: the transport, `existing`, `own`, or `adapter` because the user asked for it +- `nhcx-build/6-code-plan.md` sections 2 to 4 (the transport's functions, the configuration keys, the archive path) +- `references/transport-knowledge.md` section 2 (the contract), and section 3 (`own`), 4 (`existing`) or 5 (`adapter`) for the kind chosen +- With `adapter` only: `references/api-knowledge.md` sections 2 to 5, 7, 8 and 11 + +## Build + +### Settings + +Read from the target's configuration mechanism (stage 3). + +| Setting | Transport | Meaning | +| --- | --- | --- | +| transport kind | all | `existing`, `own` or `adapter` | +| participant code | all | The hospital's, with `@hcx`: `x-hcx-sender_code` | +| facility HFR id, name, phone | all | The provider Organization | +| cases directory | all | The per-case archive root | +| per-payer workflow id overrides | all | Optional, for a payer that insists on a code the table does not carry (`cancel` as 122) | +| ABDM client id and secret | own | The session token (`transport-knowledge.md` section 3.3) | +| private key | own | The PEM behind the certificate on the participant record, read from a file or a secret store | +| sessions, NHCX and registry addresses, `X-CM-ID` | own | From `nhcx-package/baseurl.yaml`; the sandbox by default | +| NHCX signing key | own | For the exchange's JWT on inbound calls. Empty until onboarding gives it, and logged while empty | +| adapter URL, adapter API key, callback secret | adapter | `references/api-knowledge.md` section 2. Also fill the adapter's `config.sample.json` into `nhcx-build/adapter.config.json`, secrets as `${ENV}` placeholders | +| whatever the existing client reads | existing | Named here, not duplicated | + +Secrets are read from configuration: never in code, never in `nhcx-build/`. + +### The transport + +One `send` with the signature in `transport-knowledge.md` section 2, and beside it `policies`, `participants`, `token`, `thread` and `fetch_missed`. What sits under them depends on the kind: + +| Kind | `send` | `policies`, `participants`, `token` | `thread`, `fetch_missed` | +| --- | --- | --- | --- | +| `own` | Seal and post (`transport-knowledge.md` sections 3.3 to 3.8): the token, the recipient's certificate, the protected header, a compact JWE, `{"payload"}` to `/v1/`, a `401` retried once | The participant service directly (sections 3.6 and 3.7) | `thread` reads the per-case archive; `fetch_missed` answers `unavailable` | +| `existing` | Calls the app's own client and maps its answer onto `{txn_id, correlation_id, api_call_id}` (section 4) | The app's own calls, or the participant service directly | What the app keeps; else as `own` | +| `adapter` | POSTs `{jwe_headers, fhir}` to `/fhir/out/` with the bearer key (`api-knowledge.md` sections 4 and 5) | `/internal/policies/search`, `/internal/participants/list`, `/token` | The adapter's ledger and `/internal/txn/*` (`api-knowledge.md` sections 7 and 8) | + +Common to every kind: + +1. A send without a recipient, a workflow id or the beneficiary's ABHA is refused before anything goes on the wire. +2. The recipient is the policy's processor: `recipient_of(row)` is `claim.recipient_code`, else `claim.payer_code` for an episode opened before the processor was kept. +3. A correlation id is passed only on the two answer legs, the communication reply and the payment acknowledgement. On a request the transport mints it (`own`: the message's own `api_call_id`). +4. A refusal raises `TransportError(code, message, protocol_response, retryable)`: the gateway's status and body (`own`), the adapter's `error.code` and `upstream_body` (`adapter`), or the existing client's error. A ProtocolResponse inside it is a refusal at the door; the caller records the payer's words. +5. The outbound message is archived before `send` returns: `//NNN--out.json` with what was sent and what came back, and a `transactions.txt` line (sequence, time, direction, path, workflow id, correlation id, api call id, txn id, outcome). With `own`, the archive entry is the `txn_id`. +6. The caller stores `txn_id`, `correlation_id` and `api_call_id` on the leg. + +## Rules + +- Use nhcx-adapter only when the user asked for it; `1-idea.md` records their words. Never propose it. +- Keep an existing NHCX integration and wrap it. Never put a second transport beside it. +- Seal and open JWEs only for `own`, and only with a JOSE library: `RSA-OAEP-256`, `A256GCM`, compact serialisation. Never hand-roll the cryptography. +- The workflow id goes out on every leg that has one; `x-hcx-ben-abha-id` goes out on every message. +- The sandbox refuses sends faster than one per 30 seconds per case (PAYR-1322). The transport does not throttle; the caller does. Say so in the docstring. +- The private key never leaves the server that receives callbacks, and never enters a log. + +## Validate + +- [ ] A send with no recipient, no workflow id or no beneficiary ABHA is refused before anything goes on the wire. +- [ ] The protected header of a send carries every mandatory field under the protocol's rules: sender and recipient with `@hcx`, a fresh `api_call_id`, a `correlation_id` equal to the `api_call_id` on a request and to the request's on an answer, the workflow id, `x-hcx-timestamp` in ISO 8601 with `+05:30`, `x-hcx-status` `request.initiated` or `response.complete`, and `x-hcx-ben-abha-id`. Observed on what the transport emits: the JWE header opened with a test key pair (`own`), the posted `jwe_headers` with the adapter's completion rules (`adapter`), the existing client's output (`existing`). +- [ ] The recipient is the episode's `recipient_code`, the policy's `processingid`, whenever the episode has one. +- [ ] A refusal raises `TransportError` carrying the code and the words the exchange or the adapter gave. With `own`, a `401` is retried once with a fresh token, and a second `401` raises. +- [ ] The archive file and the `transactions.txt` line exist after a send, with the sequence number zero-padded to three digits. +- [ ] Secrets are read from configuration, not present in code or in `nhcx-build/`. +- [ ] With `own`: a bundle sealed for a test certificate opens with its private key to the same bytes and the same protected header; the token is reused while fresh and fetched again when stale; a recipient's certificate is fetched once and then read from the cache. + +## Tests + +- Stub the HTTP layer and assert the URL, the headers and the body of one send with and one without a correlation id: `bearer_auth` and `{"payload"}` for `own`; the bearer key and `{jwe_headers, fhir}` for `adapter`. +- `own`: seal with a test key pair and open it again; check the header fields above; a `401` then a `202` sends twice with two tokens; a certificate in SPKI form loads as well as an X.509 one. +- `adapter`: a `502` with a ProtocolResponse `upstream_body` raises an error whose text carries the payer's `x-hcx-error_details` message; a `404` from `txn/related` is terminal, not retried. +- The archive sequence increments across two sends on one case. + +## Pseudo code + +The `own` transport's token, certificate cache, sealing and receiving end: `references/transport-knowledge.md` section 3.12. The adapter client: `references/api-knowledge.md` section 11. What every kind shares: + +``` +settings = { + transport: env("NHCX_TRANSPORT", "own"), # own | existing | adapter; adapter only when the user asked for it + participant_code: env("NHCX_PARTICIPANT_CODE"), # "@hcx" + facility: {hfr_id: env("NHCX_HFR_ID"), name: env("NHCX_FACILITY_NAME"), phone: ...}, + cases_dir: env("NHCX_CASES_DIR", "data/cases"), + workflow_overrides: parse_json(env("NHCX_WORKFLOW_IDS", "{}")), # {"1518@hcx": {"cancel": "122"}} + nhcx: {sessions: env("NHCX_SESSIONS_URL", "https://dev.abdm.gov.in/api/hiecm/gateway/v3/sessions"), # own + base: env("NHCX_BASE_URL", "https://apisbx.abdm.gov.in/hcx"), + registry: env("NHCX_REGISTRY_URL", "https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice"), + cm_id: env("NHCX_CM_ID", "sbx"), + client_id: env("NHCX_CLIENT_ID"), client_secret: env("NHCX_CLIENT_SECRET"), + private_key: read_secret(env("NHCX_PRIVATE_KEY_FILE")), signing_key: env("NHCX_SIGNING_KEY", "")}, + adapter: {url: env("NHCX_ADAPTER_URL"), api_key: env("NHCX_ADAPTER_API_KEY"), # adapter only + callback_secret: env("NHCX_CALLBACK_SECRET")}, +} + +transport = {"own": OwnTransport, "existing": ExistingTransport, "adapter": AdapterTransport}[settings.transport]() +# each offers send, policies, participants, token, thread, fetch_missed (transport-knowledge.md section 2) + +function recipient_of(row): return row.recipient_code or row.payer_code + +function ben_abha(claim_no): # the payer's Patient from the coverage answer, else the HMIS patient + row = claim_by_no(claim_no) + return digits(abha_in(row.patient_json) or patient(row.patient_id).abha) + +function with_hcx(code): return code if code.endswith("@hcx") else code + "@hcx" + +# the archive, outbound half; 7.3 writes the inbound half through the same function +function archive.record(claim_no, usecase, direction, payload): + folder = settings.cases_dir + "/" + (claim_no or "unmatched"); mkdir(folder) + n = next_sequence(folder) # 001, 002, ... + write(folder + f"/{n:03d}-{usecase}-{direction}.json", pretty(payload)) + append(folder + "/transactions.txt", f"{n:03d} {now()} {direction} {payload.path} wf={payload.workflow_id} " + f"cid={payload.correlation_id} acid={payload.api_call_id} txn={payload.txn_id} {payload.outcome}") + return f"{claim_no or 'unmatched'}/{n:03d}" +``` + +## Done when + +- Validate passes for the transport chosen. +- `own`: the onboarding the user must do is written into `nhcx-build/7-modules/7.1.md`: the credentials, the key and certificate, the participant record, the `endpoint_url`, and the NHCX signing key to ask NHA for. `adapter`: `nhcx-build/adapter.config.json` exists with placeholders. `existing`: the wrapper and every gap it closed are listed. +- `nhcx-build/7-modules/7.1.md` is written. diff --git a/plugins/nhcx/skills/nhcx-coverage/stages/7-write-code/7.10-communication-and-payment.md b/plugins/nhcx/skills/nhcx-coverage/stages/7-write-code/7.10-communication-and-payment.md new file mode 100644 index 000000000..271d56732 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-coverage/stages/7-write-code/7.10-communication-and-payment.md @@ -0,0 +1,124 @@ +# Module 7.10: communication and payment + +Purpose: the two legs the payer starts. A CommunicationRequest is classified as a query, a notification or a note and answered accordingly; a PaymentNotice is recorded, matched to its claim, and acknowledged. + +Skills: `nhcx-communication` (classification, the notification acknowledgement, the reply) and `nhcx-payment` (the payment notice and its acknowledgement). Validate rows 1, 3, 4 and 5 are the communication half's; rows 2, 6 and 7 the payment half's; row 8 is both. + +## Depends on + +7.1 to 7.3, 7.7, 7.11 (for the payer's query mode; build 7.11's adapter table first if not yet). + +## Inputs + +- `references/flow-knowledge.md` section 3 (the two payer kinds, the classification rule) and section 1 rows "Payment notice" and "Communication" +- `references/fhir-knowledge.md` sections 9 and 10 +- Pins: `nhcx-package/fhir/B4/communication-request.json` (the payer's message), `B4/communication-response.json` (the reply), `nhcx-package/fhir/B7/payment-notice-ack.json` +- Payer messages: `nhcx-package/fhir/C6/C6-preauth-query-wf24.json` and `C6/C6-claim-query-wf27.json` (generic queries), `C6/C6-notification-wfN02.json` (PMJAY notification), `nhcx-package/fhir/C9/*.json` (payment notices) + +## Build + +### Classification + +`classify_communication(adapter, reason_code, intent) -> kind`, in order: a `resubmit` payer's request is a notification; `intent proposal` is a notification, `order` a query; then `reasonCode`: absent, `additionalinfo`, `questionnaire`, `query` is a query, anything else (`tatquery`, `grievance`, `walletupdate`, `policychange`, `claimarbitration`, with `claimArbitartion` folded in) a notification. A bare `Communication` with no request is a note: recorded, shown, never acted on. + +### Receiving + +`parse_communication_request(bundle)`: the Task's status, intent, reason; the CommunicationRequest's id, `basedOn` (the Claim), one question per `payload[].contentString`; the leg asked about (from the Claim's `use` or the `basedOn` identifier). Store a `claim_query` row keyed on the message's correlation id with `kind`, `stage`, `questions_json`, status `open`. + +### Acknowledging a notification + +`build_acknowledgement_bundle(query_id)`: the payer's own bundle sent back with `Task.status` flipped to `completed`, the reason echoed and the provider Organization first, on `v1/communication/on_request` with the request's correlation id and workflow id echoed in `jwe_headers`. Sent by `acknowledge_notification` from outside the callback (the desk's next request, or a worker). Status `acknowledged`. + +### Answering a query (communication payer) + +`build_communication_bundle(query_id, text, document_ids)`: a TaskBundle with a Task `deliver`, `completed`, including the Communication; the Communication `basedOn` the request (never `inResponseTo`) and `about` the Claim, its text a `contentString`, each document a `contentAttachment` under the document-type extension (its url is participant-defined: read it from configuration; the pin comparison takes the pin's own url); the CommunicationRequest echoed; then the Claim, Patient, provider Organization, payer Organization, Practitioner and Coverage lifted from the queried leg's bundle as sent. This bundle carries `meta.lastUpdated` and `timestamp` (the IG example does). Sent on `v1/communication/on_request` with the request's correlation id and workflow id. Status `answered`. + +For a `resubmit` payer the answer is not here: it is 7.7's query answer on a fresh thread. The inbox item for a PMJAY query is the leg's `query_note`, and its reply box calls `submit_preauth` or `submit_claim` with the reply. + +### Payment notice + +`parse_payment_notice(bundle)`: `PaymentNotice.amount`, `paymentStatus`, `paymentDate`, the `request` reference's identifier (the claim number), `payment` identifier (the UTR when settled), the `PaymentReconciliation` details when present. `record_payment` matches the claim number, dedupes on the correlation id, stores `claim_payment` and `claim_payment_detail`, and stamps the episode `payment`/`noticed` or `paid`. + +### Payment acknowledgement + +`build_payment_ack(payment_id)`: a TaskBundle in the shape of `B7/payment-notice-ack.json`, sent on `v1/paymentnotice/on_request` with the notice's correlation id and, for PMJAY, workflow `17`; for a generic payer the notice's own workflow id echoed (`None` in the adapter table means echo). Sent by `acknowledge_payment` from outside the callback. `ack_status` `sent` or `error`. + +## Rules + +- The reply names the request in `Communication.basedOn`, never `inResponseTo`. +- A `resubmit` payer's CommunicationRequest is always a notification, whatever it says. +- A notification is acknowledged at once and the case is left alone. +- The acknowledgement and the reply are the only two sends that carry `x-hcx-correlation_id` (with the payment acknowledgement). + +## Validate + +- [ ] `B4/communication-response.json` pin: the builder fed the request pin (`B4/communication-request.json`) and the pre-auth pin (`B3/preauth-request.json`) produces the response pin byte for byte (`meta.lastUpdated`, `timestamp` and `authoredOn` excluded). +- [ ] `B7/payment-notice-ack.json` pin comparison passes. +- [ ] Classification: the generic query (`C6/C6-preauth-query-wf24.json`: `intent order`, `additionalinfo`) is a query; the PMJAY notification (`C6/C6-notification-wfN02.json`: `intent proposal`, `information`) is a notification; the same PMJAY bundle under a `communication` adapter with `intent order` is a query; a bare Communication is a note. +- [ ] The reply's `Communication.basedOn` names the request and `inResponseTo` is absent. +- [ ] The acknowledgement and the reply carry `x-hcx-correlation_id` equal to the request's; the workflow id is echoed. +- [ ] Two deliveries of one notice create one `claim_payment` row. +- [ ] The PMJAY acknowledgement carries workflow `17`; the generic one echoes the notice's. +- [ ] No send happens inside the callback (7.1 stub sees zero sends during receipt). + +## Tests + +- The two pin comparisons. +- Classification table as a parametrised test. +- B6, B7, C6, D8, D13 and the notification rows from the matrix. + +## Pseudo code + +Classification, the acknowledgement, the reply and the payment reader: `fhir/FHIR.md` sections 7 and 8. Wiring: + +``` +APPLY["inbound_request"] = function (row, env): + kind = resource_types(env.fhir) + if "PaymentNotice" in kind: record_payment(row, env) + elif "CommunicationRequest" in kind: receive_communication(row, env) + elif "Communication" in kind: record_note(row, env) # a bare Communication: shown, never acted on + +function receive_communication(row, env): + p = fhir.parse_communication_request(env.fhir); adapter = payers.for_claim(row) + kind = fhir.classify_communication(adapter, p.reason, p.intent) + q = insert("claim_query", {claim_id: row.id, correlation_id: env.jwe_headers["x-hcx-correlation_id"], request_id: p.request_id, + workflow_id: env.jwe_headers["x-hcx-workflow_id"], sender_code: env.jwe_headers["x-hcx-sender_code"], + kind, stage: leg_asked_about(row, p), reason_code: p.reason, intent: p.intent, questions_json: p.questions, + request_json: env.fhir, status: "open", received_at: now()}) + if kind == "notification": enqueue(acknowledge_notification, q.id) # sent outside the callback + +function acknowledge_notification(query_id): + q = query(query_id); row = claim(q.claim_id) + bundle = fhir.build_acknowledgement_bundle(q.request_json, settings.facility) + r = transport.send("v1/communication/on_request", bundle, q.sender_code, workflow_id = q.workflow_id, correlation_id = q.correlation_id, claim_no = row.claim_no, usecase = "communication-ack") + update(q, {status: "acknowledged", reply_txn_id: r.txn_id, reply_api_call_id: r.api_call_id, replied_at: now()}) + +function answer_query(query_id, text, document_ids): # communication payer + q = query(query_id); row = claim(q.claim_id) + if payers.for_claim(row).query_mode == "resubmit": return submit_preauth(row.id, reply = text) if q.stage == "preauth" else submit_claim(row.id, reply = text) + sent = (preauth(row.id) if q.stage == "preauth" else submission(row.id)).request_json + bundle = fhir.build_communication_bundle(q, text, [doc_with_bytes(i) for i in document_ids], sent, settings.facility, payer_of(row), now_ist()) + r = transport.send("v1/communication/on_request", bundle, q.sender_code, workflow_id = q.workflow_id, correlation_id = q.correlation_id, claim_no = row.claim_no, usecase = "communication-reply") + update(q, {status: "answered", reply_text: text, reply_document_ids: document_ids, reply_txn_id: r.txn_id, replied_at: now()}); stamp_case(row.id) + +function record_payment(row, env): + p = fhir.parse_payment_notice(env.fhir) + pay = insert_or_ignore("claim_payment", {claim_id: row.id, correlation_id: env.jwe_headers["x-hcx-correlation_id"], workflow_id: env.jwe_headers["x-hcx-workflow_id"], + sender_code: env.jwe_headers["x-hcx-sender_code"], amount: p.amount, payment_status: p.payment_status, payment_date: p.payment_date, + utr: p.utr, notice_json: env.fhir, ack_status: "pending", received_at: now()}) + if not pay: return # the unique constraint caught a redelivery + for d in p.details: insert("claim_payment_detail", {payment_id: pay.id, type: d.type, amount: d.amount}) + enqueue(acknowledge_payment, pay.id) + +function acknowledge_payment(payment_id): + pay = payment(payment_id); row = claim(pay.claim_id); adapter = payers.for_claim(row) + bundle = fhir.payment_ack(submission(row.id).claim_ref or row.claim_no, now_ist(), settings.facility, payer_of(row)) + wf = adapter.workflow_ids.payment_ack or pay.workflow_id # 17 for PMJAY; echo for a generic payer + r = transport.send("v1/paymentnotice/on_request", bundle, pay.sender_code, workflow_id = wf, correlation_id = pay.correlation_id, claim_no = row.claim_no, usecase = "payment-ack") + update(pay, {ack_status: "sent", ack_txn_id: r.txn_id, ack_api_call_id: r.api_call_id, acked_at: now()}); stamp_case(row.id) +``` + +## Done when + +- Validate passes. +- `nhcx-build/7-modules/7.10.md` is written. diff --git a/plugins/nhcx/skills/nhcx-coverage/stages/7-write-code/7.11-state-and-payer-adapters.md b/plugins/nhcx/skills/nhcx-coverage/stages/7-write-code/7.11-state-and-payer-adapters.md new file mode 100644 index 000000000..94fbfc313 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-coverage/stages/7-write-code/7.11-state-and-payer-adapters.md @@ -0,0 +1,145 @@ +# Module 7.11: state and payer adapters + +Purpose: two small tables of truth the whole build reads. The payer adapter says how a payer behaves; the stage machine says where an episode stands and what it waits for. + +Skills: the foundation (`core/FOUNDATION.md`). The first skill builds the payer adapter table whole; each skill adds the `case_stage` branches and the `next_actions` rows for its own legs. + +## Depends on + +7.2. (7.7 to 7.10 call it; build the adapter table as early as 7.4 needs the participant codes.) + +## Inputs + +- `references/flow-knowledge.md` sections 2, 3 and 4, whole +- `nhcx-build/1-idea.md` (the payers in scope) + +## Build + +### The payer adapter + +A table keyed by participant code (normalised: `1518` and `1518@hcx` are one key), each entry holding: + +| Field | PMJAY | Generic | +| --- | --- | --- | +| `query_mode` | `resubmit` | `communication` | +| `workflow_ids` | the PMJAY column of flow-knowledge section 2 | the generic column; `payment_ack` is `None` (echo) | +| `program_code` | `AB-PMJAY` | none | +| `auth_requirements` | asked | asked | +| `status_enquiry` | refused; do not offer | offered | +| `claim_resubmit` | none; reprocess only | `16` | +| `payer_system` | the identifier system for the payer Organization | same | + +`adapter_for(participant_code)` returns the entry or the generic default. `for_claim(row)` reads the episode's payer code. Overrides from configuration (7.1) merge on top, per payer, so a payer that insists on `cancel` as 122 is one config line. + +### Stage and sub-stage + +Stages: `eligibility`, `preauth`, `enhancement`, `claim`, `payment`. Sub-stages: `draft`, `checking`, `eligible`, `not-eligible`, `requested`, `resubmitted`, `answered`, `queried`, `approved`, `partial`, `rejected`, `cancelling`, `cancelled`, `refused`, `noticed`, `paid`. Send kind to sub-stage: `preauth`, `claim`, `enhancement` set `requested`; `*_resubmit` sets `resubmitted`; `*_query_response` and `enhancement_resubmit` set `answered`. `requested`, `answered`, `resubmitted` mean "with the payer". + +`case_stage(row, ...) -> (stage, sub_stage)`: a payment notice wins, then the filed claim, then the pre-auth (stage `enhancement` if the last submission kind was one), then a saved draft, then the eligibility status. An open communication query on a leg that is with the payer flips the sub-stage to `queried`. + +`stamp_case(claim_id)`: recompute and write both onto the episode. Called after every leg write by 7.3, 7.4 to 7.10. + +### Next actions + +The table in `flow/FLOW.md` ("The status line and the actions") and `flow/flow.json` `next_actions` is the specification; the labels are used verbatim. + +`next_actions(claim_id) -> [{label, tab, tone}]`, first is what the case waits for: an unanswered query always leads with "Answer the payer (n)"; the leg's own reply box only for a `resubmit` payer, a `communication` payer is sent to the inbox; a claim refused at the door offers "send again" while `claim_send_kind` still yields a kind, else "Ask for a reprocess"; after a rejection the pre-auth offers a fresh 12; a payer whose adapter refuses status enquiry never gets a "Ask status" action. + +## Rules + +- An unmapped payer is generic. +- The two words are derived, never set by a screen. +- Stamp after every write. A test that checks state after every step is what makes stage 8 possible. + +## Validate + +- [ ] `adapter_for("1518@hcx")` and `adapter_for("1518")` return the PMJAY entry; an unknown code returns generic. +- [ ] The PMJAY `workflow_ids` table equals flow-knowledge section 2's PMJAY column for every kind listed; the generic table has `payment_ack` as echo and `claim_query_response` as `151`. +- [ ] A configuration override for one kind changes only that kind. +- [ ] `case_stage` on each seeded state (draft; checking; eligible; pre-auth submitting; approved; queried by communication; enhancement requested; claim submitting; payment noticed; paid) returns the expected pair (write the table in the test). +- [ ] `next_actions` leads with the query when one is open; offers no status enquiry for PMJAY; offers a fresh 12 after a rejection. +- [ ] For every row of `flow.json` `next_actions`, the seeded state yields that label, character for character. +- [ ] After every leg write in 7.4 to 7.10, `claim.stage` and `sub_stage` equal `case_stage` recomputed. + +## Tests + +- A parametrised table for `case_stage`. +- A parametrised table for `next_actions`. +- The adapter lookups and the override. + +## Pseudo code + +``` +QUERY_MODE_RESUBMIT = "resubmit"; QUERY_MODE_COMMUNICATION = "communication" + +PMJAY = {"name": "PMJAY", "query_mode": QUERY_MODE_RESUBMIT, "program_code": "AB-PMJAY", "auth_requirements": true, + "status_enquiry": false, "payer_system": "https://nhcx.abdm.gov.in", + "workflow_ids": {"preauth": "12", "preauth_resubmit": "121", "preauth_query_response": "19", "enhancement": "13", "enhancement_resubmit": "131", + "cancel": "PC01", "claim": "15", "claim_query_response": "161", "claim_resubmit": null, "payment_ack": "17", "reprocess": "36", "release": "36"}} +GENERIC = {"name": "generic", "query_mode": QUERY_MODE_COMMUNICATION, "program_code": null, "auth_requirements": true, "status_enquiry": true, + "payer_system": "https://nhcx.abdm.gov.in", + "workflow_ids": {... as PMJAY except "claim_query_response": "151", "claim_resubmit": "16", "payment_ack": null}} # null = echo the notice's id +ADAPTERS = {"1518": PMJAY} # keyed without @hcx + +function adapter_for(participant_code): + key = (participant_code or "").split("@")[0] + base = deepcopy(ADAPTERS.get(key, GENERIC)) + for (k, v) in settings.workflow_overrides.get(with_hcx(key), {}): base.workflow_ids[k] = v + return base + +function for_claim(row): return adapter_for(row.payer_code) + +STAGES = ["eligibility", "preauth", "enhancement", "claim", "payment"] +KIND_TO_SUB = {"preauth": "requested", "claim": "requested", "enhancement": "requested", "preauth_resubmit": "resubmitted", "claim_resubmit": "resubmitted", + "preauth_query_response": "answered", "claim_query_response": "answered", "enhancement_resubmit": "answered"} +WITH_PAYER = {"requested", "answered", "resubmitted"} + +function leg_sub_stage(leg): + if leg.status == "submitting": return KIND_TO_SUB.get(leg.submission_kind, "requested") + return {"approved": "approved", "partial": "partial", "queried": "queried", "rejected": "rejected", "error": "refused", + "cancelling": "cancelling", "cancelled": "cancelled", "draft": "draft"}.get(leg.status, leg.status) + +function case_stage(row): + paid = sum(p.amount for p in payments(row.id) if p.payment_status in ("paid", "cleared")) + if payments(row.id): return ("payment", "paid" if paid > 0 else "noticed") + cs = submission(row.id) + if cs and cs.status != "draft": + sub = leg_sub_stage(cs) + if sub in WITH_PAYER and "claim" in open_query_stages(row): sub = "queried" + return ("claim", sub) + pa = preauth(row.id) + if pa and pa.status != "draft": + stage = "enhancement" if pa.submission_kind in ("enhancement", "enhancement_resubmit") else "preauth" + sub = leg_sub_stage(pa) + if sub in WITH_PAYER and "preauth" in open_query_stages(row): sub = "queried" + return (stage, sub) + if pa: return ("preauth", "draft") + return ("eligibility", {"checking": "checking", "eligible": "eligible", "not-eligible": "not-eligible"}.get(row.status, "draft")) + +function stamp_case(claim_id): (s, sub) = case_stage(claim(claim_id)); update(claim(claim_id), {stage: s, sub_stage: sub}) + +function next_actions(claim_id): + row = claim(claim_id); adapter = for_claim(row); out = []; pa = preauth(claim_id); cs = submission(claim_id) + open_q = open_queries(claim_id) + if open_q: out.append({label: f"Answer the payer ({len(open_q)})", tab: "communication" if adapter.query_mode == "communication" else ("claim" if open_q[0].stage == "claim" else "preauth"), tone: "primary"}) + if row.status in ("draft", "not-eligible", "error"): out.append({label: "Check cover", tab: "cover", tone: "primary"}) + elif not row.plan_id: out.append({label: "Fetch the plan", tab: "plan", tone: "primary"}) + elif not pa or pa.status == "draft": out.append({label: "Submit the pre-authorisation", tab: "preauth", tone: "primary"}) + elif pa.status == "queried" and adapter.query_mode == "resubmit": out.append({label: "Answer the query", tab: "preauth", tone: "primary"}) + elif pa.status == "rejected": out.append({label: "Send a fresh pre-authorisation", tab: "preauth", tone: "primary"}) # 12, never 121 + elif pa.status == "error": out.append({label: "Send again", tab: "preauth", tone: "warn"}) + elif pa.status in ("approved", "partial") and (not cs or cs.status == "draft"): + out.append({label: "Discharge and claim", tab: "claim", tone: "primary"}) + if enhancement_lines(claim_id): out.append({label: "Send the enhancement", tab: "lines", tone: "default"}) + out.append({label: "Cancel the pre-authorisation", tab: "preauth", tone: "danger"}) + elif cs and cs.status == "error": out.append({label: "Send again" if claim_send_kind(claim_id) else "Ask for a reprocess", tab: "claim", tone: "warn"}) + elif cs and cs.status == "rejected": out.append({label: "Ask for a reprocess", tab: "claim", tone: "warn"}) + for p in payments(claim_id): if p.ack_status != "sent": out.append({label: "Acknowledge the payment", tab: "payments", tone: "default"}) + if adapter.status_enquiry and (pa or cs): out.append({label: "Ask status", tab: "enquiries", tone: "default"}) + return out +``` + +## Done when + +- Validate passes. +- `nhcx-build/7-modules/7.11.md` is written. diff --git a/plugins/nhcx/skills/nhcx-coverage/stages/7-write-code/7.12-screens.md b/plugins/nhcx/skills/nhcx-coverage/stages/7-write-code/7.12-screens.md new file mode 100644 index 000000000..130115d38 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-coverage/stages/7-write-code/7.12-screens.md @@ -0,0 +1,124 @@ +# Module 7.12: screens + +Purpose: the screens in `screens.json`, built the way the target builds screens, every value derived from a stored message, plus the JSON state address a driver reads. + +Skills: the foundation (`core/FOUNDATION.md`) builds the case screen shell: all eight tabs, the status line, the state address, the page-load polls, the cases list. Each skill fills its own tabs and screens, and adds its legs to the state address. + +## Depends on + +7.1 to 7.11. Screens come last because they render what the readers stored. + +## Inputs + +- `nhcx-build/5-screen-plan.md`, `nhcx-build/screens.json` +- `nhcx-build/3-discovery.md` (screen conventions, helpers, styling) +- `nhcx-package/docs/03-Building a Provider/09-UI Guide.md` +- `ui/UI-GUIDE.md` for the route shape, the state address and the helper vocabulary; two or three route modules of the target for its conventions + +## Build + +### The case screen walks the flow + +Tabs in the order and with the labels of `flow.json` `tabs`; the Pre-authorisation tab appears once the verdict is `eligible`. Above the tabs the status line and the actions from 7.11. Each step F1 to F13 has its control on the tab the flow names, offered only when the step's `holds` hold. The page-load polls run in the order `flow.json` `page_load_polls` gives, bounded, before rendering. + +### Every screen in `screens.json` + +For each screen: the route, the handler, the render. Each value in the screen's `values` list is rendered from the element it names; the empty state is what shows before the message arrived. A decision-bearing value with no message renders as waiting. There is no status control anywhere. + +### The case screen + +The timeline: one row per leg row and per archived message, in time order, with direction, path, workflow id label (7.8's labels), status word, and the payer's words verbatim (`disposition`, item remarks, process notes, `x-hcx-error_details` on a refusal). The actions open now are `next_actions` from 7.11, rendered as buttons that post to the senders; the first action is highlighted. Each pane (cover, plan, lines, forms, documents, pre-auth, communication, claim, payments) shows only when its leg exists. + +### The JSON state address + +`GET /state` returns everything the case screen shows, as JSON, after the same polls the screen runs: stage, sub-stage, next actions, each leg's status and ids, the inbox items, the payments. Stage 10's drivers read this. + +### Polling on the request path + +Where there is no worker, the case screen and the state address run 7.3's poll fallback for any leg that is `submitting` or `checking` before rendering. Bound it: one poll per leg per request, a short timeout, and never a send. + +### Standalone mode + +Also the capture screens from 7.13, in the same style. + +## Rules + +- No screen shows a decision the exchange has not sent. +- Nothing the exchange already knows is typed. Rates, payer names, `preAuthRef`, the approved amount, the UTR and the payer's wording are rendered, never fields. +- An unknown case is a 404, never an invented page. +- Screens answer within two seconds; the poll is bounded. +- Forms post and the page re-renders; no client-side rendering is needed. + +## Validate + +- [ ] The case page's tabs are the eight of `flow.json`, in order, with those labels (string test on the HTML). +- [ ] Every step of `flow.json` with a `routes` entry answers on that route (or the plan's equivalent recorded in `screens.json`). +- [ ] Every route in `screens.json` answers 200 for a seeded case and 404 for an unknown one. +- [ ] A case with a pre-auth `submitting` and no answer renders "waiting" (or the plan's word) and neither "approved" nor "rejected" appears on the page. +- [ ] After a 21 is applied (`nhcx-package/fhir/C5/C5-approved-wf21.json`), the page shows its `preAuthRef` and approved amount verbatim. +- [ ] After a payment notice is applied (`nhcx-package/fhir/C9/C9-notice-wf30.json`), the payments screen shows its UTR verbatim. +- [ ] After a query is applied, the inbox shows the request's `contentString` text verbatim. +- [ ] No `` or `, unless spec.typed +``` + +### Which actions to offer + +``` +function actions(case): + out = [] + q = open_queries(case) + if q: out.append(action("Answer the payer (n)", tab = inbox if payer.query_mode == communication else leg_tab)) + leg = current_leg(case) + if leg.status == "rejected" and leg.kind == "preauth": out.append(action("Send a fresh pre-authorisation", sends = 12)) + if leg.status == "approved" and no_request_in_flight(case) and leg.kind == "preauth": + out.append(action("Enhance", sends = 13)); out.append(action("Cancel", sends = PC01)); out.append(action("Discharge and claim", tab = claim)) + if leg.kind == "claim" and leg.status == "rejected": out.append(action("Ask for a reprocess", sends = 36)) + if payer.status_enquiry: out.append(action("Ask status", sends = task status)) + for notice in unacknowledged_notices(case): out.append(action("Acknowledge payment", sends = 17 or echo)) + return out +``` + +## Component vocabulary (suggested, for a standalone build) + +A suggested set of helpers. Server-rendered HTML from Python functions returning strings, styled by the 0build kit 0.5.4 from jsDelivr. Components: `z-card`, `z-button`, `z-input`, `z-select`, `z-table`, `z-nav`, `z-tab` with `data-z-switcher`, `z-alert`, `z-badge`, `z-breadcrumb`. Utilities take values through custom properties (`class="display-grid gap" style="--gap: 4"`). Helpers a screen needs: `page`, `card`, `stack`, `table`, `grid`, `field`, `text_input`, `select`, `button`, `post_button`, `confirm_form`, `badge`, `when`, `muted`, `dl`, `tabs`, `stat`, `empty_state`. Tables cap at about eight columns; merge facts into a main line with a muted sub-line. Every state-changing action that is not a full form is a `post_button`; destructive ones confirm. + +In `integrate` mode use the HMIS's own components and conventions; the layouts above are the content, not the markup. diff --git a/plugins/nhcx/skills/nhcx-insurance/SKILL.md b/plugins/nhcx/skills/nhcx-insurance/SKILL.md new file mode 100644 index 000000000..b19b856da --- /dev/null +++ b/plugins/nhcx/skills/nhcx-insurance/SKILL.md @@ -0,0 +1,95 @@ +--- +name: nhcx-insurance +description: Add the NHCX insurance plan (the payer's package master) to a hospital information system or a standalone claims desk. Request it once per facility and policy, parse both published shapes, reuse it across episodes, and quote treatment lines from it, held to the pinned bundle. Starts by checking whether the app already fetches a plan or quotes packages, and whether the coverage it depends on exists, then builds, extends or reuses only what is missing. Self-contained; needs no other skill installed. Use for the insurance plan request, the package master, package rates, quoting line items, NHCX use cases B2 and D1, flow steps F4 and F7. +--- + +# NHCX insurance: the package master and the lines quoted from it + +This skill asks the payer for its package master on an eligible episode, flattens it into rows the desk can search, reuses a held master on later episodes, and lets the desk quote the treatment as lines priced by the plan. Every package code, rate, tier, document requirement and questionnaire the later use cases send comes from here. + +Read `core/LADDER.md` first. It holds the ladder every NHCX skill walks: the definition of compliant, the stages, the workspace, how to run a stage, and the rules. This folder carries everything it needs and runs on its own; the other six NHCX skills are separate folders, and none of them has to be installed. Paths starting `core/`, `stages/`, `references/`, `fhir/`, `flow/`, `ui/`, `templates/` or `scripts/` are relative to this folder. Paths starting `nhcx-package/` are in the NHCX package, which `scripts/fetch-package.sh` fetches into the target project beside `nhcx-build/`; `references/material.md` names the package file of every pin by its label. + +## What this skill covers + +| | | +| --- | --- | +| Flow steps | F4 Fetch the package master, F7 Quote the treatment | +| Tabs | Insurance plan (tab 2): the master search, a package view, "All forms". Line items (tab 3): what is quoted, what goes with it, the whole master | +| Wire | `v1/insuranceplan/request`: a TaskBundle with a Task `poll` and inputs `policyNumber` and `providerId`, workflow id = the case number; `on_request` back with the InsurancePlan and Questionnaires (workflow 5 from the SHA) | +| Next actions | "Fetch the package master", "Quote the treatment" | +| Use cases | B2 Request insurance plan; D1 Fetch the insurance plan | +| Module | 7.5, whole | +| Pins | `insurance`: `nhcx-package/fhir/B2/insurance-plan-request.json` | +| Payer fixtures | `nhcx-package/fhir/C4/C4-response-pmjay.json` (package-based, PMJAY), `nhcx-package/fhir/C4/C4-response-generic.json` (coverage-based) | +| Tables | `claim_plan`, `claim_plan_benefit`, `claim_plan_form`, `claim_line`; `claim.plan_id` | +| FHIR | `fhir/FHIR.md` section 3; `references/fhir-knowledge.md` section 4 | + +## Needs and hands on + +Needs: an episode with a policy code, a payer code and a coverage verdict `eligible`. That is the coverage use case's work (`nhcx-coverage`); stage 0 checks for it below, whichever way the app got it. + +Hands on: a plan `ready` on the episode, with benefits (rate, kind, conditions, tiers and implants, document requirements) and forms by url; quoted lines with integer quantities at the plan's rates, tiers carrying `parent_code`. Pre-authorisation builds the auth-requirements items, the Claim items, the forms and the documents from these. + +## Capability check + +Stage 0 (`stages/0-capability-check.md`) gives every capability below a verdict: search for the markers, run the check, record what was observed. + +### Own + +| Id | What | Look for | Present when (observed) | +| --- | --- | --- | --- | +| `insurance.request-builder` | `build_plan_request` | `insuranceplan/request`, `policyNumber`, `providerId`, `insurance-request-generic` | Fed the pin's data, it produces the `insurance` pin byte for byte (this bundle has no `created`) | +| `insurance.plan-parser` | `parse_plan_bundle`, both published shapes merged on package code | `InsurancePlan`, `specificCost`, `coverage[].benefit`, `Claim-SupportingInfoRequirement`, `Claim-Condition`, `stgquestionnaire` | Fed `C4-response-pmjay.json`, it yields benefits with a non-empty rate, at least one requirement with a code and a `documentationUrl`, and forms keyed by url with questions; fed `C4-response-generic.json`, it yields benefits from `coverage[].benefit[].limit[]` | +| `insurance.plan-leg` | F4: send, store, settle | a plan table with a status of `fetching`, `ready`, `empty`, `error` | With the 7.1 stub: one send on `v1/insuranceplan/request`, workflow id = the claim number, the three ids on the plan row; `C4-response-pmjay.json` applied through the door settles `ready` and replaces benefits and forms whole | +| `insurance.plan-reuse` | One plan per facility and policy | a lookup on policy code, provider id and payer before sending | A second episode on the same policy, provider and payer takes the held plan with zero sends (7.5 Validate, row 3) | +| `insurance.lines` | F7: lines from the plan | `add_line`, a line table with `parent_code` and integer quantities | A procedure line takes the plan's rate as `unit_price`; a tier carries `parent_code`; refused: a code the plan lacks, a tier the procedure does not offer, a duplicate, a zero quantity, anything before the plan is `ready` (7.5 Validate, rows 4 and 5) | +| `insurance.screens` | The Insurance plan and Line items tabs | the master search, the package view, the quoting page | Rates, tiers and requirements render from the stored plan; no rate is an input anywhere | + +### Foundation + +All six capabilities in `core/FOUNDATION.md`. Present when the coverage use case built them; `foundation.storage` is partial until this skill's four tables exist. + +### Prerequisites + +The coverage use case owns these (`nhcx-coverage`). The checks are here, so that skill need not be installed. + +| Capability | Why | Look for | Present when (observed) | +| --- | --- | --- | --- | +| `coverage.episode` | The plan is keyed on the episode's policy and payer | an episode table with `claim_no`, `member_id`, `policy_code`, `payer_code` | Opening an episode from a policy row stores a unique claim number, the member id, the policy code and the payer code | +| `coverage.check-leg`, `coverage.response-reader` | F4 holds `eligible`; without a verdict there is nothing to fetch for | a send on `v1/coverageeligibility/check`; `inforce` read from `CoverageEligibilityResponse` | With a stubbed client the check sends with workflow id = the claim number; the answers in `nhcx-package/fhir/C3` applied to the episode settle it `eligible` or `not-eligible` | + +### Host facts + +Billing lines and the charge master (for reconciliation only, never for prices); whether a line can carry a payer package code and a category. + +## The ladder, for this skill + +| Stage | What is specific here | +| --- | --- | +| 0 | The tables above. | +| 1 | Confirm the shared page, or write it if this skill runs first on the app. Own rows: B2, D1. | +| 2 | Risks: one plan per facility and policy (a second request while one is open is PAYR-1406); a PMJAY master runs to tens of megabytes (56 MB seen); prices from the plan only. | +| 3 | The host facts above. | +| 4 | Confirm the homes of `claim_plan*` and `claim_line`, or write every table's home if this skill maps first. The plan request's source map; the parser's destinations; where the raw master is kept (the archive, or a column that holds tens of megabytes). | +| 5 | The Insurance plan and Line items tabs; actions F4, F7. | +| 6 | 7.5, and the foundation modules stage 0 found absent or partial. | +| 7 | 7.5, as far as its verdict says. | +| 8 | 7.5's Validate section whole. | +| 9 | The pin comparison; parser tests on both shapes; matrix rows B2 and D1, and the reuse case; the cross-cutting rows on the plan thread. | +| 10 | Rung 1. Rung 3 walks B2; rung 4 walks D1. | +| 11 | This skill's section. | + +## Rules for these legs + +- Prices come from the plan, never from a form and never from the HMIS charge master. `unit_price` is not editable on any screen. +- The master is keyed on policy code, provider id and payer. A facility empanelled under two policies holds two. +- Reuse before request. Ask only when nothing is held or the desk asks to refresh; a refetch replaces benefits and forms whole. +- Tiers are modifiers on the wire: a tier line carries `parent_code` and rides on its procedure's `Claim.item.modifier` when the pre-auth bundle is built. +- Questions sit on `item.prefix` more often than on `item.text`. A `/questionnaire/` url is a policy form; a `/stgquestionnaire/` url a treatment guideline. +- The validator cannot check a whole master; skip it at rung 2 and say so. + +## Done when + +- Every gate in this skill's block of `nhcx-build/STATE.md` is closed with evidence. +- The insurance pin passes; both parser shapes pass; the reuse case sends nothing. +- The compliance points in `core/LADDER.md` hold for F4 and F7. diff --git a/plugins/nhcx/skills/nhcx-insurance/core/FOUNDATION.md b/plugins/nhcx/skills/nhcx-insurance/core/FOUNDATION.md new file mode 100644 index 000000000..2037811b9 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-insurance/core/FOUNDATION.md @@ -0,0 +1,65 @@ +# The foundation: what every skill stands on + +Six modules carry every leg, and no one skill owns them. Every skill's stage 0 checks them. The first skill that finds one absent or partial builds or extends it in its own stage 7, and records itself as `Built by` in the Foundation block of `nhcx-build/STATE.md`. Later skills find it present and reuse it. An HMIS that already has one (an NHCX integration, a webhook door, a claims table) has it `existing`. + +| Id | Module | What | Every skill adds | +| --- | --- | --- | --- | +| `foundation.transport` | 7.1 | Settings; the one transport behind `send` (the app's existing NHCX integration, the build's own, or nhcx-adapter when the user asked for it); the policy lookup; the outbound archive | Nothing; it sends through it | +| `foundation.storage` | 7.2 | The episode table with its claim number, payer and recipient codes, stage and sub-stage; the leg tables | The leg tables its `SKILL.md` lists, in its own migration | +| `foundation.callback` | 7.3 | The transport's receiving end and the door: dedupe, archive before apply, match by correlation id then claim number, the door refusal, the poll fallback where there is a ledger | Its readers, wired into the door's dispatch | +| `foundation.state` | 7.11 | The payer adapter table; `case_stage`, `stamp_case`, `next_actions` | The stage branches and next-action rows for its legs, labels verbatim from `flow/flow.json` | +| `foundation.screens` | 7.12 | The case screen shell: the eight tabs in the flow's order, the status line and actions, the JSON state address, the page-load polls, the cases list | Its own tabs and screens | +| `foundation.shell` | 7.13 | Standalone only: patients, admissions, practitioners, diagnoses, documents, settings, the run script | Nothing; `not applicable` in integrate mode | + +## Recognising each one + +For each capability: what to search for, what must be observed for it to be present, and what makes it partial. Search code, dependencies, migrations, configuration and tests. Run every check offline, with the network stubbed. + +### `foundation.transport` (7.1) + +- Look for an NHCX integration of the app's own: `x-hcx-`, `JWEPayload`, `RSA-OAEP-256`, `A256GCM`, a JOSE library among the dependencies, `bearer_auth`, a sessions URL on the ABDM gateway, `participanthcxservice`, `fetch/certs`, `participant/get/policies`, routes ending in `on_submit`, `on_check` or `on_request`, a vendor's NHCX or HCX client, a gateway service the app calls. Look also for nhcx-adapter already in use: `/fhir/out/`, `/out/v1/`, `jwe_headers`, an adapter URL setting, `/ledger/thread/`, `/internal/txn/related`. +- Present when: what was found meets the contract in `references/transport-knowledge.md` section 2, observed through 7.1's Validate rows 1 to 6 (and row 7 for an app that seals its own messages), with the network stubbed and a test key pair for the seal; and `send` is one function a test can replace. +- Partial when: it sends but misses a contract item (no `x-hcx-ben-abha-id`, the `payerid` as the recipient, no ids back to the caller, no archive) or cannot be stubbed. Extend it in place (`references/transport-knowledge.md` section 4). Never add a second transport beside it. +- Absent when: the app has no NHCX integration. The transport is then `own`, built from `references/transport-knowledge.md` section 3, unless the user has asked for nhcx-adapter. +- nhcx-adapter is never the answer to a partial or absent transport unless the user asked for it. Do not suggest it. + +### `foundation.storage` (7.2) + +- Look for: tables or models with `claim_no`, `correlation_id`, `txn_id`, `sub_stage`; migrations that mention claim, preauth or nhcx. +- Present when: observed on a migrated scratch database, or read from the schema file and confirmed by a migration run: the episode table has a unique claim number, member id, policy code, payer code, recipient code, patient and encounter keys, `stage` and `sub_stage`; every leg table this skill needs exists with `txn_id`, `correlation_id`, `api_call_id` and `thread_correlation_id`; the migration runs twice without error; deleting an episode removes its children (7.2 Validate, rows 2, 3, 5 and 6). For `nhcx-communication` and `nhcx-payment`, also row 4: the correlation id on their tables is unique by constraint. +- Partial when: the episode exists but a leg table this skill needs does not, a leg table lacks `thread_correlation_id` or `api_call_id`, or the episode keeps no `recipient_code`. The skill adds its tables and columns in a new migration. + +### `foundation.callback` (7.3) + +- Look for: routes under `/v1/` ending in `on_submit`, `on_check`, `on_request`, `/v1/error`, or a route with `callback` in it; `JWEPayload`, `ProtocolResponse`, `x-hcx-correlation_id`, `x-hcx-api_call_id`, a receipt with `protocol_status`. +- Present when: 7.3 Validate rows 1 to 5, 7 and 8 are observed by calling the receiving end with deliveries of the transport's kind (every inbound path reaches it; an unreadable body is archived and changes nothing; one api call id delivered twice changes state once and is `ignored`; an unknown correlation id is answered and archived under `unmatched`; a delivery is archived even when the apply raises; no outbound call during a delivery; the inbound authentication of the kind). Row 6, the door refusal, is checked by each skill on its own thread. +- Partial when: it receives but routes by path instead of by correlation id, lacks the dedupe, archives after applying, answers the exchange with anything but the 202 receipt (`own`, `existing`), hosts no `/v1/error`, or, with `adapter`, has no poll fallback. Extend it; there is one door. +- A skill whose reader is not wired into the door is partial for its own capability, not for the door. + +### `foundation.state` (7.11) + +- Look for: `query_mode`, `resubmit`, `1518`, a workflow id table (`"12"`, `"PC01"`, `"161"`), `sub_stage`, `next_actions`, a stamp after each write. +- Present when: 7.11 Validate rows 1 to 3 are observed (`adapter_for` with `1518@hcx` and `1518` gives PMJAY and an unknown code gives generic; the PMJAY workflow table equals `references/flow-knowledge.md` section 2; an override changes one kind only), and rows 4 to 7 hold on the seeded states the legs built so far can reach. +- Partial when: the payer table exists and the stage machine does not, or the stage machine lacks this skill's stage branches or labels. Each skill adds its own. + +### `foundation.screens` (7.12) + +- Look for: routes like `/claims`, `/claims/`, `/claims//state`; the tab keys `eligibility`, `plan`, `lines`, `validate`, `preauth`, `communication`, `claim`, `payments`. +- Present when: 7.12 Validate rows 1, 3, 8 and 9 are observed on the shell (the eight tabs in the flow's order with the flow's labels; routes answer 200 for a seeded case and 404 for an unknown one; no input or select named for a rate, a payer name, a `preAuthRef`, a UTR or a status; the state address returns `stage`, `sub_stage`, `next_actions` and `legs`). Rows 4 to 7 belong to the skills whose tabs they test. +- Partial when: the case screen exists without some tabs, without the status line, or without the state address. +- An HMIS with its own screens: the shell may live inside them, for example a panel on the admission screen that opens the case. Present is judged on the eight tabs and the state address, not on the look. + +### `foundation.shell` (7.13, standalone only) + +- Present when: every row of 7.13's Validate section is observed. +- In integrate mode: `not applicable`. The HMIS is the shell; stage 3 finds its patients, admissions, practitioners and documents. + +## Who builds what + +| Verdict at stage 0 | What the running skill does | +| --- | --- | +| `absent` | Builds it in stage 7, before its own modules. 7.1 and 7.3 whole, for the transport chosen at stage 1. 7.2: the episode table and this skill's leg tables. 7.11: the payer adapter table whole, and this skill's stage branches and labels. 7.12: the shell with all eight tabs present in order, its own tabs filled, the others showing their empty state. 7.13 whole, in standalone mode. | +| `partial` | Extends it in the existing code, for the difference stage 0 named, and runs the module's whole Validate section after. | +| `present` | Reuses it. Stage 8 still runs the rows this skill depends on. | + +Record: the Foundation row in `STATE.md` with `Built by` (the skill, or `existing`), and the module record `nhcx-build/7-modules/7.N.md` with a part for each skill that touched it. diff --git a/plugins/nhcx/skills/nhcx-insurance/core/LADDER.md b/plugins/nhcx/skills/nhcx-insurance/core/LADDER.md new file mode 100644 index 000000000..7a6f3f12b --- /dev/null +++ b/plugins/nhcx/skills/nhcx-insurance/core/LADDER.md @@ -0,0 +1,185 @@ +# The NHCX build ladder + +This skill is one of seven NHCX skills, one per use case: `nhcx-coverage`, `nhcx-insurance`, `nhcx-preauth`, `nhcx-claim`, `nhcx-communication`, `nhcx-payment` and `nhcx-reprocess`. Each is a folder of its own and runs on its own: it carries this ladder, the stages, the module files, the references, the flow, the templates and the fetch script. The seven copies of these are the same; only `SKILL.md` differs. This file holds what they share. `SKILL.md` says which flow steps, legs, capabilities, modules, pins and test rows are this skill's own, and what it needs from the use cases before it. + +## Paths + +Paths that start with `core/`, `stages/`, `references/`, `fhir/`, `flow/`, `ui/`, `templates/` or `scripts/` are relative to this skill's folder, the one that holds `SKILL.md`. Paths that start with `nhcx-package/` are in the NHCX package, fetched into the target project beside `nhcx-build/` (below). Paths that start with `nhcx-build/` are the workspace in the target project. + +## Getting the material + +Pins, payer fixtures and docs come from the NHCX package, published at https://github.com/nha-in/nhcx-package. `scripts/fetch-package.sh` downloads the latest release, unpacks it to `nhcx-package/` beside `nhcx-build/` and verifies its MANIFEST (pass a link or a local path to use a different build). `references/material.md` says what the package holds, gives the file of every pin by its label (`preauth/request` is `nhcx-package/fhir/B3/preauth-request.json`), and lists what it does not hold. Read it once, at stage 0. + +## What the skills produce + +Software that raises cashless claims on the National Health Claims Exchange (NHCX) with a private insurer and with PMJAY, in one of two shapes: + +| Mode | You start with | You end with | +| --- | --- | --- | +| `integrate` | A working hospital information system (HMIS, EMR, HIS, billing system) in any language | The same system, with a claims module that speaks NHCX through its transport, kept in sidecar tables and removable | +| `standalone` | Nothing | A self-contained claims desk: its own patients, admissions, documents and screens, speaking NHCX through a transport of its own | + +Every message goes through one transport, chosen at stage 1 from three (`references/transport-knowledge.md` section 1): + +| Transport | When | What the build does | +| --- | --- | --- | +| `existing` | Stage 0 found the app already speaks NHCX: its own client, a vendor gateway, an SDK | Wraps it behind 7.1's `send` and 7.3's door, and closes its gaps; never replaces it | +| `own` | The app has no NHCX integration, and the user has not asked for nhcx-adapter | Builds the protocol into the app from NHA's published chapters: the ABDM session token, the key and certificate, the participant record, the recipient's certificate, the JWE, the callback and its receipt | +| `adapter` | Only when the user asks for nhcx-adapter | Downloads it from https://github.com/nha-in/nhcx-adapter/releases and talks plain FHIR to it (`references/api-knowledge.md`) | + +Never propose nhcx-adapter; use it only when the user asks for it. Whichever the transport, the rest of the build sees the same two things: `send`, and a door that receives `{meta, jwe_headers, fhir}`. + +## The seven skills + +One skill per use case. Together they walk the whole flow in `flow/FLOW.md`; each one alone builds its slice. This folder builds only its own row. The others are named so that a verdict can say which skill owns a missing piece. + +| Skill | Flow steps | Legs | Use cases | Pins | +| --- | --- | --- | --- | --- | +| `nhcx-coverage` | F1, F2, F3 | policy search; `v1/coverageeligibility/check` purpose `discovery`, `validation`, `benefits` | A2, B1, D3 | `coverage/{discovery,validation,benefits}` | +| `nhcx-insurance` | F4, F7 | `v1/insuranceplan/request`; lines quoted from the plan | B2, D1 | `insurance` | +| `nhcx-preauth` | F5, F6, F8, F9, F9a, F9b for a `resubmit` payer, F9c, F9d, F9e | auth requirements; `v1/preauth/submit` 12, 19, 13, 131 and predetermination; cancel PC01 | B3, B8 cancel, B9, D2, D4 to D8 | `coverage/authrequirements`, `preauth/{request,enhancement,queryupdate,cancel}` | +| `nhcx-claim` | F10, F11 | `v1/claim/submit` 15; 161 (PMJAY) or 151 (generic); 16 (generic) | B5, D9, D10 | `claim/{request,queryupdate}` | +| `nhcx-communication` | F9b and the claim query for a `communication` payer, F12b | `v1/communication/request` in; `v1/communication/on_request` out | B4 | `communication/response`, and the `communication/request` reader | +| `nhcx-payment` | F12 | `v1/paymentnotice/request` in; `v1/paymentnotice/on_request` out on 17 or the notice's own id | B7, D13 | `payment/notice-ack` | +| `nhcx-reprocess` | F13 | `v1/task/submit`: reprocess and release on 36, status; 37 and the status Task read | A5, B8 reprocess, D11, D12 | `claim/{reprocess,release}` | + +`flow/flow.json` names the skills of every step in `skills`. Fifteen pins, each owned by exactly one skill, plus the communication request read as the sixteenth comparison. + +### The order they depend on + +The use cases depend on one another in the order the episode happens. A full build runs the seven skills top to bottom. Any one can run alone on an app that already has what it needs; stage 0 establishes whether it does, with the checks in this skill's `SKILL.md` under "Prerequisites". The other skills do not have to be installed for that check. + +| Skill | Needs | Because | +| --- | --- | --- | +| `nhcx-coverage` | nothing | It opens the episode | +| `nhcx-insurance` | coverage: an episode with an `eligible` verdict | The plan is fetched for an eligible episode's policy | +| `nhcx-preauth` | coverage (eligible, and its builder for auth requirements); insurance (plan ready, lines quoted) | Items, prices, documents and forms come from the plan; F9 holds `eligible` | +| `nhcx-claim` | preauth: an approved or partial pre-auth with its `preAuthRef`, the dossier, the Claim builder | The claim goes under the pre-auth's number, built by the same builder | +| `nhcx-communication` | preauth or claim: a leg the payer can ask about, with its bundle as sent | A query names a Claim; the reply lifts entries from the bundle sent | +| `nhcx-payment` | claim: a filed claim | A notice is matched by the claim number | +| `nhcx-reprocess` | claim: a decided claim; payment for a release; preauth for status on a pre-auth | A reprocess reopens a decided claim; a release follows a short payment | + +## The foundation + +Six modules carry every leg and belong to no one skill: 7.1 (the transport), 7.2 (storage), 7.3 (the callback door), 7.11 (state and payer adapters), 7.12 (the case screen shell) and 7.13 (the standalone shell). Every skill's stage 0 checks them. The first skill that finds one absent builds it; a skill that runs later on the same app finds it present and reuses it. `core/FOUNDATION.md` says how to recognise each and what makes it present. + +## What compliant means + +Every skill is held to the same points, for its own legs: + +1. Every hospital-side leg the skill owns (`references/flow-knowledge.md` section 1) is sent with its workflow id, and every payer answer on it is read. +2. Every bundle the skill sends matches its pin in `nhcx-package/fhir` byte for byte, `created` excepted. +3. The callback door answers 2xx fast, dedupes on `x-hcx-api_call_id`, archives before it applies, and matches by correlation id first. +4. No screen shows a decision the exchange has not sent, and nothing the exchange already said is retyped. +5. The offline tests pass, and the report says honestly which rungs of the test pyramid were climbed. +6. The software walks the flow in `flow/FLOW.md`, step for step: the same steps in the same order, the same tabs with the same names, the same guards, the same action labels. The flow is copied, never redesigned. +7. Nothing the app already did is built a second time. Every capability stage 0 found present is reused, and validated and tested like new code. + +## The flow + +An NHCX provider desk walks one path from policy search to settlement, and a build from these skills walks it. `flow/FLOW.md` is that path: thirteen steps with their branches, the case screen's eight tabs in order, the status line, the action labels the desk sees, the guards before every send, and what runs on every page load. `flow/flow.json` is the same, machine-readable, with step ids `F1` to `F13`. Read FLOW.md whole at stage 1; stage 4 copies the steps, stage 5 puts the screens on them, stage 7 implements them by id, stage 8 checks every step has a route. An agent that reorders, merges or renames these steps has left the skill. + +## The ladder + +Twelve stages, 0 to 11. Each has one file under `stages/`, reads the artefacts of the stages before it, writes into `nhcx-build/` in the target project, and ends at a gate. A gate is a list of conditions a reader can check without trusting you. Do not start a stage until the gate before it is closed, and never close a gate by asserting it; close it by pointing at the evidence. + +This skill runs every stage over its own slice. Stage 1 is shared with any other NHCX skill that runs on the same app: the first writes it and later ones confirm it. Parts of stages 3 to 6 are the episode's, not the skill's: the first skill to reach them writes those parts whole, and later skills build on them. + +| Stage | File | Scope | Writes | Gate closes when | +| --- | --- | --- | --- | --- | +| 0 | `stages/0-capability-check.md` | this skill | `nhcx-build/0-capability.md` section, `nhcx-build/capabilities.json` entries | Every own, foundation and prerequisite capability has a verdict with observed evidence | +| 1 | `stages/1-idea.md` | shared | `nhcx-build/1-idea.md` | The mode, the payers, the scope of every step with its skill, and the constraints are written and the user has agreed | +| 2 | `stages/2-planning.md` | this skill | `nhcx-build/2-planning.md` section, this skill's block in `nhcx-build/STATE.md` | Every later stage has a size and a proof; every module has its action from stage 0 | +| 3 | `stages/3-discovery.md` | shared rows; this skill's host facts | `nhcx-build/3-discovery.md` | Every host fact this skill needs is answered with proof, or marked as a gap | +| 4 | `stages/4-flow-and-data-mapping.md` | the flow and table homes episode-wide; this skill's bundles | `nhcx-build/4-flow-data-mapping.md`, `nhcx-build/mapping.json` | Every table has a home, every leg the four ids, every bundle of this skill a source map | +| 5 | `stages/5-screen-plan.md` | the case screen shell episode-wide; this skill's tabs | `nhcx-build/5-screen-plan.md`, `nhcx-build/screens.json` | Every value on this skill's screens names its message; the honesty rules hold | +| 6 | `stages/6-code-plan.md` | this skill's modules; the client and configuration episode-wide | `nhcx-build/6-code-plan.md`, `nhcx-build/modules.json` | Every module this skill touches has files, dependencies, a pin and an action | +| 7 | `stages/7-write-code/README.md` and `7.N-*.md` | what stage 0 found absent or partial | Code, plus `nhcx-build/7-modules/7.N.md` | Each module's "Done when" list is met, in order | +| 8 | `stages/8-validate-modules.md` | every module part this skill owns, reused ones included | `nhcx-build/8-validation.md`, `nhcx-build/8-validation/7.N.json` | Every row passes, or carries a named, accepted exception | +| 9 | `stages/9-write-tests.md` | this skill's pins, readers and matrix rows | Test code, plus `nhcx-build/9-tests.md` | Every row this skill owns has a test, or a written reason it cannot | +| 10 | `stages/10-run-tests.md` | this skill's tests | `nhcx-build/10-test-run.md` and the raw outputs | The offline rung passes; the higher rungs are run only when the user starts the services | +| 11 | `stages/11-build-report.md` | this skill | `nhcx-build/11-report.md` section | The report is written from the artefacts, names every gap, and a stranger could resume from it | + +Stage 7 is a module ladder of its own, 7.1 to 7.13. Each module file carries its own Build, Pseudo code, Validate and Tests sections, and names the skills that build it; stage 8 runs the Validate sections and stage 9 writes the Tests sections, so a module is never validated against a checklist written somewhere else. + +## The workspace + +Everything this skill writes lives in one folder in the target project, so the work can be resumed, reviewed and deleted as a unit. When several NHCX skills work on one app they share that folder, whichever skill folder each runs from: each adds its own section or entries and leaves the others alone. + +``` +nhcx-build/ + STATE.md the gate ledger: the shared rows, the foundation, one block per skill + capabilities.json every capability checked, its verdict and its evidence; read and written by every skill + 0-capability.md one section per skill; scratch checks under 0-capability/ + 1-idea.md shared + 2-planning.md one section per skill + 3-discovery.md shared; each row says which skill answered it + 4-flow-data-mapping.md the flow and table homes, then one section per skill; plus mapping.json + 5-screen-plan.md the case screen shell, then one section per skill; plus screens.json + 6-code-plan.md the client and configuration, then one section per skill; plus modules.json + 7-modules/7.1.md .. 7.13.md one record per module; a shared module has a part per skill + 8-validation.md one section per skill; plus 8-validation/7.N.json, each row tagged with its skill + 9-tests.md one section per skill + 10-test-run.md one section per skill; plus 10-test-run/-*.log + 11-report.md a summary across skills, then one section per skill + NOTES.md every place a skill was silent, ambiguous or wrong +``` + +`templates/` holds the skeleton of each artefact. Copy the skeleton, fill it, keep its headings: later stages find things by heading. + +## How to run a stage + +1. Read `nhcx-build/STATE.md`. If stage 1 in the Shared block is open, and this skill's stage 0 is closed, run stage 1. Otherwise find the first open gate in this skill's block. That is the stage to run; do not skip ahead and do not redo a closed stage unless the user asks. +2. Read the stage file. Read the artefacts it lists under Inputs, and this skill's `SKILL.md` row for the stage. Read the references it names, in the sections it names. +3. Do the work. Write the artefact from its template, in this skill's section. +4. Walk the gate. For each condition, write the evidence into STATE.md: a file path, a line, a command and its output. A condition with no evidence stays open. Every artefact that names a step, a tab or an action uses the ids and words from `flow/flow.json`. +5. If a gate needs the user (stage 0 when a prerequisite is missing; stage 1 always when it is first written; stage 10 rungs 3 and 4 always), stop and ask. Otherwise continue to the next stage. + +Resuming later is step 1 again. Nothing lives in your memory; everything lives in `nhcx-build/`. + +You may be asked to run one stage alone with the earlier artefacts already written. Treat those as closed; do not rewrite them. + +## Rules that hold throughout + +- Reading and offline commands only until stage 10 says otherwise. Never start a service or send live traffic unless the user asks. +- Never edit the files in `nhcx-package/`. They are the truth you are held to. +- Build only what stage 0 found absent or partial. A capability found present is reused through its existing code, never built a second time: two transports or two callback doors break the rule that one module sends and one receives. +- Present means a check was observed passing. Code that looks right is partial until its check has run. +- Never build another skill's capability inside this one. When a prerequisite is missing, stop and say which skill owns it. +- When this skill extends a module another skill built, it re-runs that skill's Validate rows for the module. The rows are in the module file, which every skill folder carries. +- This skill writes its own section of a shared artefact and leaves the other skills' sections alone. +- Never hard-code a document code, a package code or a questionnaire url. Take them from the payer's plan or auth-requirements answer. +- Every outbound leg stores three things from the transport's answer: `txn_id`, `correlation_id` and `api_call_id`. Every message is addressed to the policy's processor (`recipient_code`) and carries the beneficiary's ABHA. Every inbound message is matched by `x-hcx-correlation_id` first and by the claim number inside the bundle second. +- Take the decisions from the module files (Build, Rules, Pseudo code) and `fhir/FHIR.md`, and write them in the target's language and conventions. Never invent a shape the pins do not show. +- Write `nhcx-build/NOTES.md` as you go. A fact the skill does not give you is a gap to record, never a guess to bury in code. +- No em dashes anywhere you write. Short sentences. Tables for anything with more than three columns of fact. +- Do not claim a rung of the test pyramid was climbed when it was not. The report's value is its honesty. + +## Reference map + +| File | Holds | Read at | +| --- | --- | --- | +| `core/FOUNDATION.md` | The six foundation capabilities: how to recognise each, what makes it present, who builds it | Stage 0, stage 7 when building one | +| `references/flow-knowledge.md` | The episode and its legs, every workflow id, the two payer kinds, the classification rule, stage vocabulary, the use-case catalogue, rules no document states | Stages 1, 2, 4, 7.4 to 7.11 | +| `references/transport-knowledge.md` | The three transports and when each applies; the contract `send` and the door rely on; building the protocol yourself from NHA's chapters (token, key and certificate, participant record, policy lookup, recipient certificate, JWE, callback and receipt, status and `/v1/error`); wrapping an existing integration; getting nhcx-adapter when asked | Stages 0, 1, 4, 6, 7.1, 7.3 | +| `references/api-knowledge.md` | The nhcx-adapter contract, read only when the user chose the adapter: config, routes, envelope and answer, delivery, ledger, kit endpoints, curl | 7.1 and 7.3, adapter only | +| `references/fhir-knowledge.md` | Every bundle sent and received, element ids, HPIN, consent questionnaires, supportingInfo, LM100, ONS and DTM, the TaskBundle reply, where the pins live, the validator | Stages 4, 6, 7.4 to 7.10, 8 | +| `references/errors-and-debugging.md` | PAYR and ERR codes with meaning and fix, gateway errors, reading a ledger thread, correlation mistakes, redelivery, sandbox pace | Stages 8, 10, 11 | +| `references/testing-knowledge.md` | The test pyramid, the test-case matrix per use case, a skeleton offline test | Stages 2, 9, 10 | +| `fhir/FHIR.md` | The FHIR guide: every bundle sent and read, entries in pinned order, the code systems, pseudo code for each builder and reader, the refusal each rule guards against | Stages 0, 4, 6, 7.4 to 7.10, 8 | +| `ui/UI-GUIDE.md` | The screens: the two honesty rules, where every value comes from, a layout per screen, the state words, pseudo code for the status line, the timeline and the actions | Stages 5, 7.12, 7.13 | +| `flow/FLOW.md`, `flow/flow.json` | The one path an episode walks: steps F1 to F13 and their skills, the tab order, the action labels, the guards, the page-load polls | Stage 1 whole; stages 4, 5, 7, 8 by step id | +| `references/material.md` | Where the pins, fixtures and docs live: the NHCX package, the pin map, what the package lacks | Stage 0, and whenever a cited file is needed | + +## Keeping the seven copies in step + +Everything in this folder except `SKILL.md` is the same in all seven skill folders. A change to one of these files is made in all seven. `diff -r --exclude=SKILL.md` between any two skill folders prints nothing when they agree. + +## Deliverables + +- This skill's sections of `nhcx-build/`, every gate in its STATE.md block closed with evidence or open with a reason. +- Its verdicts in `capabilities.json`, each with the check that decided it. +- Schema additions for its legs (integrate) or its tables in the whole schema (standalone), under the target's conventions. +- Builders and readers for every leg it owns, each compared with its pin in the offline test. +- Its tabs and screens, deriving every state from received messages. +- Tests covering its rows of the matrix, a run record, and a report section a stranger could act on. diff --git a/plugins/nhcx/skills/nhcx-insurance/fhir/FHIR.md b/plugins/nhcx/skills/nhcx-insurance/fhir/FHIR.md new file mode 100644 index 000000000..90b85cbae --- /dev/null +++ b/plugins/nhcx/skills/nhcx-insurance/fhir/FHIR.md @@ -0,0 +1,658 @@ +# NHCX FHIR: the bundles a hospital sends and reads + +Every bundle here is held to a pin in the NHCX package, under `nhcx-package/fhir/B*`. Read `../references/fhir-knowledge.md` for the why; this file is the how. The pseudo code is language-neutral: a `dict` is a JSON object, a `list` is a JSON array, and `ref(url)` is `{"reference": url}`. + +## 1. Conventions every bundle follows + +"Validator" below is the HL7 FHIR validator with the NRCeS `ndhm.in` IG, run as `../references/fhir-knowledge.md` section 11 describes. + +| Rule | Detail | Refusal if broken | +| --- | --- | --- | +| Bundle | `resourceType Bundle`, `type collection`, `id` fixed per shape, `meta.profile` = the NRCES bundle profile | validator error | +| Entries | Every entry has an absolute `fullUrl` under `https://nhcx.abdm.gov.in/...`; every `reference` resolves to a `fullUrl` in the same bundle | validator error, PAYR-10xx | +| Profiles | Every resource carries `meta.profile` = `https://nrces.in/ndhm/fhir/r4/StructureDefinition/` | validator warning | +| No timestamps on requests | No `meta.versionId`, `meta.lastUpdated`, bundle `timestamp` (the communication reply is the exception) | none, but the pin differs | +| Money | `{"value": n, "currency": "INR"}`; whole numbers as integers, never `3300.0` | pin differs | +| Instants | IST with `+05:30`, seconds precision | PAYR on dates | +| Identifiers | Typed with a `type.coding` from the NDHM identifier-type system or HL7 v2-0203, `system` where the pin has one | PAYR-1083 and kin | + +### Code systems, named once + +``` +NDHM = "https://nrces.in/ndhm/fhir/r4/CodeSystem/" +PROFILE = "https://nrces.in/ndhm/fhir/r4/StructureDefinition/" +BASE = "https://nhcx.abdm.gov.in" +HL7 = "http://terminology.hl7.org/CodeSystem/" +SNOMED = "http://snomed.info/sct" +ICD10 = "http://hl7.org/fhir/sid/icd-10" +HPR = "https://hpr.abdm.gov.in" + +ID_TYPE = NDHM + "ndhm-identifier-type-code" # PMJAY, ABHA, HPID, HPIN, CLN +V2_0203 = HL7 + "v2-0203" # MB, MD, NH, NPI, NIIP +V2_0360 = HL7 + "v2-0360" # qualification degrees +ORG_TYPE = HL7 + "organization-type" # prov, pay +ACT_CODE = HL7 + "v3-ActCode" # HIP +REL = HL7 + "subscriber-relationship" # self +PRIORITY = HL7 + "processpriority" # normal +CARE_ROLE = HL7 + "claimcareteamrole" # primary, assist +DX_TYPE = HL7 + "ex-diagnosistype" # admitting +DX_ONADM = HL7 + "ex-diagnosis-on-admission" # yes +FIN_TASK = HL7 + "financialtaskcode" # poll, cancel, reprocess, release, status +FIN_INPUT = HL7 + "financialtaskinputtype" # include +COMM_CAT = HL7 + "communication-category" # notification + +BENEFIT_CAT = NDHM + "ndhm-benefit-category" # Claim.item.category (specialty) +PROC_CODE = NDHM + "ndhm-procedure-code" # Claim.item.productOrService (package) +PROGRAM = NDHM + "ndhm-program-code" # AB-PMJAY +SI_CATEGORY = NDHM + "ndhm-supportinginfo-category" # INV, ONS, OTH, HDS, DIS, NMI, INF, STG +SI_CODE = NDHM + "ndhm-supportinginfo-code" # ADDD, EDT, PSP, DSDE, DTM, DTH, LAMA, DAMA, CQD, ODN +DOC_CODE = BASE + "/document-code" # the plan's MANDxxxx codes, else ODN +TASK_INPUT = NDHM + "ndhm-task-input-type-code" # policyNumber, providerId, claimNumber, intimationNumber, document +TASK_INPUT_X = BASE + "/task-input-type" # amount +TASK_OUTPUT = NDHM + "ndhm-task-output-type" # status +TASK_OUTVAL = NDHM + "ndhm-task-output-value" # paymentack +TASK_CODES = NDHM + "ndhm-task-codes" # deliver +REASON = NDHM + "ndhm-reason-code" # treatmentplanchanged, claimrejected, partialpayment, rejectiondisputed +CAT_CODE = BASE + "/category-code" # CoverageEligibilityRequest.item.category +PRODUCT_CODE = BASE + "/product-code" # CoverageEligibilityRequest.item.productOrService +PROC_TYPE = BASE + "/procedure-type" # conservative, medical, surgical +DOC_TYPE_EXT = settings.document_type_extension_url # on a Communication attachment; participant-defined (nhcx-package/docs/05-FHIR Reference/17-Communication.md). + # The communication/response pin carries its author's own url: the pin comparison sets this from the pin. +``` + +### Shared helpers + +``` +function cc(system, code, display=null): # CodeableConcept + coding = {"code": code}; if system: coding.system = system; if display: coding.display = display + return {"coding": [coding]} + +function typed_id(type_system, type_code, type_display, value, system=null): + out = {"type": cc(type_system, type_code, type_display), "value": value} + if system: out.system = system # put "system" before "value" as the pins do; canonical JSON sorts anyway + return out + +function entry(url, resource): return {"fullUrl": url, "resource": resource} + +function profile(name): return {"profile": [PROFILE + name]} + +function bundle(id, profile_name, entries): # profile_name: "ClaimBundle", "TaskBundle", "CoverageEligibilityRequestBundle" + return {"resourceType": "Bundle", "id": id, "meta": profile(profile_name), "type": "collection", "entry": entries} + +function organization(role, identifier_code, identifier_display, id_value, name, res_id=null): + o = {"resourceType": "Organization", "meta": profile("Organization"), + "identifier": [typed_id(V2_0203, identifier_code, identifier_display, id_value, BASE)], + "type": [cc(ORG_TYPE, role, "Healthcare Provider" if role == "prov" else "Payer")], "name": name} + if res_id: o.id = res_id + return o + +function provider_org(facility, res_id=null): return organization("prov", "NPI", "National provider identifier", facility.hfr_id, facility.name, res_id) +function payer_org(payer, res_id=null): return organization("pay", "NIIP", "National Insurance Payor Identifier (Payor)", strip_hcx(payer.participant_code), payer.name, res_id) +function strip_hcx(code): return code.split("@")[0] + +function money(v): return {"value": int(v) if v == int(v) else round(v, 2), "currency": "INR"} +``` + +## 2. Coverage eligibility request + +Pins: `coverage/{discovery,validation,benefits,authrequirements}`. Sent on `v1/coverageeligibility/check`, workflow id = the case number. Purposes: `discovery` (who covers this person), `validation` (is the policy in force), `benefits` (balances), `auth-requirements` (rule on the quoted items). + +Entries, in order: CoverageEligibilityRequest, Patient, provider Organization, payer Organization, Location, Coverage, PractitionerRole. + +``` +function build_coverage_request(d): + # d: purpose, member_id, policy_code (null on discovery), facility{hfr_id,name}, payer{participant_code,name}, created, items[] (benefits, auth-requirements only) + U = BASE + cer = {"resourceType": "CoverageEligibilityRequest", "meta": profile("CoverageEligibilityRequest"), + "identifier": [{"system": BASE}], "status": "active", + "priority": cc(PRIORITY, "normal", "Normal"), "purpose": [d.purpose], + "patient": ref(U + "/patient"), "created": d.created, + "enterer": ref(U + "/practitioner-role"), "provider": ref(U + "/provider"), + "insurer": ref(U + "/payer"), "facility": ref(U + "/location"), + "insurance": [{"focal": true, "coverage": ref(U + "/coverage")}]} + if d.purpose in ("benefits", "auth-requirements"): + cer.item = [eligibility_item(i) for i in d.items] + patient = {"resourceType": "Patient", "meta": profile("Patient"), + "identifier": [typed_id(ID_TYPE, "PMJAY", "Pradhan Mantri Jan Aarogya Yojana (PMJAY) ID", d.member_id), + typed_id(V2_0203, "MB", "Member Number", d.member_id)]} # no name, no demographics + coverage = {"resourceType": "Coverage", "meta": profile("Coverage"), + "identifier": [typed_id(V2_0203, "NH", "National Health Plan Identifier", d.policy_code or "NONE")], + "status": "active", "type": cc(ACT_CODE, "HIP", "health insurance plan policy"), + "subscriber": ref(U + "/patient"), "subscriberId": d.member_id, "beneficiary": ref(U + "/patient"), + "relationship": cc(REL, "self"), "payor": [ref(U + "/payer")]} + location = {"resourceType": "Location", "name": d.facility.name, "managingOrganization": ref(U + "/provider")} + role = {"resourceType": "PractitionerRole", "meta": profile("PractitionerRole"), + "code": [cc(SNOMED, "307988006", "Medical technician")]} + return bundle("coverage-" + d.purpose.replace("-", "") + "-request-generic", "CoverageEligibilityRequestBundle", [ + entry(U + "/coverage-eligibility/request", cer), entry(U + "/patient", patient), + entry(U + "/provider", provider_org(d.facility)), entry(U + "/payer", payer_org(d.payer)), + entry(U + "/location", location), entry(U + "/coverage", coverage), entry(U + "/practitioner-role", role)]) + +function eligibility_item(i): + # i: category{code,display}, code, display, quantity (integer), tiers[] {code, display} + out = {"category": cc(CAT_CODE, i.category.code, i.category.display), + "productOrService": cc(PRODUCT_CODE, i.code, i.display), + "quantity": {"value": int(i.quantity)}} + if i.tiers: out.modifier = [cc(null, t.code, t.display) for t in i.tiers] # no system on a tier + return out +``` + +Bundle ids: `coverage-discovery-request-generic`, `coverage-validation-request-generic`, `coverage-benefits-request-generic`, `coverage-authrequirements-request-generic`. + +### Reader: CoverageEligibilityResponse + +The payer echoes the request's entries and appends its own; take the last of each type. + +``` +function parse_validation_bundle(b): + resp = last(b, "CoverageEligibilityResponse"); pat = last(b, "Patient"); cov = last(b, "Coverage") + out = {"outcome": resp.outcome, "disposition": resp.disposition, "inforce": resp.insurance[0].inforce, + "auth_required": any(item.authorizationRequired for item in resp.insurance[0].item or []), + "allowed": null, "used": null} + for item in resp.insurance[0].item or []: + for ben in item.benefit or []: + if ben.allowedMoney and (out.allowed is null or ben.allowedMoney.value > out.allowed): + out.allowed = ben.allowedMoney.value; out.used = (ben.usedMoney or {}).value or 0 + out.patient = {"name": pat.name[0].text, "gender": pat.gender, "birthDate": pat.birthDate, + "abha": first_identifier(pat, "ABHA"), "photo": pat.photo[0].data if pat.photo else null} + out.coverage = {"class": cov.class[0].name if cov.class else null, "period": cov.period} + return out +# status: eligible if inforce else not-eligible; balance shown = allowed - used +``` + +### Reader: the auth-requirements ruling + +``` +function parse_auth_bundle(b): + resp = last(b, "CoverageEligibilityResponse"); items = []; requirements = [] + for item in resp.insurance[0].item or []: + items.append({"code": item.productOrService.coding[0].code, "authorised": item.authorizationRequired, + "excluded": item.excluded, "benefit": item.benefit[0] if item.benefit else null}) + for sup in item.authorizationSupporting or []: + text = sup.text or "" # the scheme overloads free text + r = {"line": item.productOrService.coding[0].code, "code": sup.coding[0].code if sup.coding else null, + "display": sup.coding[0].display if sup.coding else text} + if "fullUrl:" in text: r.kind = "form"; r.url = after("fullUrl:", text).strip(); r.stage = "pre" + else: r.kind = "document"; r.stage = "post" if "Type: post" in text else "pre" + r.at_preauth = (r.kind == "form") or (r.stage == "pre") + requirements.append(r) + return {"items": items, "requirements": requirements} +``` + +## 3. Insurance plan request + +Pin: `insurance`. Sent on `v1/insuranceplan/request`, workflow id = the case number. One entry. + +``` +function build_plan_request(policy_code, provider_id): + task = {"resourceType": "Task", "meta": profile("Task"), "status": "requested", "intent": "order", + "code": cc(FIN_TASK, "poll"), + "input": [{"type": cc(TASK_INPUT, "policyNumber"), "valueString": policy_code}, + {"type": cc(TASK_INPUT, "providerId"), "valueString": provider_id}]} + return bundle("insurance-request-generic", "TaskBundle", [entry(BASE + "/insurance/request", task)]) +# no id, no authoredOn, no requester; at least one input is mandatory +``` + +### Reader: the plan + +``` +function parse_plan_bundle(b): + plan = first(b, "InsurancePlan"); forms = {q.url: q for q in all(b, "Questionnaire")} + benefits = {} # keyed by package code + for p in plan.plan or []: # shape 1: package-based + for sc in p.specificCost or []: + specialty = sc.category.coding[0] + for ben in sc.benefit or []: + code = ben.type.coding[0].code; row = benefits.setdefault(code, new_benefit(code, ben.type.coding[0].display, specialty)) + for cost in ben.cost or []: + kind = cost.type.coding[0].code # Procedure | Implant | Stratification + if kind == "Procedure": row.rate = cost.value.value; row.kind = "Procedure" + else: row.extras.append({"kind": kind, "code": cost.qualifiers[0].coding[0].code, "display": cost.qualifiers[0].coding[0].display, "amount": cost.value.value}) + row.conditions.update(read_conditions(ben.extension)); row.requirements += read_requirements(ben.extension) + for cov in plan.coverage or []: # shape 2: coverage-based + for ben in cov.benefit or []: + code = ben.type.coding[0].code; row = benefits.setdefault(code, new_benefit(code, ben.type.coding[0].display, cov.type.coding[0])) + for lim in ben.limit or []: + if lim.code.coding[0].code == code: row.rate = lim.value.value + else: row.extras.append({"kind": "Stratification", "code": lim.code.coding[0].code, "display": lim.code.coding[0].display, "amount": lim.value.value}) + row.conditions.update(read_conditions(ben.extension)); row.requirements += read_requirements(ben.extension) + policy_requirements = read_requirements(plan.extension) # policy-wide: identity proof, consent forms + return {"plan": {"id": plan.id, "name": plan.name}, "benefits": list(benefits.values()), + "policy_requirements": policy_requirements, + "forms": [{"url": u, "title": q.title, "kind": "stg" if "/stgquestionnaire/" in u else "policy", + "questions": [{"linkId": it.linkId, "text": it.prefix or it.text, "type": it.type, + "options": [o.valueString or o.valueCoding.display for o in it.answerOption or []], + "default": first_selected(it)} for it in q.item]} for u, q in forms.items()]} + +function read_conditions(exts): # extension url family "...Claim-Condition": children named by their url tail + out = {} + for e in exts or []: + if "Claim-Condition" in e.url: + for child in e.extension or []: out[tail(child.url)] = child.valueString or child.valueBoolean or child.valueCodeableConcept.coding[0].code + return out + +function read_requirements(exts): # "...Claim-SupportingInfoRequirement": one nested requirement per document + out = [] + for e in exts or []: + if "Claim-SupportingInfoRequirement" in e.url: + for req in e.extension or []: + r = {} + for f in req.extension or []: + if tail(f.url) == "category": r.category = f.valueCodeableConcept.coding[0].code + if tail(f.url) == "code": r.code = f.valueCodeableConcept.coding[0].code; r.display = f.valueCodeableConcept.coding[0].display + if tail(f.url) == "documentationUrl": r.url = f.valueUri or f.valueString + out.append(r) + return out +``` + +## 4. The Claim bundle + +Pins: `preauth/request`, `preauth/enhancement`, `preauth/queryupdate`, `claim/request`, `claim/queryupdate`. One builder, three switches: `leg` (`preauth`, `claim`, `predetermination`), `flow` (`request`, `enhancement`, `queryupdate`), `use` (`preauthorization`, `claim`, `predetermination`). + +Entries, in order: Claim, Patient, provider Organization (id 1), payer Organization (id 2), Coverage (id 1), Practitioner (one per care team member), Procedure (one per package line), QuestionnaireResponse (one per answered form). + +``` +function claim_bundle(leg, use, d): + # d: flow, claim_no, created, admission{admitted_at, discharged_at, surgery_at, death_at, mode, stage}, + # patient{member_id, abha, name, phone, gender, birthDate}, facility, payer, policy_code, + # care_team[] {hpid, licence, hpin, name, qualification_code, qualification_display, specialty_snomed, specialty_display}, + # diagnoses[] {code, display}, lines[] (procedures and implants, each with tiers[]), documents[] {code, category, content_type, bytes, title}, + # forms[] {url, answers[] {linkId, type, value}}, program_code (AB-PMJAY or null), factor_rule (pmjay or null), + # preauth_ref (claim leg), summary{code, content_type, bytes, title} (claim leg), query_reply (queryupdate) + U = BASE; anchor = U + "/" + leg + "/" + d.flow + practitioners = [practitioner_resource(m, n + 1) for n, m in enumerate(d.care_team)] + procedures = [procedure_resource(line, n + 1, completed = (leg == "claim"), when = d.admission.surgery_at or d.admission.admitted_at) for n, line in enumerate(package_lines(d.lines))] + (qrs, form_refs) = questionnaire_responses(d.forms, d.created) + (si, si_refs) = supporting_info(d, leg, form_refs) + claim = {"resourceType": "Claim", "id": d.claim_no, "meta": profile("Claim"), + "identifier": [typed_id(ID_TYPE, "CLN", "Claim number", d.claim_no, BASE)], + "status": "active", "type": cc(SNOMED, "737481003", "Inpatient care management (procedure)"), "use": use, + "patient": ref(U + "/patient"), + "billablePeriod": {"start": d.admission.admitted_at, "end": d.admission.discharged_at or planned_end(d)}, + "created": d.created, "insurer": ref(U + "/payer"), "provider": ref(U + "/provider"), + "priority": cc(PRIORITY, "normal", "Normal"), + "careTeam": [{"sequence": n + 1, "provider": ref(practitioner_url(n)), + "role": cc(CARE_ROLE, "primary" if n == 0 else "assist", "Primary provider" if n == 0 else "Assisting Provider"), + "qualification": cc(SNOMED, m.specialty_snomed, m.specialty_display)} for n, m in enumerate(d.care_team)], + "supportingInfo": si, + "diagnosis": [{"sequence": n + 1, "diagnosisCodeableConcept": cc(ICD10, dx.code, dx.display), + "type": [cc(DX_TYPE, "admitting", "Admitting Diagnosis")], "onAdmission": cc(DX_ONADM, "yes", "Yes")} for n, dx in enumerate(d.diagnoses)], + "procedure": [{"id": "Procedure/" + str(n + 1), "sequence": n + 1, + "type": [cc(PROC_TYPE, line.procedure_type.lower(), line.procedure_type)], # from the plan's ProcedureType condition + "date": d.admission.surgery_at or d.admission.admitted_at, + "procedureReference": {"reference": U + "/procedure/" + str(n + 1), "display": line.display}} for n, line in enumerate(package_lines(d.lines))], + "insurance": [{"sequence": 1, "focal": true, "coverage": ref(U + "/coverage")}], + "item": claim_items(d, si_refs), + "total": money(sum(item.net.value for item in items))} + if leg == "claim": claim.insurance[0].preAuthRef = [d.preauth_ref] # the payer's ClaimResponse.preAuthRef + entries = [entry(anchor, claim), entry(U + "/patient", patient_resource(d.patient)), + entry(U + "/provider", provider_org(d.facility, "1")), entry(U + "/payer", payer_org(d.payer, "2")), + entry(U + "/coverage", coverage_resource(d.policy_code, d.patient.member_id))] + entries += [entry(practitioner_url(n), p) for n, p in enumerate(practitioners)] + entries += [entry(U + "/procedure/" + str(n + 1), p) for n, p in enumerate(procedures)] + entries += [entry(U + "/questionnaireresponse/" + str(n + 1), q) for n, q in enumerate(qrs)] + return bundle(leg + "-" + d.flow + "-request-generic", "ClaimBundle", entries) + # preauth-request-generic, preauth-enhancement-request-generic, preauth-queryupdate-request-generic, claim-request-generic, claim-queryupdate-request-generic + +function practitioner_url(n): return BASE + "/practitioner" + ("" if n == 0 else "/" + str(n + 1)) + +function patient_resource(p): + ids = [typed_id(ID_TYPE, "PMJAY", "Pradhan Mantri Jan Aarogya Yojana (PMJAY) ID", p.member_id)] + if p.abha: ids.append(typed_id(ID_TYPE, "ABHA", "Ayushman Bharat Health Account (ABHA) ID", p.abha)) + ids.append(typed_id(V2_0203, "MB", "Member Number", p.member_id)) + return {"resourceType": "Patient", "id": "1", "meta": profile("Patient"), "identifier": ids, + "name": [{"text": p.name}], "telecom": [{"system": "phone", "value": p.phone}], "gender": p.gender, "birthDate": p.birthDate} + +function practitioner_resource(m, n): + ids = [typed_id(ID_TYPE, "HPID", "Healthcare Professional ID (HPID)", m.hpid or m.hpin, BASE)] + if m.licence: ids.append(typed_id(V2_0203, "MD", "Medical License number", m.licence, BASE)) + ids.append(typed_id(ID_TYPE, "HPIN", "Health Practitioner ID issued by NDHM", m.hpin, HPR)) # PAYR-1083 without it + return {"resourceType": "Practitioner", "id": str(n), "meta": profile("Practitioner"), "identifier": ids, + "name": [{"text": m.name}], "qualification": [{"code": cc(V2_0360, m.qualification_code, m.qualification_display)}]} + +function coverage_resource(policy_code, member_id): + return {"resourceType": "Coverage", "id": "1", "meta": profile("Coverage"), + "identifier": [typed_id(V2_0203, "NH", "National Health Plan Identifier", policy_code)], + "status": "active", "type": cc(ACT_CODE, "HIP", "health insurance plan policy"), + "subscriber": ref(BASE + "/patient"), "subscriberId": member_id, "beneficiary": ref(BASE + "/patient"), + "relationship": cc(REL, "self"), "payor": [ref(BASE + "/payer")]} + +function procedure_resource(line, n, completed, when): + return {"resourceType": "Procedure", "id": str(n), "meta": profile("Procedure"), + "status": "completed" if completed else "preparation", + "code": {"coding": [{"system": SNOMED, "code": "71388002", "display": "Procedure"}], "text": line.display}, + "subject": ref(BASE + "/patient"), "performedDateTime": when} +``` + +### Items: one per procedure or implant, never per tier + +``` +function package_lines(lines): return [l for l in lines if l.kind in ("procedure", "implant")] # tiers ride on their parent + +function claim_items(d, si_refs): + groups = package_lines(d.lines); factors = procedure_factors(groups, d.factor_rule) + items = [] + for n, line in enumerate(groups): + tiers = [t for t in d.lines if t.kind == "tier" and t.parent_code == line.code] + net = line.amount + sum(t.amount for t in tiers) + item = {"id": "Item/" + str(n + 1), "sequence": n + 1, "careTeamSequence": [1], "diagnosisSequence": [1], + "procedureSequence": [n + 1], "informationSequence": si_refs, # every supportingInfo sequence + "category": cc(BENEFIT_CAT, line.category.code, line.category.display), + "productOrService": cc(PROC_CODE, line.code, line.display)} + if tiers: item.modifier = [cc(null, t.code, t.display) for t in tiers] + if d.program_code: item.programCode = [cc(PROGRAM, d.program_code, "Ayushman Bharat Pradhan Mantri Jan Arogya Yojana (AB-PMJAY)")] + item.servicedPeriod = {"start": day(d.admission.admitted_at), "end": day(d.admission.discharged_at or planned_end(d))} + item.quantity = {"value": int(line.quantity)} + item.unitPrice = money(net / line.quantity) + if factors: item.factor = factors[n] + item.net = money(net) + items.append(item) + return items + +function procedure_factors(groups, rule): + # PMJAY multiple-procedure rule: by cost rank, 1, 0.5, 0.25; a generic payer sends no factor + if rule != "pmjay" or len(groups) < 2: return null # the single-item pins carry factor 0.5 (their own contradiction); compare without it + ranked = sorted(range(len(groups)), key = lambda i: -groups[i].amount) + return {i: [1, 0.5, 0.25][min(rank, 2)] for rank, i in enumerate(ranked)} +``` + +### supportingInfo: the table, then the numbering + +``` +function supporting_info(d, leg, form_refs): + si = [] + for doc in d.documents: # one per attached file; never drop one + si.append({"category": cc(SI_CATEGORY, doc.category or "INV", display_for(doc.category or "INV")), + "code": cc(DOC_CODE, doc.code or "ODN", doc.title), # the plan's code, else ODN + "valueAttachment": {"contentType": doc.content_type, "data": base64(doc.bytes), "title": doc.title}}) + if leg == "claim": + si.append({"category": cc(SI_CATEGORY, "HDS", "Discharge summary"), "code": cc(DOC_CODE, d.summary.code or "HDS", d.summary.title), + "valueAttachment": {"contentType": d.summary.content_type, "data": base64(d.summary.bytes), "title": d.summary.title}}) + si.append(scalar("ONS", "ADDD", "Admission date -Discharge date", d.admission.admitted_at)) + si.append(scalar("OTH", "EDT", "EncounterDateTime", d.admission.admitted_at)) + if leg == "claim": + if d.admission.surgery_at: si.append(scalar("ONS", "PSP", "Procedure start", d.admission.surgery_at)) + si.append(scalar("ONS", "DSDE", "Discharge date", d.admission.death_at or d.admission.discharged_at)) + if d.admission.mode == "death": si.append(scalar("ONS", "DTM", "Date and time of death", d.admission.death_at)) # PAYR-1096 without it + code = {"normal": "DTH", "lama": "LAMA", "dama": "DAMA", "death": "DTM"}[d.admission.mode] + si.append(scalar("DIS", code, display_for(code), stage_words(d.admission.stage))) # "Before Surgery" | "During Surgery" | "After Surgery" + if d.flow == "queryupdate": + si.append(scalar("NMI", "CQD", "Claim query detail", d.query_reply)) # the desk's words; PMJAY reads its answer from here + for (form, url) in form_refs: # one per answered form + cat = "STG" if form.kind == "stg" else "INF"; code = "STG" if form.kind == "stg" else "ODN" + si.append({"category": cc(SI_CATEGORY, cat, display_for(cat)), "code": cc(SI_CODE, code, display_for(code)), "valueReference": ref(url)}) + for n, s in enumerate(si): # number once, after assembly: PAYR-1019 without sequence + s.id = "SupportingInformation/" + str(n + 1); s.sequence = n + 1 + reorder(s, ["id", "sequence", "category", "code", "value*"]) + return (si, [s.sequence for s in si]) + +function scalar(cat, code, display, value): + return {"category": cc(SI_CATEGORY, cat, display_for(cat)), "code": cc(SI_CODE, code, display), "valueString": value} +``` + +### Questionnaire responses + +``` +function questionnaire_responses(forms, authored): + qrs = []; refs = [] + for n, form in enumerate(forms): + url = BASE + "/questionnaireresponse/" + str(n + 1) + qr = {"resourceType": "QuestionnaireResponse", "id": str(n + 1), "meta": profile("QuestionnaireResponse"), + "questionnaire": form.url, "status": "completed", "subject": ref(BASE + "/patient"), "authored": authored, + "item": [{"linkId": a.linkId, "answer": [typed_answer(a)]} for a in form.answers]} + qrs.append(qr); refs.append((form, url)) + return (qrs, refs) + +function typed_answer(a): + switch a.type: + "string", "text", "choice": return {"valueString": a.value} + "date", "dateTime": return {"valueDateTime": a.value} + "boolean": return {"valueBoolean": a.value} + "integer": return {"valueInteger": int(a.value)} + "decimal": return {"valueDecimal": a.value} + "attachment": return {"valueAttachment": {"contentType": a.content_type, "data": base64(a.bytes), "title": a.title}} +``` + +### Which forms and documents ride + +``` +function required_forms(case, stage): # stage: preauth | claim + if case.ruling: forms = [r for r in case.ruling.requirements if r.kind == "form" and (stage == "preauth" or r.stage != "pre")] + else: forms = plan_stg_forms(case.plan, case.lines) if stage == "preauth" else [] + return forms + policy_forms(case.plan) # consent every leg: PAYR-1256 / PAYR-1363; STG: PAYR-1254 / PAYR-1365 + +function required_documents(case, stage): + if case.ruling: return [r for r in case.ruling.requirements if r.kind == "document" and (r.stage == "pre") == (stage == "preauth")] + wanted = plan_documents(case.plan, case.lines) + return wanted if stage == "preauth" else [w for w in wanted if not attached_at_preauth(case, w.code)] +``` + +### The legs, and the LAMA collapse + +``` +function lines_for(case, leg): + if leg == "claim" and case.admission.mode in ("lama", "dama") and case.admission.stage in ("before", "during"): + return [{"kind": "procedure", "code": "LM100", "display": "Left against medical advice", "quantity": 1, + "amount": plan_rate(case.plan, "LM100") or 0, "category": lm100_category(case.plan)}] # PAYR-1362 if the package stays + return case.lines # LM100 never on a pre-auth: PAYR-1270 +``` + +| Leg | flow | use | Procedure status | Workflow | Extra | +| --- | --- | --- | --- | --- | --- | +| Pre-auth | `request` | `preauthorization` | `preparation` | 12 | fresh 12 after a rejection too (PAYR-1214 on 121) | +| Enhancement | `enhancement` | `preauthorization` | `preparation` | 13 | every line, old and new, same claim number; factors 1 and 0.5 | +| Query answer | `queryupdate` | `preauthorization` | `preparation` | 19 (131 after an enhancement query) | `NMI/CQD`; new correlation id | +| Claim | `request` | `claim` | `completed` | 15 | discharge scalars, `HDS`, `preAuthRef`, under the pre-auth's number (ERR-PYR-CLM-007) | +| Claim query answer | `queryupdate` | `claim` | `completed` | 161 (PMJAY), 151 (generic) | as the claim plus `NMI/CQD` | +| Predetermination | `request` | `predetermination` | `preparation` | 12 on `v1/preauth/submit` | no state effects | + +## 5. Reader: ClaimResponse + +Fed by every answer on a pre-auth, enhancement, claim or predetermination thread. Entries: ClaimResponse, Patient, two Organizations, Coverage. + +``` +function parse_claim_response(b): + r = first(b, "ClaimResponse") + status_adj = first(a for a in r.adjudication or [] if a.category.coding[0].code == "status") + out = {"use": r.use, "outcome": r.outcome, "disposition": r.disposition, + "status_reason": status_adj.reason.coding[0].code.lower() if status_adj else null, # submitted|approved|queried|rejected|cancelled + "preauth_ref": r.preAuthRef if is_string(r.preAuthRef) else (r.preAuthRef[0] if r.preAuthRef else null), + "claim_no": r.identifier[0].value if r.identifier else null, + "totals": {t.category.coding[0].code: t.amount.value for t in r.total or []}, # by category, never by position + "items": [], "notes": [n.text for n in r.processNote or []]} + for it in r.item or []: + adj = {a.category.coding[0].code: a for a in it.adjudication or []} + out.items.append({"sequence": it.itemSequence, + "status": adj.status.reason.coding[0].code.lower() if adj.status else null, + "eligible": adj.eligible.amount.value if adj.eligible else null, + "submitted": adj.submitted.amount.value if adj.submitted else null, + "reason": adj.reason.reason.coding[0].display if adj.reason else "", # verbatim, pipe-delimited USER~datetime~type~comment~trust + "eligpercent": adj.eligpercent.value if adj.eligpercent else null, + "deductible": adj.deductible.amount.value if adj.deductible else null}) + return out + +function verdict_status(p): # copy exactly; never read outcome alone + if p.outcome == "queued" or p.status_reason == "submitted": return "submitting" + if p.status_reason == "cancelled": return "rejected" + if p.status_reason == "queried": return "queried" + if p.outcome == "error": return "rejected" + if p.outcome == "partial": return "partial" if p.status_reason == "approved" else "queried" + if p.outcome == "complete": return "approved" if p.status_reason in ("approved", null) else "queried" + return "queried" + +function apply_claim_response(leg, p, envelope): + leg.status = verdict_status(p) + if p.preauth_ref: leg.preauth_ref = p.preauth_ref # never overwrite a value with an empty one + leg.eligible_amount = p.totals.get("eligible") or p.totals.get("benefit") + leg.submitted_amount = p.totals.get("submitted") + leg.approved_amount = p.totals.get("benefit") # what the screen shows as the decision + leg.items_json = p.items; leg.query_note = join(p.notes + [i.reason for i in p.items if i.reason]) + leg.thread_correlation_id = envelope.jwe_headers["x-hcx-correlation_id"] + leg.answered_at = now() if leg.status != "submitting" else leg.answered_at +``` + +Payer workflow ids are labels for the timeline only: 20 received, 21 approved, 22 enhancement approved, 23 rejected, 24 queried, 25 claim received, 26 approved, 27 queried, 291 rejected. The bundle decides the state. + +## 6. Task bundles the hospital sends + +Pins: `preauth/cancel`, `claim/reprocess`, `claim/release`, `payment/notice-ack`. Sent on `v1/task/submit` (the payment acknowledgement on `v1/paymentnotice/on_request`). Entries: Task, provider Organization, payer Organization. + +``` +function task_bundle(id, anchor, task, facility, payer): + return bundle(id, "TaskBundle", [entry(BASE + anchor, task), entry(BASE + "/provider", provider_org(facility)), entry(BASE + "/payer", payer_org(payer))]) + +function base_task(code, status, authored_on, description): + return {"resourceType": "Task", "meta": profile("Task"), "status": status, "intent": "order", + "code": cc(FIN_TASK, code), "description": description, "authoredOn": authored_on, + "requester": ref(BASE + "/provider"), "owner": ref(BASE + "/payer")} + +function task_input(code, display, value): return {"type": cc(TASK_INPUT, code, display), "valueString": value} +function based_on(claim_no): return [{"identifier": typed_id(ID_TYPE, "CLN", "Claim number", claim_no, BASE), "display": "Claim " + claim_no}] + +function cancel_task(claim_no, reason, authored_on, facility, payer): # workflow PC01 + t = base_task("cancel", "requested", authored_on, "Cancel the preauthorization " + claim_no) + t.reasonCode = cc(REASON, reason.code, reason.display) # treatmentplanchanged, ... + t.input = [task_input("claimNumber", "ClaimNumber", claim_no), task_input("intimationNumber", "IntimationNumber", claim_no)] + return task_bundle("preauth-cancel-request-generic", "/preauth/cancel", t, facility, payer) + +function reprocess_task(claim_no, member_id, reason, description, documents, authored_on, facility, payer): # workflow 36 + t = base_task("reprocess", "requested", authored_on, description) + t.reasonCode = cc(REASON, reason.code, reason.display) # claimrejected | partialpayment | rejectiondisputed + t.basedOn = based_on(claim_no) + t.input = [task_input("claimNumber", "ClaimNumber", claim_no), task_input("intimationNumber", "IntimationNumber", claim_no)] + t.input += [{"type": cc(TASK_INPUT, "document", "Document"), "valueAttachment": {"contentType": d.content_type, "data": base64(d.bytes), "title": d.title}} for d in documents] + t.for = {"identifier": typed_id(ID_TYPE, "PMJAY", "Pradhan Mantri Jan Aarogya Yojana (PMJAY) ID", member_id)} # MB on a generic payer + return task_bundle("claim-reprocess-request-generic", "/claim/reprocess", t, facility, payer) + +function release_task(claim_no, amount, authored_on, facility, payer): # workflow 36 + t = base_task("release", "requested", authored_on, "Release the balance amount for claim " + claim_no) + t.reasonCode = cc(REASON, "partialpayment", "Reprocess request due to partial payment by payer") + t.basedOn = based_on(claim_no) + t.input = [task_input("claimNumber", "ClaimNumber", claim_no), {"type": cc(TASK_INPUT_X, "amount", "Amount"), "valueMoney": money(amount)}] + return task_bundle("claim-release-request-generic", "/claim/release", t, facility, payer) + +function status_task(claim_no, authored_on, facility, payer): # workflow = the leg's correlation id; PMJAY refuses (PAYR-1018) + t = base_task("status", "requested", authored_on, "Status of " + claim_no) + t.input = [task_input("claimNumber", "ClaimNumber", claim_no)] + return task_bundle("claim-status-request-generic", "/claim/status", t, facility, payer) + +function payment_ack(claim_no, authored_on, facility, payer): # workflow 17 (PMJAY) or the notice's own id; x-hcx-correlation_id = the notice's + t = base_task("status", "completed", authored_on, "Received the payment for claim " + claim_no) + t.output = [{"type": cc(TASK_OUTPUT, "status", "Status"), "valueCodeableConcept": cc(TASK_OUTVAL, "paymentack", "Payment is acknowledged")}, + {"type": cc(TASK_INPUT, "claimNumber", "ClaimNumber"), "valueString": claim_no}] + return task_bundle("payment-notice-ack-generic", "/payment/notice-ack", t, facility, payer) +``` + +The pins and the build both carry `intimationNumber`, so the offline comparison diffs the pins unchanged. + +### Readers: PC02, 37, status + +``` +function parse_task_answer(b): + t = first(b, "Task"); cr = first(b, "ClaimResponse") # a 37 may carry a ClaimResponse queued + outputs = {o.type.coding[0].code: o for o in t.output or []} + return {"status": t.status, "code": t.code.coding[0].code, + "claim_status": (outputs.get("claimStatus") or outputs.get("status") or {}).valueCodeableConcept.coding[0].code if outputs else null, + "description": t.description, "queued": cr is not null and cr.outcome == "queued"} +# PC02: pre-auth -> cancelled, episode gets a fresh claim number, the withdrawn one stays on the leg +# 37: enquiry row -> answered; a fresh verdict follows on the claim's own thread +``` + +## 7. Communication + +Pins: `communication/request` (the payer's TaskBundle, the reader's input) and `communication/response` (the hospital's reply). On `v1/communication/request` in, `v1/communication/on_request` out, with the request's correlation id and workflow id echoed. + +``` +function parse_communication_request(b): + t = first(b, "Task"); cr = first(b, "CommunicationRequest") + return {"task_status": t.status, "intent": t.intent, "reason": t.reasonCode.coding[0].code.lower() if t.reasonCode else null, + "request_id": cr.id, "request_url": fullurl_of(b, cr), + "questions": [p.contentString for p in cr.payload or [] if p.contentString], + "about_claim": (cr.basedOn or [{}])[0].display, "claim_no": claim_no_in(b)} + +function classify_communication(adapter, reason, intent): + if adapter.query_mode == "resubmit": return "notification" + if intent == "proposal": return "notification" + if intent == "order": return "query" + if reason in (null, "additionalinfo", "questionnaire", "query"): return "query" + return "notification" # tatquery, grievance, walletupdate, policychange, claimarbitration + +function build_acknowledgement_bundle(request_bundle, facility): # a notification, sent back at once + b = deepcopy(request_bundle); t = first(b, "Task"); t.status = "completed" + move_first(b, "Organization", where = provider) # provider Organization first + return b + +function build_communication_bundle(q, text, documents, sent_leg_bundle, facility, payer, now): + # q: the parsed request; sent_leg_bundle: the pre-auth or claim bundle as sent (its Claim, Patient, Organizations, Practitioner, Coverage are lifted) + task_id = uuid(); comm_id = uuid() + comm = {"resourceType": "Communication", "id": comm_id, "meta": profile("Communication"), + "identifier": [{"value": q.request_identifier}], "basedOn": [{"reference": q.request_url, "display": "CommunicationRequest"}], # never inResponseTo + "status": "completed", "category": [cc(COMM_CAT, "notification")], "priority": "routine", + "about": [{"reference": claim_anchor(sent_leg_bundle), "display": "Claim " + claim_no}], + "sender": {"reference": BASE + "/provider", "display": "Organization"}, "recipient": [{"reference": BASE + "/payer", "display": "Organization"}], + "payload": [{"contentString": text}] + [{"contentAttachment": {"contentType": d.content_type, "data": base64(d.bytes), "title": d.title}, + "extension": [{"url": DOC_TYPE_EXT, "valueString": d.code}]} for d in documents]} + task = {"resourceType": "Task", "id": task_id, "meta": profile("Task"), "status": "completed", "intent": "order", + "code": cc(TASK_CODES, "deliver"), "reasonCode": cc(null, q.reason or "additionalinfo", "Additional information requested"), + "authoredOn": now, "requester": {"reference": BASE + "/provider", "display": "Organization"}, "owner": {"reference": BASE + "/payer", "display": "Organization"}, + "input": [{"type": cc(FIN_INPUT, "include"), "valueReference": {"reference": "urn:uuid:" + comm_id, "display": "Communication"}}]} + entries = [entry("urn:uuid:" + task_id, task), entry("urn:uuid:" + comm_id, comm), entry(q.request_url, q.request_resource)] + entries += [entry(e.fullUrl, e.resource) for e in sent_leg_bundle.entry if e.resource.resourceType in ("Claim", "Patient", "Organization", "Practitioner", "Coverage")] + b = bundle("communication-response-generic", "TaskBundle", entries) + b.meta.lastUpdated = now; b.timestamp = now # the IG example carries both; the only request that does + return b +``` + +Excluded from the byte comparison of the reply: `meta.lastUpdated`, `timestamp`, `authoredOn`, the two generated uuids. + +## 8. Payment notice + +Read on `v1/paymentnotice/request`. Entries: Task, PaymentNotice, PaymentReconciliation, two Organizations. + +``` +function parse_payment_notice(b): + pn = first(b, "PaymentNotice"); pr = first(b, "PaymentReconciliation"); t = first(b, "Task") + out = {"claim_no": pn.identifier[0].value if pn.identifier else claim_no_in(b), + "amount": pn.amount.value, "payment_status": pn.paymentStatus.coding[0].code, # paid | cleared | ... + "payment_date": pn.paymentDate, "utr": null, "details": []} + if pr: + out.utr = pr.paymentIdentifier.value if pr.paymentIdentifier else null + out.gross = pr.paymentAmount.value if pr.paymentAmount else null + out.details = [{"type": d.type.coding[0].code, "amount": d.amount.value if d.amount else null} for d in pr.detail or []] # deductions, TDS + if not out.utr and pn.payment and pn.payment.identifier: out.utr = pn.payment.identifier.value + return out +# record: one claim_payment row keyed on the message's correlation id (unique), matched by claim_no; then acknowledge with payment_ack() +``` + +## 9. Validate before you send + +``` +function validate_bundle(b, pin): # the offline gate, module 7.7 Validate + assert canonical(strip(b, ["created"])) == canonical(strip(pin, ["created"])) # plus the per-shape exclusions above + urls = {e.fullUrl for e in b.entry} + for r in all_references(b): assert r in urls or r.startswith("urn:uuid:") + c = first(b, "Claim") + if c: + for it in c.item: assert it.id and it.sequence + for p in c.procedure: assert p.id and p.sequence + for n, s in enumerate(c.supportingInfo): assert s.id and s.sequence == n + 1 + for pr in all(b, "Practitioner"): assert any(i.type.coding[0].code == "HPIN" and i.system == HPR for i in pr.identifier) + assert c.total.value == sum(it.net.value for it in c.item) + assert not any(it.productOrService.coding[0].code == "LM100" for it in c.item) or c.use == "claim" + assert no literal in the builder matches r"MAND\d+|MG\d+|/questionnaire/" +``` + +| Symptom | Refusal | +| --- | --- | +| an item without `id` | PAYR-1027 | +| a supportingInfo without `sequence` | PAYR-1019 | +| a Practitioner without `HPIN` | PAYR-1083 | +| a death claim without `ONS/DTM` | PAYR-1096, PAYR-1503 | +| a LAMA claim before surgery still carrying the package | PAYR-1362 | +| `LM100` on a pre-auth | PAYR-1270 | +| the consent form unanswered | PAYR-1256 (pre-auth), PAYR-1363 (claim) | +| a package's STG form unanswered | PAYR-1254, PAYR-1365 | +| a claim under its own number | ERR-PYR-CLM-007 | +| 121 after a rejection | PAYR-1214 | +| 151, 19 or 16 on `v1/claim/submit` to PMJAY | PAYR-1321 | +| a document outside pdf, jpg, jpeg, png; a Task the sandbox does not take; a misspelt intimation input on a reprocess | PAYR-1008 | diff --git a/plugins/nhcx/skills/nhcx-insurance/flow/FLOW.md b/plugins/nhcx/skills/nhcx-insurance/flow/FLOW.md new file mode 100644 index 000000000..312668e67 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-insurance/flow/FLOW.md @@ -0,0 +1,228 @@ +# The flow: the one path a claim episode walks + +This is the reference flow for an NHCX provider desk: these steps, in this order, with these guards and these words. A build from this skill walks the same path. It does not redesign it, reorder it, merge steps, or invent screens the path does not have. Stage 4 copies it, stage 5 puts screens on it, stage 7 implements it step by step, stage 8 checks every step exists, and test drivers check the same through `flow.json`. + +## The shape + +One episode is one case (`claim` row). It has one list screen, one "new case" screen and one case screen. The case screen has tabs in the order the episode happens, and above the tabs one status line and the actions the case is waiting for. Everything else (inbox, payments across cases) is a view over the same rows. + +Tabs on the case screen, in this order and with these names: + +| # | Tab key | Tab label | Opens when | +| --- | --- | --- | --- | +| 1 | `eligibility` | Eligibility | always | +| 2 | `plan` | Insurance plan | always (empty until the plan is fetched) | +| 3 | `lines` | Line items | always (quoting refused until the plan is `ready`) | +| 4 | `validate` | Validate | always (the ruling on the quoted set) | +| 5 | `preauth` | Pre-authorisation | once the coverage verdict is `eligible` | +| 6 | `communication` | Communication | always (the payer's questions on both legs) | +| 7 | `claim` | Claim | always; its submit opens once a pre-auth is approved or partial | +| 8 | `payments` | Payments | always | + +The episode may also render on one page, with the same sections in the same order. Either shape is fine; the order and the gating are not negotiable. + +## Which skill builds which step + +Seven skills build this flow, one slice each (`core/LADDER.md`). `flow.json` names them per step in `skills`, the first named being the one that owns the step. + +| Steps | Skill | +| --- | --- | +| F1, F2, F3 | `nhcx-coverage` | +| F4, F7 | `nhcx-insurance` | +| F5, F6, F8, F9, F9a, F9c, F9d, F9e; F9b for a `resubmit` payer (19, 131) | `nhcx-preauth` | +| F10, F11; the claim query answer for a `resubmit` payer (161) | `nhcx-claim` | +| F9b and the claim query for a `communication` payer; F12b | `nhcx-communication` | +| F12 | `nhcx-payment` | +| F13 | `nhcx-reprocess` | + +The case screen, its tabs, the status line and actions, and the page-load polls are the foundation's (`core/FOUNDATION.md`): the first skill lays them out whole, and each skill fills its own tabs. + +## The status line and the actions + +Above the tabs: `stage / sub-stage` from `case_stage` (module 7.11) and the list from `next_actions`, first item highlighted. The labels are these, verbatim: + +| Stage | Sub-stage | Action offered (label, tab) | +| --- | --- | --- | +| any | an open query exists | "Answer the payer (n)", `communication` (leads every list) | +| `eligibility` | `draft`, `error`, `not-eligible` | "Check the cover", `eligibility` | +| `eligibility` | `eligible`, no plan `ready` | "Fetch the package master", `plan` | +| `eligibility` | plan ready, no lines | "Quote the treatment", `lines` | +| `eligibility` | lines quoted | "Send the pre-authorisation", `preauth` | +| `preauth` or `enhancement` | `queried` | "Answer the query", `preauth` (resubmit payer) or "Answer the payer's query", `communication` (communication payer) | +| `preauth` | `draft`, `refused` | "Send the pre-authorisation", `preauth` | +| `preauth` | `rejected` | "Send a fresh pre-authorisation", `preauth` | +| `preauth` | `approved`, `partial`, lines added since | "Send the enhancement (n added)", `preauth` | +| `preauth` | `approved`, `partial`, not discharged | "Record the discharge", `claim` | +| `preauth` | `approved`, `partial`, discharged | "File the claim", `claim` | +| `preauth` | `requested`, `answered`, `resubmitted` | "With the payer; ask where it stands", `preauth` | +| `claim` | `queried` | "Answer the claim query", `claim` or "Answer the payer's query", `communication` | +| `claim` | `rejected`, `partial` | "Ask for a reprocess", `claim` | +| `claim` | `requested`, `answered`, `resubmitted` | "With the payer; ask where it stands", `claim` | +| `claim` | `refused` | "Send the claim again", `claim` (while a send kind remains) else "Ask for a reprocess" | +| `claim` | `approved` | "Await the payment notice", `payments` | +| `payment` | a notice unacknowledged | "Acknowledge the payment notice", `payments` | +| `payment` | all acknowledged | "Settled", `payments` | + +## The steps + +Each step: where it happens, what must hold, what the user does, what the system does (module in brackets), what goes on the wire, what is stored, where the case stands afterwards, and what the screen shows next. Ids are `F1` to `F13` with letters for branches; `flow.json` carries the same ids. + +### F1. Policy search + +- Screen: Cases list, "New case", `GET /claims/new`. +- Holds: nothing. +- User: picks an identifier type (`MemberId`, `AbhaNumber`, `MobileNo`) and a value, presses "Search policies". +- System [7.4]: `search_policies` through the transport: the participant service's `participant/get/policies`; normalises each row (`member_id`, `policy_code` from `productid`, `payer_code` from `payerid`, `recipient_code` from `processingid`, `product_name`). NHCX-1016 (nothing linked) is an empty list, not an error. +- Screen: a table, one row per policy: beneficiary, product and policy, payer, ABHA, mobile, a "Select" button. No name and no photo yet; the payer returns those at F3. + +### F2. Open the case + +- Screen: the same, "Select" on a row; `POST /claims`. +- System [7.4, 7.2]: `create_claim` snapshots the policy (`member_id`, `policy_code`, `payer_code`, `recipient_code`, `policy_json`), mints the claim number, stamps `eligibility / draft`. +- Redirect: the case screen, Eligibility tab, "Claim opened." +- Next action: "Check the cover". + +### F3. Check the cover (coverage eligibility) + +- Screen: Eligibility tab, card "Coverage eligibility check": purpose select (`validation` default, `benefits`, `discovery`), policy code and member id shown from the snapshot, "Send to payer". +- Holds: member id; policy code for `validation` and `benefits`. +- System [7.4]: `run_check(purpose)`, workflow id = the claim number, status `checking`; the page shows "Awaiting payer" and refreshes; the answer arrives by callback [7.3] or poll. +- Wire: `v1/coverageeligibility/check`; `on_check` back. +- Stored: `txn_id`, `correlation_id`, `api_call_id`; on the answer `inforce`, `outcome`, `disposition`, allowed and used amounts, the payer's `Patient` (name, gender, DOB, address, ABHA, photo), `Coverage` class and period. +- After: `eligibility / eligible` or `not-eligible` (or `error` with the payer's words). A `ProtocolResponse` or a 404 on `txn/related` settles as `error`, never spins. +- Screen: card "Payer verdict": Sum insured, Utilised, Wallet balance (allowed less used), Disposition verbatim, In force, Pre-authorisation required, Checked at, Correlation. Beneficiary card fills with the payer's demographics. "Check again" allowed from any settled state. +- Next action: "Fetch the package master". + +### F4. Fetch the package master (insurance plan) + +- Screen: Insurance plan tab, "Fetch the plan" (or "Refresh"). +- Holds: `eligible`. +- System [7.5]: `reuse_plan` first (same policy, provider, payer, status `ready`: zero sends); else `request_plan`, status `fetching`, workflow id = the claim number. +- Wire: `v1/insuranceplan/request`; `on_request` back with the InsurancePlan and Questionnaires. +- Stored: `claim_plan` (`ready`, `empty` or `error`), `claim_plan_benefit` per package, `claim_plan_form` per url. Both published shapes merged on package code. +- Screen: a search over the master (name or code, specialty filter, procedure or implant), one row per package with rate, kind, "View"; a package view with rate, implants approved, tiers, conditions, documents wanted, the forms those point at as questions; an "All forms" page. Policy-wide requirements shown above the table. +- Next action: "Quote the treatment". + +### F5. Link the admission (integrate) or capture it (standalone) + +- Screen: Pre-authorisation tab, card "Link the admission" (opens once `eligible`). +- Holds: `eligible`. +- Integrate: list every current inpatient stay of the patient whose ABHA matches the payer's (digits only); "Link" stores `patient_id` and `encounter_id`, defaults the admission date from the encounter. Linking before `eligible` and to a stay that is not a current IPD admission is refused. "Unlink" keeps the draft. +- Standalone [7.13]: register the patient (from the payer's demographics) and admit them here; the same two keys are stored. +- Screen after: card "Linked admission" with ward, bed, admitted at, consultant. + +### F6. The dossier (pre-auth capture) + +- Screen: Pre-authorisation tab, once linked: the form, saved in one transaction by `save_preauth` [7.7 inputs]. +- Captured: admission date (required) and provisional discharge date (not before admission); ICD-10 diagnoses (at least one; read off the admission when it recorded them, else a picker); the treating doctor (the admission's consultant, else a picker; must have an HPIN); package case or non-package case toggle; documents (pdf, jpg, jpeg, png, each recorded against the payer requirement code it answers, else `ODN`). +- Estimated amount: always recomputed server-side from the lines (F7), never from the form. +- Guards: saving a package case with no line quoted is refused. + +### F7. Quote the treatment (lines from the plan) + +- Screen: Line items tab, "Choose line items", `GET /claims//lines`. Three parts: what is quoted (editable quantities, running total, "remove"); what the payer says goes with it (implants approved for the quoted procedures, the tiers each offers; anything already quoted drops out); the whole master to search. +- Holds: plan `ready`. Quoting anything before that is refused. +- System [7.5]: `add_line(kind, code, parent_code)`; price read from the plan at add time; `amount = rate x quantity` server-side; a tier is added through the procedure that offers it and carries `parent_code`. Refused: a code the plan lacks, a tier the procedure does not offer, a duplicate, a zero quantity. +- Forms: the chosen lines pull in the questionnaires the plan attaches (STG per package, policy forms always); they render on the Pre-authorisation tab and are answered there (`save_answers`, one row per question, file answers upload a document). +- Next action: "Send the pre-authorisation". + +### F8. Validate the set (auth requirements) + +- Screen: Validate tab, "Ask the payer" (also run silently before F9). +- Holds: at least one line. +- System [7.6]: `ensure_auth_requirements`: fingerprint the quoted set; send only when the fingerprint is new; never wait for the answer. +- Wire: `v1/coverageeligibility/check` with purpose `auth-requirements` and the items; `on_check` back (the PMJAY sandbox rarely answers). +- Stored: `claim_auth` (`checking` then `ready`), items authorised or excluded, requirements (document or form, code, url, stage `pre` or `post`, `at_preauth`). +- Screen: the ruling per line, the documents and forms it wants for each leg; the pre-auth and claim tabs read it to build their document and form cards. Without a ruling they fall back to the plan's list. + +### F9. Send the pre-authorisation + +- Screen: Pre-authorisation tab, card "Submit": what will be sent (lines, forms answered, documents attached, the total), "Send to payer". +- Holds (all before any HTTP call): `eligible`; an admission linked; an admission date; at least one diagnosis; at least one care team member with an HPIN; at least one line; every required form answered; every document the ruling or plan asks for at pre-auth attached. +- System [7.7]: `submit_preauth`: `preauth_send_kind` picks `preauth` (12); builds the Claim bundle (`preauth`, `request`); status `submitting`, `submission_kind`, `workflow_id`; stores the three ids; `thread_correlation_id` untouched until the payer answers. +- Wire: `v1/preauth/submit`, workflow 12. +- After: `preauth / requested`. +- Screen: "Awaiting payer", the timeline row for the send, Refresh. Next action: "With the payer; ask where it stands". + +#### F9a. The payer answers + +- Callback [7.3] or poll: first the acknowledgement (workflow 20, `outcome queued`, reason `submitted`): recorded, `preauth_ref` kept, the leg stays `submitting`. Then the decision on the same correlation id: `verdict_status` [7.8]. +- After: `approved` (21), `partial` (approved for less), `queried` (24), `rejected` (23). Never read `outcome` alone. +- Screen: Decision, Payer reference (`preAuthRef`), Approved amount (`total[benefit]`), Eligible amount, the item verdicts table (eligible, status, reason verbatim, eligible %, quantity), process notes verbatim. A door refusal shows as a flag with the payer's code and text, the thread restored. +- Next action per the table above. + +#### F9b. Answer a query + +- Resubmit payer (PMJAY): the query is inside the ClaimResponse (`query_note`). Screen: Pre-authorisation tab, the payer's words, a reply box, "Submit again". System: `submit_preauth(reply)` with kind `preauth_query_response` (19; 131 after an enhancement query), flow `queryupdate`, `NMI/CQD` = the reply, a new correlation id. After: `answered`, then the decision. +- Communication payer (generic): the query is a CommunicationRequest on a new thread, filed in `claim_query` (F12 inbox). Screen: Communication tab, the questions verbatim, a reply box, documents to attach (existing or new, each under the payer's code else `ODN`), "Send the reply". System [7.10]: `answer_query`: the TaskBundle reply on `v1/communication/on_request` with the request's correlation id and workflow id. The leg stays `queried` until the decision arrives on its own thread. An empty reply is refused before any HTTP call. + +#### F9c. Enhancement + +- Screen: Line items tab, add a line after a decision; the Pre-authorisation card shows "enhancement pending (n added)"; "Submit enhancement". +- Holds: `approved` or `partial`; no request in flight. +- System: `submit_preauth` with kind `enhancement` (13; `enhancement_resubmit` 131 on a query): the whole bundle again, every line old and new, same claim number, factors 1 and 0.5. After: `enhancement / requested`, then 22 (or 21 from the SHA), 231, 241. + +#### F9d. Cancel + +- Screen: Pre-authorisation tab, "Withdraw": a reason picker (the seven documented reasons) and a note, required for Other. Hidden once a claim has been raised; refused on a `rejected` pre-auth and twice. +- System [7.9]: `cancel_preauth`: Task `cancel`, workflow PC01, on its own thread (`cancel_correlation_id`), `cancelling`. +- After PC02: `cancelled`; the episode gets a fresh claim number, the withdrawn one stays on the leg. + +#### F9e. Predetermination (a quote) + +- Screen: Pre-authorisation tab, "Ask for a quote". +- System [7.7]: the very bundle F9 would send with `use predetermination`, on `v1/preauth/submit`, workflow 12, its own row (`asking` then `answered`). Nothing on the pre-auth changes. + +### F10. Record the discharge + +- Screen: Claim tab, card "Discharge": mode (Normal, LAMA, DAMA, Death), stage (Before, During, After surgery), discharge date and time, surgery date and time, death date and time (death only). +- Holds: a pre-auth `approved` or `partial`. +- Stored: on `claim_submission` (`draft`) or the encounter. +- Screen after: the claim card opens; for LAMA or DAMA before or during surgery it says the approved packages are voided and the claim will carry `LM100` only. +- Next action: "File the claim". + +### F11. File the claim + +- Screen: Claim tab, cards "Documents for the claim" (what the ruling deferred to this stage, plus the discharge summary, always), "Forms for the claim" (the consent again, and what the ruling deferred), "Everything attached for the claim" (any further pdf or image), "Submit the claim". +- Holds: discharge recorded; the discharge summary attached; every claim-stage form answered; amount not above the approved amount. +- System [7.7]: `submit_claim`: `claim_send_kind` (`claim` 15; `claim_query_response` 161 PMJAY or 151 generic; `claim_resubmit` 16 generic only); the Claim bundle (`claim`, `request`) under the pre-auth's claim number with `preAuthRef`, procedures `completed`, discharge scalars, `HDS`, `DIS`; `LM100` collapse when it applies. +- Wire: `v1/claim/submit`. +- After: `claim / requested`; then 25 (ack), 26 `approved`, 27 `queried`, 291 `rejected`, read as F9a. +- Screen: as the pre-auth card: decision, amounts, item verdicts with `deductible`, notes verbatim. + +#### F11, continued: claim query and reprocess + +- Query: as F9b, on the claim (161 or the Communication reply). +- Rejected or partial: "Ask for a reprocess" (F13). There is no claim resubmit on PMJAY. + +### F12. Payments + +- The payer starts it: `v1/paymentnotice/request` arrives on a new thread, matched by the claim number inside (a `CLN` identifier, then any untyped identifier on the notice, the reconciliation, the Task; never the bundle id), looked up against `claim_no` and every leg's `claim_ref`. +- System [7.10]: `record_payment`: one `claim_payment` row per notice, deduped on the notice's correlation id; details from the PaymentReconciliation; a payer that reuses the notice id updates the row. Then, at once and automatically, `acknowledge_payment`: Task `status` `completed`, output `paymentack`, to the notice's own sender, its correlation id echoed, workflow 17 (PMJAY) or the notice's own (generic). A failed acknowledgement is kept on the row; the notice is still recorded and the callback still answered 2xx. +- After: `payment / noticed` or `paid`. Paid is counted once per UTR, newest notice winning; an initiated notice without a UTR shows "Initiated, UTR awaited" and is not money received. +- Screen: Payments tab, one card per notice: status, amount, UTR as text, the breakdown, "Acknowledged at" or "Send the acknowledgement again". Across cases: the payments view. +- Next action: "Acknowledge the payment notice" while one is pending, else "Settled". + +### F12b. The inbox + +- Every CommunicationRequest is classified [7.10]: query, notification or note. Notifications are acknowledged at once (the payer's bundle back, Task `completed`) and the case left alone. Queries are filed `open` and lead every action list until answered (F9b). Notes are shown, never acted on. +- Screen: Communication tab on the case; the inbox view across cases, by kind and reason. + +### F13. The small exchanges + +- Status: "Ask where it stands" on the pre-auth and claim cards, while awaiting and after a decision; Task `status`, workflow = the leg's correlation id (fallback 13); not offered to a payer whose adapter refuses it (PMJAY, PAYR-1018). The answer fills the enquiry row; the leg is unchanged. +- Reprocess: on a decided claim not paid in full, "Send reprocess request" with a coded reason (`claimrejected`, `partialpayment`, `rejectiondisputed`), words, and documents; Task `reprocess`, workflow 36. The payer's `completed` Task (37) reopens the claim: the submission goes back to `requested` and the new verdict lands on the claim's own thread. +- Release: once part of an approved claim is paid, "Ask for the balance" with the amount owed; Task `release`, reason `partialpayment`, `valueMoney`, workflow 36. +- Each ask is its own `claim_enquiry` row on its own thread, shown on the card it belongs to, newest first. + +## What runs on every page load of the case + +In this order, before rendering, each bounded to one poll and a short timeout, never a send: coverage (`checking`), plan (`fetching`), ruling (`checking`), claim (`submitting`), predeterminations (`asking`), pre-auth (`submitting` or `cancelling`), enquiries (`asking`). Then the beneficiary card, the policy card, the verdict card, the status line and actions, the tabs. A "Refresh" button reloads the same tab. + +## What is not in the flow + +- No status control anywhere. Stage and sub-stage are derived. +- No manual acknowledgement of a payment notice as the only path; it goes automatically and the screen shows that it went. +- No "chase" button without the status exchange behind it. +- No separate discharge submission on PMJAY; the discharge rides on the claim. +- No claim resubmit on PMJAY; a decided claim is reprocessed. diff --git a/plugins/nhcx/skills/nhcx-insurance/flow/flow.json b/plugins/nhcx/skills/nhcx-insurance/flow/flow.json new file mode 100644 index 000000000..315d1a4b8 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-insurance/flow/flow.json @@ -0,0 +1,818 @@ +{ + "source": "flow/FLOW.md", + "tabs": [ + { + "key": "eligibility", + "label": "Eligibility", + "opens": "always" + }, + { + "key": "plan", + "label": "Insurance plan", + "opens": "always" + }, + { + "key": "lines", + "label": "Line items", + "opens": "always; quoting refused until the plan is ready" + }, + { + "key": "validate", + "label": "Validate", + "opens": "always" + }, + { + "key": "preauth", + "label": "Pre-authorisation", + "opens": "coverage verdict eligible" + }, + { + "key": "communication", + "label": "Communication", + "opens": "always" + }, + { + "key": "claim", + "label": "Claim", + "opens": "always; submit once the pre-auth is approved or partial" + }, + { + "key": "payments", + "label": "Payments", + "opens": "always" + } + ], + "stages": [ + "eligibility", + "preauth", + "enhancement", + "claim", + "payment" + ], + "sub_stages": [ + "draft", + "checking", + "eligible", + "not-eligible", + "requested", + "resubmitted", + "answered", + "queried", + "approved", + "partial", + "rejected", + "cancelling", + "cancelled", + "refused", + "noticed", + "paid" + ], + "next_actions": [ + { + "when": "an open query exists", + "label": "Answer the payer (n)", + "tab": "communication", + "leads": true + }, + { + "stage": "eligibility", + "sub_stage": [ + "draft", + "error", + "not-eligible" + ], + "label": "Check the cover", + "tab": "eligibility" + }, + { + "stage": "eligibility", + "when": "no plan ready", + "label": "Fetch the package master", + "tab": "plan" + }, + { + "stage": "eligibility", + "when": "no lines", + "label": "Quote the treatment", + "tab": "lines" + }, + { + "stage": "eligibility", + "when": "lines quoted", + "label": "Send the pre-authorisation", + "tab": "preauth" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "queried" + ], + "label": "Answer the query", + "tab": "preauth", + "payer": "resubmit" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "queried" + ], + "label": "Answer the payer's query", + "tab": "communication", + "payer": "communication" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "draft", + "refused" + ], + "label": "Send the pre-authorisation", + "tab": "preauth" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "rejected" + ], + "label": "Send a fresh pre-authorisation", + "tab": "preauth" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "approved", + "partial" + ], + "when": "lines added since", + "label": "Send the enhancement (n added)", + "tab": "preauth" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "approved", + "partial" + ], + "when": "not discharged", + "label": "Record the discharge", + "tab": "claim" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "approved", + "partial" + ], + "when": "discharged", + "label": "File the claim", + "tab": "claim" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "requested", + "answered", + "resubmitted" + ], + "label": "With the payer; ask where it stands", + "tab": "preauth" + }, + { + "stage": "claim", + "sub_stage": [ + "queried" + ], + "label": "Answer the claim query", + "tab": "claim", + "payer": "resubmit" + }, + { + "stage": "claim", + "sub_stage": [ + "queried" + ], + "label": "Answer the payer's query", + "tab": "communication", + "payer": "communication" + }, + { + "stage": "claim", + "sub_stage": [ + "rejected", + "partial" + ], + "label": "Ask for a reprocess", + "tab": "claim" + }, + { + "stage": "claim", + "sub_stage": [ + "requested", + "answered", + "resubmitted" + ], + "label": "With the payer; ask where it stands", + "tab": "claim" + }, + { + "stage": "claim", + "sub_stage": [ + "refused" + ], + "label": "Send the claim again", + "tab": "claim", + "when": "a send kind remains, else Ask for a reprocess" + }, + { + "stage": "claim", + "sub_stage": [ + "approved" + ], + "label": "Await the payment notice", + "tab": "payments" + }, + { + "stage": "payment", + "when": "a notice unacknowledged", + "label": "Acknowledge the payment notice", + "tab": "payments" + }, + { + "stage": "payment", + "when": "all acknowledged", + "label": "Settled", + "tab": "payments" + } + ], + "steps": [ + { + "id": "F1", + "name": "Policy search", + "screen": "new case", + "tab": null, + "routes": [ + "GET /claims/new" + ], + "module": "7.4", + "skills": ["nhcx-coverage"], + "holds": [], + "user": "Search policies", + "sends": { + "path": "participant/get/policies", + "kind": "registry REST" + }, + "stores": [], + "after": null, + "shows": "one row per policy with Select" + }, + { + "id": "F2", + "name": "Open the case", + "screen": "new case", + "tab": null, + "routes": [ + "POST /claims" + ], + "module": "7.4", + "skills": ["nhcx-coverage"], + "holds": [], + "user": "Select", + "sends": null, + "stores": [ + "claim: member_id, policy_code, payer_code, recipient_code, policy_json, claim_no" + ], + "after": { + "stage": "eligibility", + "sub_stage": "draft" + }, + "next_action": "Check the cover" + }, + { + "id": "F3", + "name": "Check the cover", + "screen": "case", + "tab": "eligibility", + "routes": [ + "POST /claims//check" + ], + "module": "7.4", + "skills": ["nhcx-coverage"], + "holds": [ + "member id", + "policy code for validation and benefits" + ], + "user": "purpose, Send to payer", + "sends": { + "path": "v1/coverageeligibility/check", + "workflow": "", + "reply": "on_check" + }, + "stores": [ + "txn_id", + "correlation_id", + "api_call_id", + "inforce", + "outcome", + "disposition", + "allowed_amount", + "used_amount", + "patient demographics", + "coverage class and period" + ], + "after": { + "stage": "eligibility", + "sub_stage": "eligible|not-eligible|error" + }, + "shows": "Payer verdict: sum insured, utilised, wallet balance, disposition verbatim", + "next_action": "Fetch the package master" + }, + { + "id": "F4", + "name": "Fetch the package master", + "screen": "case", + "tab": "plan", + "routes": [ + "POST /claims//plan", + "GET /claims//plan/", + "GET /claims//plan/forms" + ], + "module": "7.5", + "skills": ["nhcx-insurance"], + "holds": [ + "eligible" + ], + "user": "Fetch the plan (reuse first)", + "sends": { + "path": "v1/insuranceplan/request", + "workflow": "", + "reply": "on_request" + }, + "stores": [ + "claim_plan", + "claim_plan_benefit", + "claim_plan_form" + ], + "after": { + "plan": "ready|empty|error" + }, + "shows": "searchable master, package view, all forms", + "next_action": "Quote the treatment" + }, + { + "id": "F5", + "name": "Link or capture the admission", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//link", + "POST /claims//unlink" + ], + "module": "7.13 or the HMIS", + "skills": ["nhcx-preauth"], + "holds": [ + "eligible" + ], + "user": "Link the admission", + "sends": null, + "stores": [ + "claim.patient_id", + "claim.encounter_id", + "admission date default" + ], + "after": null + }, + { + "id": "F6", + "name": "The dossier", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//preauth", + "POST /claims//documents", + "POST /claims//documents/required" + ], + "module": "7.7 inputs", + "skills": ["nhcx-preauth"], + "holds": [ + "linked" + ], + "user": "Save the dossier", + "sends": null, + "stores": [ + "claim_diagnosis", + "claim_care_team", + "claim_document (code, stage)", + "claim_item" + ], + "guards": [ + "admission date required", + "at least one diagnosis", + "doctor with HPIN", + "package case needs a line" + ] + }, + { + "id": "F7", + "name": "Quote the treatment", + "screen": "lines", + "tab": "lines", + "routes": [ + "GET /claims//lines", + "POST /claims//lines", + "POST /claims//lines/quantities", + "POST /claims//lines//delete", + "POST /claims//forms" + ], + "module": "7.5", + "skills": ["nhcx-insurance"], + "holds": [ + "plan ready" + ], + "user": "add procedure, implant or tier; quantities; answer the forms the lines pull in", + "sends": null, + "stores": [ + "claim_line (rate from the plan, parent_code on a tier)", + "claim_form_answer" + ], + "guards": [ + "code not in plan", + "tier not offered by the procedure", + "duplicate", + "zero quantity" + ], + "next_action": "Send the pre-authorisation" + }, + { + "id": "F8", + "name": "Validate the set", + "screen": "case", + "tab": "validate", + "routes": [ + "POST /claims//auth" + ], + "module": "7.6", + "skills": ["nhcx-preauth"], + "holds": [ + "at least one line" + ], + "user": "Ask the payer (validate)", + "sends": { + "path": "v1/coverageeligibility/check", + "purpose": "auth-requirements", + "workflow": "", + "reply": "on_check", + "awaited": false + }, + "stores": [ + "claim_auth (fingerprint)", + "claim_auth_item", + "claim_auth_requirement" + ], + "after": { + "auth": "checking|ready" + } + }, + { + "id": "F9", + "name": "Send the pre-authorisation", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//submit" + ], + "module": "7.7", + "skills": ["nhcx-preauth"], + "holds": [ + "eligible", + "linked", + "admission date", + "diagnosis", + "care team with HPIN", + "a line", + "required forms answered", + "required documents attached" + ], + "user": "Send to payer", + "sends": { + "path": "v1/preauth/submit", + "workflow": "12", + "kind": "preauth", + "reply": "on_submit 20 then 21|23|24" + }, + "stores": [ + "claim_preauth: submitting, submission_kind, workflow_id, txn_id, correlation_id, api_call_id, request_json" + ], + "after": { + "stage": "preauth", + "sub_stage": "requested" + }, + "next_action": "With the payer; ask where it stands" + }, + { + "id": "F9a", + "name": "The payer answers", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /nhcx/callback/v1/preauth/on_submit" + ], + "module": "7.8", + "skills": ["nhcx-preauth"], + "holds": [], + "user": null, + "reads": "20 queued (stay submitting, keep preauth_ref) then the decision via verdict_status", + "stores": [ + "status", + "preauth_ref", + "approved_amount", + "eligible_amount", + "items_json", + "query_note", + "thread_correlation_id" + ], + "after": { + "stage": "preauth", + "sub_stage": "approved|partial|queried|rejected" + }, + "shows": "decision, payer reference, approved amount, item verdicts, notes verbatim; door refusal as a flag" + }, + { + "id": "F9b", + "name": "Answer a query", + "screen": "case", + "tab": "preauth or communication", + "routes": [ + "POST /claims//submit (reply)", + "POST /claims//queries//reply" + ], + "module": "7.7 or 7.10", + "skills": ["nhcx-preauth", "nhcx-communication"], + "holds": [ + "queried" + ], + "user": "reply text and documents", + "sends": { + "resubmit": { + "path": "v1/preauth/submit", + "workflow": "19 or 131", + "flow": "queryupdate", + "new_thread": true + }, + "communication": { + "path": "v1/communication/on_request", + "workflow": "", + "correlation_id": "" + } + }, + "after": { + "stage": "preauth", + "sub_stage": "answered (resubmit) or queried until the decision (communication)" + } + }, + { + "id": "F9c", + "name": "Enhancement", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//submit" + ], + "module": "7.7", + "skills": ["nhcx-preauth"], + "holds": [ + "approved or partial", + "lines added", + "no request in flight" + ], + "user": "Submit enhancement", + "sends": { + "path": "v1/preauth/submit", + "workflow": "13 or 131", + "flow": "enhancement", + "whole_bundle": true + }, + "after": { + "stage": "enhancement", + "sub_stage": "requested" + } + }, + { + "id": "F9d", + "name": "Cancel", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//cancel" + ], + "module": "7.9", + "skills": ["nhcx-preauth"], + "holds": [ + "not rejected", + "not cancelled", + "no claim raised" + ], + "user": "Withdraw the pre-authorisation", + "sends": { + "path": "v1/task/submit", + "workflow": "PC01", + "task": "cancel", + "own_thread": true + }, + "after": { + "stage": "preauth", + "sub_stage": "cancelling then cancelled; fresh claim number" + } + }, + { + "id": "F9e", + "name": "Predetermination", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//predetermination" + ], + "module": "7.7", + "skills": ["nhcx-preauth"], + "holds": [ + "as F9" + ], + "user": "Ask for a quote", + "sends": { + "path": "v1/preauth/submit", + "workflow": "12", + "use": "predetermination" + }, + "after": { + "predetermination": "asking then answered; the pre-auth unchanged" + } + }, + { + "id": "F10", + "name": "Record the discharge", + "screen": "case", + "tab": "claim", + "routes": [ + "POST /claims//discharge" + ], + "module": "7.7 inputs", + "skills": ["nhcx-claim"], + "holds": [ + "approved or partial" + ], + "user": "mode (normal, lama, dama, death), stage, discharge, surgery and death times", + "sends": null, + "stores": [ + "claim_submission draft: discharge_mode, discharge_stage, dates" + ], + "next_action": "File the claim" + }, + { + "id": "F11", + "name": "File the claim", + "screen": "case", + "tab": "claim", + "routes": [ + "POST /claims//claim", + "POST /claims//claim/documents" + ], + "module": "7.7", + "skills": ["nhcx-claim", "nhcx-communication"], + "holds": [ + "discharge recorded", + "discharge summary attached", + "claim-stage forms answered", + "amount not above approved" + ], + "user": "Submit the claim", + "sends": { + "path": "v1/claim/submit", + "workflow": "15 (161 or 151 query answer; 16 generic resubmit)", + "kind": "claim", + "under": "the pre-auth's claim number", + "reply": "on_submit 25 then 26|27|291" + }, + "after": { + "stage": "claim", + "sub_stage": "requested then approved|queried|rejected|partial" + } + }, + { + "id": "F12", + "name": "Payments", + "screen": "case", + "tab": "payments", + "routes": [ + "POST /nhcx/callback/v1/paymentnotice/request", + "POST /claims//payments//ack", + "GET /claims/payments" + ], + "module": "7.10", + "skills": ["nhcx-payment"], + "holds": [], + "user": null, + "reads": "PaymentNotice matched by claim number; deduped on its correlation id", + "sends": { + "path": "v1/paymentnotice/on_request", + "workflow": "17 (PMJAY) or the notice's own", + "correlation_id": "", + "to": "the notice's sender", + "automatic": true + }, + "after": { + "stage": "payment", + "sub_stage": "noticed|paid" + }, + "next_action": "Acknowledge the payment notice, then Settled" + }, + { + "id": "F12b", + "name": "The inbox", + "screen": "inbox", + "tab": "communication", + "routes": [ + "POST /nhcx/callback/v1/communication/request", + "GET /claims/inbox", + "POST /claims//queries//acknowledge" + ], + "module": "7.10", + "skills": ["nhcx-communication"], + "holds": [], + "reads": "classify: query | notification | note", + "sends": { + "notification": { + "path": "v1/communication/on_request", + "automatic": true + } + }, + "after": { + "query": "open, leads every action list" + } + }, + { + "id": "F13", + "name": "Status, reprocess, release", + "screen": "case", + "tab": "preauth or claim", + "routes": [ + "POST /claims//status", + "POST /claims//reprocess", + "POST /claims//release" + ], + "module": "7.9", + "skills": ["nhcx-reprocess"], + "holds": [ + "status: payer allows it", + "reprocess: claim decided and not paid in full", + "release: part paid" + ], + "sends": { + "path": "v1/task/submit", + "workflow": "leg correlation id (status) or 36", + "own_thread": true + }, + "after": { + "enquiry": "asking then answered|error; a reprocess reopens the claim to requested" + } + } + ], + "page_load_polls": [ + "coverage checking", + "plan fetching", + "ruling checking", + "claim submitting", + "predeterminations asking", + "preauth submitting or cancelling", + "enquiries asking" + ], + "not_in_the_flow": [ + "a status control", + "a manual-only payment acknowledgement", + "a chase button without the status exchange", + "a separate discharge submission on PMJAY", + "a claim resubmit on PMJAY" + ] +} \ No newline at end of file diff --git a/plugins/nhcx/skills/nhcx-insurance/references/api-knowledge.md b/plugins/nhcx/skills/nhcx-insurance/references/api-knowledge.md new file mode 100644 index 000000000..3b07e901d --- /dev/null +++ b/plugins/nhcx/skills/nhcx-insurance/references/api-knowledge.md @@ -0,0 +1,400 @@ +# API knowledge: the nhcx-adapter contract (optional transport) and the HMIS endpoints that face it + +Read this file only when the transport is nhcx-adapter, and use nhcx-adapter only when the user has asked for it (`references/transport-knowledge.md` section 1). Otherwise the build reaches NHCX through the app's existing integration or its own transport, and `references/transport-knowledge.md` sections 3 and 4 replace everything here. + +This file describes nhcx-adapter (https://github.com/nha-in/nhcx-adapter) as its release ships it, and the HMIS side a build needs to face it. A release carries the binary, `config.sample.json`, `serve.sh`, `stop.sh`, `update.sh` and `README.md`. `nhcx-package/docs/02-Getting Started/10-NHCX Adapter.md` covers the same adapter. When a detail matters, check the release README and `config.sample.json` for the version you run. + +## 1. What the adapter is + +One binary, one `config.json`, no database. You POST plain FHIR to it. It mints the protocol ids, fetches the recipient's certificate, encrypts a compact JWE, posts to the NHCX gateway, and records the exchange in a file ledger. NHCX callbacks reach it encrypted; it decrypts them and POSTs plain FHIR to your HMIS. Both directions are synchronous; there is no queue (release README, "How it works"). + +The same binary can front several participants at once. Inbound, `x-hcx-recipient_code` picks the profile whose key decrypts and whose callback receives. Outbound, `x-hcx-sender_code` picks who sends (release README, "Hosting several participants"). Encrypting for a code the same adapter holds is allowed. So one adapter can host a hospital and a test payer together, and a test between them needs no second gateway. + +## 2. Configuration + +File: `config.sample.json` in the release. `${NAME}` reads an environment variable; `@file` reads a file next to the config. Unknown keys are rejected. + +| Key | Default | What it does | +| --- | --- | --- | +| `env` | `sandbox` | `sandbox` or `production`. Picks the gateway (`https://apisbx.abdm.gov.in/hcx/v1` or `https://apis.abdm.gov.in/hcx/v1`), registry, session endpoint and `X-CM-ID` (`sbx` or `abdm`). | +| `listen` | `127.0.0.1:8090` | The HTTP listener. | +| `publicUrl` | empty | How NHCX reaches the adapter. Register `/in` as the participant's `endpoint_url`. | +| `apiKey` | `${NHCX_ADAPTER_API_KEY}` | The key your HMIS presents on `/out`, `/fhir/out`, `/ledger*`, `/token`. Demanded in production, honoured but not demanded in sandbox. `requireApiKey: true` closes a sandbox adapter. | +| `participant.participantId` | none; the sample carries an example code | Your registry code. `@hcx` is added if missing. | +| `participant.clientId`, `clientSecret` | `${NHCX_CLIENT_ID}`, `${NHCX_CLIENT_SECRET}` | ABDM credentials that mint the session token. | +| `participant.privateKey` | `@private_key.pem` | The RSA key of your registered certificate. | +| `participants[]` | `[]` | Further hosted identities. Each needs only `participantId` and `callback`; the rest is inherited. | +| `callback.url` | `http://127.0.0.1:8765/nhcx/callback` in the sample | Where decrypted messages are POSTed. | +| `callback.appendPath` | `true` | Appends the NHCX path: `.../callback` receives `v1/preauth/on_submit` at `.../callback/v1/preauth/on_submit`. | +| `callback.timeoutSeconds` | `20` | One delivery. NHCX wants its 202 within 30 seconds. | +| `callback.apiKey` | empty | Sent to your HMIS as `Authorization: Bearer `. | +| `callback.routes` | `{}` | Per-path overrides, used exactly as written: `{"v1/preauth/on_submit": "http://preauth-svc/hook"}`. | +| `callback.also` | absent | Extra targets for the same delivery (two systems behind one participant code). Every target must accept or NHCX redelivers to all. | +| `ledger.enabled`, `ledger.dir`, `ledger.retentionDays`, `ledger.storeBodies` | `true`, `data/ledger`, `30`, `true` | The traffic ledger. A hand-written config that leaves out `retentionDays` keeps every day. | +| `maxBodyBytes` | 8 MiB in the v1.0.1 README | Caps request bodies on both surfaces. A PMJAY package master is far larger: set 100 MiB (`104857600`) explicitly. | +| `panel.password`, `panel.path` | empty, `/panel` | The browser console; off until a password is set. | +| `auth.mode`, `auth.tokenTtlSeconds` | `sessions`, `1200` | How the ABDM token is obtained. | + +Minimal working config for one hospital: + +```json +{ + "env": "sandbox", + "listen": "127.0.0.1:8090", + "publicUrl": "https:///in", + "apiKey": "${NHCX_ADAPTER_API_KEY}", + "participant": { + "participantId": "@hcx", + "clientId": "${NHCX_CLIENT_ID}", + "clientSecret": "${NHCX_CLIENT_SECRET}", + "privateKey": "@private_key.pem" + }, + "callback": { "url": "http://127.0.0.1:/nhcx/callback", "appendPath": true, "apiKey": "" } +} +``` + +Start it with `./nhcx-adapter serve`, or `./serve.sh` from the release archive; `./stop.sh` stops a background server. It checks token, participant record, certificate and registered endpoint first and offers to fix each in a terminal (release README, "Startup checks"). `./nhcx-adapter check --no-tui` is the same as a health gate. `serve --no-tui --skip-checks` starts it with no prompts and no checks, for a script that has already checked. + +## 3. Routes + +| Route | Auth | Does | +| --- | --- | --- | +| `POST /out/{path...}` | API key | Send. `path` is the NHCX API path, `v1/preauth/submit`. | +| `POST /fhir/out/{path...}` | API key | Same handler, hcxkit's prefix. The client in section 11 sends here. | +| `POST /in/{path...}` | none | NHCX delivers here. Register `/in`. | +| `POST /v1/{path...}` | none | Alias of `/in` for a registry `endpoint_url` of `/`. | +| `GET /ledger` | API key | Newest first. Filters: `direction, entity, kind, status, sender, recipient, participant, correlation_id, workflow_id, since, until, before, limit` (1 to 500). `since` and `until` take RFC 3339, a date, or a duration such as `24h`. | +| `GET /ledger/stats` | API key | Counts by direction, status, entity. | +| `GET /ledger/thread/{cid}` | API key | Every message on one correlation id plus the derived state. | +| `GET /ledger/{id}` | API key | One message in full, bundle included. | +| `GET /token`, `POST /token/refresh` | API key | The ABDM session token, for calls the adapter does not make (registry, PMJAY payer service). `?participant=` for a hosted identity. | +| `GET /healthz`, `GET /readyz` | none | Liveness; readiness is 503 until a token is held. | +| `GET /panel` | its own password | Operator console: Live, Ledger, Send, Lookup, Setup. | +| `/internal/*` | none | hcxkit-compatible console API, section 8. | + +API key check: `Authorization: Bearer ` first, then `X-Api-Key: `. Constant-time compare. A miss answers `401 {"ok":false,"error":{"code":"UNAUTHORIZED","message":"missing or invalid API key"}}`. + +## 4. The outbound envelope + +The body must be a JSON object. Header precedence, lowest to highest: + +1. HTTP request headers named `x-hcx-*`. +2. The `jwe_headers` object (hcxkit spelling). +3. Top-level `x-hcx-*` keys. +4. Top-level short aliases: `sender`, `recipient`, `correlation_id`, `request_id`, `api_call_id`, `workflow_id`, `status`. + +The payload is `fhir`, else `payload`, else the body itself when it carries `resourceType`. Otherwise `400 INVALID_ENVELOPE`. + +The protected header names: + +``` +x-hcx-api_call_id x-hcx-request_id x-hcx-correlation_id x-hcx-timestamp +x-hcx-status x-hcx-sender_code x-hcx-recipient_code x-hcx-workflow_id +``` + +Completion rules: + +- Sender and recipient codes get `@hcx` appended if missing. +- `api_call_id`, `request_id`, `correlation_id` are kept only when they are plain 8-4-4-4-12 UUIDs; anything else is replaced with a fresh UUID. So a response must carry the request's `correlation_id` as a UUID or the thread is lost. +- `x-hcx-status` defaults to `request.initiated`, or `response.complete` when the last path segment starts with `on_`. +- `x-hcx-timestamp` defaults to now as `YYYY-MM-DDThh:mm:ss±hhmm`. The zone has no colon: `+0530`, not `+05:30`. +- An empty `x-hcx-workflow_id` is dropped, not sent. +- On an `on_` path with no usable correlation id, the adapter threads the message to the newest inbound request of that entity from that recipient. Do not rely on it; send the id. + +What a hospital sends on a normal leg: + +```json +{ + "jwe_headers": { + "x-hcx-sender_code": "@hcx", + "x-hcx-recipient_code": "@hcx", + "x-hcx-workflow_id": "12" + }, + "fhir": { "resourceType": "Bundle", "type": "collection", "...": "..." } +} +``` + +Add `"x-hcx-correlation_id": ""` only on the two reply legs: the communication reply on `v1/communication/on_request` and the payment acknowledgement on `v1/paymentnotice/on_request`. + +## 5. The outbound answer + +The HTTP status is the NHCX gateway's own. Body: + +```json +{ + "ok": true, + "path": "v1/preauth/submit", + "url": "https://apisbx.abdm.gov.in/hcx/v1/preauth/submit", + "headers": { "x-hcx-correlation_id": "...", "x-hcx-api_call_id": "...", "x-hcx-request_id": "...", "x-hcx-workflow_id": "12", "x-hcx-status": "request.initiated", "x-hcx-timestamp": "...", "x-hcx-sender_code": "...", "x-hcx-recipient_code": "..." }, + "gateway_status": 202, + "response": { "...": "the NHCX 202 body" }, + "duration_ms": 412, + "ledger_id": "7UMV0007", + "txn_id": "7UMV0007", + "correlation_id": "...", + "request_id": "..." +} +``` + +Store three things on the leg: `txn_id` (the ledger id), `correlation_id` (the thread), and `headers["x-hcx-api_call_id"]`. Store them on every send. + +Local failures come back as `{"ok": false, "error": {"code", "message", "retryable"}, "request_id", "upstream_status", "upstream_body"}` with these statuses: `400` for `INVALID_ENVELOPE`, `INVALID_PAYLOAD`, `INVALID_BODY`, `INVALID_JWE`, `NO_PATH`, `NO_RECIPIENT`, `WRONG_RECIPIENT`, `BODY_READ`; `401` for the API key; `413` `BODY_TOO_LARGE`; `422` for `DECRYPT_FAILED`, `CERT_NOT_FOUND`, `SELF_ENCRYPTION_KEY`; `502` for any code starting `CALLBACK_`, `GATEWAY_`, `CERT_FETCH_`, `TOKEN_`; `501` `LEDGER_DISABLED`. A gateway refusal is recorded in the ledger as `rejected` with `GATEWAY_HTTP_`. + +## 6. The inbound callback your HMIS receives + +The adapter POSTs to `callback.url` plus the NHCX path. Body: + +```json +{ + "meta": { + "type": "in", + "payloadType": "fhir", + "path": "v1/preauth/on_submit", + "ip": "1.2.3.4", + "time": "", + "redelivery": false, + "participant": "@hcx" + }, + "jwe_headers": { + "alg": "RSA-OAEP-256", "enc": "A256GCM", + "x-hcx-api_call_id": "...", "x-hcx-correlation_id": "...", "x-hcx-request_id": "...", + "x-hcx-sender_code": "@hcx", "x-hcx-recipient_code": "@hcx", + "x-hcx-status": "response.partial", "x-hcx-timestamp": "...", "x-hcx-workflow_id": "20" + }, + "fhir": { "resourceType": "Bundle", "...": "..." } +} +``` + +`payloadType` is `fhir` for a bundle and `protocol` for a ProtocolResponse. A ProtocolResponse is a refusal. Then `fhir` is the plain JSON body with `type: "ProtocolResponse"`, `x-hcx-status: response.error` and `x-hcx-error_details` at its top level. + +HTTP headers on the delivery: + +| Header | Value | +| --- | --- | +| `X-Nhcx-Path` | `v1/preauth/on_submit` | +| `X-Nhcx-Payload-Kind` | `fhir` or `protocol` | +| `X-Nhcx-Correlation-Id` | the thread | +| `X-Nhcx-Api-Call-Id` | this delivery's id, stable across redeliveries | +| `X-Nhcx-Redelivery` | `true` when the ledger already holds this api_call_id (absent otherwise) | +| `X-Nhcx-Participant` | the hosted identity it was addressed to | +| `X-Hcxkit-Txn-Id` | equals `x-hcx-api_call_id` (what a kit-style backend dedupes on) | +| `X-Hcxkit-Type` | entity: `coverage`, `insurance`, `preauth`, `claim`, `task`, `payment`, `communication`, `status` | +| `X-Hcxkit-Flow` | `request` for an arriving response, `on_request` for an arriving request (inverted on purpose) | +| `X-Hcxkit-Payload-Kind` | same as `X-Nhcx-Payload-Kind` | +| `Authorization` | `Bearer ` when configured | + +Contract: answer any 2xx quickly. The adapter then answers NHCX with the 202 acceptance body and an `X-Nhcx-Ledger-Id` header: + +```json +{ + "timestamp": "11/09/2026 10:00:00:123", + "api_call_id": "...", "correlation_id": "...", + "result": { "sender_code": "...", "recipient_code": "...", "entity_type": "preauth", "protocol_status": "request.queued" }, + "error": { "code": "", "message": "" } +} +``` + +A non-2xx from your HMIS becomes `CALLBACK_HTTP_` and NHCX redelivers. NHCX makes five attempts, then drops the correlation id. Your handler must therefore be idempotent on `x-hcx-api_call_id`. Do not do slow work inside the callback: store the envelope, answer 200, apply it after. Apply a delivery on a context detached from the incoming request, so a gateway that hangs up cannot roll the write back. + +The HMIS callback handler: + +- Routes `POST /callback`, `POST /callback/` and `POST /nhcx/callback`. +- Takes an optional shared secret on the query string (`?token=`). +- Reads `X-Hcxkit-Type`, `X-Hcxkit-Flow` and `X-Hcxkit-Payload-Kind`. +- Archives the envelope before applying it. +- Answers `400` for an unreadable body, because redelivery cannot help. Anything unexpected becomes a 500, so the adapter retries. +- Returns `{"status": "settled" | "unmatched" | "ignored"}`. +- Routes by correlation id, never by path. + +## 7. The ledger + +Layout: `ledger.dir//.json`, one file per message, plus `/index.jsonl` with one summary line per message. Ids are eight base32 characters (alphabet `0-9A-V`), a day prefix and a counter that restarts each day: `7UMV0001` is the first message of its day. Pruned hourly by `retentionDays`. + +Entry fields: `id, direction (out|in), created_at, path, entity, action, kind (request|response), format (fhir|protocol|json), sender, recipient, correlation_id, api_call_id, request_id, workflow_id, hcx_status, status, error{code,message}, redelivery, duration_ms, peer{url,status_code,response}, also[], headers{}, fhir{}, fhir_summary{resource_type,bundle_type,entries,resource_types,focus,identifier,patient,outcome}`. + +`status` values: outbound `accepted`, `rejected`, `failed`; inbound `delivered`, `delivery_failed`, `rejected`. + +Thread: `{correlation_id, entity, workflow_id, counterparty, role (initiator|responder), state, started, updated, messages[]}`. `state` is derived by walking the messages in order: + +- `awaiting_response`: you sent a request. +- `awaiting_our_response`: a request reached you. +- `partial`: a `response.partial` arrived. +- `completed`: a response closed it. +- `error`: a rejection, a failed send or delivery, a protocol message, or an `error` status. +- `unknown`. + +Two ledger behaviours you rely on. An outbound `on_` response with no `correlation_id` is threaded to the newest matching inbound request. An inbound whose `api_call_id` was seen before is flagged `redelivery: true`. + +CLI, same data, no server needed for `follow`: + +```sh +nhcx-adapter ledger list --since 24h --entity preauth --status rejected +nhcx-adapter ledger follow --direction in +nhcx-adapter ledger show 7UMV0007 +nhcx-adapter ledger thread +nhcx-adapter ledger stats +nhcx-adapter decrypt --file body.json +nhcx-adapter cert +nhcx-adapter send --path v1/preauth/submit --recipient --file bundle.json +``` + +## 8. hcxkit-compatible endpoints + +A client written against hcxkit polls the adapter for the other side's answer instead of only waiting for its callback. The adapter serves the sliver of hcxkit's `/internal` API that such a client needs. None of these need the API key. Keep the adapter's port off any network you do not control (`nhcx-package/docs/02-Getting Started/10-NHCX Adapter.md`, "Before you expose it"). + +| Route | Body | Answers | +| --- | --- | --- | +| `GET /internal/config/get` | none | `{participant{participantId,name,callbackUrl}, participants[], CMID, env, urls{nhcx,participant,sessions}}` | +| `POST /internal/participants/search` | `{"participant_code": ""}` | `{participants:[registry record + participant_code, participant_name, endpoint_url, status, roles]}`; an unknown code is `{participants: []}` | +| `POST /internal/txn/related` | `{"txnId": ""}` | every ledger row on the same correlation id, both directions, as `{id, direction, status, sender, recipient, correlation_id, api_call_id, type, flow, created_at}`; `404 TXN_NOT_FOUND` when the ledger no longer holds it | +| `POST /internal/txn/fhir` | `{"txnId": ""}` | `{meta{type,payloadType,path,time}, jwe_headers, fhir}`, the same envelope shape a delivery carries | +| `POST /internal/txn/dispatch` | `{"txnId": ""}` | `{txnId, status}` with `dispatch_failed` for a failed or rejected send, `dispatched` for accepted or delivered, plus `errorCode`, `errorMessage` | +| `GET /internal/txn/list?limit=200` | none | the recent ledger, newest first, same row shape | +| `POST /internal/policies/search` | `{"identifiertype": "MemberId", "MobileNo" or "AbhaNumber", "identifiervalue": "..."}` (also `mobile`, `abhaNo`) | the ABDM registry's `participant/get/policies` answer, status passed through; "No policies found" is an error the caller reads as empty | +| `POST /internal/policies/abha/link`, `.../delink` | forwarded verbatim | registry answer | +| `POST /internal/participants/list` | forwarded verbatim | registry roster | +| `POST /internal/participants/certs` | `{"participantid": ""}` | `{participant_code, encryption_cert}` | +| `GET /internal/participants/saved` | none | the configured profiles | + +The polling pattern: + +1. After a send, call `/internal/txn/related` with the stored `txn_id`. +2. Take the inbound rows on the thread that were not sent by you. Keep only rows addressed to the participant the send came from. +3. Fetch each with `/internal/txn/fhir`, newest first. +4. Take the first whose bundle carries the resource the reply is made of (ClaimResponse, CoverageEligibilityResponse, InsurancePlan, Task). +5. Apply it through the same code path the callback uses. Dedupe on `x-hcx-api_call_id`. + +A `404` from `txn/related` means the ledger was reset. Settle the leg as an error instead of spinning. + +## 9. curl examples + +Set these once. The address is the adapter's default `listen`: + +```sh +export ADAPTER=http://127.0.0.1:8090 +export KEY= +export ME=@hcx +export PAYER=@hcx +``` + +Liveness and readiness: + +```sh +curl -s $ADAPTER/healthz +curl -s $ADAPTER/readyz +``` + +Send a coverage eligibility check. Write the envelope to a file first. The bundle is the package's validation request, `nhcx-package/fhir/B1/validation.json`, with your own identifiers substituted. Run this from the project root that holds `nhcx-package/`: + +```sh +python3 - <<'EOF' +import json, os +bundle = json.load(open("nhcx-package/fhir/B1/validation.json")) +env = {"jwe_headers": {"x-hcx-sender_code": os.environ["ME"], + "x-hcx-recipient_code": os.environ["PAYER"], + "x-hcx-workflow_id": ""}, + "fhir": bundle} +json.dump(env, open("/tmp/coverage-out.json", "w")) +EOF +curl -s $ADAPTER/fhir/out/v1/coverageeligibility/check \ + -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \ + --data-binary @/tmp/coverage-out.json +``` + +Read the answer back from the ledger with the `correlation_id` from that response: + +```sh +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger/thread/" +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger?direction=in&entity=coverageeligibility&since=1h" +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger/" +``` + +Same thread through the kit endpoints (no key): + +```sh +curl -s $ADAPTER/internal/txn/related -H 'Content-Type: application/json' -d '{"txnId":""}' +curl -s $ADAPTER/internal/txn/fhir -H 'Content-Type: application/json' -d '{"txnId":""}' +``` + +A session token for the PMJAY payer service or a registry call: + +```sh +curl -s -H "Authorization: Bearer $KEY" $ADAPTER/token +``` + +Simulate a delivery to your own callback while the adapter is not involved (useful for the callback handler's unit test). This is the exact shape the adapter posts. Wrap the package's bare payer bundle, here the pre-auth approval `nhcx-package/fhir/C5/C5-approved-wf21.json`, as `{"meta":{...},"jwe_headers":{...},"fhir":}` first: + +```sh +python3 - <<'EOF' +import json +bundle = json.load(open("nhcx-package/fhir/C5/C5-approved-wf21.json")) +env = {"meta": {"type": "in", "payloadType": "fhir", "path": "v1/preauth/on_submit"}, + "jwe_headers": {"x-hcx-correlation_id": "", "x-hcx-api_call_id": "", + "x-hcx-sender_code": "@hcx", + "x-hcx-recipient_code": "@hcx", + "x-hcx-status": "response.complete", "x-hcx-workflow_id": "21"}, + "fhir": bundle} +json.dump(env, open("/tmp/delivery.json", "w")) +EOF +curl -s -X POST "http://127.0.0.1:/nhcx/callback/v1/preauth/on_submit" \ + -H 'Content-Type: application/json' -H 'X-Nhcx-Path: v1/preauth/on_submit' \ + -H 'X-Nhcx-Payload-Kind: fhir' -H 'X-Nhcx-Correlation-Id: ' -H 'X-Nhcx-Api-Call-Id: ' \ + -H 'X-Hcxkit-Txn-Id: ' -H 'X-Hcxkit-Type: preauth' -H 'X-Hcxkit-Flow: request' -H 'X-Hcxkit-Payload-Kind: fhir' \ + -H 'Authorization: Bearer ' \ + --data-binary @/tmp/delivery.json +``` + +## 10. The HMIS-side endpoints a build exposes + +Use these as the model for what your HMIS needs. `` is the claim episode id. + +| Method | Path | Purpose | Leg | +| --- | --- | --- | --- | +| GET | `/claims`, `/claims/new`, `/claims/` | list, policy search, detail | none | +| POST | `/claims` | open an episode from a chosen policy | none | +| GET | `/claims//state` | the whole episode as JSON after the page-load polls | none | +| POST | `/claims//check` | coverage eligibility (validation, benefits, discovery) | `v1/coverageeligibility/check` | +| POST | `/claims//plan` | fetch or refresh the package master | `v1/insuranceplan/request` | +| GET | `/claims//plan/forms`, `.../forms/`, `.../plan/` | questionnaires and one package | none | +| POST | `/claims//link`, `/unlink` | attach or detach the admission | none | +| POST | `/claims//preauth` | save the dossier draft | none | +| GET, POST | `/claims//lines`, `.../lines/quantities`, `.../lines//delete` | procedure, implant and tier lines | none | +| POST | `/claims//forms` | save questionnaire answers | none | +| POST | `/claims//auth` | auth-requirements ruling | `v1/coverageeligibility/check` | +| POST | `/claims//submit` | pre-auth 12, query answer 19, enhancement 13, enhancement answer 131 | `v1/preauth/submit` | +| POST | `/claims//predetermination` | a quote | `v1/preauth/submit` | +| POST | `/claims//cancel` | cancel Task PC01 | `v1/task/submit` | +| POST | `/claims//status` | status enquiry Task | `v1/task/submit` | +| POST | `/claims//reprocess`, `/release` | reprocess or balance release, 36 | `v1/task/submit` | +| POST | `/claims//queries//reply`, `.../acknowledge` | communication reply or notification acknowledgement | `v1/communication/on_request` | +| POST | `/claims//discharge` | record how the stay ended | none | +| POST | `/claims//claim` | claim 15, query answer 161 or 151, resubmit 16 | `v1/claim/submit` | +| POST | `/claims//claim/documents`, `/documents`, `/documents/required`, `.../delete` | attachments | none | +| GET | `/claims//documents/` | view an attachment | none | +| POST | `/claims//payments//ack` | resend a payment acknowledgement | `v1/paymentnotice/on_request` | +| POST | `/v1/` under the registered `endpoint_url` (own transport), or `/callback`, `/callback/`, `/nhcx/callback` (nhcx-adapter) | a delivery | inbound | + +The HMIS configuration a build needs: + +- The transport's settings: for nhcx-adapter, its base URL (it listens on `127.0.0.1:8090` by default) and API key; for your own transport, the ABDM client id and secret, the private key, and the sessions, NHCX and registry addresses (`references/transport-knowledge.md` section 3). +- The payer's participant code (`1518@hcx` for the PMJAY SHA Himachal Pradesh sandbox) and the payer's name. +- The callback shared secret. +- A workflow-id override table, JSON, that overrides the per-payer table key by key, for example `cancel=122`. +- A map from payer code to payer adapter, for example `1518=pmjay,=generic`. +- The archive folder for cases, and a switch to turn the archive off. + +The sender code is not an environment variable. It is the facility's participant code, held in the HMIS's own settings. + +## 11. What the adapter client looks like in code + +The whole client is one function, `_api(path, payload, timeout, method, claim_id, use_case)`. It builds the URL from the base, adds `Authorization: Bearer` when a key is set, POSTs JSON, raises `GatewayError(message, status)` on any non-2xx or network failure, decodes JSON, and archives the envelope beside the case when `claim_id` is given. Every send in the module goes through it, which is what lets a test replace it with a stub: + +```python +posted = {} +def _ack(path, payload=None, **kw): + posted["path"], posted["payload"] = path, payload + return {"txn_id": "01PLAN", "correlation_id": "corr-plan-1"} +claims._api = _ack +``` + +Give your HMIS the same single door. diff --git a/plugins/nhcx/skills/nhcx-insurance/references/errors-and-debugging.md b/plugins/nhcx/skills/nhcx-insurance/references/errors-and-debugging.md new file mode 100644 index 000000000..9be844d82 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-insurance/references/errors-and-debugging.md @@ -0,0 +1,167 @@ +# Errors and debugging + +Sources: + +- `nhcx-package/nhcx-error.yaml`: every NHCX, PAYR and ERR-PYR code, with the standard and reference payer readings side by side. +- `nhcx-package/docs/06-Reference/01-Error Codes.md`: the same codes as tables. +- `nhcx-package/docs/01-Overview/04-JWE, Status and Errors.md`, "Codes met live". +- `nhcx-package/docs/03-Building a Provider/11-PMJAY Sandbox Run.md`: one full case run, refusal by refusal. +- `nhcx-package/docs/06-Reference/02-Troubleshooting.md`. +- The nhcx-adapter release README, "Troubleshooting". + +The live readings are from runs against the PMJAY SHA Himachal Pradesh sandbox payer (`1518@hcx`). + +## 1. Where an error comes from + +Three places refuse a message, and the family of the code says which (`nhcx-error.yaml`, `spaces`): + +| Family | Who refused | How you hear it | +| --- | --- | --- | +| Gateway answers to your own send (`400`, `401`) | the exchange, before the message goes further | the HTTP answer to your POST on `/v1/...`; a `401` is an expired token or a missing `Bearer` | +| A delivery your key cannot open (own transport) | your receiving end | the JWE will not decrypt: the certificate on your participant record is not the key you hold | +| Adapter codes (`INVALID_ENVELOPE`, `CERT_NOT_FOUND`, `CALLBACK_HTTP_500`), nhcx-adapter only | nhcx-adapter, before or after the wire | the HTTP answer to your `/fhir/out` call, `{"ok": false, "error": {...}}` | +| `NHCX-*` | the exchange; the message never reached the payer | the HTTP answer to your call (`gateway_status` 4xx with `upstream_body`), or a `ProtocolResponse` delivered to your callback later | +| `PAYR-*`, `ERR-PYR-*` | the payer; the message reached it | a `ProtocolResponse` on your callback with `x-hcx-status: response.error` and `x-hcx-error_details {code, message}`, on the request's correlation id | + +A `ProtocolResponse` is plain JSON, not a bundle. The exchange delivers it with `type: ProtocolResponse` and the `x-hcx-` fields in the clear; nhcx-adapter passes it on with `X-Nhcx-Payload-Kind: protocol` and `fhir` set to the body. Read `fhir.type == "ProtocolResponse"` and `fhir["x-hcx-error_details"]`. Settle the leg as refused at the door with the payer's words, and keep the thread the payer last answered on. + +PAYR numbers are not globally unique. The same number means different things on different sheets (`nhcx-error.yaml` lists them under `collisions`), and the live sandbox reuses several with a meaning the published sheet does not give. Match on the message text and log both. + +## 2. PAYR and ERR codes met live + +The published text is from `nhcx-package/nhcx-error.yaml`. Where the standard and reference payer sheets collide, both readings are given. The live text and the fix are from the sandbox runs. + +| Code | Published text | Live text | What it means | Fix | +| --- | --- | --- | --- | --- | +| PAYR-1008 | Invalid FHIR bundle received (reference payer); Eligible coverage amount is insufficient (standard) | "Invalid content type" or "Invalid input, code and reason code" or "Invalid Base64" | Three faults on one code: a document outside pdf, jpg, jpeg, png and fhir+json; a Task code paired with a reason the scheme does not accept (every `status`, `reprocess`, `release` Task on the sandbox, and a reprocess with the intimation input misspelt); an attachment it will not decode | Check the content type. For a Task, the sandbox takes only one financial task code, `cancel` (`11-PMJAY Sandbox Run.md`, "What the sandbox will not take"). Spell the reprocess input `intimationNumber` | +| PAYR-1018 | Time limit for submission expired (standard); No task reason code received (reference payer) | asks for a `Task.reasonCode` on a status enquiry | The status Task is refused as incomplete; with a reason it is refused with PAYR-1008 | Do not offer a status enquiry on PMJAY; switch it off in the PMJAY payer adapter | +| PAYR-1019 | Requested additional information was not received in time (standard); Invalid sequence received in supporting info element (reference payer) | "Invalid sequence received in supporting info element" | A `supportingInfo` entry with no `sequence` | Number the whole list once it is assembled | +| PAYR-1027 | (item error family) | "Invalid item id found for item in claim component" | `Claim.item` has no element `id` (`Item/1`). Nothing to do with the package code | Put `id` on every item, procedure and supportingInfo | +| PAYR-1083 | (practitioner family) | "No HPR details found for the practitioner ... category code as HPIN" | The Practitioner carries no identifier typed `HPIN` | Add the `HPIN` identifier under `https://hpr.abdm.gov.in` | +| PAYR-1096, PAYR-1503 | (supporting-info value-type family) | the death date is missing | A death claim without the `ONS`/`DTM` entry | Add `ONS`/`DTM` with the death instant and answer the plan's death forms | +| PAYR-1214 | No previous preauthorization approved record found for the resubmission request | same | A 121 after a rejection | Send a fresh 12 | +| PAYR-1238 | Beneficiary is having an active preauthorization request at this hospital with reference number ... | same; the reference ends in the SHA's case id | Scheme rule, not a bundle fault: one live pre-auth per beneficiary per hospital. Perversely the first sign the bundle is right, because validation runs first | Cancel the other case (PC01) or let it be rejected; sweep before a run | +| PAYR-1245 | Rule failure | "Only one conservative procedure can be booked for a case" | The master's `ProcedureType`; an enhancement on a conservative case must add a medical package | Pick a package whose `ProcedureType` is medical | +| PAYR-1254, PAYR-1365 | Response for STG Questionnaire id ... is mandatory for procedure code ... | same | A package's treatment-guideline questionnaire unanswered | Answer every `/stgquestionnaire/` form the plan attaches to the quoted packages | +| PAYR-1256, PAYR-1363 | Response for Authentication Consent Questionnaire is missing | same | The plan's consent questionnaire unanswered where no biometric token was taken; 1256 on the pre-auth, 1363 on the claim | Answer the policy-level consent form on both legs | +| PAYR-1270 | Item LM100 is not applicable for preauthorization request | same | `LM100` on a pre-auth | Only a LAMA or DAMA claim before or during surgery carries it | +| PAYR-1321 | Error occurred while processing the request due to invalid workflow id | same | 151, 19 or 16 on `v1/claim/submit` | Answer a claim query on 161; never resubmit a decided claim, reprocess it | +| PAYR-1322 | No active case found for the given case number | "Active instance found for case number" | A request is already open on that case; the scheme takes one at a time | Wait about 30 seconds after a decision, then send again; up to three tries | +| PAYR-1362 | No procedure with code LM100 received with 'Requested' status | same | A LAMA or DAMA claim before or during surgery that still carries the package | Collapse the claim to one `LM100` line | +| PAYR-1367, PAYR-1368 | No biometric records found ... / units of cycle information received | same | A cyclic package (dialysis) claimed without a biometric record per cycle and cycle information | Do not claim a cyclic package unless the HMIS can produce both | +| PAYR-1401 | policy not allowed for the hospital | same | The plan was asked for under a policy the hospital is not empanelled under | Ask under the beneficiary's own policy code from the policy search | +| PAYR-1406 | Existing request with correlation id ... is in progress | same | A second plan request while one is still being served | Wait 15 to 60 minutes; reuse the master you hold | +| ERR-PYR-CLM-007 | on none of the published sheets; `nhcx-error.yaml` lists it as observed live | "No prior preauthorization or claim record found for case number" | The claim was sent under a number of its own instead of the pre-auth's | Send the claim under the pre-auth's claim number | + +Refusals arrive in order: the SHA validates the bundle first and applies the scheme's rules only to a bundle that passed. A refusal in the `PAYR-102x` block is structural, so check ids and sequences before values. + +## 3. Gateway protocol errors + +From `nhcx-package/nhcx-error.yaml` (the gateway space) and the live notes: + +| Code | Message | When you meet it | Fix | +| --- | --- | --- | --- | +| NHCX-1006 | Duplicate request. Request with same correlation id already exist | A request sent again on a correlation id the exchange already holds | Mint a fresh correlation id for every request; only a response echoes one | +| NHCX-1010 | No Data with given Correlation id for call back request | A response sent on a thread the exchange has retired: the request was redelivered five times without a 2xx, or the id was never a request | Acknowledge inbound requests at once; a payer that decides minutes later sends `outcome queued` first | +| NHCX-1012 | No records found with the requested api caller id | The sandbox's own `v1/status` route, whatever id you pass | Ask status as a Task on `v1/task/submit` | +| NHCX-1015 | Invalid response received from receiver (published); the registry answers "You are not authorized to update/modify details" | Updating a participant's endpoint or certificate with a client id that did not create it | Use the creator's credentials or the NHCX participant portal (nhcx-adapter release README, "Troubleshooting") | +| NHCX-1016 | Invalid Api Action / no policies found (the registry, on a policy search) | A policy search that finds nothing | Read it as an empty result | +| NHCX-1018 | Invalid ABHA number received | An ABHA not in `XX-XXXX-XXXX-XXXX` form on the envelope | Format it, or omit the header | + +With nhcx-adapter as the transport, its local codes and their HTTP statuses are in `api-knowledge.md` section 5. The ones you will meet first: + +- `CERT_NOT_FOUND`: the recipient has no certificate on the registry; nothing to fix locally. +- `SELF_ENCRYPTION_KEY`: the registry handed out your own certificate for another code; run `nhcx-adapter cert --refresh`. +- `DECRYPT_FAILED` on `/in`: your registered certificate is not the key you hold; run `nhcx-adapter check`. +- `WRONG_RECIPIENT` on `/in`: a message for a participant this adapter does not hold. +- `CALLBACK_HTTP_` and `CALLBACK_UNREACHABLE`: your HMIS refused or was down; NHCX will redeliver up to five times. +- `TOKEN_HTTP_401`: wrong `clientId` or `clientSecret`, or sandbox credentials against production. + +## 4. Reading a ledger thread + +The per-case archive is the first place to look, with any transport: every message sent and received, by correlation id, in `//transactions.txt` (step 4). With nhcx-adapter as the transport, its ledger also holds what reached it but not your HMIS; the commands below read it. + +Step 1. Find the thread. From the leg row's `correlation_id`, or from the case number in a summary: + +```sh +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger/thread/" | python3 -m json.tool +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger?since=2h&direction=in&limit=100" | python3 -c 'import json,sys; [print(r["id"], r["created_at"][11:19], r["direction"], r["path"], r["workflow_id"], r["hcx_status"], r["status"], r.get("fhir_summary",{}).get("outcome")) for r in json.load(sys.stdin)["items"]]' +nhcx-adapter ledger thread # no server needed +``` + +Step 2. Read the derived `state`: + +| state | Meaning | What to do | +| --- | --- | --- | +| `awaiting_response` | You sent a request and nothing came back | Wait; on the SHA a decision needs the desk. Check `peer.status_code` on the outbound row is 202 | +| `partial` | A `response.partial` arrived (20, 25, or the SHA's 37) | The payer has it. The decision comes on the same thread | +| `completed` | A `response.complete` arrived | The leg should be settled in the HMIS. If it is not, the callback failed or the reader misread it | +| `awaiting_our_response` | A request reached you (a CommunicationRequest, a payment notice) | Your reply is due on this correlation id | +| `error` | A rejection, a failed send or delivery, or a protocol message | Open the message with `error` or `format: protocol` | + +Step 3. Read one message in full, bundle included: + +```sh +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger/" | python3 -m json.tool | less +``` + +On an inbound row, `peer.status_code` is what your callback answered and `peer.response` is its body. A `delivery_failed` row with a 500 is your handler raising. On an outbound row, `peer.status_code` is the gateway's answer and `peer.response` its body. A `rejected` row carries `GATEWAY_HTTP_` and the NHCX error in `peer.response`. + +Step 4. Compare with the HMIS's own archive for the case, `//transactions.txt`. Each line names the workflow id, correlation id, api call id, ledger id and file. + +- A message in the ledger and not in the archive is a callback that failed. +- A message in the archive marked `outcome=unmatched` is one the HMIS could not tie to a case: the correlation id is on no leg row, and the bundle names no claim number the HMIS knows. +- A message in neither is a send that never left; look at the HMIS's error on the leg row. + +Files, when the server is down: `//.json`, and `index.jsonl` in the same folder for the summaries. `ledger.dir` is `data/ledger` by default. + +## 5. Correlation mistakes + +Each of these was made once in a real build. + +- Answering on the wrong thread. A communication reply or a payment acknowledgement must carry the request's `x-hcx-correlation_id`; every other leg must not carry one. A PMJAY query answer (19, 131, 161) goes on a new correlation id; a same-thread answer is swallowed without a refusal. +- Sending a non-UUID correlation id. nhcx-adapter replaces anything that is not an 8-4-4-4-12 UUID with a fresh one, so the thread is silently lost; store what the transport returned, not what you sent. With your own transport, a request's correlation id is its own `api_call_id` and an answer echoes the request's. +- Matching by path or by header type. Route an inbound message by its correlation id first, then by the claim number inside the bundle. With nhcx-adapter, the `X-Hcxkit-Flow` header is inverted on purpose and must not be a filter. +- Closing a thread on the first reply. The acknowledgement and the decision share one correlation id; a settled-status guard throws the approval away. +- Losing the thread after a refusal at the door. A send refused with a ProtocolResponse went out under a correlation id the payer never took in. The case still lives on the thread the payer last answered; keep it as `thread_correlation_id`. +- Reusing a correlation id after an error. The exchange retires it; the next attempt needs a fresh one. +- Forgetting the workflow id on a reply. Some payers match the payment acknowledgement on the notice's own workflow id; PMJAY wants 17. + +## 6. Redelivery and deduplication + +NHCX redelivers an unacknowledged message up to five times and then drops the correlation id. The SHA redelivers a large plan answer on its own, two or three times about a minute apart, under the same `x-hcx-api_call_id`. A case archive showed it as three lines on one api call id. With `callback.also` configured, one delivery reaches every target, and a refusal by any one of them makes NHCX redeliver to all. + +So: + +- Dedupe on `x-hcx-api_call_id` (with nhcx-adapter, `X-Hcxkit-Txn-Id` carries the same value). Either store the last applied `api_call_id` on the leg row and ignore a repeat, or keep an inbound ledger keyed on it and answer `duplicate`. A payer that omits the id is deduped on identical outcome and adjudication. +- Dedupe payment notices and communication requests on their correlation id, with a unique index on each table. +- Answer 2xx before doing slow work. The exchange allows 30 seconds for the 202 receipt (nhcx-adapter gives your HMIS 20 of them, `callback.timeoutSeconds`); anything slower is a failed delivery. +- Un-record a delivery whose application failed for a passing reason (database away), so the redelivery is not waved off as a duplicate. +- With nhcx-adapter, treat `X-Nhcx-Redelivery: true` as a hint, not a rule: the ledger flag is per adapter process and is lost on a ledger reset. + +## 7. A send reported as failed can still have landed + +Seen live on the sandbox three times in one night. A pre-authorisation went out through nhcx-adapter, the connection dropped after the request had been written, and it answered the hospital `GATEWAY_UNREACHABLE` with HTTP 502. NHCX had taken the message: the SHA acknowledged it four seconds later on the correlation the adapter had minted. A hospital that treats that 502 as "not sent" sends again. The scheme refuses the duplicate (ERR-PYR-PRE-030 "Active instance found for case number", PAYR-1238 for a fresh pre-auth), and a live case stands at the payer that the hospital has no record of. + +So: + +- nhcx-adapter's failure body names the ids the message went out under: `ledger_id`, `txn_id`, `correlation_id`, `api_call_id`, `request_id` and the `headers` map. Keep them. With your own transport the ids are the ones you minted before sealing: store them before the POST, so a failed POST still has a thread to look for. +- Record the failed leg under that correlation, not as nothing. Carry the ids on the client's error and write them onto the leg row. +- When an answer arrives on a failed leg's correlation, revive it: the leg becomes a sent leg, the record moves from draft to with-the-payer, and the desk is not offered a second send. A protocol error answer revives nothing. +- Anything that creates a record before it sends must name that record in the refusal, or the record is orphaned where nobody can see it. An enhancement handler returns the child it raised alongside the gateway's words. + +## 8. Sandbox pace rules + +What the SHA Himachal Pradesh sandbox (`1518@hcx`) did across the runs. `nhcx-package/docs/03-Building a Provider/11-PMJAY Sandbox Run.md` records one such run in order. + +- One live pre-authorisation per beneficiary per hospital (PAYR-1238). Every HMIS that shares the facility's participant code shares the limit, so sweep before a run: withdraw every approved case without a claim, then wait ten seconds. +- One request at a time per case (PAYR-1322). About 30 seconds between a decision and the next leg; an enhancement refused with "Active instance" is resent up to three times. +- Decisions are taken on the NHCX Payer Service desk, not on the exchange (`nhcx-package/docs/03-Building a Provider/12-PMJAY Adjudication APIs.md`). A case has to be driven through roles: PPD-Trust decides a pre-auth; a claim walks CEX-Trust, CPD-Trust, the Medical Audit Committee, ACO-Trust, SHA-Trust and the Claim Review Committee. The desk answers "Event Meta Log not found" or "Case not found" until the exchange has delivered the request; retry every six seconds, up to 150 seconds. A decision the desk accepts is sometimes never sent; taken again a minute later it is answered in seconds, so decide up to four rounds of 90 seconds. +- An enhancement's query has to be taken a minute after the acknowledgement. +- A claim episode with a query answered and the roles walked takes about ten minutes. Run cases one at a time and allow 20 minutes per case. +- The plan answer arrives in pieces over a minute and is redelivered; expect the same api call id three times. +- The beneficiary registry behind the ABDM session refuses a search now and then while a token refreshes. Retry the search up to four times, 30 seconds apart. +- The sandbox approves a claim query answer at zero with "No query response comments received" when the `CQD` reply is missing, and sometimes even when it is present. Report it; do not assert on the amount. +- The status Task is refused on this sandbox: without a `Task.reasonCode` it answers PAYR-1018, with any reason code PAYR-1008. PMJAY decides on its own desk and answers no status enquiry, so do not offer one for it. Record the refusal on the enquiry row and move on. +- The reprocess Task is taken only under the standard's spelling, `intimationNumber`. Use that spelling on every Task (cancel included); the package's bundles carry it too. The SHA answers workflow 37, "Arbitration claim submission process completed successfully". +- A test payer you run yourself has none of these limits; six use cases ran in under four minutes against one. diff --git a/plugins/nhcx/skills/nhcx-insurance/references/fhir-knowledge.md b/plugins/nhcx/skills/nhcx-insurance/references/fhir-knowledge.md new file mode 100644 index 000000000..08ffbb6c6 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-insurance/references/fhir-knowledge.md @@ -0,0 +1,206 @@ +# FHIR knowledge: every bundle sent and received + +Sources: the bundles under `nhcx-package/fhir` (the hospital pins in `B1` to `B9`, the payer answers in `C3` to `C11`, the live PMJAY hospital captures in `D1` to `D13`) and the chapters under `nhcx-package/docs/05-FHIR Reference`. Get the package as `references/material.md` says. + +## 1. Where the examples live + +| Set | Path | What it is | +| --- | --- | --- | +| Pinned hospital bundles | `nhcx-package/fhir/B1` to `B9`, the lower-case files (`B3/preauth-request.json`) | One bundle per message a hospital sends, written to the specification with placeholders. A build is held to these byte for byte. The pin map is in `references/material.md`. | +| Payer answers | `nhcx-package/fhir/C3` to `C11` | One file per message the payer sends: the generic answer and, where one exists, its `-pmjay` twin. Feed these into your readers. | +| Live hospital captures | `nhcx-package/fhir/D1` to `D13` (PMJAY) and the capitalised B files such as `B3/B3-request.json` (generic) | Bundles taken from the sandbox wire, with the beneficiary's identifiers replaced | +| The catalogue | `nhcx-package/fhir/index.yaml` | For each file: direction, side, scheme (`generic` or `pmjay`), workflow id, focal resource, origin. Origin `example` means placeholders, not a payload; `wire` means a capture. | +| The NRCeS IG's own example | `nhcx-package/fhir/B4/communication-request.json` | The communication TaskBundle for the payer's request comes from the IG | +| Your build's archive | `//NNN--.json` and `transactions.txt` (modules 7.1 and 7.3) | Every envelope one episode sent and received, in order | +| Chapters | `nhcx-package/docs/05-FHIR Reference/*.md` | Element by element: `08-Preauthorisation Request.md`, `12-Claim Request.md`, `13-Claim Response.md`, `17-Communication.md`, `15-Cancel, Reprocess and Shortfall.md`, `16-Payment Notice and Acknowledgement.md`, `06-Insurance Plan Response, Package-Based.md`, `19-Codes and Value Sets.md` | + +Pins, by leg. Paths are under `nhcx-package/fhir/`. + +| Leg | Provider pin | Payer answer or capture | +| --- | --- | --- | +| Coverage eligibility | `B1/discovery.json`, `B1/validation.json`, `B1/benefits.json`, `B1/auth-requirements.json` | `C3/validation-response.json`, `C3/discovery-response.json`, `C3/benefits-response.json`, `C3/C3-response-generic.json`; PMJAY `C3/coverage-eligibility.json`, `C3/C3-benefits-pmjay.json`, `C3/C3-response-pmjay.json` | +| Insurance plan | `B2/insurance-plan-request.json` | `C4/C4-response-pmjay.json` (package-based, abridged), `C4/C4-response-generic.json` (coverage-based) | +| Pre-auth 12, enhancement 13, query answer 19 or 131 | `B3/preauth-request.json`, `B3/preauth-enhancement.json`, `B3/preauth-queryupdate.json` | `C5/C5-received-wf20.json`, `C5/C5-approved-wf21.json`, `C5/preauth-queried.json`, `C5/C5-rejected-wf23.json`, `C5/C5-enhancement-approved-wf22.json`; PMJAY the `-pmjay` twins and `C5/C5-queried-wf24.json` | +| Cancel PC01 | `B3/preauth-cancel.json` | `C10/C10-cancelled-wfPC02.json`, `C10/C10-cancelled-wfPC02-pmjay.json` | +| Claim 15, query answer 161 | `B5/claim-request.json`, `B5/claim-queryupdate.json` | `C7/C7-received-wf25.json`, `C7/C7-approved-wf26.json`, `C7/claim-queried.json`, `C7/C7-rejected-wf291.json`; PMJAY the `-pmjay` twins, `C7/C7-approved-deduction-wf26-pmjay.json` and `C7/C7-queried-wf27.json` | +| Reprocess 36, release 36 | `B5/claim-reprocess.json`, `B5/claim-release.json` | `C10/C10-arbitration-wf37.json`, `C10/C10-arbitration-wf37-pmjay.json` | +| Payment acknowledgement | `B7/payment-notice-ack.json` | The notice you answer: `C9/C9-notice-wf30.json`; PMJAY `C9/payment-notice.json`, `C9/C9-notice-tds-wf30-pmjay.json` | +| Communication reply | `B4/communication-response.json` | `B4/communication-request.json` (the query you answer; the IG's example), `C6/C6-preauth-query-wf24.json` and `C6/C6-claim-query-wf27.json` (live, generic), `C6/C6-notification-wfN02.json` (PMJAY) | +| Status enquiry | None. The published call carries no bundle (`nhcx-package/docs/05-FHIR Reference/18-Predetermination, Status and Search.md`). | None captured | + +## 2. Conventions every hospital bundle follows + +From `nhcx-package/docs/05-FHIR Reference/01-Bundles and Conventions.md` and the pins: + +- `Bundle.type` is `collection`; `Bundle.meta.profile` names the NRCES bundle profile (`ClaimBundle`, `TaskBundle`, `CoverageEligibilityRequestBundle`); every resource names its own profile under `https://nrces.in/ndhm/fhir/r4/StructureDefinition/`. +- Every entry has an absolute `fullUrl` under one base, `https://nhcx.abdm.gov.in/...`, and every reference resolves to another entry. A thing that is genuinely not in the bundle is named by identifier, not by a URL. The chapter's rule 3 also accepts `urn:uuid:` references; parse both. +- `Bundle.id` is fixed per shape: `coverage-validation-request-generic`, `preauth-request-generic`, `preauth-enhancement-request-generic`, `claim-queryupdate-request-generic`, `preauth-cancel-request-generic`. +- No `meta.versionId`, no `meta.lastUpdated`, no bundle `timestamp` on a request. The communication reply and acknowledgement are the exception: the IG example carries `meta.lastUpdated` and `timestamp`, and the build writes them. +- Money carries `currency: INR`; the total equals the sum of the item nets; whole numbers are written as integers. +- Instants are IST with `+05:30`. The four coverage pins in `B1` stamp `created` at `+05:00`, so leave `created` out of the byte comparison. + +## 3. Coverage eligibility request + +Builder: `build_coverage_request`. Seven entries, in this order and at these urls: + +1. `CoverageEligibilityRequest` at `/coverage-eligibility/request`: `identifier: [{system: https://nhcx.abdm.gov.in}]`, `status active`, `priority normal`, `purpose: []`, `patient`, `created`, `enterer` (the PractitionerRole), `provider`, `insurer`, `facility` (the Location), `insurance: [{focal: true, coverage}]`, and `item[]` on `benefits` and `auth-requirements`. +2. `Patient` at `/patient`: identifiers typed `PMJAY` (NDHM identifier-type system) and `MB` (v2-0203), both the member id. Nothing else; demographics are the payer's to return. +3. `Organization` provider at `/provider`: identifier `NPI` under `https://nhcx.abdm.gov.in` = the facility's registry id (HFR id); `type prov`; `name`. +4. `Organization` payer at `/payer`: identifier `NIIP` = the participant code without `@hcx` (`1518`); `type pay`. +5. `Location` at `/location`: `name`, `managingOrganization` the provider. +6. `Coverage` at `/coverage`: identifier `NH` = the policy code, or `NONE` on a discovery; `status active`; `type HIP`; `subscriber`, `beneficiary`, `subscriberId` = member id; `relationship self`; `payor`. +7. `PractitionerRole` at `/practitioner-role`: `code` SNOMED `307988006` Medical technician. + +Items (`eligibility_item`): `category` under `https://nhcx.abdm.gov.in/category-code` (the specialty), `productOrService` under `https://nhcx.abdm.gov.in/product-code` (the package), `quantity.value` as an integer, and each ward tier quoted through the package as a `modifier` coding with code and display and no system. No money, no diagnosis, no sequence. + +The four purposes differ only in `purpose`, the Coverage identifier and whether `item` is present. + +Reader (`parse_validation_bundle`): the payer echoes the request's entries and appends its own, so take the last `CoverageEligibilityResponse`, `Patient` and `Coverage`. Read `insurance[0].inforce`, `outcome`, `disposition`, `item[].authorizationRequired`, the largest `benefit[].allowedMoney` with its `usedMoney`, the Patient's name, gender, birth date, address, `ABHA` identifier and photo, the Coverage's `class[0].name` and `period`. The SHA answers on workflow id `5` (`nhcx-package/fhir/C3/C3-response-pmjay.json`). + +Auth-requirements reader (`parse_auth_bundle`, with `supporting_entry`; examples `C3/C3-response-generic.json` and `C3/C3-response-pmjay.json`): one `insurance[0].item` per line quoted, each with `authorizationRequired`, `excluded`, `benefit[0]` and `authorizationSupporting[]`. Each supporting entry is a CodeableConcept whose `text` is free text the scheme overloads: `fullUrl: ` marks a form to answer; `Type: pre` or `Type: post` says which leg a document is due at; `Procedure Code: X` says for which line. The space after the colon is sometimes missing; match both. A form is always wanted at pre-auth; a document only when its stage is `pre`. + +## 4. Insurance plan request and the plan + +Request (`build_plan_request`): a `TaskBundle` with one entry, a `Task` at `https://nhcx.abdm.gov.in/insurance/request`: `status requested`, `intent order`, `code poll` on the HL7 financial task code system, inputs typed `policyNumber` and `providerId` under the NDHM task-input code system. No id, no timestamp, no requester. At least one input is mandatory. Bundle id `insurance-request-generic`. + +Answer: an `InsurancePlanBundle` with one `InsurancePlan`, an `Organization`, and one `Questionnaire` per form the plan names (the same form repeated once per benefit that needs it; collect by `url`). The parser (`parse_plan_bundle`) reads both published shapes and merges them on package code: + +- `plan[].specificCost[].category` (the specialty) then `benefit[].type` (the package) then `cost[]`: the cost typed `Procedure` is the package rate; `Stratification` and `Implant` costs are money paid over the rate, named by their `qualifiers[0]`. +- `coverage[].benefit[].limit[]`: the limit whose code is the package's own is the rate; the rest (STRAT codes, implants) are tiers. +- Extensions on the plan, the coverage and each benefit, matched by a squashed url family: `Claim-Condition` children name conditions (`ProcedureType`, `IsDayCare`, and so on); `Claim-SupportingInfoRequirement` children are one nested requirement per document, each with `category`, `code` (`MAND0409` and the like) and `documentationUrl` pointing at a Questionnaire. Requirements on the `InsurancePlan` resource itself are policy-wide (proof of identity, the consent forms). +- A `Questionnaire` under `/questionnaire/` is a policy form; under `/stgquestionnaire/` a treatment-guideline checklist. Questions live on `item.prefix` far more often than `item.text`; answer options are plain strings; `initialSelected` is the payer's default. + +Store it once per facility and policy and copy it onto later episodes (`reuse_plan`). The PMJAY master runs to tens of megabytes; the validator cannot check it whole. + +## 5. The Claim bundle: pre-authorisation, enhancement, query answer, claim, predetermination + +One document for every leg (`claim_bundle`). Entries, in order and at these urls: + +1. `Claim` at `https://nhcx.abdm.gov.in//`: leg `preauth`, `claim` or `predetermination`; flow `request`, `enhancement` or `queryupdate`. +2. `Patient` at `/patient`, `id 1`: identifiers `PMJAY` (member id), `ABHA` (when known), `MB` (member id); `name.text`, `telecom`, `gender`, `birthDate`. +3. `Organization` provider at `/provider`, `id 1`; `Organization` payer at `/payer`, `id 2` (as in section 3). +4. `Coverage` at `/coverage`, `id 1`: `NH` identifier = policy code, `subscriberId` = member id. +5. `Practitioner` at `/practitioner` (the second and later at `/practitioner/2` and so on), `id n`: identifiers `HPID` under `https://nhcx.abdm.gov.in`, `MD` (licence) when known, and `HPIN` under `https://hpr.abdm.gov.in`. PMJAY looks the practitioner up by the `HPIN` typed identifier and refuses a bundle without one with PAYR-1083. `qualification.code` under HL7 v2-0360 with the table's own display (`degree_coding`). +6. `Procedure` at `/procedure/n`, `id n`, one per package: `status preparation` before treatment, `completed` on the claim; `code` SNOMED `71388002` with `text` = the package display; `performedDateTime`. +7. `QuestionnaireResponse` at `/questionnaireresponse/n`, one per answered form: `questionnaire` = the plan's Questionnaire url, `status completed`, `subject` the Patient, `authored`, `item[].answer[]` typed by the question (`valueString`, `valueDateTime`, `valueBoolean`, `valueInteger`, `valueDecimal`, `valueAttachment`). + +The Claim itself: + +- `id` = the claim number; `identifier[0]` typed `CLN` under `https://nhcx.abdm.gov.in` = the claim number. Element ids on every list the payer indexes: `item[].id = Item/n`, `procedure[].id = Procedure/n`, `supportingInfo[].id = SupportingInformation/n`. PAYR-1027 is an item without one. +- `status active`, `type` SNOMED `737481003` inpatient care, `use` = `preauthorization`, `claim` or `predetermination`, `billablePeriod`, `created`, `insurer`, `provider`, `priority normal`. +- `careTeam[]`: sequence, provider reference, role `primary` for the first and `assist` after, `qualification` SNOMED specialty. +- `diagnosis[]`: ICD-10 under `http://hl7.org/fhir/sid/icd-10`, type `admitting`, `onAdmission yes`. +- `procedure[]`: sequence, `type` under `https://nhcx.abdm.gov.in/procedure-type` = the plan's `ProcedureType` condition lower-cased (`conservative`, `medical`, `surgical`), `date`, `procedureReference` with the package display. +- `insurance[0]`: `sequence 1`, `focal true`, `coverage`; on the claim `preAuthRef: [""]`. The pin carries the pre-auth's own claim number there (`B5/claim-request.json` quotes `B3/preauth-request.json`'s claim id). The build carries the payer's `ClaimResponse.preAuthRef`, which the live capture `nhcx-package/fhir/D9/D9-request.json` shows as `2026091110000810`. +- `item[]` (`claim_items`): one per procedure or implant, never per tier. `sequence`, `careTeamSequence`, `diagnosisSequence`, `procedureSequence` (its own Procedure), `informationSequence` (every supportingInfo), `category` under `ndhm-benefit-category` (the specialty), `productOrService` under `ndhm-procedure-code` (the package), `modifier[]` one coding per ward tier with code and display and no system, `programCode` `AB-PMJAY` under `ndhm-program-code` for PMJAY and none for a generic payer, `servicedPeriod` as dates, `quantity`, `unitPrice` = net divided by quantity, `factor` from the scheme's multiple-procedure rule (1, 0.5, 0.25 by cost rank; PMJAY only), `net` = the line plus its tiers. +- `total` = the sum of the nets. + +supportingInfo (`supporting_info`), every entry numbered once the list is assembled (PAYR-1019 is an entry without `sequence`): + +| When | category | code | value | +| --- | --- | --- | --- | +| every leg, one per attached document | `INV` (or the document's own category) under `ndhm-supportinginfo-category` | the plan's requirement code (`MAND0408`) under `https://nhcx.abdm.gov.in/document-code`, else `ODN` | `valueAttachment {contentType, data, title}` | +| every leg | `ONS` | `ADDD` | `valueString` admission instant | +| every leg | `OTH` | `EDT` | `valueString` admission instant | +| claim | `HDS` | the plan's summary code (`MAND0006` in the pin) else `HDS` | `valueAttachment` the discharge summary | +| claim, when a surgery time is known | `ONS` | `PSP` | `valueString` surgery instant | +| claim | `ONS` | `DSDE` | `valueString` discharge instant, or the death instant | +| claim, death only | `ONS` | `DTM` | `valueString` death instant (PAYR-1096 and PAYR-1503 without it) | +| claim | `DIS` | `DTH`, `LAMA`, `DAMA` or `DTM` | `valueString` the stage: `Before Surgery`, `During Surgery`, `After Surgery` | +| query answer (flow `queryupdate`) | `NMI` | `CQD` | `valueString` the desk's reply. The SHA reads its query response comments from here; an answer without one is decided as if none was given | +| every leg, one per answered form | `INF` (or `STG` for a treatment guideline) | `ODN` (or `STG`) | `valueReference` to the QuestionnaireResponse entry | + +Which forms ride (`required_forms`): with an auth-requirements ruling, the forms it named for the leg; without one, at pre-auth every guideline form the plan attaches to the quoted packages; and on both legs every policy-level form. The scheme refuses a pre-auth that answers neither biometrically nor with its Authentication Consent questionnaire (PAYR-1256, PAYR-1271), a claim without the consent answered again at discharge (PAYR-1363, PAYR-1364), and a package without its STG questionnaire (PAYR-1254, PAYR-1365). The live D4 capture carries two policy questionnaires; the live D9 claim carries four, including the Discharge Consent (`nhcx-package/fhir/D9/D9-request.json`). + +Which documents ride (`required_documents`, `preauth_documents`): the ruling's list for the leg, else the plan's list for the quoted packages at pre-auth and whatever was not attached there at the claim. A file attached against a requirement carries that requirement's code; a file nobody asked for carries `ODN`. Never drop one. Content types the scheme takes: pdf, jpg, jpeg, png (PAYR-1008 otherwise). + +The legs differ in these ways only: + +| Leg | flow | use | Procedure status | Extra | +| --- | --- | --- | --- | --- | +| Pre-auth 12 | `request` | `preauthorization` | `preparation` | | +| Enhancement 13 | `enhancement` | `preauthorization` | `preparation` | every line, old and new, under the same claim number; the costlier package at factor 1 and the other at 0.5 (the live capture `nhcx-package/fhir/D6/D6-enhancement.json` carries the two lines at 1 and 0.5) | +| Query answer 19 or 131 | `queryupdate` | `preauthorization` | `preparation` | the `NMI`/`CQD` reply | +| Claim 15 | `request` | `claim` | `completed` | discharge scalars, summary, `preAuthRef`, the claim under the pre-auth's number (ERR-PYR-CLM-007) | +| Claim query answer 161 | `queryupdate` | `claim` | `completed` | as the claim, plus `NMI`/`CQD` | +| Predetermination | `request` | `predetermination` | `preparation` | sent on `v1/preauth/submit` with workflow 12 | + +LAMA and DAMA before or during surgery (`claim_lines`): the claim carries one item, procedure `LM100` at the plan's rate (the sandbox prices it at zero), no tier, and the payer disqualifies every approved item (PAYR-1362 if the package is still there). After surgery the package stands and `LM100` is not used. PAYR-1270 is `LM100` on a pre-auth. + +## 6. The ClaimResponse you read + +Shape (`nhcx-package/docs/01-Overview/07-Payer Flexibility.md`, "Answer detail"): `ClaimResponse`, `Patient`, the two `Organization` entries, `Coverage`, in that order. Fields to read (`parse_claim_response`): + +- `use`: `preauthorization` or `claim`; a bundle with none is whatever you sent on that thread. +- `outcome`: `queued` (acknowledgement), `partial` (queried, or approved for less), `complete`, `error` (rejected). +- `adjudication[]` at claim level: the entry whose `category` is `status` carries `reason.coding.code`: `submitted`, `approved`, `queried`, `rejected`, `cancelled`. +- `preAuthRef`: the payer's case number; see `flow-knowledge.md` section 3 for which answers carry it. +- `identifier[0].value`: your claim number, echoed on every answer. +- `total[]`: a repeating list by `category`, never positional: `benefit` (granted this round), `eligible` (what the case stands at), `submitted`; PMJAY adds `tax` and `incentive`. +- `item[].adjudication[]` by category: `eligible` (amount), `status` (reason `Approved`, `Queried`, `Rejected`), `reason` (the desk's remark, pipe-delimited `USER~datetime~type~comment~trust`, kept verbatim), `eligpercent`, `eligquant`, `deductible` with its reason after a claim. +- `processNote[].text`. +- `type` is present only on the pre-auth acknowledgement (SNOMED `737481003`). + +The status rule (`verdict_status`): `queued` or reason `submitted` is still `submitting`; reason `cancelled` is `rejected`; reason `queried` is `queried`; outcome `error` is `rejected`; outcome `partial` is `partial` only with reason `approved`, else `queried`; outcome `complete` is `approved` with reason `approved` or none, else `queried`. Never read `outcome` alone. + +## 7. Task bundles the hospital sends + +A `TaskBundle` with the `Task` at `https://nhcx.abdm.gov.in//` followed by the provider and payer Organizations. The Task: `status requested` (`completed` on an acknowledgement), `intent order`, `code` on the HL7 financial task code system with no display, `description`, `authoredOn`, `requester` the provider, `owner` the payer. + +| Task | code | reasonCode (NDHM reason code system) | inputs | Other | +| --- | --- | --- | --- | --- | +| Cancel PC01 | `cancel` | one of `treatmentplanchanged`, `patientrequest`, `financialconstraints`, `alternativetreatment`, `duplicateclaim`, `administrativeerror`, `other` (with `other` the description is the only justification) | `claimNumber`, `intimationNumber` (both typed under `ndhm-task-input-type-code`) | anchor `/preauth/cancel` | +| Reprocess 36 | `reprocess` | `claimrejected`, `partialpayment` or `rejectiondisputed` with the reference's displays | `claimNumber`, `intimationNumber` (the standard's spelling), one `document` input per attachment as `valueAttachment` | `basedOn[0].identifier` typed `CLN`; `for.identifier` typed `PMJAY` on the scheme, `MB` elsewhere; anchor `/claim/reprocess` | +| Release 36 | `release` | `partialpayment` | `claimNumber`, `amount` as `valueMoney` under `https://nhcx.abdm.gov.in/task-input-type` | `basedOn` as above; anchor `/claim/release` | +| Status | `status` | none | `claimNumber` | anchor `//status`; not in the package, whose status call carries no bundle (`18-Predetermination, Status and Search.md`); refused by PMJAY | +| Payment acknowledgement 17 | `status`, `status completed` | none | none; `output[]`: `status` = `paymentack` under the NDHM task-output systems, and `claimNumber` | anchor `/payment/notice-ack` | + +The spelling rule: the input is `intimationNumber`, the standard's spelling, on every Task. A reprocess under any other spelling is refused with PAYR-1008 (proven live; `nhcx-package/docs/01-Overview/07-Payer Flexibility.md`, "One spelling on the Task"). The pinned cancel and reprocess Tasks carry the same spelling, so the offline comparison diffs them unchanged. + +## 8. Task answers you read + +`parse_task_response`: find the `Task`, then follow each `output[].valueReference` to the entry it names; when that is a `ClaimResponse`, read it with the same parser as a verdict. + +- PC02 (`nhcx-package/fhir/C10/C10-cancelled-wfPC02.json`): Task `completed`, code `approve`, `output[0]` an `include` reference to a `ClaimResponse` with adjudication reason `cancelled`, `use preauthorization`. Accept the cancel when the Task status is `completed` or `accepted` and the outcome is not `error`. Retire the claim number after an accepted cancel. +- 37 (`nhcx-package/fhir/C10/C10-arbitration-wf37.json`): Task `accepted`, code `approve`, a `ClaimResponse` with outcome `queued`, `use claim`. Put the claim leg back to `submitting`; the new verdict comes on the claim's own thread. +- A status answer: none captured in the package. A generic payer that answers a status Task sends a Task `completed`, code `status`, `output[]` with `claimNumber` and a `claimStatus` string; PMJAY refuses the enquiry instead. + +## 9. The communication loop + +The query, generic payer (`nhcx-package/fhir/C6/C6-preauth-query-wf24.json`; the IG's example at `nhcx-package/fhir/B4/communication-request.json`): a `TaskBundle` with a `Task` `poll`, `requested`, `intent order`, `reasonCode additionalinfo`, one `include` input pointing at the `CommunicationRequest`; the request with `identifier` (the claim number), `basedOn` the Claim, `payload[].contentString` one per ask, `reasonCode[].text` repeating them; then the Claim, Patient, the two Organizations, Practitioner and Coverage. It arrives on `v1/communication/request` on a new correlation id, with the queried leg's correlation id in `x-hcx-workflow_id` when the payer sends one. + +The notification, PMJAY (`nhcx-package/fhir/C6/C6-notification-wfN02.json`): a Task `poll`, `completed`, `intent proposal`, reason `information` under `http://terminology.hl7.org/CodeSystem/communication-category`, a `CommunicationRequest` with one `contentString`, and the two Organizations. + +Reader (`parse_communication_request`): the first `CommunicationRequest`; the claim numbers it names in `about[]`, `basedOn[]` and `identifier[]`; the asks from `payload[].contentString`, else `reasonCode[].text`, else the Task's `description`; the Task's `intent` and `reasonCode`. Match the claim by those numbers first, then by a request id already held, then by the correlation id of one of your sends, then by the workflow id as a thread. + +The reply (`build_communication_bundle`; pin `nhcx-package/fhir/B4/communication-response.json`): a `TaskBundle` with `meta.lastUpdated`, `identifier` under the payer system, `timestamp`, and entries in this order: + +1. `Task` at `urn:uuid:`: `status completed`, `intent order`, `code deliver` under `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-codes`, `authoredOn`, `requester` the provider, `owner` the payer, one `input` typed `include` (HL7 financialtaskinputtype) pointing at the Communication, `reasonCode` echoed from the request's Task when it carried one. +2. `Communication` at `urn:uuid:`: `identifier` echoed from the request, `basedOn: [{reference: }]`, `about: [{reference: }]`, `status completed`, `category notification`, `priority routine`, `recipient` the payer, `sender` the provider, `payload[]`: a `contentString` for the text, then one `contentAttachment {contentType, title, creation, data}` per document, each with an `extension` carrying the document code. The extension url is participant-defined (`17-Communication.md`): write it under your own system and keep one url. `inResponseTo` is never set: FHIR allows only a Communication there and the validator refuses a request. +3. The `CommunicationRequest` echoed as it arrived. +4. The case as the payer holds it, lifted from the queried leg's own bundle: `Claim`, `Patient`, provider `Organization`, payer `Organization`, `Practitioner`, `Coverage`. + +Envelope for the reply: `x-hcx-correlation_id` = the request's, `x-hcx-workflow_id` = the request's, else the queried leg's correlation id, else the claim number; sender and recipient swapped. + +The acknowledgement of a notification: the payer's own bundle sent back with `Task.status` set to `completed`, its intent and reason as sent, the provider Organization ahead of the payer's, a fresh `timestamp`. A request that came without a Task gets one built round it, coded `poll`, intent `proposal`, pointing at the request. The package's `B4/communication-acknowledgement.json` is a different shape: a `status` Task, `completed`, with a `status` output and the two Organizations, and no CommunicationRequest. + +## 10. The payment notice you read and the acknowledgement you send + +Notice (`nhcx-package/fhir/C9/C9-notice-wf30.json`; PMJAY `C9/payment-notice.json` and `C9/C9-notice-tds-wf30-pmjay.json`): a Task `deliver`, `requested`, with a `status` input; a `PaymentNotice` with a `CLN` identifier (the claim number), `amount`, `paymentStatus paid`; a `PaymentReconciliation` with the same identifier, `disposition`, `paymentDate`, `paymentAmount`, `paymentIdentifier` typed `UTR`, and `detail[]` lines (`RF` and `Payment` in `payment-notice.json`; `TDS` and `Payment` in the other two); the two Organizations. It arrives on `v1/paymentnotice/request` on a new thread, workflow 30, 31 or 33. + +Reader (`parse_payment_notice`): the claim number from the `CLN` identifier on the notice, the reconciliation, the Task, or the first entry's untyped identifier, never from the bundle identifier; the amount from the notice or `paymentAmount`; the UTR; the details. Dedupe on the notice's correlation id; a second notice with the same `PaymentNotice.id` updates the first (`record_payment`). Count money once per UTR (`paid_total`). + +Acknowledgement: the Task in section 7, sent on `v1/paymentnotice/on_request` to whoever sent the notice (not always the claim's payer), with `x-hcx-correlation_id` = the notice's and `x-hcx-workflow_id` = `17` for PMJAY or the notice's own id for a generic payer. + +## 11. Validating a bundle + +The package ships no validator. Use the HL7 FHIR validator (`validator_cli.jar`, from HL7) with the NRCeS IG package `ndhm.in`, version 6.5.0. A bundle refused with PAYR-1004 or PAYR-1008 goes through the validator before anything else (`nhcx-package/docs/06-Reference/02-Troubleshooting.md`). The rules it checks against are in `nhcx-package/docs/05-FHIR Reference/01-Bundles and Conventions.md`. + +```sh +java -Xmx4g -jar validator_cli.jar \ + -version 4.0.1 -ig -tx n/a -output result.json +``` + +Pass every file in one call; starting the JVM is the slow part. `-tx n/a` keeps the terminology checks offline; drop it to add them. A bundle passes when the output holds no issue of severity error or fatal. + +The provider pins carry 0 to 13 errors each and the SHA accepted every one as it stands. An error that says "a code the profile does not define" is the scheme's own vocabulary, not a fault to fix. A warning is advice. diff --git a/plugins/nhcx/skills/nhcx-insurance/references/flow-knowledge.md b/plugins/nhcx/skills/nhcx-insurance/references/flow-knowledge.md new file mode 100644 index 000000000..098cd9dbc --- /dev/null +++ b/plugins/nhcx/skills/nhcx-insurance/references/flow-knowledge.md @@ -0,0 +1,206 @@ +# Flow knowledge: the claim episode, its workflow ids, the two payer kinds, the use cases + +Sources: the NHCX package, fetched by `scripts/fetch-package.sh` into `nhcx-package/` beside `nhcx-build/`. That means the overview chapters under `nhcx-package/docs/01-Overview`, the workflow sheet `nhcx-package/workflow.yaml`, the use-case catalogue `nhcx-package/usecases.yaml`, and the payer bundles under `nhcx-package/fhir/C3` to `nhcx-package/fhir/C11`. The published chapters live under `nhcx-package/docs/01-Overview`, `nhcx-package/docs/05-FHIR Reference` and `nhcx-package/docs/03-Building a Provider`. Everything else here was learnt live on the NHCX sandbox. + +## 1. The episode + +One hospital admission that an insurer pays for is one claim episode. Store it as one record with a claim number. Any number works if it is unique per hospital, short, sortable, and fits the payer's `CLN` identifier. The episode has these legs, each a separate exchange with its own correlation id: + +| Order | Leg | You send | Payer answers | Thread | +| --- | --- | --- | --- | --- | +| 1 | Policy lookup | The participant service's `participant/get/policies`, through the transport; the recipient of every later leg is the policy's `processingid` | synchronous JSON | none, plain REST | +| 2 | Coverage eligibility | `v1/coverageeligibility/check`, purpose `discovery`, `validation` or `benefits` | `on_check` | new per check | +| 3 | Insurance plan (package master) | `v1/insuranceplan/request` | `on_request` | new; one plan per facility and policy | +| 4 | Auth requirements | `v1/coverageeligibility/check`, purpose `auth-requirements`, with items | `on_check` (the PMJAY sandbox rarely answers; `nhcx-package/fhir/C3/C3-response-pmjay.json` is an SHA ruling, `C3/C3-response-generic.json` a generic one) | new per procedure set | +| 5 | Pre-authorisation | `v1/preauth/submit` wf 12 | `on_submit` 20 first, then 21, 23 or 24 | new; the acknowledgement comes first on the same thread | +| 5a | Pre-auth query answer | `v1/preauth/submit` wf 19 (PMJAY) or `v1/communication/on_request` (generic) | 21 or 23 | new (PMJAY) or the request's (generic) | +| 5b | Enhancement | `v1/preauth/submit` wf 13, the whole pre-auth again with the added line | 20 then 22, 231 or 241 (the SHA sandbox has also answered with 21) | new | +| 5c | Enhancement query answer | `v1/preauth/submit` wf 131 | 22 or 231 | new | +| 5d | Cancel | `v1/task/submit` wf PC01 | `task/on_submit` PC02 | new | +| 5e | Predetermination | `v1/preauth/submit`, `Claim.use = predetermination`, wf 12 | `on_submit` | new | +| 6 | Claim | `v1/claim/submit` wf 15, `Claim.use = claim`, under the pre-auth's number | 25 then 26, 27 or 291 | new | +| 6a | Claim query answer | `v1/claim/submit` wf 161 (PMJAY) or `v1/communication/on_request` (generic) | 26 or 291 | new (PMJAY) or the request's (generic) | +| 6b | Reprocess or release | `v1/task/submit` wf 36 | `task/on_submit` 37, then a fresh verdict on the claim's thread | new | +| 7 | Payment notice | the payer sends `v1/paymentnotice/request` wf 30 (31, 33) | you answer `v1/paymentnotice/on_request` wf 17 (PMJAY) or the notice's own id (generic) | the notice's | +| any | Status enquiry | `v1/task/submit`, Task code `status` | `task/on_submit` (generic); PMJAY refuses it | new | +| any | Communication | the payer sends `v1/communication/request` | you answer `v1/communication/on_request` | the request's | + +The payer's acknowledgement is `x-hcx-status: response.partial` and the decision is `response.complete`, on the same correlation id (`nhcx-package/docs/01-Overview/07-Payer Flexibility.md`, "Answer detail"). Read the acknowledgement as "the payer has it", never as a decision. Map `ClaimResponse.outcome` `queued`, or an adjudication reason `submitted`, to leg status `submitting` (`verdict_status`). + +## 2. Every workflow id + +The hospital's table. PMJAY and a generic payer differ in three rows: `claim_query_response`, `claim_resubmit` and `payment_ack`. + +| Kind | PMJAY | Generic | Path | Note | +| --- | --- | --- | --- | --- | +| `preauth` | `12` | `12` | `v1/preauth/submit` | A new pre-auth. Also a fresh request after a rejection: PMJAY refuses 121 there with PAYR-1214. | +| `preauth_resubmit` | `121` | `121` | `v1/preauth/submit` | Kept in the table. `preauth_send_kind` never picks it after a rejection. | +| `preauth_query_response` | `19` | `19` | `v1/preauth/submit` | The answer to a 24. A generic payer asks by communication instead, so this is a PMJAY leg. | +| `enhancement` | `13` | `13` | `v1/preauth/submit` | The whole pre-auth again under the parent's number, plus the added line. | +| `enhancement_resubmit` | `131` | `131` | `v1/preauth/submit` | The answer to a 241. | +| `cancel` | `PC01` | `PC01` | `v1/task/submit` | Task code `cancel`. The handbook's section 8.6 says 122 (`nhcx-package/docs/01-Overview/06-Workflow Codes.md`, "Reconciled Discrepancies and Authority Rules", takes PC01). If a payer insists on 122, override it per payer in configuration. | +| `claim` | `15` | `15` | `v1/claim/submit` | The final bill. | +| `claim_query_response` | `161` | `151` | `v1/claim/submit` | PMJAY refuses 151, 19 and 16 with PAYR-1321; 161 is taken. | +| `claim_resubmit` | none | `16` | `v1/claim/submit` | PMJAY has no claim resubmit. A decided claim goes back only as a reprocess. | +| `payment_ack` | `17` | none (echo the notice's own id) | `v1/paymentnotice/on_request` | `None` in the table means "echo". | +| `reprocess` | `36` | `36` | `v1/task/submit` | Task code `reprocess`; acknowledged on 37. | +| `release` | `36` | `36` | `v1/task/submit` | Task code `release`, reason `partialpayment`, an `amount` input. | +| status enquiry | the leg's correlation id, fallback `13` | same | `v1/task/submit` | The fallback id is `13`. The NHCX sandbox refuses `v1/status` with NHCX-1012. | +| coverage, plan, auth requirements | your case number | your case number | see section 1 | The sheet lists no code. Send the episode's case number. | + +The payer's ids you must branch on (`nhcx-package/workflow.yaml`, `nhcx-package/docs/01-Overview/06-Workflow Codes.md`), with what the sandbox actually sent: + +| Id | Meaning | Status word | +| --- | --- | --- | +| `20` | Pre-auth or enhancement received | `response.partial` | +| `21` | Pre-auth approved | `response.complete` | +| `22` | Enhancement approved. A generic payer sends 22. The SHA sandbox has answered an enhancement with 21, and `nhcx-package/fhir/C5/C5-enhancement-approved-wf22-pmjay.json` is an SHA answer on 22. Accept both. | `response.complete` | +| `23` | Pre-auth rejected | `response.complete` | +| `231` | Enhancement denied | `response.complete` | +| `24` | Pre-auth queried | the sheet says `request.initiated`; the SHA sent `response.complete` | +| `241` | Enhancement queried | as 24 | +| `25` | Claim received | `response.partial` | +| `26` | Claim approved | `response.complete` | +| `27` | Claim queried | as 24 | +| `28`, `29` | Claim in process, forwarded | `response.partial` | +| `291` | Claim rejected | `response.complete` | +| `251`, `252`, `253`, `254` | Reprocess received, approved, rejected, queried | listed; both live payers answer a 36 with 37 instead | +| `37` | Arbitration acknowledged (the reprocess taken) | `response.complete` (the SHA sent `response.partial`) | +| `PC02` | Cancellation done | `response.complete` | +| `30`, `31`, `33` | Payment initiated, processed, settled with UTR | `request.initiated`, new thread | +| `5` | The SHA's coverage eligibility and plan answers | `response.complete` (`nhcx-package/fhir/index.yaml` gives 5 for `C3/C3-response-pmjay.json` and `C4/C4-response-pmjay.json`) | +| `N02` | Notification to a provider (a PMJAY CommunicationRequest) | `request.initiated` | + +Other codes exist (10, 11, 14, 141, 18, 45 to 47, 181, 491, 34, 35, 38, 39, G11 to G13, RP1 to RP3, DC01, DC02, N01, N03, N04, the R-series). A hospital build sends none of them. See `nhcx-package/docs/01-Overview/06-Workflow Codes.md` for the full sheet and the seven codes the handbook and the sheet publish differently. + +## 3. Two kinds of payer + +Read `nhcx-package/docs/01-Overview/07-Payer Flexibility.md` in full. A generic payer is any payer on the exchange, IRDAI-regulated insurers and TPAs included (`nhcx-package/fhir/README.md`). The rule, as coded: + +| | PMJAY (`query_mode: resubmit`) | Generic (`query_mode: communication`) | +| --- | --- | --- | +| The query arrives as | a `ClaimResponse` on the case's own thread, `outcome: partial`, item status `Queried`, wf 24, 241 or 27 | a `CommunicationRequest` TaskBundle on `v1/communication/request`, on a new thread, wf 24, 241 or 27 | +| The answer | the whole bundle again on `v1/preauth/submit` or `v1/claim/submit`, wf 19, 131 or 161, a new correlation id, the reply text on the `NMI`/`CQD` supportingInfo entry | a Communication TaskBundle on `v1/communication/on_request`, the request's correlation id and workflow id echoed | +| A `CommunicationRequest` from this payer | always a notification: acknowledge and leave the case alone | classified (below) | + +Where the payer's case number arrives. The package files are under `nhcx-package/fhir/`; the rule is in `07-Payer Flexibility.md`, "When the case number arrives". + +| Answer | PMJAY | Generic | +| --- | --- | --- | +| 20 on a fresh pre-auth | The package says none, and `C5/C5-received-wf20-pmjay.json` carries none. A live SHA 20 has also carried the path form, `PMJAY/HP/S/2024/R2/`. Handle both. | present (`C5/C5-received-wf20.json`) | +| 20 on an enhancement | none; keep the parent's | present | +| 21, 23, 24 | the bare number (`C5/C5-approved-wf21-pmjay.json`, `C5/C5-rejected-wf23-pmjay.json`, `C5/C5-queried-wf24.json`) | present (`C5/C5-approved-wf21.json`, `C5/C5-rejected-wf23.json`) | +| 25 | the path form (`C7/C7-received-wf25-pmjay.json`) | present (`C7/C7-received-wf25.json`) | +| 26, 27, 291, PC02, 37 | none | none | + +So the brief's rule holds with care. A generic payer's `response.partial` acknowledgement carries the payer's case number. PMJAY's 25 carries it; its 20 may not. Read `ClaimResponse.preAuthRef` on every answer. Keep a value and never overwrite it with an empty one (`apply_preauth`). The bare number is what the payer service desk wants; the path form ends in it. + +`query_mode` lives on the payer adapter. Choose the adapter by the payer's participant code through configuration: `1518@hcx` is PMJAY, and an unmapped code is generic. + +### The classification rule + +`classify_communication(adapter, reason, intent)` applies these, in order: + +1. If the payer's `query_mode` is `resubmit`: notification. +2. Else if `Task.intent` is `proposal`: notification. If `order`: query. +3. Else look at `Task.reasonCode`: absent, `additionalinfo`, `questionnaire` or `query` is a query; anything else (`tatquery`, `grievance`, `walletupdate`, `policychange`, `claimarbitration`) is a notification. Fold `claimArbitartion` into `claimarbitration`. +4. A bare `Communication` with no `CommunicationRequest` is a note: recorded, shown, never acted on. + +Acknowledge a notification at once. Send the payer's own bundle back with `Task.status` flipped to `completed`, the reason echoed and the provider Organization first. File a query open for the desk, and answer it later with the TaskBundle reply (see `fhir-knowledge.md`). The reply names the request in `Communication.basedOn`, never `inResponseTo`. + +The live shapes. A generic payer's query (`nhcx-package/fhir/C6/C6-preauth-query-wf24.json`) carries a Task `poll`, `requested`, `intent order`, reason `additionalinfo`, and a CommunicationRequest with one `contentString` per ask and `basedOn` the Claim. PMJAY's notification (`nhcx-package/fhir/C6/C6-notification-wfN02.json`) carries a Task `poll`, `completed`, `intent proposal`, reason `information` under the HL7 communication-category system. + +## 4. Stage, sub-stage, next actions + +Stamp two words onto the episode after every leg write (`stamp_case`), and compute a next-action list from them. Copy the vocabulary; it is what a desk needs to see. + +Stages: `eligibility`, `preauth`, `enhancement`, `claim`, `payment`. + +Sub-stages: `draft`, `checking`, `eligible`, `not-eligible`, `requested`, `resubmitted`, `answered`, `queried`, `approved`, `partial`, `rejected`, `cancelling`, `cancelled`, `refused`, `noticed`, `paid`. + +How a send kind maps to a sub-stage: `preauth`, `claim`, `enhancement` set `requested`; `*_resubmit` sets `resubmitted`; `*_query_response` and `enhancement_resubmit` set `answered`. `requested`, `answered` and `resubmitted` mean "with the payer". + +Derivation (`case_stage`): a payment notice wins, then the filed claim, then the pre-auth (stage `enhancement` if the last submission kind was an enhancement), then a saved draft, then the eligibility status. An open communication query on a leg that is with the payer flips the sub-stage to `queried`, because a generic payer's query never touches the leg row. + +Next actions (`next_actions`) are `{label, tab, tone}`; the first is what the case waits for. Rules worth copying: + +- An unanswered query always leads with "Answer the payer (n)". +- The leg's own reply box is offered only for a `resubmit` payer. A `communication` payer's desk is sent to the communication tab. +- A claim refused at the door offers "send again" while `claim_send_kind` still yields a kind, else "Ask for a reprocess". +- After a rejection the pre-auth offers a fresh 12, not 121. + +## 5. Rules the exchange enforces that no document states + +Each was found live on the sandbox. + +- Acknowledge or lose the thread. NHCX redelivers an unanswered submission, then drops it and retires the correlation id; a verdict sent later is refused with NHCX-1010. Both live payers answer twice on one correlation: `outcome: queued` first, the decision after. Your reader must not close a thread on the first reply. +- One message is taken once. The SHA redelivers the same `api_call_id` two or three times, about a minute apart, and a transport can fan one delivery out to several receivers (nhcx-adapter's `callback.also`). Dedupe on `x-hcx-api_call_id`. +- One live pre-auth per beneficiary per hospital (PAYR-1238). Clear it with PC01 or a rejection (`nhcx-package/docs/03-Building a Provider/11-PMJAY Sandbox Run.md`, "PAYR-1238 An active preauthorisation exists"). Sweep live pre-auths before a test run. +- One request at a time per case (PAYR-1322, "Active instance found"). Wait about 30 seconds after a decision before the next leg. When a refusal says "Active instance", wait and resend, up to three times. +- One plan per facility and policy. Key it on policy code, provider id and payer. Copy the held master onto a new episode instead of asking again (`reuse_plan`). A PMJAY master runs to tens of megabytes; one fetched live was 56 MB. +- Never drop a document. A file nobody asked for by name goes under `ODN`, "other document". A file attached against a requirement carries that requirement's code (`attach_required_document`). Take the code list from the plan, not from a constant. +- Ask the auth-requirements check, never await it (`ensure_auth_requirements`). Fingerprint the quoted set (`procedure_set`) so an unchanged set is not asked twice. Send the quantity as a whole number. +- Tiers are modifiers, not lines. A ward or ICU tier rides on `Claim.item.modifier` under its procedure, and that item's `net` carries both. +- The claim goes under the pre-auth's number (ERR-PYR-CLM-007), and PMJAY bills the package alone at the whole amount (`11-PMJAY Sandbox Run.md`, "ERR-PYR-CLM-007" and "What the package master decides"). +- Answers to a PMJAY query go on a new correlation id (`07-Payer Flexibility.md`, "On the claim thread"). A same-thread answer is swallowed: no acknowledgement, no refusal, and the desk dies on the old id. +- Cancel retires the number. Give the episode a fresh claim number after an accepted PC01, and keep the withdrawn one on the leg. +- A send refused at the door keeps the case on the thread the payer last answered. An enhancement refused at the door leaves the pre-auth approved. + +## 6. The use-case catalogue + +Codes and titles are quoted from `nhcx-package/usecases.yaml`, rendered as `nhcx-package/docs/01-Overview/05-NHCX Use Cases.md`. "Proves" is what a test run must show for each one. "Package file" is the provider bundle the package holds for it, under `nhcx-package/fhir/`. + +### A: shared + +| Code | Title | What it proves | +| --- | --- | --- | +| A1 | Get participant list | You can find the payer's code in the registry (the participant service's `fetch/participants/list`). | +| A2 | Get policy | You can find a beneficiary's policy and the processor code that becomes `x-hcx-recipient_code` (the participant service's `participant/get/policies`). | +| A3 | Get public key | The transport fetches the recipient's certificate (`fetch/certs`) and caches it. | +| A4 | Get auth token | The transport holds an ABDM session token (the gateway's sessions call) and refreshes it. | +| A5 | Get status | A status Task on `v1/task/submit` gets a Task back (generic), or a PAYR-1018 then PAYR-1008 refusal (PMJAY). The package holds no bundle for A5 (`nhcx-package/fhir/README.md`). | +| A6 | Receive errors | Your callback accepts a `ProtocolResponse` on any path and answers 2xx. | + +### B: hospital on the generic network + +| Code | Title | Workflow | Proves | Package file | +| --- | --- | --- | --- | --- | +| B1 | Check coverage eligibility | none | The check goes out; `inforce` and the wallet come back. | `B1/B1-check.json` | +| B2 | Request insurance plan | none | The package master lands and is stored once per policy. | `B2/B2-request.json` | +| B3 | Submit pre-authorisation | 12, 13 | Sent, acknowledged on 20, decided on 21 or 23; an enhancement on 13 decided on 22. | `B3/B3-request.json`, `B3/B3-enhancement.json` | +| B4 | Respond to a communication | 24, 27 echoed | A CommunicationRequest is classified and the TaskBundle reply goes on the request's thread. | `B4/B4-preauth-query-answer.json`, `B4/B4-claim-query-answer.json` | +| B5 | Submit claim | 15 | The claim under the pre-auth's number, acknowledged 25, decided 26 or 291. | `B5/B5-request.json` | +| B6 | Search claims | none | Not built by these skills. | `B6/claim-search.json` (example) | +| B7 | Acknowledge payment notice | 30 echoed | The notice is filed by claim number, deduped by correlation id, acknowledged on `on_request`. | `B7/B7-acknowledgement.json` | +| B8 | Reprocess or cancel | 36, PC01 | A decided claim is reopened (37 then a new verdict); a live pre-auth is withdrawn (PC02). | `B8/B8-reprocess.json`, `B8/B8-cancel.json` | +| B9 | Submit predetermination | 12 | A quote comes back as a ClaimResponse; nothing else changes. | `B9/predetermination-request.json` (example); the answer is `C11/predetermination-response.json` | + +### C: payer answering (for reference; you build the reader, not the sender) + +C3 coverage answer, C4 plan answer, C5 pre-auth answers (20, 21, 22, 23, 24, 231, 241), C6 communication (24, 241, 27, N02), C7 claim answers (25, 26, 27, 28, 29, 291), C9 payment notice (30, 31, 33), C10 Task answers (PC02, 37, 251 to 254), C11 predetermination. Reader inputs: `nhcx-package/fhir/C3` to `nhcx-package/fhir/C11`. The files ending `-pmjay` are the SHA's own; the rest are the generic payer's. `nhcx-package/fhir/index.yaml` gives each file's scheme, workflow id and origin. The PMJAY captures have the beneficiary's identifiers replaced. + +### D: hospital on PMJAY + +| Code | Title | Workflow | Proves | Package file | +| --- | --- | --- | --- | --- | +| D1 | Fetch the insurance plan | none | The scheme's master, both `coverage[]` and `specificCost[]`, nested document requirements, questionnaires. | `D1/D1-request.json` | +| D2 | Authenticate the beneficiary | not NHCX | Biometric token or the consent questionnaire fallback. | none | +| D3 | Check coverage eligibility | none | The wallet answer on wf 5. | `D3/D3-check.json` | +| D4 | Submit pre-authorisation | 12 | Element ids, HPIN, consent QuestionnaireResponse, documents from the master; acknowledged 20, decided 21 or 23 with `preAuthRef`. | `D4/D4-request.json` | +| D5 | Resubmit pre-authorisation | 121 | Not reachable on the sandbox after a rejection (PAYR-1214); send a fresh 12. | none | +| D6 | Raise an enhancement | 13, 131 | A second package (medical, not conservative: PAYR-1245) under the parent's number; a 241 answered on 131. | `D6/D6-enhancement.json`, `D6/D6-enhancement-query-answer.json` | +| D7 | Answer a pre-authorisation query | 19 | The 24 answered as a fresh submit with `CQD` reply text, new correlation id, then 21. | `D7/D7-query-answer.json` | +| D8 | Cancel pre-authorisation | PC01 | Task `cancel` with `claimNumber` and `intimationNumber`; PC02 back. | `D8/D8-cancel.json` | +| D9 | Submit claim | 15 | Under the pre-auth's number, the package alone, discharge scalars, Discharge Consent answered, PDF documents; 25 then 26. | `D9/D9-request.json` | +| D10 | Answer a claim query | 161 | The 27 answered on 161 with a written reply; the sandbox approves at zero. | `D10/D10-query-answer.json` | +| D11 | Reprocess a rejected claim | 36 | Task `reprocess`, reason `claimrejected`, second input spelled `intimationNumber` on every Task (a reprocess under any other spelling is refused PAYR-1008). The SHA answers 37, "Arbitration claim submission process completed successfully", and reopens the case; a generic payer answers 37 too. | `D11/D11-reprocess.json` | +| D12 | Claim a shortfall | 36 | Task `reprocess` with `partialpayment` after a settled payment. Out of reach on the sandbox: its finance side issues the notice on its own schedule, and the combination is refused before notice 33 is acknowledged (`11-PMJAY Sandbox Run.md`, "What the sandbox will not take"). | none | +| D13 | Acknowledge the payment notice | 17 | Notice 30 filed and acknowledged on `on_request` with 17. | `D13/D13-acknowledgement.json` | + +Discharge variants the D9 claim must cover, each proven on the sandbox: normal after surgery; LAMA and DAMA before, during and after surgery; death before, during and after surgery. Before or during surgery, LAMA and DAMA collapse the claim to one `LM100` line; a death carries `ONS`/`DTM`. `nhcx-package/docs/03-Building a Provider/08-PMJAY Provider.md` states the LAMA and DAMA rule. + +## 7. What each payer sends back, in order + +A pre-authorisation on the SHA sandbox: 20 (`queued`, `response.partial`, `ClaimResponse.type` present only here, as in `nhcx-package/fhir/C5/C5-received-wf20-pmjay.json`), then 24 (query) or 21 or 23. A claim: 25, then 27 or 26 or 291. A cancel: PC02 as a Task `completed`, code `approve`, `output[0]` an `include` reference to a ClaimResponse whose adjudication reason is `cancelled` (`C10/C10-cancelled-wfPC02-pmjay.json`). A reprocess: 37 as a Task `accepted` with a `queued` ClaimResponse (`C10/C10-arbitration-wf37-pmjay.json`), then 26 or 291 on the claim's thread. A payment: 30 on a new thread with a Task `deliver`, a `PaymentNotice` and a `PaymentReconciliation` (`C9/payment-notice.json`). + +A generic payer sends the same ids with the generic differences: 22 for an enhancement, `preAuthRef` on every acknowledgement and every pre-auth decision, queries as CommunicationRequests, `response.complete` on 37. Its files are the ones without `-pmjay` under `nhcx-package/fhir/C5`, `C6`, `C7`, `C9` and `C10`. diff --git a/plugins/nhcx/skills/nhcx-insurance/references/material.md b/plugins/nhcx/skills/nhcx-insurance/references/material.md new file mode 100644 index 000000000..d8882931d --- /dev/null +++ b/plugins/nhcx/skills/nhcx-insurance/references/material.md @@ -0,0 +1,120 @@ +# Material: where the pins, fixtures and docs live + +The stage and module files cite pins, payer fixtures and chapters. All of them come from one source, the NHCX package. This file says how to get it, what it holds, and which package file each citation means. + +## The package + +| Source | Has | Get it | +| --- | --- | --- | +| The NHCX package (`nhcx-package/`) | The docs, every API as a request, the FHIR bundles (the fifteen hospital pins, the payer answers, the live PMJAY captures with identifiers replaced), the field mappings per use case, `workflow.yaml`, `usecases.yaml`, `nhcx-error.yaml`, `baseurl.yaml`, a `MANIFEST` with a sha256 per file | `scripts/fetch-package.sh`, or by hand (below) | +| nhcx-adapter (optional: only when the user asks for it) | The binary, `config.sample.json`, `serve.sh`, `README.md` | The latest release of https://github.com/nha-in/nhcx-adapter, downloaded only when the user chose it (`references/transport-knowledge.md` section 5). Its contract is in `references/api-knowledge.md`. | + +By default `scripts/fetch-package.sh` takes the build attached to the latest GitHub release of `nha-in/nhcx-package`. It checks the download against the sha256 the release records. To use a different build, pass a link or a local path: `scripts/fetch-package.sh `. + +By hand: download the `nhcx-package-v.zip` asset from https://github.com/nha-in/nhcx-package/releases/latest. Unzip it beside `nhcx-build/`. It unpacks to `nhcx-package/`. + +Where the web is off, copy the package in. Do not try to fetch it. + +After unpacking, check it. `nhcx-package/MANIFEST` names the version and lists every file with its size and sha256. Verify at least the pins you will be held to. + +What the package holds: + +| Path | What it is | +| --- | --- | +| `nhcx-package/fhir/B1` to `B9` | Hospital bundles. Lower-case files (`preauth-request.json`) are the pins, written to the specification with placeholders. Capitalised files (`B3-request.json`) are live captures. | +| `nhcx-package/fhir/C3` to `C11` | Payer answers. A generic file and, where one exists, its `-pmjay` twin. | +| `nhcx-package/fhir/D1` to `D13` | Live PMJAY hospital captures, identifiers replaced | +| `nhcx-package/fhir/index.yaml` | The catalogue: for each file its direction, side, scheme (`generic` or `pmjay`), workflow id, focal resource, origin (`wire` or `example`) | +| `nhcx-package/docs/` | The chapters, `01-Overview` to `07-Go Live` | +| `nhcx-package/mappings/.yaml` | Field mappings per bundle; `A1.yaml` is the master dictionary | +| `nhcx-package/apis/` | Every API as a request (a Bruno collection) | +| `nhcx-package/workflow.yaml`, `usecases.yaml`, `nhcx-error.yaml`, `baseurl.yaml` | Workflow ids, use cases, error codes, base URLs | +| `nhcx-package/MANIFEST` | Version, and a size and sha256 per file | + +## The pin map + +Every hospital-side pin, and its file in the package. The fifteen hospital-built pins are the bytes a build is held to (canonical JSON). The last row is a payer's message, the reader's input. + +| Pin | Package | Module | +| --- | --- | --- | +| `coverage/discovery` | `nhcx-package/fhir/B1/discovery.json` | 7.4 | +| `coverage/validation` | `nhcx-package/fhir/B1/validation.json` | 7.4 | +| `coverage/benefits` | `nhcx-package/fhir/B1/benefits.json` | 7.4 | +| `coverage/authrequirements` | `nhcx-package/fhir/B1/auth-requirements.json` | 7.6 | +| `insurance` | `nhcx-package/fhir/B2/insurance-plan-request.json` | 7.5 | +| `preauth/request` | `nhcx-package/fhir/B3/preauth-request.json` | 7.7 | +| `preauth/enhancement` | `nhcx-package/fhir/B3/preauth-enhancement.json` | 7.7 | +| `preauth/queryupdate` | `nhcx-package/fhir/B3/preauth-queryupdate.json` | 7.7 | +| `preauth/cancel` | `nhcx-package/fhir/B3/preauth-cancel.json` | 7.9 | +| `claim/request` | `nhcx-package/fhir/B5/claim-request.json` | 7.7 | +| `claim/queryupdate` | `nhcx-package/fhir/B5/claim-queryupdate.json` | 7.7 | +| `claim/reprocess` | `nhcx-package/fhir/B5/claim-reprocess.json` | 7.9 | +| `claim/release` | `nhcx-package/fhir/B5/claim-release.json` | 7.9 | +| `communication/response` | `nhcx-package/fhir/B4/communication-response.json` | 7.10 | +| `payment/notice-ack` | `nhcx-package/fhir/B7/payment-notice-ack.json` | 7.10 | +| `communication/request` (a payer's message, the reader's input) | `nhcx-package/fhir/B4/communication-request.json`. It is the NRCeS IG's own example, with the Patient's name, identifier, birth date and phone replaced. | 7.10 | + +## The payer fixtures + +What the readers are fed. `generic` is what any payer on the exchange sends, IRDAI-regulated insurers and TPAs included. `pmjay` is the SHA's own message, a live capture with the beneficiary's identifiers replaced. Some identifiers are absent from the PMJAY files: `C5-received-wf20-pmjay.json` carries no `preAuthRef`. Read a value from the file before you assert it. Paths are under `nhcx-package/fhir/`. + +| Answer | Generic | PMJAY | Reader | +| --- | --- | --- | --- | +| Coverage, validation | `C3/validation-response.json` | `C3/coverage-eligibility.json` | 7.4 | +| Coverage, discovery | `C3/discovery-response.json` | none | 7.4 | +| Coverage, benefits | `C3/benefits-response.json` | `C3/C3-benefits-pmjay.json` | 7.4 | +| Coverage, auth-requirements | `C3/C3-response-generic.json` | `C3/C3-response-pmjay.json` (workflow 5) | 7.6 | +| Insurance plan | `C4/C4-response-generic.json` (coverage-based) | `C4/C4-response-pmjay.json` (package-based) | 7.5 | +| Pre-auth received 20 | `C5/C5-received-wf20.json` | `C5/C5-received-wf20-pmjay.json` | 7.8 | +| Pre-auth approved 21 | `C5/C5-approved-wf21.json` | `C5/C5-approved-wf21-pmjay.json` | 7.8 | +| Enhancement approved 22 | `C5/C5-enhancement-approved-wf22.json` | `C5/C5-enhancement-approved-wf22-pmjay.json` | 7.8 | +| Pre-auth rejected 23 | `C5/C5-rejected-wf23.json` | `C5/C5-rejected-wf23-pmjay.json` | 7.8 | +| Pre-auth queried 24 | `C5/preauth-queried.json` | `C5/C5-queried-wf24.json` | 7.8 | +| Claim received 25 | `C7/C7-received-wf25.json` | `C7/C7-received-wf25-pmjay.json` | 7.8 | +| Claim approved 26 | `C7/C7-approved-wf26.json` | `C7/C7-approved-wf26-pmjay.json`, `C7/C7-approved-deduction-wf26-pmjay.json` | 7.8 | +| Claim queried 27 | `C7/claim-queried.json` | `C7/C7-queried-wf27.json` | 7.8 | +| Claim rejected 291 | `C7/C7-rejected-wf291.json` | `C7/C7-rejected-wf291-pmjay.json` | 7.8 | +| Cancellation done PC02 | `C10/C10-cancelled-wfPC02.json` | `C10/C10-cancelled-wfPC02-pmjay.json` | 7.9 | +| Arbitration acknowledged 37 | `C10/C10-arbitration-wf37.json` | `C10/C10-arbitration-wf37-pmjay.json` | 7.9 | +| Query on the communication API, 24 and 27 | `C6/C6-preauth-query-wf24.json`, `C6/C6-claim-query-wf27.json` | none | 7.10 | +| Notification N02 | none | `C6/C6-notification-wfN02.json` | 7.10 | +| The query the reply answers | `B4/communication-request.json` (the IG's example) | none | 7.10 | +| Payment notice 30 | `C9/C9-notice-wf30.json` | `C9/payment-notice.json`, `C9/C9-notice-tds-wf30-pmjay.json` | 7.10 | +| Predetermination | `B9/predetermination-request.json` (the request), `C11/predetermination-response.json` | none | 7.7, 7.8 | + +`nhcx-package/fhir/index.yaml` catalogues every file: direction, side, scheme, workflow id, focal resource, origin (`wire` or `example`). An `example` file is placeholders written to the specification, not a payload. + +## The live hospital captures + +What a hospital actually sent, as the payer accepted it. The module files quote these shapes. Paths are under `nhcx-package/fhir/`. + +| Scheme | Files | +| --- | --- | +| PMJAY | `D1/D1-request.json` (plan), `D3/D3-check.json` (auth-requirements), `D4/D4-request.json` (pre-auth 12), `D6/D6-enhancement.json` (13), `D6/D6-enhancement-query-answer.json` (131), `D7/D7-query-answer.json` (19), `D8/D8-cancel.json` (PC01), `D9/D9-request.json` (claim 15), `D10/D10-query-answer.json` (161), `D11/D11-reprocess.json` (36), `D13/D13-acknowledgement.json` (17) | +| Generic | `B1/B1-check.json`, `B2/B2-request.json`, `B3/B3-request.json`, `B3/B3-enhancement.json`, `B4/B4-preauth-query-answer.json`, `B4/B4-claim-query-answer.json`, `B5/B5-request.json`, `B7/B7-acknowledgement.json`, `B8/B8-cancel.json`, `B8/B8-reprocess.json` | + +## The docs and the data files + +| Cited | Package | +| --- | --- | +| a chapter | `nhcx-package/docs/`, from `01-Overview` to `07-Go Live` | +| workflow ids (`references/flow-knowledge.md` section 2) | `nhcx-package/workflow.yaml`, the maintained source; rendered as `nhcx-package/docs/01-Overview/06-Workflow Codes.md` | +| use cases (`flow-knowledge.md` section 6) | `nhcx-package/usecases.yaml`; rendered as `nhcx-package/docs/01-Overview/05-NHCX Use Cases.md` | +| PAYR and ERR codes (`references/errors-and-debugging.md`) | `nhcx-package/nhcx-error.yaml` | +| field mappings per bundle (stage 4) | `nhcx-package/mappings/.yaml`; `A1.yaml` is the master dictionary | +| base URLs, sandbox and production | `nhcx-package/baseurl.yaml` | +| every API as a request | `nhcx-package/apis/` (a Bruno collection) | +| the bundle catalogue | `nhcx-package/fhir/index.yaml` | + +## What the package does not hold + +| Missing | Without it | +| --- | --- | +| A status-enquiry answer | None captured. The published status call carries no bundle either way (`nhcx-package/docs/05-FHIR Reference/18-Predetermination, Status and Search.md`). | +| A validator wrapper | Run the HL7 FHIR validator directly, as `references/fhir-knowledge.md` section 11 describes | +| Reference application source | The decisions are written into the module files and the references. Build from them. Record in `NOTES.md` where you would have wanted more. | +| End-to-end drivers and checkers | Write the stage 10 driver against your own build's state address | + +## Which is newer + +Where the references and the package disagree, the package is newer for the published facts (workflow ids, error text, base URLs). The references are newer for what was seen live (which ids a payer actually sent, which refusals mean what). Say which you followed in `NOTES.md`. diff --git a/plugins/nhcx/skills/nhcx-insurance/references/testing-knowledge.md b/plugins/nhcx/skills/nhcx-insurance/references/testing-knowledge.md new file mode 100644 index 000000000..4a24d7946 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-insurance/references/testing-knowledge.md @@ -0,0 +1,405 @@ +# Testing knowledge + +Sources: the NHCX package, fetched by `scripts/fetch-package.sh` into `nhcx-package/` beside `nhcx-build/`. That means the pins and payer fixtures under `nhcx-package/fhir` (catalogued in `nhcx-package/fhir/index.yaml`), the use-case catalogue `nhcx-package/usecases.yaml`, and the chapters named below. Also what live runs on the NHCX sandbox taught. + +## 1. The pyramid + +| Rung | What it proves | Needs | How | +| --- | --- | --- | --- | +| 1. Offline | Every builder equals its pin (`created` excepted); every reader settles the right state from a payer fixture; the state machine refuses what it should | nothing running; a throwaway database; the transport's send stubbed; `nhcx-package/` | one suite in one process (sections 2 to 4) | +| 2. Validator | Every built bundle validates against the NRCeS profiles with no error you cannot explain | Java, the HL7 FHIR validator, the bundles your tests wrote | section 5 | +| 3. A generic payer on the sandbox | Every leg over the real exchange with a payer whose desk you can drive; queries as CommunicationRequests; payment released | the transport on the sandbox (your app's own, or nhcx-adapter when the user chose it), a generic payer you can drive, the sandbox reaching your callback | section 6 | +| 4. Live PMJAY sandbox | `1518@hcx`: the scheme's own refusals and rules, decisions taken on the payer service desk | the sandbox, a real beneficiary, patience | section 6 | + +Climb in order. Rungs 1 and 2 need no service and no consent. Rungs 3 and 4 put traffic on the live NHCX sandbox, and only the user starts them. + +## 2. Writing rung 1 for a new HMIS + +Build one suite with this shape, whatever the language: + +- One process, one seeded database under a temporary path, sections in the order the episode runs. `section(name)` starts a group; `check(label, condition, detail)` records one assertion and never raises. The run exits non-zero at the end if anything failed. +- The transport's `send` is one function, and the test replaces it. Every send goes through it; the test assigns a stub that records the path, recipient, workflow id, correlation id and bundle, and returns `{"txn_id": ..., "correlation_id": ..., "api_call_id": ...}`. Restore the real one in `finally`. The receiving end is tested apart from the door: for your own transport, seal a payer bundle with a test key pair, POST it, and check the 202 receipt and the envelope the door receives. +- Call the callback handler directly with an envelope, not over HTTP: `receive({"jwe_headers": {...}, "fhir": bundle}, "", "", "fhir")`. The return value is one of `settled`, `unmatched`, `ignored`. Feed it the payer bundles under `nhcx-package/fhir/C3` to `nhcx-package/fhir/C11`, both the generic files and the `-pmjay` ones. The auth-requirements rulings are `C3/C3-response-generic.json` (one line, 10 supporting entries) and `C3/C3-response-pmjay.json` (two lines, 22 entries). +- The pin comparison builds each bundle from the pin's own data and compares canonical JSON (`json.dumps(bundle, sort_keys=True)`) against the pin. The data is all in `nhcx-package/fhir/B3/preauth-request.json`: member `MD5SLS4X5`, policy `PMJAY/HP/S/G`, provider `IN1910000151`, payer `1518@hcx`, package `MG0111A` with tier `STRAT006b`, the four `MAND` documents. Drop from both sides only `created`. The bundle id and every entry's `fullUrl` are fixed strings in the pins (`preauth-request-generic`, `https://nhcx.abdm.gov.in/preauth/request`), and the build produces them as they are. +- The single-item pins carry `factor 0.5`. That contradicts the rule their own enhancement follows (`nhcx-package/fhir/B3/preauth-enhancement.json`: the costlier line 1, the next 0.5), so compare those with `factor` removed. Compare the cancel and reprocess pins as they are; they carry `intimationNumber`, the spelling the build sends. +- Read every expected value in a reader check from the fixture you feed: `preAuthRef`, amounts, claim numbers, the UTR. The PMJAY captures have the beneficiary's identifiers replaced, and some fields are absent (`C5/C5-received-wf20-pmjay.json` carries no `preAuthRef`). A typed literal tests your memory, not the reader. +- Negative checks are half the value. A code the plan does not carry is refused. A send while the leg is with the payer is refused. A redelivered api call id is ignored. A claim refused at the door goes back to `queried` with the question restored. A cancel while the payer holds the case is accepted, and a cancel of a rejected one is refused. +- Put the regression sections near the bottom. Each is a defect that reached working code, named after what went wrong. Add one each time the sandbox teaches you something. + +In a language whose JSON encoder does not sort keys, decode into a map and encode again before comparing, so key order cannot fail a check. Where a byte comparison is too strict, as with the wire captures, compare element by element. + +## 3. The test-case matrix + +One row per hospital-side use case. Preconditions are the state the HMIS must be in. The action is what the desk or the test does. The expected wire is what must go out and come back; the per-case archive shows it (and the adapter's ledger, when it is the transport). The expected state is what the HMIS must hold afterwards. Codes are those of `nhcx-package/usecases.yaml`. Workflow ids are the PMJAY table unless the row says generic. + +| Use case | Preconditions | Action | Expected wire | Expected state | +| --- | --- | --- | --- | --- | +| A5 Get status (generic) | A pre-auth or claim leg with the payer; a generic payer | Ask status for the leg | `v1/task/submit`, Task `status` with `claimNumber`, workflow = the leg's correlation id; a Task back with `claimStatus` | An enquiry row `answered` with the status word; the leg unchanged | +| A5 Get status (PMJAY) | as above; PMJAY | Ask status | the same Task; a ProtocolResponse PAYR-1018 (no reason) or PAYR-1008 (with one) | The enquiry row `error` with the payer's words; nothing else changes | +| B1 Check coverage eligibility | A patient with a member id and policy from the policy search; facility HFR id and participant code set | Validate, then discover | `v1/coverageeligibility/check` twice, new correlation each, workflow = the case number; `on_check` with the request echoed and a `CoverageEligibilityResponse` | `claim.status eligible`, `inforce 1`, allowed and used amounts, the payer's Patient demographics | +| B2 Request insurance plan | Eligible; no master held for this facility and policy | Fetch the plan | `v1/insuranceplan/request`, a Task `poll` with `policyNumber` and `providerId`; `on_request` with the InsurancePlan and Questionnaires | `claim_plan.status ready`, benefits with rates, tiers, requirements, forms by url; a second episode on the same policy copies it without a send | +| B3 Submit pre-authorisation | Plan ready; lines quoted from it; dossier saved; admission linked; documents and forms for the pre-auth stage attached | Submit | `v1/coverageeligibility/check` purpose `auth-requirements` first (sent, not awaited), then `v1/preauth/submit` workflow 12 equal to the pin but for identifiers; `on_submit` 20 (`queued`, `response.partial`) then 21 | `claim_preauth.status submitting` after the 20 with `preauth_ref` kept, `approved` after the 21 with `approved_amount`; stage `preauth`, sub-stage `approved` | +| B3 Auth-requirements ruling | The check sent with the pre-auth; the payer answers it | Nothing; read on arrival | inbound `on_check`, a CoverageEligibilityResponse with purpose `auth-requirements`, one `insurance[0].item` per quoted line with `authorizationRequired`, `excluded` and `authorizationSupporting[]` (`C3/C3-response-generic.json`, `C3/C3-response-pmjay.json`) | each quoted line holds its ruling and what is due at pre-auth (a form always, a document only when its `Type` is `pre`); the pre-auth leg unchanged | +| B3 Enhancement | Approved; a line added since (`enhancement_lines` non-empty) | Submit again | `v1/preauth/submit` workflow 13, every line old and new, factors 1 and 0.5; 20 then 22 (generic); the SHA has answered 21 or 22 | `submission_kind enhancement`, `enhancement_no 1`, `preauth_ref` kept, then `approved`; stage `enhancement` | +| B4 Respond to a communication (generic) | A pre-auth or claim with the payer; the payer sends a CommunicationRequest on a new thread | The desk replies with text and a document | inbound `v1/communication/request` with Task `poll`, reason `additionalinfo`; outbound `v1/communication/on_request` with the request's correlation id and workflow id, a TaskBundle: Task `deliver`, Communication `basedOn` the request, the request echoed, the case entries | `claim_query` row `kind query`, `status open` then `answered` with `reply_json`; the leg row untouched; sub-stage `queried` while open | +| B4 Notification | Any leg; the payer sends a CommunicationRequest with intent `proposal` or reason `tatquery` | Nothing; it is acknowledged on arrival | outbound `v1/communication/on_request` at once, the payer's bundle with `Task.status completed`, provider Organization first | `claim_query` row `kind notification`, `status acknowledged`; the case's stage unchanged | +| B5 Submit claim | Approved pre-auth; discharge recorded with mode and stage; claim-stage documents and forms attached | Submit the claim | `v1/claim/submit` workflow 15, `use claim`, `preAuthRef`, the discharge scalars, the summary; 25 (`queued`) then 26 | `claim_submission.status submitting` then `approved` with amounts and item verdicts; stage `claim` | +| B7 Acknowledge payment notice (generic) | An approved claim; the payer's desk releases payment | Nothing; acknowledged on arrival | inbound `v1/paymentnotice/request` workflow 30 on a new thread; outbound `v1/paymentnotice/on_request` with the notice's correlation id and its own workflow id echoed, Task `status completed` with `paymentack` | `claim_payment` row with amount, UTR, `ack_status sent`; stage `payment`, sub-stage `paid`; a redelivery of the notice is `ignored` | +| B8 Cancel | A pre-auth `submitting`, `approved`, `partial` or `queried` | Cancel with a reason | `v1/task/submit` workflow PC01, Task `cancel`, inputs `claimNumber` and `intimationNumber`; `task/on_submit` PC02 with a ClaimResponse adjudicated `cancelled` | `claim_preauth.status cancelling` then `cancelled`; the episode gets a fresh claim number, the old one stays on `claim_ref`; a cancel of a `rejected` pre-auth is refused before sending | +| B8 Reprocess (generic) | A claim `rejected` or `partial` | Reprocess with reason `claimrejected` and a document | `v1/task/submit` workflow 36, Task `reprocess`, `intimationNumber`, `basedOn` CLN, `document` inputs, `for` the member; 37 (Task `accepted`, ClaimResponse `queued`); then 26 on the claim's thread | The enquiry row `answered` with `reopened`; `claim_submission` back to `submitting`, then `approved` | +| B9 Submit predetermination | Eligible; dossier saved | Ask for a quote | `v1/preauth/submit` workflow 12 with `use predetermination`; a ClaimResponse back | A `claim_predetermination` row `answered` with `allowed_amount`; the pre-auth row untouched | +| D1 Fetch the insurance plan | Eligible on PMJAY | Fetch | as B2; the answer on workflow 5, both `specificCost[]` and `coverage[]`, nested document requirements, `/questionnaire/` and `/stgquestionnaire/` forms | as B2, with `ProcedureType` conditions and the consent forms among the policy documents | +| D2 Authenticate the beneficiary | A policy from the BIS | Not NHCX; take the consent questionnaire path | none | The consent form answered for the pre-auth stage | +| D3 Check coverage eligibility | as B1 with member `MD5SLS4X5` style ids | Validate | as B1; the answer on workflow 5 with the wallet | as B1 | +| D4 Submit pre-authorisation | as B3, plus: HPIN on the doctor, `Item/n` ids, consent and STG forms answered, documents under the plan's `MAND` codes | Submit | `v1/preauth/submit` workflow 12; 20 with the path-form `preAuthRef` or none (flow-knowledge.md section 3), then 21 with the bare number | as B3; `preauth_ref` = the bare case number after the 21 | +| D5 Resubmit pre-authorisation | A pre-auth `rejected` | Submit again | a fresh 12, never 121 | a new `submitting` round; 121 would be PAYR-1214 | +| D6 Raise an enhancement | Approved; a medical package added (not conservative) | Submit | workflow 13; 20 without `preAuthRef` (keep the parent's); 241 arrives as a ClaimResponse `partial` on the case thread; the desk answers on 131 with a `CQD` reply; then approved | `enhancement_no 1`; `queried` then `answered` then `approved`; a second conservative package would be PAYR-1245 | +| D7 Answer a pre-authorisation query | The 24 arrived as a ClaimResponse `partial`, item status `Queried` | The desk writes a reply and submits again | `v1/preauth/submit` workflow 19, flow `queryupdate`, `NMI`/`CQD` carrying the words, a new correlation id; 20 then 21 | `submission_kind preauth_query_response`, `query_note` holding the payer's question, then `approved`; an empty reply is refused before sending | +| D8 Cancel pre-authorisation | as B8 on PMJAY | Cancel | as B8 | as B8 | +| D9 Submit claim | as B5, plus: the claim under the pre-auth's claim number, the package alone at the whole amount, Discharge Consent answered, PDF documents | Submit | `v1/claim/submit` workflow 15; 25 with `preAuthRef` as a path; then 26 | as B5; item verdicts with `eligible`, `status Approved` | +| D9 LAMA or DAMA before or during surgery | Discharge mode `lama` or `dama`, stage `Before Surgery` or `During Surgery` | Submit the claim | one item `LM100`, no tier, `DIS` = `LAMA` or `DAMA` with the stage | approved; the package would be PAYR-1362 | +| D9 Death | Discharge mode `death` with a date and time | Submit the claim | `ONS`/`DTM` and `DSDE` with the death instant, `DIS`/`DTM`, the death forms | approved; without `DTM` PAYR-1096 | +| D10 Answer a claim query | The 27 arrived as a ClaimResponse `partial` | The desk writes a reply and submits again | `v1/claim/submit` workflow 161, `NMI`/`CQD`, a new correlation id; 25 then 26 | `submission_kind claim_query_response`, then `approved`, possibly at zero | +| D11 Reprocess a rejected claim | A claim `rejected` | Reprocess | as B8 reprocess; on the sandbox a ProtocolResponse PAYR-1008 | the enquiry row `error` with the refusal; on a generic payer as B8 | +| D12 Claim a shortfall | A settled payment short of the approved amount | Release with `partialpayment` and the amount | `v1/task/submit` workflow 36, Task `release`, `valueMoney` | an enquiry row; out of reach on the sandbox | +| D13 Acknowledge the payment notice | An approved claim; the SHA's finance side sends 30 | Nothing; acknowledged on arrival | outbound `v1/paymentnotice/on_request` with workflow 17, the notice's correlation id, to the notice's sender | as B7 | + +Cross-cutting rows every matrix needs: + +| Case | Action | Expected | +| --- | --- | --- | +| Redelivery | Deliver the same envelope twice | the second returns `ignored`; state unchanged | +| Unmatched | Deliver an answer on an unknown correlation id | `unmatched`; archived under `unmatched`; nothing changes | +| Refusal at the door | Deliver a ProtocolResponse on a leg's thread | the leg `error` (or `queried` restored for a query answer, `approved` restored for an enhancement) with the payer's words; `correlation_id` restored to `thread_correlation_id` | +| Ledger reset (nhcx-adapter only) | The adapter answers 404 on `txn/related` | the leg `error` with "send again"; no spinning | +| Stage after every write | Any of the above | `stage` and `sub_stage` on the episode agree with `case_stage` recomputed from the legs | + +## 4. A skeleton offline test + +Replace the placeholders marked `` with your HMIS's own. Every pin and payer answer is loaded from the package. + +```python +#!/usr/bin/env python3 +"""Offline NHCX checks for : builders against the package pins, readers against the payer fixtures. + + NHCX_PACKAGE=nhcx-package python3 nhcx_offline_test.py # exit 0 when every check passes +""" +from __future__ import annotations + +import copy +import json +import os +import tempfile + +PKG = os.environ.get("NHCX_PACKAGE", "nhcx-package") +GENERIC_PAYER = "" + +os.environ[""] = os.path.join(tempfile.mkdtemp(prefix="nhcx-test-"), "t.db") + +import as nhcx # noqa: E402 the module that owns transport, build_*, receive + +failures = 0 +current = "general" +tally: dict[str, list[int]] = {} + + +def section(name: str) -> None: + global current + current = name + tally.setdefault(name, [0, 0]) + print(f"\n-- {name} " + "-" * max(3, 60 - len(name))) + + +def check(label: str, condition: bool, detail: str = "") -> None: + global failures + tally.setdefault(current, [0, 0]) + tally[current][0 if condition else 1] += 1 + if not condition: + failures += 1 + print(f"[{' ok ' if condition else ' FAIL '}] {label}" + (f" ({detail})" if detail else "")) + + +def pin(rel: str) -> dict: + """A bundle from the package by its path under fhir/, e.g. pin("B3/preauth-request.json").""" + with open(os.path.join(PKG, "fhir", rel), encoding="utf-8") as fh: + return json.load(fh) + + +def resource(bundle: dict, kind: str) -> dict: + return next(e["resource"] for e in bundle["entry"] if e["resource"]["resourceType"] == kind) + + +def task_input(task: dict, code: str): + return next(i.get("valueString") for i in task.get("input", []) if i["type"]["coding"][0]["code"] == code) + + +def total(claim_response: dict, category: str): + return next((t["amount"].get("value") for t in claim_response.get("total", []) + if t["category"]["coding"][0]["code"] == category), None) + + +def normalised(bundle: dict, factor: bool = True) -> dict: + """Drop only `created`, which a builder stamps when it sends; with factor=False, the Claim items' factor too.""" + out = copy.deepcopy(bundle) + + def walk(node): + if isinstance(node, dict): + node.pop("created", None) + for value in node.values(): + walk(value) + elif isinstance(node, list): + for value in node: + walk(value) + + walk(out) + if not factor: + for entry in out["entry"]: + if entry["resource"]["resourceType"] == "Claim": + for item in entry["resource"].get("item", []): + item.pop("factor", None) + return out + + +def canonical(bundle: dict, factor: bool = True) -> str: + return json.dumps(normalised(bundle, factor), sort_keys=True, ensure_ascii=False) + + +def same(label: str, ours: dict, want: dict, factor: bool = True) -> None: + a, b = canonical(ours, factor), canonical(want, factor) + check(label, a == b, "" if a == b else a[:300]) + + +# The package pins' own data: nhcx-package/fhir/B3/preauth-request.json and B1/*.json. +# Every builder is fed this and must produce the pin. +REF = { + "claim_no": "VB26AA2600001", "member_id": "MD5SLS4X5", "policy": "PMJAY/HP/S/G", + "provider": {"id": "IN1910000151", "name": "Facility Name"}, + "payer": {"code": "1518@hcx", "id": "1518", "name": "Insurance Company"}, + "patient": {"name": "Patient Name", "gender": "male", "dob": "2004-09-18", + "phone": "9999999999", "abha": "91718280654077", "member_id": "MD5SLS4X5"}, + "practitioner": {"name": "Practitioner Name", "hpr_id": "982374978-2343", "license_no": "MCI-12345", + "qualification": "Doctor of Medicine", "qualification_code": "MD", + "specialty": "General medicine", "specialty_code": "394802001"}, + "diagnosis": {"code": "A97", "display": "Dengue"}, + "item": {"code": "MG0111A", "display": "Pleural Effusion", "category_code": "MG", + "category_display": "General Medicine", "quantity": 1, "unit_price": 3300, "net": 3300, + "kind": "Procedure", "procedure_type": "conservative"}, + "tier": {"code": "STRAT006b", "display": "HDU", "kind": "Stratification", "parent_code": "MG0111A"}, + # The benefits and auth-requirements pins quote a different package. + "coverage_item": {"code": "MG004C", "display": "Dengue shock syndrome (Dengue fever)", + "category_code": "MG", "category_display": "General Medicine", "quantity": 1, + "tier": {"code": "STRAT006c", "display": "ICU - Without Ventilator"}}, +} + + +def main() -> int: + section("coverage eligibility: ours is the pin") + for purpose, rel in (("discovery", "B1/discovery.json"), ("validation", "B1/validation.json"), + ("benefits", "B1/benefits.json"), ("auth-requirements", "B1/auth-requirements.json")): + want = pin(rel) + ours = nhcx.build_coverage_request((purpose, want)) + same(f"coverage {purpose}", ours, want) + + section("insurance plan request: ours is the pin") + same("plan request", nhcx.build_plan_request(REF["policy"], REF["provider"]["id"]), + pin("B2/insurance-plan-request.json")) + + section("claim bundles: ours is the pin") + ref_pa = pin("B3/preauth-request.json") + ref_pdf = next(si["valueAttachment"]["data"] for si in resource(ref_pa, "Claim")["supportingInfo"] + if "valueAttachment" in si) + dossier = (REF, ref_pdf, ref_pa) + same("preauth request", nhcx.build_preauth_bundle(dossier, flow="request"), ref_pa, factor=False) + ref_qu = pin("B3/preauth-queryupdate.json") + reply = next(si["valueString"] for si in resource(ref_qu, "Claim")["supportingInfo"] + if si["category"]["coding"][0]["code"] == "NMI") + same("preauth query update", + nhcx.build_preauth_bundle(dossier, flow="queryupdate", query_response=reply), + ref_qu, factor=False) + ref_cancel = pin("B3/preauth-cancel.json") + cancel = resource(ref_cancel, "Task") + reason = cancel["reasonCode"]["coding"][0] + same("preauth cancel", + nhcx.build_cancel_task(task_input(cancel, "claimNumber"), (reason["code"], reason["display"]), + cancel["authoredOn"], REF["provider"], REF["payer"]), + ref_cancel) + ref_ack = pin("B7/payment-notice-ack.json") + ack = resource(ref_ack, "Task") + acked_claim = next(o["valueString"] for o in ack["output"] if "valueString" in o) + same("payment acknowledgement", + nhcx.build_payment_ack(acked_claim, ack["authoredOn"], REF["provider"], REF["payer"]), + ref_ack) + + section("the transport is the one door, and it can be stubbed") + posted: list[dict] = [] + real_send = nhcx.transport.send + + def submitted(payer: str, corr: str): + def _send(path, bundle, recipient, workflow_id, correlation_id=None, **kw): + posted.append({"path": path, "recipient": recipient, "workflow_id": workflow_id, + "correlation_id": correlation_id, "bundle": bundle}) + return {"txn_id": "01TEST", "correlation_id": corr, "api_call_id": "acid-" + corr} + + seeded = (payer) # eligible, plan ready, lines quoted, dossier saved + nhcx.transport.send = _send + try: + nhcx.submit_preauth(seeded) + finally: + nhcx.transport.send = real_send + return seeded + + episode = submitted(REF["payer"]["code"], "corr-preauth-1") + sent = posted[-1] + leg = nhcx.preauth(episode) + check("the pre-auth goes out on the preauth route under workflow 12", + sent["path"] == "v1/preauth/submit" and str(sent["workflow_id"]) == "12") + check("no correlation id is passed on a request", sent["correlation_id"] is None) + check("the leg waits with the transport's ids", + leg["status"] == "submitting" and leg["txn_id"] == "01TEST" and leg["correlation_id"] == "corr-preauth-1") + + section("readers: the payer answers settle the right state") + + def deliver(bundle: dict, acid: str, workflow: str, status: str = "response.complete", + corr: str = "corr-preauth-1", sender: str = "1518@hcx") -> str: + return nhcx.receive({"jwe_headers": {"x-hcx-correlation_id": corr, + "x-hcx-api_call_id": acid, + "x-hcx-sender_code": sender, + "x-hcx-status": status, "x-hcx-workflow_id": workflow}, + "fhir": bundle}, "preauth", "request", "fhir") + + received = pin("C5/C5-received-wf20-pmjay.json") + before = nhcx.preauth(episode)["preauth_ref"] + check("the PMJAY acknowledgement leaves the leg waiting", + deliver(received, "acid-20", "20", "response.partial") == "settled" + and nhcx.preauth(episode)["status"] == "submitting") + check("an acknowledgement without preAuthRef overwrites nothing", + not resource(received, "ClaimResponse").get("preAuthRef") + and nhcx.preauth(episode)["preauth_ref"] == before) + check("the same api call id delivered again is ignored", + deliver(received, "acid-20", "20", "response.partial") == "ignored") + approval = pin("C5/C5-approved-wf21-pmjay.json") + approved = resource(approval, "ClaimResponse") + check("the approval settles the leg on the same thread with the payer's case number", + deliver(approval, "acid-21", "21") == "settled" + and nhcx.preauth(episode)["status"] == "approved" + and nhcx.preauth(episode)["approved_amount"] == total(approved, "benefit") + and nhcx.preauth(episode)["preauth_ref"] == approved["preAuthRef"]) + stage, sub_stage = nhcx.case_stage(episode) + check("the episode is stamped preauth / approved", (stage, sub_stage) == ("preauth", "approved")) + + other = submitted(GENERIC_PAYER, "corr-preauth-2") + generic = pin("C5/C5-received-wf20.json") + check("a generic payer's acknowledgement carries the case number, and it is kept", + deliver(generic, "acid-20g", "20", "response.partial", corr="corr-preauth-2", + sender=GENERIC_PAYER) == "settled" + and nhcx.preauth(other)["status"] == "submitting" + and nhcx.preauth(other)["preauth_ref"] == resource(generic, "ClaimResponse")["preAuthRef"]) + + section("auth requirements: the payer's ruling is read line by line") + for rel in ("C3/C3-response-generic.json", "C3/C3-response-pmjay.json"): + ruling = pin(rel) + answer = [e["resource"] for e in ruling["entry"] + if e["resource"]["resourceType"] == "CoverageEligibilityResponse"][-1] + want = {i["productOrService"]["coding"][0]["code"]: i.get("authorizationRequired") + for i in answer["insurance"][0]["item"]} + got = nhcx.parse_auth_bundle(ruling) # {procedure code: {"required": bool, "supporting": [...]}} + check(f"{rel}: one ruling per quoted line, required as the payer says", + {code: line["required"] for code, line in got.items()} == want) + + section("the query loop") + queried = pin("C5/C5-queried-wf24.json") + check("a PMJAY query is the leg queried, with the payer's words and case number kept", + deliver(queried, "acid-24", "24") == "settled" + and nhcx.preauth(episode)["status"] == "queried" + and bool(nhcx.preauth(episode)["query_note"]) + and nhcx.preauth(episode)["preauth_ref"] == resource(queried, "ClaimResponse")["preAuthRef"]) + try: + nhcx.submit_preauth(episode, reply="") + check("an empty reply is refused before sending", False) + except ValueError: + check("an empty reply is refused before sending", True) + check("a generic payer's CommunicationRequest is classified a query", + nhcx.classify_communication(nhcx.GENERIC_ADAPTER, "additionalinfo", "order") == "query" + and nhcx.classify_communication(nhcx.PMJAY_ADAPTER, "additionalinfo", "order") == "notification" + and nhcx.classify_communication(nhcx.GENERIC_ADAPTER, "tatquery", None) == "notification") + + section("refusal at the door") + refusal = {"type": "ProtocolResponse", "x-hcx-status": "response.error", + "x-hcx-correlation_id": "corr-preauth-1", + "x-hcx-error_details": {"code": "PAYR-1238", "message": "Beneficiary is having an active preauthorization request"}} + (episode) + check("a ProtocolResponse settles the leg as refused with the payer's words", + nhcx.receive({"jwe_headers": {"x-hcx-correlation_id": "corr-preauth-1"}, "fhir": refusal}, + "preauth", "request", "protocol") == "settled" + and nhcx.preauth(episode)["status"] == "error" + and "PAYR-1238" in (nhcx.preauth(episode)["error_message"] or "")) + + section("tasks and payment") + cancelled = pin("C10/C10-cancelled-wfPC02-pmjay.json") + verdict = resource(cancelled, "ClaimResponse")["adjudication"][0]["reason"]["coding"][0]["code"] + check("PC02 is read as an accepted cancellation", + nhcx.parse_task_response(cancelled)["adjudication"] == verdict == "cancelled") + arbitration = pin("C10/C10-arbitration-wf37-pmjay.json") + check("37 is read as the reprocess taken", + nhcx.parse_task_response(arbitration)["task_status"] == resource(arbitration, "Task")["status"]) + paid = pin("C9/payment-notice.json") + pn, pr = resource(paid, "PaymentNotice"), resource(paid, "PaymentReconciliation") + notice = nhcx.parse_payment_notice(paid) + check("the payment notice names the claim, the amount and the UTR", + notice["claim_ref"] == pn["identifier"][0]["value"] + and notice["amount"] == pn["amount"]["value"] + and notice["utr"] == pr["paymentIdentifier"]["value"]) + + print("\n" + "=" * 64) + total_checks = sum(ok + bad for ok, bad in tally.values()) + for name, (ok, bad) in tally.items(): + print(f" {name:44s} {ok:3d} passed {bad:2d} failed [{'FAIL' if bad else 'ok'}]") + print("=" * 64) + if failures: + print(f"{failures} of {total_checks} check(s) FAILED") + return 1 + print(f"all {total_checks} checks passed") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) +``` + +What each placeholder must do: + +- `` names the variable your HMIS reads its database path from, so the suite runs on a throwaway file. +- `` is the module that owns `transport`, the builders and `receive`. +- `` is the participant code of a generic payer (``) that your configuration maps to `query_mode: communication`. +- `` returns the dict your coverage builder takes, filled from `REF`. The discovery pin carries policy `NONE`. The benefits and auth-requirements pins quote `REF["coverage_item"]`. Copy the Location and PractitionerRole from the pin it is given. +- `` returns whatever your claim builder takes. That is the claim number, the item, the tier, the program `AB-PMJAY` and factors `(1, 0.5, 0.25)`. Add the four `MAND` documents (`MAND0408`, `MAND0455`, `MAND0409`, `MAND0570`, each with the pin's PDF), and copy the stay and procedure dates from the pin it is given. +- `` takes a payer code and inserts an eligible episode for that payer, with the plan and lines seeded straight into the database. +- `` puts the pre-auth row back to `submitting` on `corr-preauth-1`. + +Run the suite from the folder that holds `nhcx-package/`, or set `NHCX_PACKAGE` to its path. + +## 5. Running rung 2 + +Have your tests and live runs write every bundle they build into one archive folder. The package ships no validator. Run the HL7 FHIR validator with the NRCeS IG `ndhm.in` on the whole folder in one call, with the command and flags in `references/fhir-knowledge.md` section 11. + +Read the results in three piles. "A code the profile does not define" is the scheme's vocabulary, and it is expected. "A required element is missing" and "an id or value the base rules refuse" are yours to fix. Warnings are advice; the sandbox accepted every pin as it stands. Skip the package master; it exhausts the validator's memory. A live PAYR-1004 or PAYR-1008 is the first reason to run this rung again (`nhcx-package/docs/06-Reference/02-Troubleshooting.md`). + +## 6. Running rungs 3 and 4 + +Only the user runs these. Prepare what they start and the driver, then stop and ask. + +What the user starts: + +1. The transport. Your own or the app's existing one needs a participant record carrying its certificate and a public HTTPS `endpoint_url` the exchange can reach (`references/transport-knowledge.md` section 3). nhcx-adapter, only when the user chose it, comes from its release: `config.sample.json` filled in, started with `serve.sh`. +2. Your HMIS, reachable by the exchange through that transport. +3. For rung 3, a generic payer on the sandbox whose desk you can drive (``), mapped to `query_mode: communication`. For rung 4, nothing more: the PMJAY payer is `1518@hcx`, and its decisions are taken on the payer service desk. + +The driver is a script or a browser spec. It walks the matrix rows through the app's JSON state address or its own screens, one episode per test, in series, with a 20 minute timeout per episode. + +- Before a PMJAY run, sweep every live pre-auth for the beneficiaries the tests use. Cancel it on PC01, or have the desk reject it. Otherwise the first pre-auth is refused with PAYR-1238. +- One request at a time per case. Wait about 30 seconds after a decision before the next leg. On "Active instance found" (PAYR-1322), wait and resend, up to three times. +- Wait on the case's own state, never on a fixed sleep or a checklist. +- Log every verdict the sandbox gives, with its workflow id and words, so a refusal is a finding, not a mystery. +- Expect about four minutes for the rung 3 matrix and about ten minutes per episode on PMJAY. + +After the run, package its bundles by correlation id from the per-case archive: every message sent and received, filed under its case. With nhcx-adapter as the transport, `nhcx-adapter ledger thread ` gives the same conversation, with bodies only while `ledger.storeBodies` is true (`nhcx-package/docs/02-Getting Started/10-NHCX Adapter.md`). File each thread under its use case. diff --git a/plugins/nhcx/skills/nhcx-insurance/references/transport-knowledge.md b/plugins/nhcx/skills/nhcx-insurance/references/transport-knowledge.md new file mode 100644 index 000000000..a0838b9cd --- /dev/null +++ b/plugins/nhcx/skills/nhcx-insurance/references/transport-knowledge.md @@ -0,0 +1,283 @@ +# Transport knowledge: how the build reaches NHCX + +Every NHCX message is a FHIR bundle sealed in a JWE, sent with an ABDM session token, and answered later on the sender's own callback. Something has to do that work. This file says which of three things does it for a build, what the rest of the build expects from it, and how to build it yourself. + +Section 3 is drawn from NHA's published chapters: `nhcx-package/docs/02-Getting Started` (01 to 09, and 11), `nhcx-package/docs/01-Overview/04-JWE, Status and Errors.md` and `nhcx-package/docs/06-Reference/03-Envelope Fields.md`. Open them when a detail matters. Where they and this summary differ, they win. + +## 1. Three transports + +| Transport | Choose it when | The build | +| --- | --- | --- | +| `existing` | Stage 0 found the app already speaks NHCX: its own client that seals and posts JWEs, a vendor gateway or middleware, an HCX SDK, callbacks under `/v1/...` | Keeps it. Wraps it behind the contract in section 2 and closes the gaps section 4 lists. Never replaces a working one. | +| `own` | The app has no NHCX integration, and the user has not asked for nhcx-adapter. This is the default. | Builds the protocol into the app (section 3): the session token, the key and certificate, the participant record, the recipient's certificate, sealing and sending, the callback and its receipt. | +| `adapter` | Only when the user asks for nhcx-adapter, by name or by asking for "the adapter" | Downloads it (section 5) and talks plain FHIR to it. `references/api-knowledge.md` is its contract. | + +The rules: + +- Never propose nhcx-adapter, and never choose it because it is easier. Use it only when the user has asked for it, and write their words into `nhcx-build/1-idea.md`. +- An app with an NHCX integration of its own keeps it, even when it is partial. Extend it; never put a second transport beside it. +- The choice is made once per app, at stage 1, from stage 0's verdict on `foundation.transport`. Every skill after the first reads it from `1-idea.md`. + +## 2. The contract every transport meets + +The rest of the build (modules 7.2 to 7.13) never sees the transport, only these functions: + +| Function | Takes | Gives | Notes | +| --- | --- | --- | --- | +| `send(path, bundle, recipient, workflow_id, correlation_id = null, ben_abha_id = null, claim_no, usecase)` | The NHCX path (`v1/preauth/submit`), the bundle, the recipient's participant code, the workflow id; a correlation id only when answering (the communication reply, the payment acknowledgement); the beneficiary's ABHA, else the episode's by `claim_no` | `{txn_id, correlation_id, api_call_id, raw}` | Raises `TransportError(code, message, protocol_response, retryable)` on a refusal. Archives the outbound message. Every leg stores the three ids. | +| The receiving end | A delivery from the exchange (`own`, `existing`) or from nhcx-adapter | Calls 7.3's `receive(envelope)` with `{meta: {path, payloadType, redelivery}, jwe_headers: {every x-hcx- field}, fhir: }`; `payloadType` is `fhir`, `protocol` or `error` | Answers the sender as its transport requires (section 3.9 for `own`). The door does the rest. | +| `policies(id_type, value)` | `AbhaNumber`, `MemberId` or `MobileNo`, and the value | The participant service's answer, raw | Module 7.4 normalises it (section 3.6). | +| `participants(role)` | `PAYER`, `PROVIDER` or `TPA` | The registry's list | Cached for the day. | +| `token()` | nothing | The ABDM session token | For calls the transport does not make itself, such as the PMJAY payer service. | +| `thread(correlation_id)`, `fetch_missed(txn_id)` | | The messages on one thread; a missed answer | Only nhcx-adapter keeps a ledger to answer these. With `own` and `existing`, `thread` reads the per-case archive and `fetch_missed` answers `unavailable`; a lost answer surfaces through `/v1/error` and the status exchange instead (section 3.10). | + +Two values every transport needs from the build, both from the policy lookup (section 3.6). The recipient is the policy's `processingid`, kept on the episode as `recipient_code`. The insurer is its `payerid`, kept as `payer_code`: it goes inside the bundle and chooses the payer adapter (module 7.11). And every message carries the beneficiary's ABHA number in `x-hcx-ben-abha-id`. + +A test replaces `send` with a stub of the same signature (stage 9). Nothing else in the build changes for a test. + +## 3. Building it yourself (`own`) + +Seven things, in this order (`01-The Base Framework.md`): a token, a key and certificate, a participant record, the payer and policy lookups, the recipient's certificate, sealing and sending, and the callback. The last two are the ones every message uses. + +### 3.1 Before you start + +| Need | Why | +| --- | --- | +| The facility's HFR id | The registry that vouches for a hospital | +| ABDM sandbox client id and secret, Milestone 1 completed | NHCX uses the same credentials; there is no separate login | +| A public HTTPS server in India with a domain name | The exchange calls your callback; it will not call an IP address or a port number | +| `openssl` where the private key will live | The key pair | +| A JOSE library | RSA-OAEP-256 with A256GCM: `jose` on Node, `jwcrypto` on Python, Nimbus on Java, `jose-jwt` on .NET | + +Ask the user for the credentials. Never write them, the token or the private key into code, a log or `nhcx-build/`. + +### 3.2 Addresses and headers + +From `nhcx-package/baseurl.yaml`: + +| Service | Sandbox | Production | +| --- | --- | --- | +| ABDM session token | `https://dev.abdm.gov.in/api/hiecm/gateway/v3/sessions` | `https://apis.abdm.gov.in` plus the same path; confirm it in the onboarding letter | +| NHCX exchange, every use-case call under `/v1` | `https://apisbx.abdm.gov.in/hcx` | Shared by NHA after sandbox exit | +| Participant service | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice` | `https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice` | + +Keep every address in configuration. Every call to the participant service and the use-case endpoints carries `Accept: application/json`, `Content-Type: application/json` and `bearer_auth: Bearer `. The header is `bearer_auth`, not `Authorization`; some NHA pages write `Authorization`, so send both with the same value. + +### 3.3 The session token + +`POST` to the sessions address with three headers, none optional: `REQUEST-ID` (a fresh UUID on every call), `TIMESTAMP` (UTC with milliseconds and a trailing `Z`, from the system clock) and `X-CM-ID` (`sbx` on the sandbox, `abdm` in production). The body is `{"clientId", "clientSecret", "grantType": "client_credentials"}`. The answer carries `accessToken` and `expiresIn`. + +- NHA's documents give its life as 300, 1200 and 6000 seconds. Rely on none: keep the token and when you got it, and fetch a new one when it is a few minutes old. +- On any `401`, get a new token and retry that call once. Never retry with the same token. +- Put `Bearer` and a space before the token. Without it, `401`. + +`03-Session Token.md` also shows the two timestamp shapes in ten languages: the gateway's UTC `...975Z`, the exchange's `+05:30`. + +### 3.4 Your key and certificate + +```bash +openssl genpkey -algorithm RSA -out private.key -pkeyopt rsa_keygen_bits:2048 +openssl req -new -key private.key -out request.csr +openssl x509 -req -in request.csr -signkey private.key -out certificate.crt -days 365 +base64 -w 0 certificate.crt > certificate.b64 # macOS: base64 -i certificate.crt -o certificate.b64 +``` + +`private.key` never leaves the server that receives callbacks. `certificate.b64` goes on the participant record as `encryption_cert`. Note the expiry: a lapsed certificate stops every sender. Replace it yearly (`04-Your Certificate.md`). + +### 3.5 The participant record + +On the sandbox, `POST /participant/create` with: + +| Field | Value | +| --- | --- | +| `linked_registry_codes` | `["10001"]` (HFR) | +| `registryid` | Your ABDM client id on the sandbox; the HFR id in production | +| `roles` | `["10001"]` (provider) | +| `participant_name`, `scheme_code`, `state`, `district`, `primaryEmail`, `phone`, `primaryMobile` | The facility's | +| `encryption_cert` | The base64 certificate | +| `endpoint_url` | The base of your callback server | + +The answer is your `participant_code`: the `x-hcx-sender_code` on everything you send. `participant/update` changes the certificate or the address. Production takes four steps with a passcode to the mobile on the HFR record (`v2/participant/create`, `validate`, `v2/participant/update`, `update/validate`), and `v2/update/cert` rotates only the certificate (`05-Creating and Updating a Participant.md`). + +The exchange appends the use-case path to `endpoint_url`: a pre-auth decision arrives at `/v1/preauth/on_submit`. Only the client id that created the record may change it; any other gets NHCX-1015. + +This is the user's onboarding, not the build's. The build writes the script or the settings screen; the user runs it with their credentials. Check it worked by fetching your own certificate back (section 3.7). + +### 3.6 The payer and the policy + +- Payers: `POST /fetch/participants/list` with `role` (`PAYER`, `PROVIDER`, `TPA`), `fromdate` and `todate` (`dd/MM/yyyy`), and optionally `entitytype` (`Gov`). There is no server-side search by name: fetch, filter locally, and cache for the day. +- Policies: `POST /participant/get/policies` with `identifiertype` and `identifiervalue`. Try `AbhaNumber` (no hyphens), then `MemberId`, then `MobileNo`, and stop at the first that returns a policy. Each policy carries `payerid`, `processingid`, `memberid`, `productid` and `productname`. The published answer is a sketch: read a real one before writing the parser, and keep it raw on the episode. +- Send to the processor. `processingid` is the envelope's recipient and whose certificate seals the message; `payerid` is the insurer named inside the bundle. They are the same when the insurer processes its own claims and differ when a TPA does. Addressing the `payerid` is the portal's seventh most common mistake. A policy with no `processingid` cannot be addressed: stop and say so (`06-Finding Participants and Policies.md`). + +### 3.7 The recipient's certificate + +`POST /fetch/certs` with `{"participantid": ""}`. The answer is PEM text: usually an X.509 certificate, sometimes a bare SPKI public key (anything under about 400 bytes). Load it as a certificate and take its key; if that fails, load it as a key. NHA does not publish the JSON envelope around it, so read one real answer first. Cache by participant code for 24 hours, and refresh early when the other side stops being able to open your messages (`07-Fetching a Recipient Certificate.md`). + +### 3.8 Sealing and sending + +The protected header (`08-Building and Sending a JWE.md`, `06-Reference/03-Envelope Fields.md`): + +| Field | Value | +| --- | --- | +| `alg`, `enc` | `RSA-OAEP-256`, `A256GCM`; not `RSA-OAEP` | +| `x-hcx-sender_code` | Your participant code | +| `x-hcx-recipient_code` | The policy's `processingid` on a request; the request's sender on an answer | +| `x-hcx-api_call_id` | A fresh UUID on every message, answers included | +| `x-hcx-request_id` | A UUID per request; optional, send it | +| `x-hcx-correlation_id` | On a request, this message's own `api_call_id`. On an answer, the request's `correlation_id`, so the two ids differ on an answer | +| `x-hcx-workflow_id` | The step code (`references/flow-knowledge.md` section 2). Optional in the specification, but payers key on it: send it wherever the sheet gives one | +| `x-hcx-timestamp` | ISO 8601 with `+05:30`, no milliseconds, from the system clock | +| `x-hcx-status` | `request.initiated` on a request; `response.complete` on an answer (an `on_` path) | +| `x-hcx-ben-abha-id` | The beneficiary's ABHA number without hyphens. Mandatory on every exchange | +| `x-hcx-use_case` | Optional: `New`, `Enhancement` or `Resubmit` on a pre-auth; `New` or `Resubmit` on a claim | + +Seal with the JOSE library: the bundle as plaintext, the recipient's public key, the header above as the protected header, compact serialisation (five parts, four dots). POST `{"payload": ""}` to `/v1/` with the headers of section 3.2. The sandbox collection also repeats the `x-hcx-` fields as HTTP headers; send them both ways. + +What comes back: + +| Answer | Means | The build | +| --- | --- | --- | +| `202` with a receipt (`protocol_status: request.queued`) | The envelope was valid and is queued. It is not the decision | Store `api_call_id` and `correlation_id`, and the archive id as `txn_id`; the leg waits | +| `400` | The envelope failed validation | Raise with the gateway's body; nothing went to the payer | +| `401` | The token expired, or `Bearer` is missing | New token, retry once | +| A connection dropped after the request was written | Unknown: it may have landed | Do not resend at once (`references/errors-and-debugging.md` section 7) | + +A correlation id that failed at the gateway is retired. The next attempt needs a fresh `api_call_id` and a fresh `correlation_id` (`01-Overview/04-JWE, Status and Errors.md`). + +### 3.9 Receiving + +Host these under `endpoint_url` (`09-Receiving a Callback.md`): `/v1/coverageeligibility/on_check`, `/v1/insuranceplan/on_request`, `/v1/preauth/on_submit`, `/v1/claim/on_submit`, `/v1/predetermination/on_submit`, `/v1/search/on_submit`, `/v1/communication/request`, `/v1/paymentnotice/request`, `/v1/task/on_submit`, `/v1/on_status` and `/v1/error`. Build one handler. The path gives the receipt's `entity_type`; the correlation id routes everything else (module 7.3). + +- The address: a domain over HTTPS with TLS 1.2 or newer, hosted in India, reachable from the exchange's outbound addresses `3.109.99.210`, `13.126.152.0` and `13.200.129.223`. +- The body: `{"type": "JWEPayload", "payload": ""}`; or, when the recipient refused your message, `{"type": "ProtocolResponse", "x-hcx-...": ..., "x-hcx-status": "response.error", "x-hcx-error_details": {code, message, trace}}` with the fields in the clear. `/v1/error` carries neither: it is a plain report of a request the exchange gave up on after five attempts. Store it whole and do not parse it against a fixed schema. +- Open a `JWEPayload` with your private key: the protected header comes out in the clear and the bundle is the plaintext. A failure to decrypt means the message was sealed for a certificate that is not the one on your participant record. +- Answer every delivery with `202` and the receipt within 30 seconds, `/v1/error` and unrecognised messages included. Not `200`, and not an empty body: + + ```json + {"timestamp": "dd/MM/yyyy HH:mm:ss:SSS", "api_call_id": "", "correlation_id": "", + "result": {"sender_code": "", "recipient_code": "", "entity_type": "preauth", "protocol_status": "request.queued"}, + "error": {"code": "", "message": ""}} + ``` + + `entity_type` is the path's second-to-last segment, or the last where that is `v1`, with `on_` stripped. +- Hand the door `{meta: {path, payloadType, redelivery}, jwe_headers, fhir}`: `payloadType` `fhir` with the bundle, `protocol` with the ProtocolResponse body as `fhir`, `error` with the `/v1/error` report. The door dedupes on `x-hcx-api_call_id`, archives, matches and applies, fast and with no outbound calls, so the receipt still goes inside the 30 seconds. +- The exchange signs its calls to you with a JWT (RS256; claims `jti`, `iss`, `sub`, `iat`, `exp`). No published source gives the NHCX public key or the header the token arrives in. Build the check with the key in configuration. While no key is configured, log that at every start, accept calls only from the three addresses above, and ask NHA for the key at onboarding. Never leave the check off silently. + +### 3.10 Status and the error endpoint + +- `/v1/status` asks the exchange what became of a message you sent. The payload is empty; `x-hcx-correlation_id` is that message's `api_call_id`. The answer arrives on `/v1/on_status` with `request.queued`, `request.dispatched` or `request.stopped` (redelivery exhausted; the correlation is retired). Call it when a case has been quiet longer than the payer's turnaround, never on a timer (`11-Status and Search.md`). `references/flow-knowledge.md` section 2 records what the sandbox did with it; keep the path configurable. This is not the claim's status Task of module 7.9. +- `/v1/error` is how you learn a request died. Without it a lost message is silent. + +With no ledger to poll, these two, the per-case archive and the receipts are what an `own` transport has. A leg with no answer stays waiting; it never turns into an error on a timer. + +### 3.11 Proving it + +The sandbox's dummy payer answers when you trigger it. Send it a bundle, then `POST https://apisbx.abdm.gov.in/pmjay/sbxhcx/dummyhcxpayer/process/request` with `{"action": "Approve" | "Reject" | "Query", "method": "Preauth" | "Claim", "correlationId": ""}`. Its answer reaching your `/v1/preauth/on_submit`, sealed or as a ProtocolResponse, proves the token, the participant record, the address, the sealing and the opening together (`09-Receiving a Callback.md`, "Closing the loop"). This is live traffic: stage 10, rung 3, started by the user. + +### 3.12 Pseudo code + +``` +settings.nhcx = {sessions, base, registry, cm_id, client_id, client_secret, # from configuration, never from code + private_key, signing_key} # signing_key empty until onboarding gives it + +function token(): + if cache.token and age(cache.at) < 240s: return cache.token + r = http_post(settings.nhcx.sessions, json = {clientId: settings.nhcx.client_id, clientSecret: settings.nhcx.client_secret, + grantType: "client_credentials"}, + headers = {"REQUEST-ID": uuid4(), "TIMESTAMP": utc_millis_z(), "X-CM-ID": settings.nhcx.cm_id}) + cache = {token: r.json().accessToken, at: now()} + return cache.token + +function authed_post(url, body, extra_headers = {}): + for attempt in (1, 2): + t = token() + r = http_post(url, json = body, timeout = 90, + headers = {"Accept": "application/json", "Content-Type": "application/json", + "bearer_auth": "Bearer " + t, "Authorization": "Bearer " + t} + extra_headers) + if r.status != 401: return r + cache.token = null # one retry, with a fresh token + return r + +function registry(path, body): return authed_post(settings.nhcx.registry + "/" + path, body) + +function recipient_key(code): # cached for 24 hours + if certs[code] and age(certs[code].at) < 24h: return certs[code].key + pem = pem_in(registry("fetch/certs", {participantid: code}).json()) # read one real answer first + key = try_certificate(pem).public_key() or load_public_key(pem) # X.509 first, bare SPKI second + certs[code] = {key, at: now()} + return key + +function send(path, bundle, recipient, workflow_id, correlation_id = null, ben_abha_id = null, claim_no = null, usecase = ""): + abha = digits(ben_abha_id or ben_abha(claim_no)) + if not recipient or not workflow_id or not abha: raise ValueError("recipient, workflow id and beneficiary ABHA are required") + answer = path.split("/")[-1].startswith("on_") + api_call_id = uuid4() + header = {"alg": "RSA-OAEP-256", "enc": "A256GCM", + "x-hcx-sender_code": with_hcx(settings.participant_code), "x-hcx-recipient_code": with_hcx(recipient), + "x-hcx-api_call_id": api_call_id, "x-hcx-request_id": uuid4(), + "x-hcx-correlation_id": correlation_id if answer else api_call_id, + "x-hcx-workflow_id": str(workflow_id), "x-hcx-timestamp": now_ist_seconds(), + "x-hcx-status": "response.complete" if answer else "request.initiated", + "x-hcx-ben-abha-id": abha} + jwe = jose_encrypt_compact(to_json(bundle), recipient_key(with_hcx(recipient)), protected = header) + r = authed_post(settings.nhcx.base + "/" + path, {"payload": jwe}, extra_headers = without(header, "alg", "enc")) + txn = archive.record(claim_no, usecase, "out", {path, header, bundle, status: r.status, response: r.text}) + if r.status >= 300: + raise TransportError(code = "GATEWAY_HTTP_" + r.status, message = r.text, retryable = r.status >= 500) + return {txn_id: txn, correlation_id: header["x-hcx-correlation_id"], api_call_id: api_call_id, raw: r.json()} + +route POST /v1/ # under endpoint_url; exempt from session auth and CSRF; the exchange's addresses only +function inbound(request, path): + verify_nhcx_jwt(request, settings.nhcx.signing_key) # when the key is configured; else logged at start, never silent + body = parse_json_or_null(request.body) + if path == "error": + env = {meta: {path: "v1/error", payloadType: "error"}, jwe_headers: {}, fhir: body} + elif body and body.type == "ProtocolResponse": + env = {meta: {path: "v1/" + path, payloadType: "protocol"}, jwe_headers: x_hcx_fields(body), fhir: body} + else: + try: header, plaintext = jose_decrypt_compact(body.payload, settings.nhcx.private_key) + except: archive.record(null, "undecryptable", "in", request.body); return 202, receipt({}, path, error = "DECRYPT_FAILED") + env = {meta: {path: "v1/" + path, payloadType: "fhir"}, jwe_headers: header, fhir: parse_json(plaintext)} + receive(env) # module 7.3: dedupe, archive, match, apply; fast, no sends + return 202, receipt(env.jwe_headers, path) # within 30 seconds + +function receipt(h, path, error = ""): + return {"timestamp": now_ist("dd/MM/yyyy HH:mm:ss:SSS"), + "api_call_id": h["x-hcx-api_call_id"], "correlation_id": h["x-hcx-correlation_id"], + "result": {"sender_code": h["x-hcx-sender_code"], "recipient_code": h["x-hcx-recipient_code"], + "entity_type": entity_type(path), "protocol_status": "request.queued"}, + "error": {"code": error, "message": ""}} + +function entity_type(path): # "v1/preauth/on_submit" -> "preauth"; "v1/on_status" -> "status" + parts = ("v1/" + path).split("/"); seg = parts[-2] if parts[-2] != "v1" else parts[-1] + return seg.removeprefix("on_") +``` + +## 4. Using an existing integration (`existing`) + +How stage 0 recognises one: `x-hcx-`, `JWEPayload`, `RSA-OAEP-256`, `A256GCM`, a JOSE library among the dependencies, `bearer_auth`, a sessions URL on the ABDM gateway, `participanthcxservice`, `fetch/certs`, `participant/get/policies`, routes ending in `on_submit`, `on_check` or `on_request`, a vendor's NHCX or HCX client library, a separate gateway service the app calls. + +What it must do, checked by running it offline with the network stubbed and a test key pair for the seal: + +| Contract item (section 2) | Look at | Common gap | +| --- | --- | --- | +| `send` emits the protected header of section 3.8 | What it seals or posts | No `x-hcx-ben-abha-id`; a request correlation id that is not its own `api_call_id`; UTC timestamps; `RSA-OAEP` | +| The recipient | Who it addresses | The `payerid` instead of the `processingid` | +| The three ids back to the caller | Its return value | Only a success flag; the ids stay inside it | +| Receiving: a `202` receipt within 30 seconds on every path, `/v1/error` included | Its callback handler | `200` or an empty body; no `/v1/error`; slow work before answering | +| Handing on the header and the bundle | What it gives the app | The bundle without the header; no ProtocolResponse path | +| Dedupe on `x-hcx-api_call_id` | Its store | None | +| A record of every message | Its logs | Bodies not kept | + +The build wraps it. 7.1's `send` calls the existing client and returns the three ids. The existing callback handler, after its receipt, calls 7.3's `receive` with the envelope of section 2. Each gap is closed in the existing code, in its style (stage 7, action `extend`). The existing transport is not rewritten, and no second one is added beside it. If it cannot be made to hand on the ids or the header, record `partial` and ask the user whether to extend it further or, with their agreement, build `own` in its place. + +## 5. nhcx-adapter, only when asked + +nhcx-adapter is NHA's optional single binary that does section 3 for you (`nhcx-package/docs/02-Getting Started/10-NHCX Adapter.md`, titled "Optional"). Use it only when the user has asked for it. Then: + +1. Get it, with the user's go-ahead, from https://github.com/nha-in/nhcx-adapter/releases (the latest). Each release carries one archive per platform, `nhcx-adapter___.tar.gz` (darwin, linux, windows, freebsd; amd64, arm64, 386), holding the binary, `config.sample.json`, `serve.sh`, `stop.sh`, `update.sh` and `README.md`. Put it in a folder of the user's, not in the skill. +2. Its contract is `references/api-knowledge.md`: configuration (section 2), routes (3), the outbound envelope and answer (4, 5), the delivery your HMIS receives (6), the ledger (7), the kit endpoints (8). +3. Onboarding is sections 3.1 to 3.5 again: credentials, a key, a participant record, a public address. The adapter can generate and register the key itself (`config init`, `cert generate`, its startup checks). +4. It does not queue or retry, does not build or validate bundles, and does not verify who sent an inbound message beyond decrypting it. Its `/internal/*` routes have no authentication: bind it to loopback. + +How it maps onto section 2: `send` POSTs `{jwe_headers, fhir}` to `/fhir/out/`; the receiving end is the HMIS route the adapter posts to (`api-knowledge.md` section 6); `policies` is `/internal/policies/search`; `thread` and `fetch_missed` are its ledger and `/internal/txn/*`. diff --git a/plugins/nhcx/skills/nhcx-insurance/scripts/fetch-package.sh b/plugins/nhcx/skills/nhcx-insurance/scripts/fetch-package.sh new file mode 100755 index 000000000..efbafa50b --- /dev/null +++ b/plugins/nhcx/skills/nhcx-insurance/scripts/fetch-package.sh @@ -0,0 +1,122 @@ +#!/usr/bin/env bash +# Fetch the NHCX package and unpack it beside nhcx-build/ as nhcx-package/. +# +# scripts/fetch-package.sh [url-or-path] [target-dir] +# +# With no [url-or-path] (or "latest"), the zip is the build attached to the latest +# release of https://github.com/nha-in/nhcx-package (the nhcx-package-v.zip +# asset); its sha256 is checked against the digest GitHub records for the asset. +# Otherwise [url-or-path] is a link to the zip or a local path to it. +# [target-dir] defaults to the current directory. The zip unpacks to /nhcx-package/. +# +# Afterwards MANIFEST is checked: every file it lists must exist with the sha256 +# it records. Nothing is deleted; an existing nhcx-package/ is replaced. +set -euo pipefail + +repo="nha-in/nhcx-package" +src="${1:-latest}" +target="${2:-.}" +if [[ "$src" == "-h" || "$src" == "--help" ]]; then + echo "usage: $0 [latest|url-or-path-to-package.zip] [target-dir]" >&2 + exit 2 +fi + +download() { # + if command -v curl >/dev/null 2>&1; then + curl -fsSL -o "$2" "$1" + elif command -v wget >/dev/null 2>&1; then + wget -qO "$2" "$1" + else + echo "neither curl nor wget is available" >&2 + exit 1 + fi +} + +mkdir -p "$target" +tmp="$(mktemp -d)" +zip="$tmp/package.zip" +want_sha="" + +if [[ "$src" == "latest" ]]; then + # Ask the releases API for the latest release's zip asset and its digest. + api="https://api.github.com/repos/$repo/releases/latest" + if download "$api" "$tmp/release.json" 2>/dev/null; then + read -r tag url want_sha < <(python3 - "$tmp/release.json" <<'PY' +import json, sys +rel = json.load(open(sys.argv[1], encoding="utf-8")) +assets = [a for a in rel.get("assets", []) + if a["name"].startswith("nhcx-package") and a["name"].endswith(".zip")] +if not assets: + sys.exit(f"release {rel.get('tag_name')} has no nhcx-package*.zip asset") +a = assets[0] +digest = a.get("digest") or "" +print(rel["tag_name"], a["browser_download_url"], + digest.split(":", 1)[1] if digest.startswith("sha256:") else "") +PY + ) + else + # API unreachable or rate limited: read the tag off the releases/latest redirect + # and build the asset name from it. No digest to check in this case. + tag="$(curl -fsSIL -o /dev/null -w '%{url_effective}' "https://github.com/$repo/releases/latest")" + tag="${tag##*/}" + if [[ -z "$tag" || "$tag" == "latest" ]]; then + echo "could not resolve the latest release of $repo" >&2 + exit 1 + fi + url="https://github.com/$repo/releases/download/$tag/nhcx-package-v$tag.zip" + fi + echo "fetching $repo release $tag: $url" + download "$url" "$zip" + if [[ -n "$want_sha" ]]; then + got_sha="$(python3 -c 'import hashlib,sys; print(hashlib.sha256(open(sys.argv[1],"rb").read()).hexdigest())' "$zip")" + if [[ "$got_sha" != "$want_sha" ]]; then + echo "sha256 mismatch for $url: got $got_sha, release says $want_sha" >&2 + exit 1 + fi + fi +elif [[ -f "$src" ]]; then + cp "$src" "$zip" +else + download "$src" "$zip" +fi + +rm -rf "$target/nhcx-package" +unzip -q "$zip" -d "$target" +if [[ ! -f "$target/nhcx-package/MANIFEST" ]]; then + echo "unpacked, but $target/nhcx-package/MANIFEST is missing; is this the NHCX package?" >&2 + exit 1 +fi + +# Verify every file the MANIFEST lists. The MANIFEST is YAML; its file entries +# carry path, bytes and sha256 on separate lines. +python3 - "$target/nhcx-package" <<'PY' +import hashlib, os, re, sys +root = sys.argv[1] +text = open(os.path.join(root, "MANIFEST"), encoding="utf-8").read() +# Only the `files:` section lists a sha256 per path; the `contents:` summary above it +# lists directories. Parse entry by entry so a directory entry never borrows the next +# file's hash. +files_section = text.split("\nfiles:\n", 1)[1] if "\nfiles:\n" in text else "" +entries = [] +for chunk in re.split(r"\n\s*-\s+path:\s*", "\n" + files_section)[1:]: + path = chunk.split("\n", 1)[0].strip() + m = re.search(r"^\s+sha256:\s*([0-9a-f]{64})", chunk, re.M) + if path and m: + entries.append((path, m.group(1))) +bad = [] +for path, want in entries: + p = os.path.join(root, path) + if not os.path.isfile(p): + bad.append(f"missing {path}") + continue + got = hashlib.sha256(open(p, "rb").read()).hexdigest() + if got != want: + bad.append(f"sha256 mismatch {path}") +print(f"nhcx-package: {len(entries)} file(s) listed, {len(bad)} problem(s)") +for b in bad[:20]: + print(" " + b) +sys.exit(1 if bad else 0) +PY + +rm -rf "$tmp" +echo "ready: $target/nhcx-package (see references/material.md for the path map)" diff --git a/plugins/nhcx/skills/nhcx-insurance/stages/0-capability-check.md b/plugins/nhcx/skills/nhcx-insurance/stages/0-capability-check.md new file mode 100644 index 000000000..8186c3288 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-insurance/stages/0-capability-check.md @@ -0,0 +1,92 @@ +# Stage 0: capability check + +Purpose: before anything is planned, find out what the app already does. For this skill's own capabilities, for the foundation it stands on, and for what it needs from the use cases before it, write one verdict each with the evidence that decides it. The verdicts decide what the later stages reuse, extend, build or wait for. Nothing is built twice, and nothing is reused on faith. + +## Inputs + +- This skill's `SKILL.md`, section "Capability check": its own capabilities (what to look for, what makes each present), and its prerequisites with the check that proves each present. The skills that own the prerequisites do not need to be installed; their checks are in this skill's `SKILL.md`. +- `core/FOUNDATION.md`: the six foundation capabilities. +- `nhcx-build/capabilities.json` and `nhcx-build/0-capability.md`, if another NHCX skill already ran on this app. +- The target: the codebase (integrate), or the folder where the standalone app lives or will live. +- The pins and payer fixtures each check names, in `nhcx-package/`. If it is not beside `nhcx-build/`, fetch it now (`scripts/fetch-package.sh`); `references/material.md` names each pin's file. + +## The verdicts + +| Verdict | Means | What happens next | +| --- | --- | --- | +| `present` | Located, and its check was run and observed passing | Reuse. Stage 7 builds nothing for it. Stage 8 still runs its Validate rows; stage 9 still tests it. | +| `partial` | Located, but its check fails; or it covers some legs or branches and not others; or it was located and could not be run | Extend. Stage 7 builds the difference, in the existing code. | +| `absent` | Searched for as the skill says and not found | Build. Stage 7 builds it. | +| `unknown` | Could not be searched: no code is reachable | Planned as absent; stage 0 runs again when the code is reachable. | +| `not applicable` | The mode or the scope excludes it: 7.13 in integrate mode, a leg the user marked out | Nothing. | + +For a prerequisite, a verdict of `absent` or `unknown` is a stop: see step 5. + +Present is a claim about behaviour. Code that looks right is `partial` until its check has run. + +## Do + +### 1. Find the target + +Integrate: the codebase root, its language and framework, enough to search and to run code offline (stage 3 does the full survey). Standalone: the app folder. If it is empty and no other NHCX skill has built anything there, every capability is `absent` and this stage is short. Write which in one line. + +If `nhcx-build/capabilities.json` exists, read it. A verdict another skill recorded is a lead, not a result. If the code changed since its date (the version control log says), run its check again; otherwise carry it forward with its evidence and date. + +### 2. Locate + +For each capability in the three lists (own, foundation, prerequisites), search for the markers: NHCX paths such as `v1/preauth/submit`, resource names such as `CoverageEligibilityRequest`, workflow ids as strings, table and column names. `SKILL.md` lists them for its own capabilities; for a prerequisite, the marker is what its check names. Record every hit as `path:line`. A hit in a comment, a dead branch or a test fixture is not the capability; say so. + +Look also for the same job done another way: a pre-auth sent to a TPA portal, an eligibility check recorded from a phone call, a payment keyed in from a bank statement. That is a host capability that stages 3 and 4 may link to. The NHCX capability is still `absent`. + +### 3. Check + +For every capability located, run the check `SKILL.md` names, offline: + +- a builder: feed it the pin's own data and compare its output with the pin (canonical JSON, `created` excluded, and only the exclusions the module names); +- a reader: feed it the payer fixture and read the state it settles; +- a sender: call it with the 7.1 stub, or a stub of the app's own client, and read what it posted; +- the door: call the handler with an envelope; +- a screen: render it on a seeded state and read the text. + +Use the app's own test runner where it can host the check, else a one-off script under `nhcx-build/0-capability/`. Nothing leaves the machine. + +Where the existing code cannot be called without the network or a running service, record `partial` with `not run: `. Never `present`. + +### 4. Decide + +One verdict per capability, with where (the paths), how (the command), observed (the output, or the first lines of the diff), and the action: reuse, extend, build or wait. For `partial`, name the difference: which pin fails and at which element, which branch is missing (a PMJAY query answer on 19 but none on 131), which column is missing. + +### 5. When a prerequisite is missing + +A prerequisite is a capability another skill owns that this skill's legs cannot run without. `SKILL.md` lists them with their checks. If one is `absent` or `unknown`: + +1. Stop and tell the user which capability is missing, which skill owns it, and what this skill cannot do without it. +2. Offer the two ways on: run the owning skill first (installing it if it is not beside this one; it is the default); or continue with this skill's offline work only (builders, readers and tests against seeded rows), with the live legs marked `later` in stage 1 and the dependency written in `NOTES.md`. +3. Never build another skill's capability inside this one. It would be built without that skill's checks. + +A `partial` prerequisite does not stop the skill. Its gap goes into stage 2's risk table. + +## Write + +- `nhcx-build/capabilities.json` from `templates/capabilities.json`: one entry per capability, keyed by id, with `skill`, `module`, `verdict`, `located`, `how`, `observed`, `action`, `checked_by` and `date`. Update the entries this skill checked; leave the others. +- `nhcx-build/0-capability.md` from `templates/0-capability.md`: a section headed with this skill's name, holding the three tables (own, foundation, prerequisites) and the summary line. +- The scratch checks under `nhcx-build/0-capability/`, kept: stage 8 runs them again. +- This skill's block in `nhcx-build/STATE.md` (create the file from `templates/STATE.md` if it does not exist), with stage 0's row closed and its evidence. + +## Gate + +- [ ] Every capability in this skill's list, every foundation capability, and every prerequisite has a verdict. +- [ ] Every `present` names the command run and its observed output. None rests on reading alone. +- [ ] Every `partial` names the difference. +- [ ] Every `absent` names what was searched for, so a reader can repeat the search. +- [ ] A missing prerequisite was put to the user, and the answer is recorded. +- [ ] `capabilities.json` parses and holds this skill's entries. + +## Common mistakes + +- Marking a capability present because its endpoint name appears in the code. The pin decides. +- Rebuilding a working NHCX transport or callback door because this skill did not write it. An app that already seals, sends and receives NHCX messages keeps its own; the verdict says reuse. +- Proposing nhcx-adapter for an app that lacks a transport. The transport is then `own`; the adapter is used only when the user asks for it. +- Treating a legacy TPA workflow as the NHCX capability. It is a host capability; the NHCX one is absent. +- Checking against the live sandbox. Stage 0 is offline; the live rungs are stage 10's, and the user's. +- Carrying another skill's verdict forward after the code changed. diff --git a/plugins/nhcx/skills/nhcx-insurance/stages/1-idea.md b/plugins/nhcx/skills/nhcx-insurance/stages/1-idea.md new file mode 100644 index 000000000..b9f391316 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-insurance/stages/1-idea.md @@ -0,0 +1,80 @@ +# Stage 1: the idea + +Purpose: agree with the user what is being built before anything is designed. One page, shared by the seven skills. Wrong answers here cost the most later, so this is the one stage that always ends with a question to the user when it is first written. + +The first skill to reach this stage writes `1-idea.md` whole: the mode, the payers, the constraints, and a scope row for every step of the flow, each naming the skill that owns it. A later skill reads the page, confirms that the mode and the payers still hold, and marks its own rows. It asks the user only when it would change a row or an answer. + +## Inputs + +- This skill's section of `nhcx-build/0-capability.md`: what the app already does. A leg found present is still in scope: it is validated and tested, not rebuilt. Say so in the scope table's reason column. A prerequisite the user chose to wait for makes this skill's live legs `later`. +- `flow/FLOW.md`, whole. The build walks this path; the scope table below marks its steps in, later or out, and nothing else. `flow/flow.json` names the skills of each step in `skills`. +- What the user said. If they pasted a brief, quote it in the artefact. +- `references/flow-knowledge.md` sections 1, 3 and 6: the legs, the two payer kinds, the use-case catalogue. Read them so the scope table below uses the catalogue's codes. + +## Do + +Decide five things, in this order. A later skill confirms the first two and the fourth, and does the third for its own rows. + +### 1. Mode + +| Signal | Mode | +| --- | --- | +| A codebase, a database, a running system is named | `integrate` | +| "from scratch", "standalone", "a claims app", no existing system | `standalone` | +| Unclear | Ask. Do not guess; the two modes diverge at stage 3. | + +### 2. Payers + +Which participant codes the software will talk to, and which kind each is: + +| Payer | Participant code | Kind | Query mode | +| --- | --- | --- | --- | +| PMJAY (SHA Himachal Pradesh, sandbox) | `1518@hcx` | scheme | `resubmit` | +| A generic sandbox payer you can drive, for testing | from the participant registry | generic | `communication` | +| Any other insurer | from the registry | generic unless told otherwise | `communication` | + +Both kinds are in scope by default. A build that targets only one still keeps the payer adapter switch (module 7.11), because the second is one config line away. + +### 3. Scope of legs + +Copy the steps of `flow/flow.json` (F1 to F13 with their branches) into a scope table, with the skill that owns each (`skills`), and mark each `in`, `later` or `out`, with a reason; add the catalogue code from `flow-knowledge.md` section 6 beside each. The default scope for a first release is every hospital-side leg in `flow-knowledge.md` section 1. Cutting a leg is the user's call; propose it, do not decide it. Legs that are commonly `later`: predetermination, status enquiry (PMJAY refuses it), release of a shortfall (out of reach on the sandbox). + +A later skill changes only its own rows. + +### 4. Constraints + +Ask the codebase, not the user, where you can: + +- Language and framework (integrate: whatever the HMIS uses; standalone: Python standard library unless the user names another, because the module files' pseudo code maps onto it directly). +- The transport (`references/transport-knowledge.md` section 1): `existing` when stage 0 found the app already speaks NHCX; else `own`, built into the app from NHA's protocol; `adapter` (nhcx-adapter) only when the user has asked for it, their words quoted. Never propose the adapter. +- The inbound path. For `own`: a public HTTPS domain in India, registered as the participant's `endpoint_url` and reachable from the exchange. For `existing`: the app's own callback. For `adapter`: whether the app can receive the adapter's POST; if not, polling the adapter's ledger is the only inbound path. Write it down now. +- What onboarding needs from the user: the ABDM sandbox client id and secret (Milestone 1), the facility's HFR id, and a participant record carrying the build's certificate and callback address. +- Document storage: blob, filesystem, object store. +- Whether a background worker exists. Without one, polls happen on the request path. +- Anything the user forbids: new dependencies, schema changes to existing tables, a build step. + +### 5. Definition of done + +Write the compliance points from `core/LADDER.md` as they apply to this build, and the highest rung of the test pyramid the user wants climbed before handover (`references/testing-knowledge.md` section 1). The offline rung is never optional. + +## Write + +`nhcx-build/1-idea.md` from `templates/1-idea.md`. Keep the headings. Under two pages. A later skill edits only its scope rows and adds a line under "Agreed". + +## Gate + +- [ ] Mode is `integrate` or `standalone`, and the reason is one sentence. +- [ ] Every payer has a participant code and a query mode. +- [ ] The scope table has every step of the flow and every catalogue row, each with its skill, marked in, later or out. +- [ ] Constraints name the language, the transport (existing, own, or nhcx-adapter because the user asked for it), the inbound path and the document store. +- [ ] Definition of done names the target rung. +- [ ] The user has read the page and agreed, or a written brief stands in for the user. A later skill that changed nothing records that it confirmed the page. + +Record the gate in the Shared block of `nhcx-build/STATE.md`. + +## Common mistakes + +- Choosing `standalone` because the HMIS is unfamiliar. Unfamiliar is what stage 3 is for. +- Leaving PMJAY out because the user only named an insurer. PMJAY is the payer that refuses most; a build that handles it handles the rest. +- Dropping a leg from scope because stage 0 found it present. It stays in: present capabilities are validated and tested. +- Writing design here. Tables, screens and modules belong to stages 4 to 6. diff --git a/plugins/nhcx/skills/nhcx-insurance/stages/10-run-tests.md b/plugins/nhcx/skills/nhcx-insurance/stages/10-run-tests.md new file mode 100644 index 000000000..e7e5d8d32 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-insurance/stages/10-run-tests.md @@ -0,0 +1,59 @@ +# Stage 10: run the tests + +Purpose: climb the pyramid as far as the user asked in stage 1, for this skill's rows, and record every rung honestly. Rung 1 you run yourself. Rungs 2 to 4 need services or live payers, and only the user starts those. + +## Inputs + +- `nhcx-build/1-idea.md` (the target rung), `nhcx-build/9-tests.md` (the run command, this skill's rows) +- This skill's `SKILL.md`: its stage 10 row (which matrix rows each rung walks) +- `references/testing-knowledge.md` sections 1, 5 and 6 +- `references/errors-and-debugging.md` sections 4 to 8 (reading the ledger, sandbox pace) + +## The rungs + +| Rung | What | Who starts it | Record | +| --- | --- | --- | --- | +| 1 Offline | The suite from stage 9, against the pins and fixtures, no network | you | the full output | +| 2 Validator | The HL7 FHIR validator on every bundle this skill builds, run as `references/fhir-knowledge.md` section 11 says | you, if Java and the validator are installed | one table: bundle, errors, warnings | +| 3 Generic payer | The transport on the sandbox (the app's own, or nhcx-adapter when the user chose it) and a generic sandbox payer whose desk you can drive; this skill's legs, every query as a CommunicationRequest, payment from its desk | the user | the ledger thread per leg, the state address after each | +| 4 PMJAY sandbox | SHA Himachal Pradesh, `1518@hcx`; sweep live pre-auths first; one request at a time per case, 30 seconds between; decisions on the payer service desk | the user | the ledger, the archive folder, every refusal verbatim | + +## Do + +### Rung 1 + +Run the command from `nhcx-build/9-tests.md`: the whole suite, not only this skill's tests, because a skill that extended a shared module can break another skill's test. Save the whole output to `nhcx-build/10-test-run/-rung1.log`. In `integrate` mode also run the HMIS's own suite and save it. A failure goes back to stage 7 (the module) or stage 9 (the test); record the fix and the re-run. Do not edit a test to make it pass unless the test was wrong, and say so. + +### Rung 2 + +If the validator runs, validate every bundle this skill's tests built (write them to a folder from the tests). Warnings are advice; the sandbox accepted every pin as it stands. Errors are findings. If it does not run, write `not run` and why. + +### Rungs 3 and 4 + +Prepare, do not run: + +1. The commands the user runs: the HMIS with its public callback (`own` or `existing`), nhcx-adapter with its filled config only when the user chose it, and the payer (rung 3). For `own`, the sandbox's dummy payer proves the loop first (`references/transport-knowledge.md` section 3.11). Write them into this skill's section of `nhcx-build/10-test-run.md` under "Runbook". +2. The driver: a script or a spec that walks this skill's matrix rows through the JSON state address, waiting on the case's own state and never on a fixed sleep, logging every verdict the payer gives. The earlier legs a row needs (an eligible case, an approved pre-auth) are reached by the earlier skills' drivers or through the app's own screens. +3. The sweep for rung 4: cancel or let expire every live pre-auth for the beneficiaries the tests use (PAYR-1238 otherwise). +4. Then stop and ask the user to start the services. When they have, run the driver, save its log, and package the run's bundles by correlation id from the per-case archive (or the adapter's ledger, when it is the transport). + +While a live run is going: one request at a time per case; wait about 30 seconds after a decision; on "Active instance found" wait and resend up to three times; on a refusal read the ledger thread before touching the code. + +## Write + +This skill's section of `nhcx-build/10-test-run.md` from `templates/10-test-run.md`: per rung, `passed`, `failed`, `not run` with the reason, the log path, and the findings (each a line: what, where, the PAYR or rule, the fix or the open question). The raw logs under `nhcx-build/10-test-run/`, named for the skill. + +## Gate + +- [ ] This skill's rung 1 log exists and shows every test in the suite passing, or the failures are listed as findings with a stage to return to. +- [ ] In `integrate` mode the HMIS's own suite log exists and passes. +- [ ] Rung 2 has a table or `not run` with a reason. +- [ ] Rungs 3 and 4 have a runbook and a driver for this skill's rows, and either a log or `not run: user has not started the services`. +- [ ] No rung is marked passed without a log. + +## Common mistakes + +- Starting a service yourself: the app's public callback, or nhcx-adapter. Only the user does. +- Running only this skill's tests at rung 1. A shared module may have broken another skill's. +- Sleeping a fixed time in a driver. Wait on the state address. +- Reading a refusal as a code bug before reading the ledger thread. Half of them are scheme rules (flow-knowledge section 5). diff --git a/plugins/nhcx/skills/nhcx-insurance/stages/11-build-report.md b/plugins/nhcx/skills/nhcx-insurance/stages/11-build-report.md new file mode 100644 index 000000000..4ea8a0806 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-insurance/stages/11-build-report.md @@ -0,0 +1,64 @@ +# Stage 11: the report + +Purpose: one document a stranger can pick up to know what was built, what was found already there, what was proven, what was not, and what to do next. Written from the artefacts in `nhcx-build/`, not from memory. Its value is its honesty. + +`11-report.md` has a summary across the skills at the top and one section per skill below it. This skill writes its section and updates its row of the summary. + +## Inputs + +- Everything in `nhcx-build/`, `STATE.md` first, `NOTES.md` last +- This skill's sections of `0-capability.md`, `8-validation.md` and `10-test-run.md` + +## Do + +### 1. Read STATE.md + +Every gate row in this skill's block, and the foundation rows it built, with their evidence. A gate without evidence is reported as open, whatever you remember. + +### 2. Write this skill's section + +From `templates/11-report.md`, in this order: + +| Section | Holds | +| --- | --- | +| Capabilities | Every capability in this skill's section of `0-capability.md`: its verdict at stage 0, what was done (reused, extended, built), and its evidence after stage 8 | +| What was built | Each module part this skill built or extended, with its files and its record (`7-modules/7.N.md`) | +| Compliance | The seven points from `core/LADDER.md` for this skill's legs, each with the evidence path (the pin comparisons, the door tests, the screen tests, the rung logs) | +| The test pyramid | Per rung: passed, failed, not run, the log | +| Findings | Every failure from stages 8 and 10 with its resolution or its open state | +| Gaps | This skill's entries in `NOTES.md` folded in: what the skills did not say, what the docs did not say, what the sandbox did that no document states | +| Exceptions | Every accepted exception from stage 8 and the user's agreement | +| Runbook | How to start it, how to run the suite, how to run rungs 3 and 4, what to sweep first, where the archive and the ledger are | +| Next | The `later` legs from stage 1, the open gates, the rungs not climbed, and the skill to run next in the order `core/LADDER.md` gives | + +Then update this skill's row in the summary table: stages closed, rung reached, what it reused, extended and built, what is open. Mode, payers and "today a user can" are for the whole build; bring them up to date. + +### 3. Check the report against the rules + +- Every claim of "passes" has a log or a record path beside it. +- Every rung not run says so. +- Every capability reported as reused has its stage 8 evidence, not only stage 0's. +- No em dashes, short sentences, tables for facts. +- A stranger with this report and the target project could resume at the first open gate. + +## Write + +This skill's section of `nhcx-build/11-report.md`, and its summary row. Update `STATE.md` with the final gate. + +## Gate + +- [ ] Every section in the template is present in this skill's section. +- [ ] Every capability in this skill's section of `0-capability.md` appears under Capabilities. +- [ ] Every module part this skill touched appears in "What was built" or, if reused, under Capabilities. +- [ ] Every compliance point names evidence. +- [ ] The pyramid table matches this skill's section of `10-test-run.md`. +- [ ] This skill's entries in `NOTES.md` are folded into "Gaps" in full. +- [ ] The runbook has the start commands, the test command and the sweep. +- [ ] The summary table has this skill's row. + +## Common mistakes + +- Reporting the rung the user asked for as reached because the offline rung passed. +- Reporting a reused capability as working on the strength of stage 0 alone. +- Dropping a finding that was fixed. Fixed findings are the most useful part of the report for the next build. +- Writing the report before stage 10's logs exist. diff --git a/plugins/nhcx/skills/nhcx-insurance/stages/2-planning.md b/plugins/nhcx/skills/nhcx-insurance/stages/2-planning.md new file mode 100644 index 000000000..06c405cdc --- /dev/null +++ b/plugins/nhcx/skills/nhcx-insurance/stages/2-planning.md @@ -0,0 +1,67 @@ +# Stage 2: planning + +Purpose: turn the idea and the capability check into this skill's schedule of gates, and add its block to the ledger every later stage writes to. This is bookkeeping, and it is short. + +## Inputs + +- `nhcx-build/1-idea.md` +- This skill's section of `nhcx-build/0-capability.md`: the verdict of every capability it owns or stands on +- `core/LADDER.md`, "The ladder"; this skill's `SKILL.md`, "The ladder, for this skill" +- `references/testing-knowledge.md` section 1 (the pyramid) and section 3 (the matrix), so the acceptance tests below are the matrix's rows and not invented ones + +## Do + +### 1. Size each stage + +For every stage 3 to 11, write one row for this skill: what it produces for this build, how big it is (small, medium, large), and what proves it done. "What proves it done" is the stage's gate, restated for this skill. + +For stage 7, list the modules this skill's `SKILL.md` names and the foundation modules, each with its verdict from stage 0 turned into an action: + +| Verdict | Action in stage 7 | +| --- | --- | +| `present` | reuse: nothing built; validated in stage 8, tested in stage 9 | +| `partial` | extend: the difference, in the existing code | +| `absent`, `unknown` | build | +| `not applicable` | nothing | + +Module 7.13 depends on the mode: + +| Module | integrate | standalone | +| --- | --- | --- | +| 7.1 to 7.12 | yes | yes | +| 7.13 standalone shell | no | yes | + +Module 7.12 (screens) is smaller in `integrate` mode when the HMIS already has patients, admissions and documents; the plan says which existing screens gain a panel and which are new. + +### 2. Order and dependencies + +The ladder is sequential by stage. Inside stage 7, foundation modules come first, then this skill's modules in the order of `stages/7-write-code/README.md`; the plan may not reorder them, because each module's validation assumes the ones before it exist. + +### 3. Risks + +Copy into a risk table the rules from `references/flow-knowledge.md` section 5 that touch this skill's legs; its `SKILL.md` names them in its stage 2 row. Each rule is a way the build fails live even when the offline tests pass. When this skill builds or extends a foundation module, add the foundation's rules too: acknowledge or lose the thread; one message is taken once (dedupe on `x-hcx-api_call_id`). Add every `partial` prerequisite from stage 0, and the build's own risks: a missing HPIN on the practitioner table, no inbound route to the HMIS, a plan master too large for the database column, a callback behind auth middleware. + +### 4. What the user must do + +List every point where the ladder stops for the user: agreeing stage 1, running an owning skill first when a prerequisite is missing, supplying participant credentials (the ABDM client id and secret), registering the participant's certificate and callback address, starting the services for stage 10 rungs 3 and 4 (the app's public callback, or nhcx-adapter when the user chose it), sweeping live pre-auths before a PMJAY run. + +## Write + +- This skill's section of `nhcx-build/2-planning.md`, from `templates/2-planning.md`. +- This skill's block in `nhcx-build/STATE.md` (created at stage 0 from `templates/STATE.md`), with a row per stage and a row per module part, each module row carrying its action. +- `nhcx-build/NOTES.md`, empty but for its heading, if it does not exist. + +## Gate + +- [ ] Every stage 3 to 11 has a row with a size and a proof, for this skill. +- [ ] Every module this skill touches, and every foundation module, has its verdict and its action; 7.13 is marked by mode. +- [ ] The risk table holds every rule this skill's `SKILL.md` names for stage 2, and the foundation's rules when this skill builds or extends a foundation module. +- [ ] The user-action list names the credentials and the service starts. +- [ ] STATE.md has this skill's block with a row per stage and per module part. + +## Common mistakes + +- Estimating in days. Estimate in size; the user turns size into time. +- Planning to skip stage 8 or 9 "for the first pass". They are what makes the report true. +- Planning to rebuild a capability stage 0 found present. +- Reordering modules so screens come first. Screens derive from messages; without readers there is nothing to derive from. diff --git a/plugins/nhcx/skills/nhcx-insurance/stages/3-discovery.md b/plugins/nhcx/skills/nhcx-insurance/stages/3-discovery.md new file mode 100644 index 000000000..9feb26eca --- /dev/null +++ b/plugins/nhcx/skills/nhcx-insurance/stages/3-discovery.md @@ -0,0 +1,97 @@ +# Stage 3: discovery + +Purpose: find the surface you will build on. In `integrate` mode that is the HMIS; in `standalone` mode it is the runtime, the storage and the deployment target the user has chosen. Every answer names the file, table or endpoint that proves it. An answer without proof is a gap. + +`3-discovery.md` is shared by the seven skills: one row per concern, each naming the skill that answered it. This skill answers the rows its `SKILL.md` lists under "Host facts", and the framework and runtime rows if no skill has. A row an earlier skill answered with proof is reused; check it again only if the code changed since. + +Stage 0 looked for NHCX capabilities. This stage looks at the host: where patients, admissions, doctors, documents and bills live. + +## Inputs + +- `nhcx-build/1-idea.md`, `nhcx-build/2-planning.md`, this skill's section of `nhcx-build/0-capability.md` +- This skill's `SKILL.md`, "Host facts" +- The target codebase (integrate) or the chosen runtime (standalone) +- `stages/7-write-code/7.2-storage.md` (the claim tables) and `stages/7-write-code/7.13-standalone-shell.md` (patient, encounter, practitioner, document), as the shape to compare against + +## Do + +Answer in writing every question below that this skill's host facts name, plus the framework and runtime questions when they are not yet answered. Reading only; change nothing. + +### Framework and runtime + +| Question | Why it matters | +| --- | --- | +| Language, web framework, ORM, database engine, migration tool | Where a new table goes and how it is created | +| How configuration is read (env, file, database) | Where the transport's settings live: the participant code, and the client id and secret and the private key (`own`), or the adapter URL and key (`adapter`) | +| How the app exposes an HTTP endpoint an outside process can POST to; which auth middleware must be exempted | The callback door, module 7.3 | +| Background worker or scheduler, or none | Whether polls run on the request path or in a worker | +| How the app serves a page and what the screen conventions are | Module 7.12 must match them | +| How tests are run and where they live | Stage 9 must match them | + +### Patients + +| Question | Why it matters | +| --- | --- | +| The patient table, its primary key, the unique identifier (MRN) | `claim.patient_id` | +| Where name, gender, date of birth, phone, ABHA number live | The Patient resource in every bundle | +| Where a scheme member id (PMJAY id) and a policy code can be stored, per patient or per visit | The Coverage resource; the policy search result | + +### Admissions and encounters + +| Question | Why it matters | +| --- | --- | +| The inpatient encounter table: admission time, discharge time, ward or bed, admitting doctor, status | `billablePeriod`, `ONS/ADDD`, the care team | +| How discharge is recorded, and whether it can carry a mode (normal, LAMA, DAMA, death) and a stage (before, during, after surgery) | `DIS` and `DSDE` on the claim; the LM100 collapse | +| Diagnoses: SNOMED, ICD-10 or free text | The payer needs ICD-10 with a display | +| Procedures or surgeries, and whether a surgery time is recorded | `ONS/PSP` | + +### Billing + +| Question | Why it matters | +| --- | --- | +| Billing lines: code, quantity, unit price, net; which charge master | Lines are quoted from the payer's plan, not the HMIS master, but the two must be reconcilable | +| Whether a line can be tagged with a payer package code and a category | `claim_line` | +| Invoices and receipts: where a settlement amount and a UTR go | Payment notices, module 7.10 | + +### Documents + +| Question | Why it matters | +| --- | --- | +| Where PDFs and images live (blob column, filesystem, object store) | `valueAttachment` needs the bytes and the content type | +| Whether a file can be tagged with a payer document code and a stage (pre-auth or claim) | The plan's requirement codes; never `ODN` for a file that was asked for by name | +| Accepted content types | The scheme takes pdf, jpg, jpeg, png only (PAYR-1008) | + +### Doctors + +| Question | Why it matters | +| --- | --- | +| The practitioner table; an HPR id (HPIN); a licence number; a qualification string | PMJAY refuses a pre-auth without an HPIN typed identifier (PAYR-1083) | + +### Facility + +| Question | Why it matters | +| --- | --- | +| The facility's HFR id, name, phone; its NHCX participant code | The provider Organization; the sender code | + +### Standalone mode + +The same questions, answered for the runtime the user chose. Where the answer is "nothing exists yet", write what module 7.13 will create: `patient`, `encounter`, `practitioner`, `document`, `settings`. A standalone app still has to hold every fact the questions ask for; it simply has to capture it itself. + +## Write + +`nhcx-build/3-discovery.md` from `templates/3-discovery.md`: one table, concern by concern, columns `Concern | Where it lives (proof) | Gap | Answered by`. A gap is what stage 4 fills. Add rows; do not rewrite another skill's rows. + +## Gate + +- [ ] Every host fact this skill's `SKILL.md` names has a row, and so does every framework and runtime question. +- [ ] Every row that is not a gap names a file path, a table, or an endpoint. +- [ ] When this skill builds or extends the callback door, the callback route is answered: which URL, which middleware to exempt, or "no inbound route, poll only". +- [ ] When this skill's bundles carry a Practitioner, the HPIN question is answered; if the practitioner table has no HPR id, the gap says so. +- [ ] When this skill attaches documents, the document store is answered with content-type handling. + +## Common mistakes + +- Answering from the framework's documentation instead of the codebase. The proof column is the codebase. +- Skipping the discharge-mode question. A death claim without `DTM` is refused (PAYR-1096); the HMIS must be able to say the patient died and when. +- Treating "no background worker" as a blocker. Without one, polls run on the request path; it is a design input, not a stop. +- Answering every concern for every skill. Answer the ones this skill needs; the next skill adds its own. diff --git a/plugins/nhcx/skills/nhcx-insurance/stages/4-flow-and-data-mapping.md b/plugins/nhcx/skills/nhcx-insurance/stages/4-flow-and-data-mapping.md new file mode 100644 index 000000000..bf51c7991 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-insurance/stages/4-flow-and-data-mapping.md @@ -0,0 +1,92 @@ +# Stage 4: flow and data mapping + +Purpose: decide where every fact the exchange needs comes from and where every fact the exchange returns goes, leg by leg. This is the design stage with the most rows; get it right and stages 6 and 7 are transcription. + +Two parts of this stage belong to the episode, not to one skill: the flow table (section 1) and the home of every table (section 2), with the matching order (section 4). The first skill to run this stage writes them whole, so every later skill builds on one design; a later skill checks them and adds only what its gaps need. The field mapping (section 3) is this skill's own bundles only. + +## Inputs + +- `nhcx-build/1-idea.md` (scope), `nhcx-build/3-discovery.md` (the surface and its gaps), this skill's section of `nhcx-build/0-capability.md` (what exists already) +- This skill's `SKILL.md`: its steps, legs, bundles and tables +- `flow/FLOW.md` and `flow/flow.json`: the steps this build implements. They are copied, not redesigned. +- `references/flow-knowledge.md` sections 1, 2, 4 and 5 +- `references/transport-knowledge.md` section 2 (what a send returns, what arrives at the door) +- `references/fhir-knowledge.md` sections 3 to 10 (what each bundle needs); `fhir/FHIR.md` for the exact elements, as the builders' data dictionaries name them +- `stages/7-write-code/7.2-storage.md`: the claim tables and the columns each must hold + +## Do + +### 1. The flow, for this build + +The first skill copies every step of `flow/flow.json` into the flow table, in order, with its id and its skills, and adds two columns for this build: the HMIS event it hangs off (admission, discharge, a desk action) and the mark from stage 1 (`in`, `later`, `out`). The steps, their order, their tabs, their guards and their action labels are the flow's; this build adds where each fact comes from, nothing else. Then note the payer branches as the flow has them (F9b, F11, F12: `19`/`131`/`161` resubmits against a Communication reply; `17` against an echoed id). The stage and sub-stage vocabulary is copied as is; do not rename it. + +Write the step ids into `mapping.json` under `flow.steps` and the eight tabs, in order and with their labels, under `flow.tabs`. + +A later skill checks its own steps' rows and fills their HMIS event where the first skill left it open. + +### 2. The episode tables + +The first skill gives every table below a home, not only its own. The home is one decision for the episode (sidecar tables, or columns on the HMIS's tables), and a skill that chose differently later would split the design. It writes the columns each table must hold, and the legs' columns under `legs`. Later skills read the homes and add only the columns their gaps need. + +For each table below, decide one of three homes and write it down: + +| Home | When | +| --- | --- | +| A new sidecar table keyed on the HMIS's own ids | Default. Keeps the HMIS schema untouched and the integration removable. | +| Columns added to an existing HMIS table | Only for a scalar the HMIS already half-holds (a member id on the visit, an HPIN on the doctor) | +| An existing table used as is (`existing`) | Only when it already holds every column named below. This is the home of a capability stage 0 found present: record its real name and its columns, and a gap for each column it lacks | + +| Table | Why it exists | Must hold | +| --- | --- | --- | +| `claim` | The episode: beneficiary, policy, payer, eligibility verdict, link to the admission, pre-auth draft, stage and sub-stage | claim number, member id, policy code, payer participant code, patient and encounter keys, `txn_id`, `correlation_id`, `stage`, `sub_stage` | +| `claim_plan`, `claim_plan_benefit`, `claim_plan_form` | The payer's package master, flattened; one per facility and policy, copied onto later episodes | packages with rate, kind, conditions, extras (tiers, implants), document requirements; questionnaires by url | +| `claim_auth`, `claim_auth_item`, `claim_auth_requirement` | The auth-requirements ruling on the quoted set | per line: authorised, excluded; per requirement: kind (document or form), code, url, stage | +| `claim_line` | What is quoted: procedures, implants, ward tiers with a parent procedure | code, kind, quantity, unit price, amount, parent code | +| `claim_form_answer` | Answers to the plan's questionnaires | url, linkId, answer, stage | +| `claim_preauth` | The pre-auth leg, one row rewritten each round (12, 19, 13, 131) | status, `txn_id`, `correlation_id`, `thread_correlation_id`, `api_call_id`, `preauth_ref`, `submission_kind`, `workflow_id`, request and response json, cancel fields | +| `claim_submission` | The claim leg plus the discharge | discharge mode, stage, dates; the same exchange columns as the pre-auth | +| `claim_query` | Every CommunicationRequest or Communication from the payer, classified | `correlation_id` (unique), request id, kind, reason code, status, reply fields | +| `claim_payment`, `claim_payment_detail` | Payment notices, matched by claim number, deduped by correlation id | amount, UTR, payment status, ack fields | +| `claim_enquiry` | Status, reprocess and release Tasks, one row per ask | kind, `correlation_id`, answer | +| `claim_predetermination` | A quote, one row per ask | as a pre-auth, without state effects | +| `claim_document` | Attachments with the payer's code, category and stage | bytes or a pointer, content type, code, stage | +| `claim_diagnosis`, `claim_care_team`, `claim_item` | ICD-10 codes, doctors, non-package items | as named | + +The rule that never bends: every leg row holds `txn_id`, `correlation_id` and `api_call_id` from the transport's answer, and `thread_correlation_id` separately, because a send refused at the door must not lose the thread the payer last answered on. + +### 3. Field mapping, per bundle + +For each bundle this skill sends (its `SKILL.md` lists them; `fhir-knowledge.md` sections 3, 4, 5, 7, 9, 10), one table: `FHIR element | Source (table.column or constant or payer answer) | Transform | Gap`. Do not fill values; name sources. The elements that are always mapped from a payer answer and never from the HMIS: package codes and rates (the plan), document codes and questionnaire urls (the plan or the ruling), `preAuthRef` (the ClaimResponse), the payer's own case number. + +For each bundle this skill reads (sections 6, 8, 9, 10 and the coverage answer in section 3), one table: `FHIR element | Destination | Rule`. The status rule for a ClaimResponse is `verdict_status`, copied verbatim; never read `outcome` alone. + +Where stage 0 found a builder or reader present, map what it does today, and name each element where it differs from the pin as a gap. + +### 4. Inbound matching + +Written once, by the first skill. Write the matching order as a numbered list: `x-hcx-correlation_id` against every leg table; then the claim number inside the bundle; then unmatched, archived, 2xx returned. Write the dedupe key: `x-hcx-api_call_id`. Write the archive path: `//NNN--.json` plus `transactions.txt`. A later skill adds its leg tables to the correlation order. + +## Write + +- `nhcx-build/4-flow-data-mapping.md` from `templates/4-flow-data-mapping.md`. The first skill writes the flow table, the table homes and the matching order at the top; each skill writes a section headed with its name holding its field mappings. +- `nhcx-build/mapping.json` in the shape of `templates/mapping.json`. The first skill writes `flow`, `episode`, `tables`, `legs` and `inbound` whole; every skill adds its bundles under `bundles`, each entry with `"skill"`. Stage 6 reads it. + +## Gate + +- [ ] The flow table has every step of `flow/flow.json`, in its order, with its id, its skills and an in/later/out mark; `mapping.json` `flow.steps` lists every id and `flow.tabs` the eight tabs verbatim. +- [ ] Every table above has a home in `mapping.json` under `tables`. +- [ ] Every leg table's columns in `mapping.json` include `txn_id`, `correlation_id`, `api_call_id` and `thread_correlation_id`. +- [ ] `mapping.json` `episode.columns` includes `stage` and `sub_stage`. +- [ ] Every bundle this skill sends has a source table; every element with no source is listed as a gap, not omitted. +- [ ] Where this skill's bundles carry a Practitioner, the HPIN element's source is named (or its gap is). +- [ ] Every capability stage 0 found present is mapped to what exists, with its differences from the pin as gaps. +- [ ] The matching order, the dedupe key and the archive path are written. + +## Common mistakes + +- Redesigning the flow: merging tabs, adding a "status" step, moving the discharge out of the claim tab. The flow is the reference flow; copy it. +- Giving homes only to this skill's tables when it is the first to run the stage. The next skill would choose differently. +- Mapping package rates to the HMIS charge master. Prices come from the plan; the master is for reconciliation. +- One `correlation_id` column on the episode instead of one per leg. Each leg is its own thread. +- Forgetting `thread_correlation_id`. It is the difference between a recoverable door refusal and a dead case. +- Mapping `Patient` demographics on the coverage request. Only the member id goes out; the payer returns the rest. diff --git a/plugins/nhcx/skills/nhcx-insurance/stages/5-screen-plan.md b/plugins/nhcx/skills/nhcx-insurance/stages/5-screen-plan.md new file mode 100644 index 000000000..9ec0d8bc2 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-insurance/stages/5-screen-plan.md @@ -0,0 +1,74 @@ +# Stage 5: screen plan + +Purpose: decide the screens, and for every value on every screen, the received message it is derived from. The two honesty rules are the whole point of this stage, and a reviewer tests them before anything else. + +The case screen is the episode's (`foundation.screens`): its eight tabs, the status line and actions, the JSON state address and the cases list. The first skill to run this stage lays them out whole, every tab present with its opening condition. Each skill then plans the values and actions of its own tabs and screens, which its `SKILL.md` lists. + +## Inputs + +- `nhcx-build/1-idea.md`, `nhcx-build/3-discovery.md` (screen conventions), `nhcx-build/4-flow-data-mapping.md` +- This skill's `SKILL.md`: its tabs, its screens, its next actions +- `flow/FLOW.md` ("The shape", "The status line and the actions", every step's Screen line) and `flow/flow.json`: the screens are put on these steps, not invented. +- `references/flow-knowledge.md` section 4 (stage, sub-stage, next actions) +- `ui/UI-GUIDE.md`: the screens, a layout per screen, where every value comes from, the state words. Read it whole before planning. +- `nhcx-package/docs/03-Building a Provider/09-UI Guide.md` (the published source of the guide) + +## The two rules + +1. No screen shows a decision the exchange has not sent. Every state on every screen is derived from a stored message. A case with a request sent and no answer back reads as waiting, never approved, never rejected. That case exists only because module 7.3 kept a record of what was sent, so the screen must be able to render a leg with a request and no response. +2. Nothing the exchange already knows is typed. Payer names, policies, balances, package rates, the payer's own wording, `preAuthRef`, the approved amount, the UTR are rendered from the message that carried them. A package rate is never an editable field. + +## Do + +### 1. The screen list + +The case screen carries the eight tabs of `flow.json` `tabs`, in that order, with those labels, opening under those conditions. The status line and the action list above the tabs use the labels of `flow.json` `next_actions` verbatim. Then, minimum, once every skill has run: + +| Screen | Who | Shows | Derived from | Planned by | +| --- | --- | --- | --- | --- | +| Cases list | billing clerk | every episode, its stage and sub-stage, what it waits for | `claim.stage`, `sub_stage`, `next_actions` | the first skill | +| Case | everyone | the timeline of legs, the payer's answer verbatim, the actions open now | every leg row and its archived messages | the first skill; each skill its tabs | +| Inbox | desk | payer messages routed by kind: query, notification, note | `claim_query` | `nhcx-communication` | +| Payments | accounts | notices, deductions, UTR, reconciliation | `claim_payment`, `claim_payment_detail` | `nhcx-payment` | +| Find and cover | registration clerk | policy search, eligibility verdict, register or link | the policy search answer and the `on_check` bundle | `nhcx-coverage` | +| Plan | doctor | specialty, package, add-ons, tiers, the documents and forms the plan wants | `claim_plan_*`, `claim_auth_*` | `nhcx-insurance`, with the ruling from `nhcx-preauth` | + +`integrate` mode adds a panel to the HMIS's own admission screen linking the admission to its episode. `standalone` mode adds the capture screens module 7.13 describes (patient, admission, discharge, documents, settings). + +Where stage 0 found a screen present, plan what it shows today against the rules, and list every value that breaks one as a gap. + +### 2. Per screen, per value + +For every value on this skill's screens, one row: `Value | Message and element | Empty state`. The empty state is what the screen shows before the message arrives (for a decision: "waiting"; for a rate: nothing, the field does not exist yet). A value whose source is "the user types it" is allowed only for things the exchange cannot know: the discharge mode and dates, the desk's reply to a query, the documents, the questionnaire answers, the chosen lines. + +### 3. Actions + +Every action is one step of `flow.json` and carries its id in `step`. For every action this skill's screens offer, the leg it sends, the sub-stage that must hold for it to be offered, and the sub-stage it moves to. Take the offered-when rules from `next_actions` in flow-knowledge section 4: an unanswered query always leads; the reply box is offered only to a `resubmit` payer; after a rejection the pre-auth offers a fresh 12, not 121. + +### 4. Addresses and conventions + +Write the route for each screen in the HMIS's own style (from stage 3). The state of a case must also be readable as JSON at one address, because stage 10 drives the screens through it (for example `GET /claims//state`). Each skill adds its legs to what the address returns. + +## Write + +- `nhcx-build/5-screen-plan.md` from `templates/5-screen-plan.md`: the shell at the top (first skill), then a section per skill. +- `nhcx-build/screens.json` in the shape of `templates/screens.json`: the first skill writes `rules`, `tabs`, `state_address`, the cases list and the case screen; each skill adds its screens and actions. + +## Gate + +- [ ] `screens.json` `tabs` lists the eight tabs of `flow.json` in order with the same keys and labels. +- [ ] Every user-driven step this skill owns (its steps among F1 to F13, except F9a, F12 and F12b, which the payer starts) appears as an action with its `step` id, and every action's `label` is one of `flow.json` `next_actions` or the step's own button. +- [ ] `screens.json` holds the cases list, the case screen, and every screen this skill plans, each with a route (plus 7.13's in standalone mode). +- [ ] Every screen this skill plans has a `values` list and every value names a message element or is marked `typed` with a reason from the allowed list. +- [ ] Every decision-bearing value has an empty state of waiting. +- [ ] No `values` entry marks a rate, a payer name, a `preAuthRef` or a UTR as typed. +- [ ] Every action names its leg, its offered-when sub-stage and its resulting sub-stage. +- [ ] A JSON state address exists for a case. + +## Common mistakes + +- A status dropdown on the case. Status is derived; there is no dropdown. +- Showing `preAuthRef` from the pre-auth's own claim number. It comes from the ClaimResponse. +- Designing the desk's reply box for a `communication` payer on the leg. It belongs on the inbox item. +- Laying out only this skill's tab when it is the first to run the stage. The shell has all eight. +- Screens that need JavaScript. Forms post and the page re-renders; that is enough. diff --git a/plugins/nhcx/skills/nhcx-insurance/stages/6-code-plan.md b/plugins/nhcx/skills/nhcx-insurance/stages/6-code-plan.md new file mode 100644 index 000000000..2167000f1 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-insurance/stages/6-code-plan.md @@ -0,0 +1,68 @@ +# Stage 6: code plan + +Purpose: turn the mapping, the screen plan and the capability verdicts into a list of modules with files, dependencies, the pin each is held to, and what this skill does to each. Stage 7 builds this list in order; stage 8 validates it in order. + +The transport's shape, the configuration, the archive and the test placement (sections 2 to 5) are the episode's: the first skill to run this stage writes them, and later skills use them. + +## Inputs + +- `nhcx-build/3-discovery.md`, `nhcx-build/4-flow-data-mapping.md`, `mapping.json`, `nhcx-build/5-screen-plan.md`, `screens.json` +- This skill's section of `nhcx-build/0-capability.md` and `nhcx-build/2-planning.md` (the action per module) +- `stages/7-write-code/README.md` and every `7.N-*.md` this skill touches: the module ladder is fixed; the plan decides the files +- `references/fhir-knowledge.md` section 1: where the pins live +- `fhir/FHIR.md`: the builders and readers the modules 7.4 to 7.10 implement, so the plan names them + +## Do + +### 1. Place each module + +For each module this skill touches (its `SKILL.md` lists them) and each foundation module it builds or extends, write: + +| Field | Meaning | +| --- | --- | +| `skills` | A map from skill to action: `build`, `extend` or `reuse`. A module another skill already placed keeps its entry; add this skill and its action | +| `files` | The files it creates or changes, in the target's layout and naming (from stage 3). For a reused or extended module, the files that exist | +| `depends_on` | The modules that must exist first; the ladder's order is the floor, the plan may add more | +| `held_to` | The pin in `nhcx-package/fhir` (its file, from `references/material.md`), the payer fixture, or the rule (for modules with no bundle) | +| `copy_from` | What the module follows: its own Pseudo code section and the `fhir/FHIR.md` section it names | +| `tables` | The tables from `mapping.json` it reads and writes | +| `screens` | The screens from `screens.json` it serves (7.12 and 7.13 only) | + +`modules.json` holds one entry per module, in ladder order (7.1 to 7.13), whichever skill adds it. + +### 2. The transport's shape + +Decide once, and every module uses it: the transport kind from stage 1, and the functions of the contract in `references/transport-knowledge.md` section 2: `send`, the receiving end that hands the door a normalised envelope, `policies`, `participants`, `token`, and `thread` and `fetch_missed` where the kind has them. Name them here so 7.4 to 7.10 call the same thing. A stub of `send`, recording the path, recipient, workflow id, correlation id and bundle and returning `{"txn_id", "correlation_id", "api_call_id"}`, is what stage 9 injects. When stage 0 found an existing transport, name its functions and what wraps them. + +### 3. Configuration + +List every setting and where it lives (from stage 3): the transport kind, participant code, facility HFR id and name, cases directory, per-payer overrides for workflow ids, and the transport's own. For `own`: the ABDM client id and secret, the private key, the sessions, NHCX and registry addresses, and the NHCX signing key once onboarding gives it. For `adapter`: its URL, API key and callback secret. For `existing`: whatever its client reads. Name the environment variables or config keys in the target's convention. + +### 4. The archive + +The per-case archive path from stage 4, and which module writes it (7.3 for inbound, 7.1 for outbound). + +### 5. Test placement + +Where the offline test lives (from stage 3's "how tests are run"), and how the pin comparison is wired: canonical JSON, `created` excluded, one comparison per pin. + +## Write + +- `nhcx-build/6-code-plan.md` from `templates/6-code-plan.md`: the episode sections once, the modules table, and this skill's section. +- `nhcx-build/modules.json` in the shape of `templates/modules.json`. + +## Gate + +- [ ] `modules.json` has an entry, in ladder order, for every module this skill touches and every foundation module (7.13 in standalone mode). +- [ ] Every entry this skill touches has non-empty `files`, `depends_on` (7.1 may be empty), `held_to` and `copy_from`, and this skill in `skills` with its action. +- [ ] Every pin this skill owns appears in some module's `held_to`. +- [ ] The transport kind and its functions are named. +- [ ] The configuration list includes the transport kind, the participant code, the cases directory, and every setting the chosen transport needs. +- [ ] The test file's location and the pin comparison rule are written. + +## Common mistakes + +- Splitting the claim bundle builder across modules by leg, or by skill. One builder, one `leg` and `flow` argument, is what the pins expect; `nhcx-claim` extends what `nhcx-preauth` built. +- Planning a second transport for the reply legs. Same function; the reply legs add `x-hcx-correlation_id` to the headers. +- Planning new files for a module stage 0 found present. +- Planning the screens before the readers exist in the dependency list. diff --git a/plugins/nhcx/skills/nhcx-insurance/stages/7-write-code/7.1-config-and-transport.md b/plugins/nhcx/skills/nhcx-insurance/stages/7-write-code/7.1-config-and-transport.md new file mode 100644 index 000000000..2ad046569 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-insurance/stages/7-write-code/7.1-config-and-transport.md @@ -0,0 +1,131 @@ +# Module 7.1: configuration and the NHCX transport + +Purpose: the one path every message leaves by, whichever transport carries it. The settings, the transport chosen at stage 1 behind one `send`, the policy lookup, and the outbound half of the per-case archive. + +Skills: the foundation (`core/FOUNDATION.md`). Built whole by the first skill whose stage 0 finds it absent; every skill sends through it. + +## Depends on + +Nothing. First module. + +## Inputs + +- `nhcx-build/1-idea.md`: the transport, `existing`, `own`, or `adapter` because the user asked for it +- `nhcx-build/6-code-plan.md` sections 2 to 4 (the transport's functions, the configuration keys, the archive path) +- `references/transport-knowledge.md` section 2 (the contract), and section 3 (`own`), 4 (`existing`) or 5 (`adapter`) for the kind chosen +- With `adapter` only: `references/api-knowledge.md` sections 2 to 5, 7, 8 and 11 + +## Build + +### Settings + +Read from the target's configuration mechanism (stage 3). + +| Setting | Transport | Meaning | +| --- | --- | --- | +| transport kind | all | `existing`, `own` or `adapter` | +| participant code | all | The hospital's, with `@hcx`: `x-hcx-sender_code` | +| facility HFR id, name, phone | all | The provider Organization | +| cases directory | all | The per-case archive root | +| per-payer workflow id overrides | all | Optional, for a payer that insists on a code the table does not carry (`cancel` as 122) | +| ABDM client id and secret | own | The session token (`transport-knowledge.md` section 3.3) | +| private key | own | The PEM behind the certificate on the participant record, read from a file or a secret store | +| sessions, NHCX and registry addresses, `X-CM-ID` | own | From `nhcx-package/baseurl.yaml`; the sandbox by default | +| NHCX signing key | own | For the exchange's JWT on inbound calls. Empty until onboarding gives it, and logged while empty | +| adapter URL, adapter API key, callback secret | adapter | `references/api-knowledge.md` section 2. Also fill the adapter's `config.sample.json` into `nhcx-build/adapter.config.json`, secrets as `${ENV}` placeholders | +| whatever the existing client reads | existing | Named here, not duplicated | + +Secrets are read from configuration: never in code, never in `nhcx-build/`. + +### The transport + +One `send` with the signature in `transport-knowledge.md` section 2, and beside it `policies`, `participants`, `token`, `thread` and `fetch_missed`. What sits under them depends on the kind: + +| Kind | `send` | `policies`, `participants`, `token` | `thread`, `fetch_missed` | +| --- | --- | --- | --- | +| `own` | Seal and post (`transport-knowledge.md` sections 3.3 to 3.8): the token, the recipient's certificate, the protected header, a compact JWE, `{"payload"}` to `/v1/`, a `401` retried once | The participant service directly (sections 3.6 and 3.7) | `thread` reads the per-case archive; `fetch_missed` answers `unavailable` | +| `existing` | Calls the app's own client and maps its answer onto `{txn_id, correlation_id, api_call_id}` (section 4) | The app's own calls, or the participant service directly | What the app keeps; else as `own` | +| `adapter` | POSTs `{jwe_headers, fhir}` to `/fhir/out/` with the bearer key (`api-knowledge.md` sections 4 and 5) | `/internal/policies/search`, `/internal/participants/list`, `/token` | The adapter's ledger and `/internal/txn/*` (`api-knowledge.md` sections 7 and 8) | + +Common to every kind: + +1. A send without a recipient, a workflow id or the beneficiary's ABHA is refused before anything goes on the wire. +2. The recipient is the policy's processor: `recipient_of(row)` is `claim.recipient_code`, else `claim.payer_code` for an episode opened before the processor was kept. +3. A correlation id is passed only on the two answer legs, the communication reply and the payment acknowledgement. On a request the transport mints it (`own`: the message's own `api_call_id`). +4. A refusal raises `TransportError(code, message, protocol_response, retryable)`: the gateway's status and body (`own`), the adapter's `error.code` and `upstream_body` (`adapter`), or the existing client's error. A ProtocolResponse inside it is a refusal at the door; the caller records the payer's words. +5. The outbound message is archived before `send` returns: `//NNN--out.json` with what was sent and what came back, and a `transactions.txt` line (sequence, time, direction, path, workflow id, correlation id, api call id, txn id, outcome). With `own`, the archive entry is the `txn_id`. +6. The caller stores `txn_id`, `correlation_id` and `api_call_id` on the leg. + +## Rules + +- Use nhcx-adapter only when the user asked for it; `1-idea.md` records their words. Never propose it. +- Keep an existing NHCX integration and wrap it. Never put a second transport beside it. +- Seal and open JWEs only for `own`, and only with a JOSE library: `RSA-OAEP-256`, `A256GCM`, compact serialisation. Never hand-roll the cryptography. +- The workflow id goes out on every leg that has one; `x-hcx-ben-abha-id` goes out on every message. +- The sandbox refuses sends faster than one per 30 seconds per case (PAYR-1322). The transport does not throttle; the caller does. Say so in the docstring. +- The private key never leaves the server that receives callbacks, and never enters a log. + +## Validate + +- [ ] A send with no recipient, no workflow id or no beneficiary ABHA is refused before anything goes on the wire. +- [ ] The protected header of a send carries every mandatory field under the protocol's rules: sender and recipient with `@hcx`, a fresh `api_call_id`, a `correlation_id` equal to the `api_call_id` on a request and to the request's on an answer, the workflow id, `x-hcx-timestamp` in ISO 8601 with `+05:30`, `x-hcx-status` `request.initiated` or `response.complete`, and `x-hcx-ben-abha-id`. Observed on what the transport emits: the JWE header opened with a test key pair (`own`), the posted `jwe_headers` with the adapter's completion rules (`adapter`), the existing client's output (`existing`). +- [ ] The recipient is the episode's `recipient_code`, the policy's `processingid`, whenever the episode has one. +- [ ] A refusal raises `TransportError` carrying the code and the words the exchange or the adapter gave. With `own`, a `401` is retried once with a fresh token, and a second `401` raises. +- [ ] The archive file and the `transactions.txt` line exist after a send, with the sequence number zero-padded to three digits. +- [ ] Secrets are read from configuration, not present in code or in `nhcx-build/`. +- [ ] With `own`: a bundle sealed for a test certificate opens with its private key to the same bytes and the same protected header; the token is reused while fresh and fetched again when stale; a recipient's certificate is fetched once and then read from the cache. + +## Tests + +- Stub the HTTP layer and assert the URL, the headers and the body of one send with and one without a correlation id: `bearer_auth` and `{"payload"}` for `own`; the bearer key and `{jwe_headers, fhir}` for `adapter`. +- `own`: seal with a test key pair and open it again; check the header fields above; a `401` then a `202` sends twice with two tokens; a certificate in SPKI form loads as well as an X.509 one. +- `adapter`: a `502` with a ProtocolResponse `upstream_body` raises an error whose text carries the payer's `x-hcx-error_details` message; a `404` from `txn/related` is terminal, not retried. +- The archive sequence increments across two sends on one case. + +## Pseudo code + +The `own` transport's token, certificate cache, sealing and receiving end: `references/transport-knowledge.md` section 3.12. The adapter client: `references/api-knowledge.md` section 11. What every kind shares: + +``` +settings = { + transport: env("NHCX_TRANSPORT", "own"), # own | existing | adapter; adapter only when the user asked for it + participant_code: env("NHCX_PARTICIPANT_CODE"), # "@hcx" + facility: {hfr_id: env("NHCX_HFR_ID"), name: env("NHCX_FACILITY_NAME"), phone: ...}, + cases_dir: env("NHCX_CASES_DIR", "data/cases"), + workflow_overrides: parse_json(env("NHCX_WORKFLOW_IDS", "{}")), # {"1518@hcx": {"cancel": "122"}} + nhcx: {sessions: env("NHCX_SESSIONS_URL", "https://dev.abdm.gov.in/api/hiecm/gateway/v3/sessions"), # own + base: env("NHCX_BASE_URL", "https://apisbx.abdm.gov.in/hcx"), + registry: env("NHCX_REGISTRY_URL", "https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice"), + cm_id: env("NHCX_CM_ID", "sbx"), + client_id: env("NHCX_CLIENT_ID"), client_secret: env("NHCX_CLIENT_SECRET"), + private_key: read_secret(env("NHCX_PRIVATE_KEY_FILE")), signing_key: env("NHCX_SIGNING_KEY", "")}, + adapter: {url: env("NHCX_ADAPTER_URL"), api_key: env("NHCX_ADAPTER_API_KEY"), # adapter only + callback_secret: env("NHCX_CALLBACK_SECRET")}, +} + +transport = {"own": OwnTransport, "existing": ExistingTransport, "adapter": AdapterTransport}[settings.transport]() +# each offers send, policies, participants, token, thread, fetch_missed (transport-knowledge.md section 2) + +function recipient_of(row): return row.recipient_code or row.payer_code + +function ben_abha(claim_no): # the payer's Patient from the coverage answer, else the HMIS patient + row = claim_by_no(claim_no) + return digits(abha_in(row.patient_json) or patient(row.patient_id).abha) + +function with_hcx(code): return code if code.endswith("@hcx") else code + "@hcx" + +# the archive, outbound half; 7.3 writes the inbound half through the same function +function archive.record(claim_no, usecase, direction, payload): + folder = settings.cases_dir + "/" + (claim_no or "unmatched"); mkdir(folder) + n = next_sequence(folder) # 001, 002, ... + write(folder + f"/{n:03d}-{usecase}-{direction}.json", pretty(payload)) + append(folder + "/transactions.txt", f"{n:03d} {now()} {direction} {payload.path} wf={payload.workflow_id} " + f"cid={payload.correlation_id} acid={payload.api_call_id} txn={payload.txn_id} {payload.outcome}") + return f"{claim_no or 'unmatched'}/{n:03d}" +``` + +## Done when + +- Validate passes for the transport chosen. +- `own`: the onboarding the user must do is written into `nhcx-build/7-modules/7.1.md`: the credentials, the key and certificate, the participant record, the `endpoint_url`, and the NHCX signing key to ask NHA for. `adapter`: `nhcx-build/adapter.config.json` exists with placeholders. `existing`: the wrapper and every gap it closed are listed. +- `nhcx-build/7-modules/7.1.md` is written. diff --git a/plugins/nhcx/skills/nhcx-insurance/stages/7-write-code/7.10-communication-and-payment.md b/plugins/nhcx/skills/nhcx-insurance/stages/7-write-code/7.10-communication-and-payment.md new file mode 100644 index 000000000..271d56732 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-insurance/stages/7-write-code/7.10-communication-and-payment.md @@ -0,0 +1,124 @@ +# Module 7.10: communication and payment + +Purpose: the two legs the payer starts. A CommunicationRequest is classified as a query, a notification or a note and answered accordingly; a PaymentNotice is recorded, matched to its claim, and acknowledged. + +Skills: `nhcx-communication` (classification, the notification acknowledgement, the reply) and `nhcx-payment` (the payment notice and its acknowledgement). Validate rows 1, 3, 4 and 5 are the communication half's; rows 2, 6 and 7 the payment half's; row 8 is both. + +## Depends on + +7.1 to 7.3, 7.7, 7.11 (for the payer's query mode; build 7.11's adapter table first if not yet). + +## Inputs + +- `references/flow-knowledge.md` section 3 (the two payer kinds, the classification rule) and section 1 rows "Payment notice" and "Communication" +- `references/fhir-knowledge.md` sections 9 and 10 +- Pins: `nhcx-package/fhir/B4/communication-request.json` (the payer's message), `B4/communication-response.json` (the reply), `nhcx-package/fhir/B7/payment-notice-ack.json` +- Payer messages: `nhcx-package/fhir/C6/C6-preauth-query-wf24.json` and `C6/C6-claim-query-wf27.json` (generic queries), `C6/C6-notification-wfN02.json` (PMJAY notification), `nhcx-package/fhir/C9/*.json` (payment notices) + +## Build + +### Classification + +`classify_communication(adapter, reason_code, intent) -> kind`, in order: a `resubmit` payer's request is a notification; `intent proposal` is a notification, `order` a query; then `reasonCode`: absent, `additionalinfo`, `questionnaire`, `query` is a query, anything else (`tatquery`, `grievance`, `walletupdate`, `policychange`, `claimarbitration`, with `claimArbitartion` folded in) a notification. A bare `Communication` with no request is a note: recorded, shown, never acted on. + +### Receiving + +`parse_communication_request(bundle)`: the Task's status, intent, reason; the CommunicationRequest's id, `basedOn` (the Claim), one question per `payload[].contentString`; the leg asked about (from the Claim's `use` or the `basedOn` identifier). Store a `claim_query` row keyed on the message's correlation id with `kind`, `stage`, `questions_json`, status `open`. + +### Acknowledging a notification + +`build_acknowledgement_bundle(query_id)`: the payer's own bundle sent back with `Task.status` flipped to `completed`, the reason echoed and the provider Organization first, on `v1/communication/on_request` with the request's correlation id and workflow id echoed in `jwe_headers`. Sent by `acknowledge_notification` from outside the callback (the desk's next request, or a worker). Status `acknowledged`. + +### Answering a query (communication payer) + +`build_communication_bundle(query_id, text, document_ids)`: a TaskBundle with a Task `deliver`, `completed`, including the Communication; the Communication `basedOn` the request (never `inResponseTo`) and `about` the Claim, its text a `contentString`, each document a `contentAttachment` under the document-type extension (its url is participant-defined: read it from configuration; the pin comparison takes the pin's own url); the CommunicationRequest echoed; then the Claim, Patient, provider Organization, payer Organization, Practitioner and Coverage lifted from the queried leg's bundle as sent. This bundle carries `meta.lastUpdated` and `timestamp` (the IG example does). Sent on `v1/communication/on_request` with the request's correlation id and workflow id. Status `answered`. + +For a `resubmit` payer the answer is not here: it is 7.7's query answer on a fresh thread. The inbox item for a PMJAY query is the leg's `query_note`, and its reply box calls `submit_preauth` or `submit_claim` with the reply. + +### Payment notice + +`parse_payment_notice(bundle)`: `PaymentNotice.amount`, `paymentStatus`, `paymentDate`, the `request` reference's identifier (the claim number), `payment` identifier (the UTR when settled), the `PaymentReconciliation` details when present. `record_payment` matches the claim number, dedupes on the correlation id, stores `claim_payment` and `claim_payment_detail`, and stamps the episode `payment`/`noticed` or `paid`. + +### Payment acknowledgement + +`build_payment_ack(payment_id)`: a TaskBundle in the shape of `B7/payment-notice-ack.json`, sent on `v1/paymentnotice/on_request` with the notice's correlation id and, for PMJAY, workflow `17`; for a generic payer the notice's own workflow id echoed (`None` in the adapter table means echo). Sent by `acknowledge_payment` from outside the callback. `ack_status` `sent` or `error`. + +## Rules + +- The reply names the request in `Communication.basedOn`, never `inResponseTo`. +- A `resubmit` payer's CommunicationRequest is always a notification, whatever it says. +- A notification is acknowledged at once and the case is left alone. +- The acknowledgement and the reply are the only two sends that carry `x-hcx-correlation_id` (with the payment acknowledgement). + +## Validate + +- [ ] `B4/communication-response.json` pin: the builder fed the request pin (`B4/communication-request.json`) and the pre-auth pin (`B3/preauth-request.json`) produces the response pin byte for byte (`meta.lastUpdated`, `timestamp` and `authoredOn` excluded). +- [ ] `B7/payment-notice-ack.json` pin comparison passes. +- [ ] Classification: the generic query (`C6/C6-preauth-query-wf24.json`: `intent order`, `additionalinfo`) is a query; the PMJAY notification (`C6/C6-notification-wfN02.json`: `intent proposal`, `information`) is a notification; the same PMJAY bundle under a `communication` adapter with `intent order` is a query; a bare Communication is a note. +- [ ] The reply's `Communication.basedOn` names the request and `inResponseTo` is absent. +- [ ] The acknowledgement and the reply carry `x-hcx-correlation_id` equal to the request's; the workflow id is echoed. +- [ ] Two deliveries of one notice create one `claim_payment` row. +- [ ] The PMJAY acknowledgement carries workflow `17`; the generic one echoes the notice's. +- [ ] No send happens inside the callback (7.1 stub sees zero sends during receipt). + +## Tests + +- The two pin comparisons. +- Classification table as a parametrised test. +- B6, B7, C6, D8, D13 and the notification rows from the matrix. + +## Pseudo code + +Classification, the acknowledgement, the reply and the payment reader: `fhir/FHIR.md` sections 7 and 8. Wiring: + +``` +APPLY["inbound_request"] = function (row, env): + kind = resource_types(env.fhir) + if "PaymentNotice" in kind: record_payment(row, env) + elif "CommunicationRequest" in kind: receive_communication(row, env) + elif "Communication" in kind: record_note(row, env) # a bare Communication: shown, never acted on + +function receive_communication(row, env): + p = fhir.parse_communication_request(env.fhir); adapter = payers.for_claim(row) + kind = fhir.classify_communication(adapter, p.reason, p.intent) + q = insert("claim_query", {claim_id: row.id, correlation_id: env.jwe_headers["x-hcx-correlation_id"], request_id: p.request_id, + workflow_id: env.jwe_headers["x-hcx-workflow_id"], sender_code: env.jwe_headers["x-hcx-sender_code"], + kind, stage: leg_asked_about(row, p), reason_code: p.reason, intent: p.intent, questions_json: p.questions, + request_json: env.fhir, status: "open", received_at: now()}) + if kind == "notification": enqueue(acknowledge_notification, q.id) # sent outside the callback + +function acknowledge_notification(query_id): + q = query(query_id); row = claim(q.claim_id) + bundle = fhir.build_acknowledgement_bundle(q.request_json, settings.facility) + r = transport.send("v1/communication/on_request", bundle, q.sender_code, workflow_id = q.workflow_id, correlation_id = q.correlation_id, claim_no = row.claim_no, usecase = "communication-ack") + update(q, {status: "acknowledged", reply_txn_id: r.txn_id, reply_api_call_id: r.api_call_id, replied_at: now()}) + +function answer_query(query_id, text, document_ids): # communication payer + q = query(query_id); row = claim(q.claim_id) + if payers.for_claim(row).query_mode == "resubmit": return submit_preauth(row.id, reply = text) if q.stage == "preauth" else submit_claim(row.id, reply = text) + sent = (preauth(row.id) if q.stage == "preauth" else submission(row.id)).request_json + bundle = fhir.build_communication_bundle(q, text, [doc_with_bytes(i) for i in document_ids], sent, settings.facility, payer_of(row), now_ist()) + r = transport.send("v1/communication/on_request", bundle, q.sender_code, workflow_id = q.workflow_id, correlation_id = q.correlation_id, claim_no = row.claim_no, usecase = "communication-reply") + update(q, {status: "answered", reply_text: text, reply_document_ids: document_ids, reply_txn_id: r.txn_id, replied_at: now()}); stamp_case(row.id) + +function record_payment(row, env): + p = fhir.parse_payment_notice(env.fhir) + pay = insert_or_ignore("claim_payment", {claim_id: row.id, correlation_id: env.jwe_headers["x-hcx-correlation_id"], workflow_id: env.jwe_headers["x-hcx-workflow_id"], + sender_code: env.jwe_headers["x-hcx-sender_code"], amount: p.amount, payment_status: p.payment_status, payment_date: p.payment_date, + utr: p.utr, notice_json: env.fhir, ack_status: "pending", received_at: now()}) + if not pay: return # the unique constraint caught a redelivery + for d in p.details: insert("claim_payment_detail", {payment_id: pay.id, type: d.type, amount: d.amount}) + enqueue(acknowledge_payment, pay.id) + +function acknowledge_payment(payment_id): + pay = payment(payment_id); row = claim(pay.claim_id); adapter = payers.for_claim(row) + bundle = fhir.payment_ack(submission(row.id).claim_ref or row.claim_no, now_ist(), settings.facility, payer_of(row)) + wf = adapter.workflow_ids.payment_ack or pay.workflow_id # 17 for PMJAY; echo for a generic payer + r = transport.send("v1/paymentnotice/on_request", bundle, pay.sender_code, workflow_id = wf, correlation_id = pay.correlation_id, claim_no = row.claim_no, usecase = "payment-ack") + update(pay, {ack_status: "sent", ack_txn_id: r.txn_id, ack_api_call_id: r.api_call_id, acked_at: now()}); stamp_case(row.id) +``` + +## Done when + +- Validate passes. +- `nhcx-build/7-modules/7.10.md` is written. diff --git a/plugins/nhcx/skills/nhcx-insurance/stages/7-write-code/7.11-state-and-payer-adapters.md b/plugins/nhcx/skills/nhcx-insurance/stages/7-write-code/7.11-state-and-payer-adapters.md new file mode 100644 index 000000000..94fbfc313 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-insurance/stages/7-write-code/7.11-state-and-payer-adapters.md @@ -0,0 +1,145 @@ +# Module 7.11: state and payer adapters + +Purpose: two small tables of truth the whole build reads. The payer adapter says how a payer behaves; the stage machine says where an episode stands and what it waits for. + +Skills: the foundation (`core/FOUNDATION.md`). The first skill builds the payer adapter table whole; each skill adds the `case_stage` branches and the `next_actions` rows for its own legs. + +## Depends on + +7.2. (7.7 to 7.10 call it; build the adapter table as early as 7.4 needs the participant codes.) + +## Inputs + +- `references/flow-knowledge.md` sections 2, 3 and 4, whole +- `nhcx-build/1-idea.md` (the payers in scope) + +## Build + +### The payer adapter + +A table keyed by participant code (normalised: `1518` and `1518@hcx` are one key), each entry holding: + +| Field | PMJAY | Generic | +| --- | --- | --- | +| `query_mode` | `resubmit` | `communication` | +| `workflow_ids` | the PMJAY column of flow-knowledge section 2 | the generic column; `payment_ack` is `None` (echo) | +| `program_code` | `AB-PMJAY` | none | +| `auth_requirements` | asked | asked | +| `status_enquiry` | refused; do not offer | offered | +| `claim_resubmit` | none; reprocess only | `16` | +| `payer_system` | the identifier system for the payer Organization | same | + +`adapter_for(participant_code)` returns the entry or the generic default. `for_claim(row)` reads the episode's payer code. Overrides from configuration (7.1) merge on top, per payer, so a payer that insists on `cancel` as 122 is one config line. + +### Stage and sub-stage + +Stages: `eligibility`, `preauth`, `enhancement`, `claim`, `payment`. Sub-stages: `draft`, `checking`, `eligible`, `not-eligible`, `requested`, `resubmitted`, `answered`, `queried`, `approved`, `partial`, `rejected`, `cancelling`, `cancelled`, `refused`, `noticed`, `paid`. Send kind to sub-stage: `preauth`, `claim`, `enhancement` set `requested`; `*_resubmit` sets `resubmitted`; `*_query_response` and `enhancement_resubmit` set `answered`. `requested`, `answered`, `resubmitted` mean "with the payer". + +`case_stage(row, ...) -> (stage, sub_stage)`: a payment notice wins, then the filed claim, then the pre-auth (stage `enhancement` if the last submission kind was one), then a saved draft, then the eligibility status. An open communication query on a leg that is with the payer flips the sub-stage to `queried`. + +`stamp_case(claim_id)`: recompute and write both onto the episode. Called after every leg write by 7.3, 7.4 to 7.10. + +### Next actions + +The table in `flow/FLOW.md` ("The status line and the actions") and `flow/flow.json` `next_actions` is the specification; the labels are used verbatim. + +`next_actions(claim_id) -> [{label, tab, tone}]`, first is what the case waits for: an unanswered query always leads with "Answer the payer (n)"; the leg's own reply box only for a `resubmit` payer, a `communication` payer is sent to the inbox; a claim refused at the door offers "send again" while `claim_send_kind` still yields a kind, else "Ask for a reprocess"; after a rejection the pre-auth offers a fresh 12; a payer whose adapter refuses status enquiry never gets a "Ask status" action. + +## Rules + +- An unmapped payer is generic. +- The two words are derived, never set by a screen. +- Stamp after every write. A test that checks state after every step is what makes stage 8 possible. + +## Validate + +- [ ] `adapter_for("1518@hcx")` and `adapter_for("1518")` return the PMJAY entry; an unknown code returns generic. +- [ ] The PMJAY `workflow_ids` table equals flow-knowledge section 2's PMJAY column for every kind listed; the generic table has `payment_ack` as echo and `claim_query_response` as `151`. +- [ ] A configuration override for one kind changes only that kind. +- [ ] `case_stage` on each seeded state (draft; checking; eligible; pre-auth submitting; approved; queried by communication; enhancement requested; claim submitting; payment noticed; paid) returns the expected pair (write the table in the test). +- [ ] `next_actions` leads with the query when one is open; offers no status enquiry for PMJAY; offers a fresh 12 after a rejection. +- [ ] For every row of `flow.json` `next_actions`, the seeded state yields that label, character for character. +- [ ] After every leg write in 7.4 to 7.10, `claim.stage` and `sub_stage` equal `case_stage` recomputed. + +## Tests + +- A parametrised table for `case_stage`. +- A parametrised table for `next_actions`. +- The adapter lookups and the override. + +## Pseudo code + +``` +QUERY_MODE_RESUBMIT = "resubmit"; QUERY_MODE_COMMUNICATION = "communication" + +PMJAY = {"name": "PMJAY", "query_mode": QUERY_MODE_RESUBMIT, "program_code": "AB-PMJAY", "auth_requirements": true, + "status_enquiry": false, "payer_system": "https://nhcx.abdm.gov.in", + "workflow_ids": {"preauth": "12", "preauth_resubmit": "121", "preauth_query_response": "19", "enhancement": "13", "enhancement_resubmit": "131", + "cancel": "PC01", "claim": "15", "claim_query_response": "161", "claim_resubmit": null, "payment_ack": "17", "reprocess": "36", "release": "36"}} +GENERIC = {"name": "generic", "query_mode": QUERY_MODE_COMMUNICATION, "program_code": null, "auth_requirements": true, "status_enquiry": true, + "payer_system": "https://nhcx.abdm.gov.in", + "workflow_ids": {... as PMJAY except "claim_query_response": "151", "claim_resubmit": "16", "payment_ack": null}} # null = echo the notice's id +ADAPTERS = {"1518": PMJAY} # keyed without @hcx + +function adapter_for(participant_code): + key = (participant_code or "").split("@")[0] + base = deepcopy(ADAPTERS.get(key, GENERIC)) + for (k, v) in settings.workflow_overrides.get(with_hcx(key), {}): base.workflow_ids[k] = v + return base + +function for_claim(row): return adapter_for(row.payer_code) + +STAGES = ["eligibility", "preauth", "enhancement", "claim", "payment"] +KIND_TO_SUB = {"preauth": "requested", "claim": "requested", "enhancement": "requested", "preauth_resubmit": "resubmitted", "claim_resubmit": "resubmitted", + "preauth_query_response": "answered", "claim_query_response": "answered", "enhancement_resubmit": "answered"} +WITH_PAYER = {"requested", "answered", "resubmitted"} + +function leg_sub_stage(leg): + if leg.status == "submitting": return KIND_TO_SUB.get(leg.submission_kind, "requested") + return {"approved": "approved", "partial": "partial", "queried": "queried", "rejected": "rejected", "error": "refused", + "cancelling": "cancelling", "cancelled": "cancelled", "draft": "draft"}.get(leg.status, leg.status) + +function case_stage(row): + paid = sum(p.amount for p in payments(row.id) if p.payment_status in ("paid", "cleared")) + if payments(row.id): return ("payment", "paid" if paid > 0 else "noticed") + cs = submission(row.id) + if cs and cs.status != "draft": + sub = leg_sub_stage(cs) + if sub in WITH_PAYER and "claim" in open_query_stages(row): sub = "queried" + return ("claim", sub) + pa = preauth(row.id) + if pa and pa.status != "draft": + stage = "enhancement" if pa.submission_kind in ("enhancement", "enhancement_resubmit") else "preauth" + sub = leg_sub_stage(pa) + if sub in WITH_PAYER and "preauth" in open_query_stages(row): sub = "queried" + return (stage, sub) + if pa: return ("preauth", "draft") + return ("eligibility", {"checking": "checking", "eligible": "eligible", "not-eligible": "not-eligible"}.get(row.status, "draft")) + +function stamp_case(claim_id): (s, sub) = case_stage(claim(claim_id)); update(claim(claim_id), {stage: s, sub_stage: sub}) + +function next_actions(claim_id): + row = claim(claim_id); adapter = for_claim(row); out = []; pa = preauth(claim_id); cs = submission(claim_id) + open_q = open_queries(claim_id) + if open_q: out.append({label: f"Answer the payer ({len(open_q)})", tab: "communication" if adapter.query_mode == "communication" else ("claim" if open_q[0].stage == "claim" else "preauth"), tone: "primary"}) + if row.status in ("draft", "not-eligible", "error"): out.append({label: "Check cover", tab: "cover", tone: "primary"}) + elif not row.plan_id: out.append({label: "Fetch the plan", tab: "plan", tone: "primary"}) + elif not pa or pa.status == "draft": out.append({label: "Submit the pre-authorisation", tab: "preauth", tone: "primary"}) + elif pa.status == "queried" and adapter.query_mode == "resubmit": out.append({label: "Answer the query", tab: "preauth", tone: "primary"}) + elif pa.status == "rejected": out.append({label: "Send a fresh pre-authorisation", tab: "preauth", tone: "primary"}) # 12, never 121 + elif pa.status == "error": out.append({label: "Send again", tab: "preauth", tone: "warn"}) + elif pa.status in ("approved", "partial") and (not cs or cs.status == "draft"): + out.append({label: "Discharge and claim", tab: "claim", tone: "primary"}) + if enhancement_lines(claim_id): out.append({label: "Send the enhancement", tab: "lines", tone: "default"}) + out.append({label: "Cancel the pre-authorisation", tab: "preauth", tone: "danger"}) + elif cs and cs.status == "error": out.append({label: "Send again" if claim_send_kind(claim_id) else "Ask for a reprocess", tab: "claim", tone: "warn"}) + elif cs and cs.status == "rejected": out.append({label: "Ask for a reprocess", tab: "claim", tone: "warn"}) + for p in payments(claim_id): if p.ack_status != "sent": out.append({label: "Acknowledge the payment", tab: "payments", tone: "default"}) + if adapter.status_enquiry and (pa or cs): out.append({label: "Ask status", tab: "enquiries", tone: "default"}) + return out +``` + +## Done when + +- Validate passes. +- `nhcx-build/7-modules/7.11.md` is written. diff --git a/plugins/nhcx/skills/nhcx-insurance/stages/7-write-code/7.12-screens.md b/plugins/nhcx/skills/nhcx-insurance/stages/7-write-code/7.12-screens.md new file mode 100644 index 000000000..130115d38 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-insurance/stages/7-write-code/7.12-screens.md @@ -0,0 +1,124 @@ +# Module 7.12: screens + +Purpose: the screens in `screens.json`, built the way the target builds screens, every value derived from a stored message, plus the JSON state address a driver reads. + +Skills: the foundation (`core/FOUNDATION.md`) builds the case screen shell: all eight tabs, the status line, the state address, the page-load polls, the cases list. Each skill fills its own tabs and screens, and adds its legs to the state address. + +## Depends on + +7.1 to 7.11. Screens come last because they render what the readers stored. + +## Inputs + +- `nhcx-build/5-screen-plan.md`, `nhcx-build/screens.json` +- `nhcx-build/3-discovery.md` (screen conventions, helpers, styling) +- `nhcx-package/docs/03-Building a Provider/09-UI Guide.md` +- `ui/UI-GUIDE.md` for the route shape, the state address and the helper vocabulary; two or three route modules of the target for its conventions + +## Build + +### The case screen walks the flow + +Tabs in the order and with the labels of `flow.json` `tabs`; the Pre-authorisation tab appears once the verdict is `eligible`. Above the tabs the status line and the actions from 7.11. Each step F1 to F13 has its control on the tab the flow names, offered only when the step's `holds` hold. The page-load polls run in the order `flow.json` `page_load_polls` gives, bounded, before rendering. + +### Every screen in `screens.json` + +For each screen: the route, the handler, the render. Each value in the screen's `values` list is rendered from the element it names; the empty state is what shows before the message arrived. A decision-bearing value with no message renders as waiting. There is no status control anywhere. + +### The case screen + +The timeline: one row per leg row and per archived message, in time order, with direction, path, workflow id label (7.8's labels), status word, and the payer's words verbatim (`disposition`, item remarks, process notes, `x-hcx-error_details` on a refusal). The actions open now are `next_actions` from 7.11, rendered as buttons that post to the senders; the first action is highlighted. Each pane (cover, plan, lines, forms, documents, pre-auth, communication, claim, payments) shows only when its leg exists. + +### The JSON state address + +`GET /state` returns everything the case screen shows, as JSON, after the same polls the screen runs: stage, sub-stage, next actions, each leg's status and ids, the inbox items, the payments. Stage 10's drivers read this. + +### Polling on the request path + +Where there is no worker, the case screen and the state address run 7.3's poll fallback for any leg that is `submitting` or `checking` before rendering. Bound it: one poll per leg per request, a short timeout, and never a send. + +### Standalone mode + +Also the capture screens from 7.13, in the same style. + +## Rules + +- No screen shows a decision the exchange has not sent. +- Nothing the exchange already knows is typed. Rates, payer names, `preAuthRef`, the approved amount, the UTR and the payer's wording are rendered, never fields. +- An unknown case is a 404, never an invented page. +- Screens answer within two seconds; the poll is bounded. +- Forms post and the page re-renders; no client-side rendering is needed. + +## Validate + +- [ ] The case page's tabs are the eight of `flow.json`, in order, with those labels (string test on the HTML). +- [ ] Every step of `flow.json` with a `routes` entry answers on that route (or the plan's equivalent recorded in `screens.json`). +- [ ] Every route in `screens.json` answers 200 for a seeded case and 404 for an unknown one. +- [ ] A case with a pre-auth `submitting` and no answer renders "waiting" (or the plan's word) and neither "approved" nor "rejected" appears on the page. +- [ ] After a 21 is applied (`nhcx-package/fhir/C5/C5-approved-wf21.json`), the page shows its `preAuthRef` and approved amount verbatim. +- [ ] After a payment notice is applied (`nhcx-package/fhir/C9/C9-notice-wf30.json`), the payments screen shows its UTR verbatim. +- [ ] After a query is applied, the inbox shows the request's `contentString` text verbatim. +- [ ] No `` or `, unless spec.typed +``` + +### Which actions to offer + +``` +function actions(case): + out = [] + q = open_queries(case) + if q: out.append(action("Answer the payer (n)", tab = inbox if payer.query_mode == communication else leg_tab)) + leg = current_leg(case) + if leg.status == "rejected" and leg.kind == "preauth": out.append(action("Send a fresh pre-authorisation", sends = 12)) + if leg.status == "approved" and no_request_in_flight(case) and leg.kind == "preauth": + out.append(action("Enhance", sends = 13)); out.append(action("Cancel", sends = PC01)); out.append(action("Discharge and claim", tab = claim)) + if leg.kind == "claim" and leg.status == "rejected": out.append(action("Ask for a reprocess", sends = 36)) + if payer.status_enquiry: out.append(action("Ask status", sends = task status)) + for notice in unacknowledged_notices(case): out.append(action("Acknowledge payment", sends = 17 or echo)) + return out +``` + +## Component vocabulary (suggested, for a standalone build) + +A suggested set of helpers. Server-rendered HTML from Python functions returning strings, styled by the 0build kit 0.5.4 from jsDelivr. Components: `z-card`, `z-button`, `z-input`, `z-select`, `z-table`, `z-nav`, `z-tab` with `data-z-switcher`, `z-alert`, `z-badge`, `z-breadcrumb`. Utilities take values through custom properties (`class="display-grid gap" style="--gap: 4"`). Helpers a screen needs: `page`, `card`, `stack`, `table`, `grid`, `field`, `text_input`, `select`, `button`, `post_button`, `confirm_form`, `badge`, `when`, `muted`, `dl`, `tabs`, `stat`, `empty_state`. Tables cap at about eight columns; merge facts into a main line with a muted sub-line. Every state-changing action that is not a full form is a `post_button`; destructive ones confirm. + +In `integrate` mode use the HMIS's own components and conventions; the layouts above are the content, not the markup. diff --git a/plugins/nhcx/skills/nhcx-payment/SKILL.md b/plugins/nhcx/skills/nhcx-payment/SKILL.md new file mode 100644 index 000000000..09c11047e --- /dev/null +++ b/plugins/nhcx/skills/nhcx-payment/SKILL.md @@ -0,0 +1,92 @@ +--- +name: nhcx-payment +description: Add NHCX payment notices to a hospital information system or a standalone claims desk. Receive the payer's PaymentNotice, match it to its claim by the claim number, record it once, and acknowledge it at once (workflow 17 on PMJAY, the notice's own id for a generic payer), held to the pinned bundle. Starts by checking whether the app already records NHCX payments or acknowledges notices, and whether it holds the filed claim a notice names, then builds, extends or reuses only what is missing. Self-contained; needs no other skill installed. Use for payment notices, settlement, UTR, payment acknowledgement, NHCX use cases B7 and D13, flow step F12. +--- + +# NHCX payment: the notice and its acknowledgement + +This skill takes the payer's payment notice when it arrives, files it against its claim once however often it is delivered, acknowledges it straight away, and shows the desk what was paid and against which UTR. + +Read `core/LADDER.md` first. It holds the ladder every NHCX skill walks: the definition of compliant, the stages, the workspace, how to run a stage, and the rules. This folder carries everything it needs and runs on its own; the other six NHCX skills are separate folders, and none of them has to be installed. Paths starting `core/`, `stages/`, `references/`, `fhir/`, `flow/`, `ui/`, `templates/` or `scripts/` are relative to this folder. Paths starting `nhcx-package/` are in the NHCX package, which `scripts/fetch-package.sh` fetches into the target project beside `nhcx-build/`; `references/material.md` names the package file of every pin by its label. + +## What this skill covers + +| | | +| --- | --- | +| Flow step | F12 Payments | +| Tabs | Payments (tab 8); the payments view across cases | +| Wire | In: `v1/paymentnotice/request`, workflow 30 (also 31, 33), on a new thread. Out: `v1/paymentnotice/on_request` with the notice's correlation id, a Task `status completed` with output `paymentack`, workflow 17 (PMJAY) or the notice's own id echoed (generic) | +| Next actions | "Await the payment notice", "Acknowledge the payment notice", "Settled" | +| Use cases | B7, D13; C9 as readers | +| Module | 7.10, the payment half | +| Pins | `payment/notice-ack`: `nhcx-package/fhir/B7/payment-notice-ack.json` | +| Payer fixtures | `nhcx-package/fhir/C9/payment-notice.json`, `C9-notice-wf30.json`, `C9-notice-tds-wf30-pmjay.json`; the live PMJAY acknowledgement in `nhcx-package/fhir/D13` | +| Tables | `claim_payment` (its correlation id unique), `claim_payment_detail` | +| FHIR | `fhir/FHIR.md` section 8; `references/fhir-knowledge.md` section 10 | + +## Needs and hands on + +Needs: a filed claim. The notice names the claim number, which is looked up against the episode's claim number and every leg's `claim_ref`. Stage 0 checks for it below, whichever way the app got it. + +Hands on: payment rows with amount, UTR, status and acknowledgement; the episode at `payment / noticed` or `paid`. A notice short of the approved amount is what a release (the reprocess use case) asks the balance against. + +## Capability check + +Stage 0 (`stages/0-capability-check.md`) gives every capability below a verdict: search for the markers, run the check, record what was observed. + +### Own + +| Id | What | Look for | Present when (observed) | +| --- | --- | --- | --- | +| `payment.notice-reader` | `parse_payment_notice`, and the match to a claim | `PaymentNotice`, `PaymentReconciliation`, `paymentStatus`, `CLN` | Fed `nhcx-package/fhir/C9/payment-notice.json`, it yields the claim number, the amount and the UTR; the claim number comes from a `CLN` identifier, then any untyped identifier on the notice, the reconciliation or the Task, and never from the bundle id | +| `payment.record` | One row per notice | a payment table keyed on the notice's correlation id | Delivered through the door, one notice makes one row with its details; the same notice twice makes one row, by the unique constraint (7.10 Validate, row 6); a payer that reuses the notice id updates the row; the episode stamps `payment / noticed` or `paid`, paid counted once per UTR | +| `payment.acknowledge` | The acknowledgement, sent at once and automatically | a send on `v1/paymentnotice/on_request`; `paymentack` | The builder produces `payment/notice-ack` byte for byte; PMJAY gets workflow 17 and a generic payer its notice's own id (7.10 Validate, rows 2 and 7); the notice's correlation id is echoed; nothing is sent inside the callback; a failed acknowledgement stays on the row and the callback still answers 2xx | +| `payment.screens` | The Payments tab and view | a card per notice | Status, amount, the UTR as text, the breakdown, and "Acknowledged at" or "Send the acknowledgement again", all from the stored notice; an initiated notice without a UTR reads "Initiated, UTR awaited" and is not counted as money received | + +### Foundation + +All six capabilities in `core/FOUNDATION.md`. `foundation.callback` is partial until the door matches an inbound request by the claim number inside it; `foundation.storage` until `claim_payment` exists with its unique correlation id; `foundation.state` until a notice wins in `case_stage`. + +### Prerequisites + +The claim use case (`nhcx-claim`) owns these. The checks are here, so that skill need not be installed. + +| Capability | Why | Look for | Present when (observed) | +| --- | --- | --- | --- | +| `claim.send` | A notice is matched by the claim number of a filed claim | a claim leg with `claim_ref` and `correlation_id` | A claim sent with a stubbed client on `v1/claim/submit` (workflow 15) stores `claim_ref`, and the claim number in `nhcx-package/fhir/C9/payment-notice.json` can be looked up against the episode's number or a leg's `claim_ref` | +| `claim.response-reader` | A payer pays an approved claim; "Await the payment notice" follows the approval | a ClaimResponse reader on the claim thread | `nhcx-package/fhir/C7/C7-received-wf25.json` then `C7-approved-wf26.json` on the claim's correlation id leave the claim `approved` | + +### Host facts + +Invoices and receipts: where a settlement amount and a UTR could be written back, if stage 4 says so. + +## The ladder, for this skill + +| Stage | What is specific here | +| --- | --- | +| 0 | The tables above. | +| 1 | Confirm the shared page, or write it if this skill runs first on the app. Own rows: B7, D13. | +| 2 | Risks: acknowledge or lose the thread (NHCX redelivers, then retires the id); a redelivered notice counted twice; 17 against an echoed id; a notice matched by the bundle id instead of the claim number. | +| 3 | The host facts above. | +| 4 | The homes of `claim_payment` and `claim_payment_detail`; the notice's destinations; the acknowledgement's source map; whether a UTR is written back to the HMIS receipt. If this skill maps first, every table's home too. | +| 5 | The Payments tab and view. F12 is started by the payer: the only action is "Send the acknowledgement again". | +| 6 | The payment half of 7.10; the foundation modules stage 0 found absent or partial. | +| 7 | The payment half of 7.10, as far as its verdicts say. | +| 8 | 7.10 Validate rows 2, 6, 7 and 8. | +| 9 | The pin comparison; reader tests on every C9 fixture; matrix rows B7 and D13; the cross-cutting rows for an inbound notice (redelivery, unmatched). | +| 10 | Rung 1. Rung 3: a generic payer's desk releases payment. Rung 4: the SHA's finance side sends 30 on its own schedule, which may not fall within a run; say so rather than wait. | +| 11 | This skill's section. | + +## Rules for these legs + +- The payer starts this leg. The acknowledgement goes at once and automatically, and the screen shows that it went; the button is only the retry. +- Match by the claim number inside the notice, never by the bundle id. +- Dedupe on the notice's correlation id with a unique constraint, not a check in code. +- PMJAY is acknowledged on workflow 17; a generic payer's notice id is echoed (`None` in the payer table means echo). +- Paid is counted once per UTR, the newest notice winning. + +## Done when + +- Every gate in this skill's block of `nhcx-build/STATE.md` is closed with evidence. +- The acknowledgement pin passes; a redelivered notice makes no second row. +- The compliance points in `core/LADDER.md` hold for F12. diff --git a/plugins/nhcx/skills/nhcx-payment/core/FOUNDATION.md b/plugins/nhcx/skills/nhcx-payment/core/FOUNDATION.md new file mode 100644 index 000000000..2037811b9 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-payment/core/FOUNDATION.md @@ -0,0 +1,65 @@ +# The foundation: what every skill stands on + +Six modules carry every leg, and no one skill owns them. Every skill's stage 0 checks them. The first skill that finds one absent or partial builds or extends it in its own stage 7, and records itself as `Built by` in the Foundation block of `nhcx-build/STATE.md`. Later skills find it present and reuse it. An HMIS that already has one (an NHCX integration, a webhook door, a claims table) has it `existing`. + +| Id | Module | What | Every skill adds | +| --- | --- | --- | --- | +| `foundation.transport` | 7.1 | Settings; the one transport behind `send` (the app's existing NHCX integration, the build's own, or nhcx-adapter when the user asked for it); the policy lookup; the outbound archive | Nothing; it sends through it | +| `foundation.storage` | 7.2 | The episode table with its claim number, payer and recipient codes, stage and sub-stage; the leg tables | The leg tables its `SKILL.md` lists, in its own migration | +| `foundation.callback` | 7.3 | The transport's receiving end and the door: dedupe, archive before apply, match by correlation id then claim number, the door refusal, the poll fallback where there is a ledger | Its readers, wired into the door's dispatch | +| `foundation.state` | 7.11 | The payer adapter table; `case_stage`, `stamp_case`, `next_actions` | The stage branches and next-action rows for its legs, labels verbatim from `flow/flow.json` | +| `foundation.screens` | 7.12 | The case screen shell: the eight tabs in the flow's order, the status line and actions, the JSON state address, the page-load polls, the cases list | Its own tabs and screens | +| `foundation.shell` | 7.13 | Standalone only: patients, admissions, practitioners, diagnoses, documents, settings, the run script | Nothing; `not applicable` in integrate mode | + +## Recognising each one + +For each capability: what to search for, what must be observed for it to be present, and what makes it partial. Search code, dependencies, migrations, configuration and tests. Run every check offline, with the network stubbed. + +### `foundation.transport` (7.1) + +- Look for an NHCX integration of the app's own: `x-hcx-`, `JWEPayload`, `RSA-OAEP-256`, `A256GCM`, a JOSE library among the dependencies, `bearer_auth`, a sessions URL on the ABDM gateway, `participanthcxservice`, `fetch/certs`, `participant/get/policies`, routes ending in `on_submit`, `on_check` or `on_request`, a vendor's NHCX or HCX client, a gateway service the app calls. Look also for nhcx-adapter already in use: `/fhir/out/`, `/out/v1/`, `jwe_headers`, an adapter URL setting, `/ledger/thread/`, `/internal/txn/related`. +- Present when: what was found meets the contract in `references/transport-knowledge.md` section 2, observed through 7.1's Validate rows 1 to 6 (and row 7 for an app that seals its own messages), with the network stubbed and a test key pair for the seal; and `send` is one function a test can replace. +- Partial when: it sends but misses a contract item (no `x-hcx-ben-abha-id`, the `payerid` as the recipient, no ids back to the caller, no archive) or cannot be stubbed. Extend it in place (`references/transport-knowledge.md` section 4). Never add a second transport beside it. +- Absent when: the app has no NHCX integration. The transport is then `own`, built from `references/transport-knowledge.md` section 3, unless the user has asked for nhcx-adapter. +- nhcx-adapter is never the answer to a partial or absent transport unless the user asked for it. Do not suggest it. + +### `foundation.storage` (7.2) + +- Look for: tables or models with `claim_no`, `correlation_id`, `txn_id`, `sub_stage`; migrations that mention claim, preauth or nhcx. +- Present when: observed on a migrated scratch database, or read from the schema file and confirmed by a migration run: the episode table has a unique claim number, member id, policy code, payer code, recipient code, patient and encounter keys, `stage` and `sub_stage`; every leg table this skill needs exists with `txn_id`, `correlation_id`, `api_call_id` and `thread_correlation_id`; the migration runs twice without error; deleting an episode removes its children (7.2 Validate, rows 2, 3, 5 and 6). For `nhcx-communication` and `nhcx-payment`, also row 4: the correlation id on their tables is unique by constraint. +- Partial when: the episode exists but a leg table this skill needs does not, a leg table lacks `thread_correlation_id` or `api_call_id`, or the episode keeps no `recipient_code`. The skill adds its tables and columns in a new migration. + +### `foundation.callback` (7.3) + +- Look for: routes under `/v1/` ending in `on_submit`, `on_check`, `on_request`, `/v1/error`, or a route with `callback` in it; `JWEPayload`, `ProtocolResponse`, `x-hcx-correlation_id`, `x-hcx-api_call_id`, a receipt with `protocol_status`. +- Present when: 7.3 Validate rows 1 to 5, 7 and 8 are observed by calling the receiving end with deliveries of the transport's kind (every inbound path reaches it; an unreadable body is archived and changes nothing; one api call id delivered twice changes state once and is `ignored`; an unknown correlation id is answered and archived under `unmatched`; a delivery is archived even when the apply raises; no outbound call during a delivery; the inbound authentication of the kind). Row 6, the door refusal, is checked by each skill on its own thread. +- Partial when: it receives but routes by path instead of by correlation id, lacks the dedupe, archives after applying, answers the exchange with anything but the 202 receipt (`own`, `existing`), hosts no `/v1/error`, or, with `adapter`, has no poll fallback. Extend it; there is one door. +- A skill whose reader is not wired into the door is partial for its own capability, not for the door. + +### `foundation.state` (7.11) + +- Look for: `query_mode`, `resubmit`, `1518`, a workflow id table (`"12"`, `"PC01"`, `"161"`), `sub_stage`, `next_actions`, a stamp after each write. +- Present when: 7.11 Validate rows 1 to 3 are observed (`adapter_for` with `1518@hcx` and `1518` gives PMJAY and an unknown code gives generic; the PMJAY workflow table equals `references/flow-knowledge.md` section 2; an override changes one kind only), and rows 4 to 7 hold on the seeded states the legs built so far can reach. +- Partial when: the payer table exists and the stage machine does not, or the stage machine lacks this skill's stage branches or labels. Each skill adds its own. + +### `foundation.screens` (7.12) + +- Look for: routes like `/claims`, `/claims/`, `/claims//state`; the tab keys `eligibility`, `plan`, `lines`, `validate`, `preauth`, `communication`, `claim`, `payments`. +- Present when: 7.12 Validate rows 1, 3, 8 and 9 are observed on the shell (the eight tabs in the flow's order with the flow's labels; routes answer 200 for a seeded case and 404 for an unknown one; no input or select named for a rate, a payer name, a `preAuthRef`, a UTR or a status; the state address returns `stage`, `sub_stage`, `next_actions` and `legs`). Rows 4 to 7 belong to the skills whose tabs they test. +- Partial when: the case screen exists without some tabs, without the status line, or without the state address. +- An HMIS with its own screens: the shell may live inside them, for example a panel on the admission screen that opens the case. Present is judged on the eight tabs and the state address, not on the look. + +### `foundation.shell` (7.13, standalone only) + +- Present when: every row of 7.13's Validate section is observed. +- In integrate mode: `not applicable`. The HMIS is the shell; stage 3 finds its patients, admissions, practitioners and documents. + +## Who builds what + +| Verdict at stage 0 | What the running skill does | +| --- | --- | +| `absent` | Builds it in stage 7, before its own modules. 7.1 and 7.3 whole, for the transport chosen at stage 1. 7.2: the episode table and this skill's leg tables. 7.11: the payer adapter table whole, and this skill's stage branches and labels. 7.12: the shell with all eight tabs present in order, its own tabs filled, the others showing their empty state. 7.13 whole, in standalone mode. | +| `partial` | Extends it in the existing code, for the difference stage 0 named, and runs the module's whole Validate section after. | +| `present` | Reuses it. Stage 8 still runs the rows this skill depends on. | + +Record: the Foundation row in `STATE.md` with `Built by` (the skill, or `existing`), and the module record `nhcx-build/7-modules/7.N.md` with a part for each skill that touched it. diff --git a/plugins/nhcx/skills/nhcx-payment/core/LADDER.md b/plugins/nhcx/skills/nhcx-payment/core/LADDER.md new file mode 100644 index 000000000..7a6f3f12b --- /dev/null +++ b/plugins/nhcx/skills/nhcx-payment/core/LADDER.md @@ -0,0 +1,185 @@ +# The NHCX build ladder + +This skill is one of seven NHCX skills, one per use case: `nhcx-coverage`, `nhcx-insurance`, `nhcx-preauth`, `nhcx-claim`, `nhcx-communication`, `nhcx-payment` and `nhcx-reprocess`. Each is a folder of its own and runs on its own: it carries this ladder, the stages, the module files, the references, the flow, the templates and the fetch script. The seven copies of these are the same; only `SKILL.md` differs. This file holds what they share. `SKILL.md` says which flow steps, legs, capabilities, modules, pins and test rows are this skill's own, and what it needs from the use cases before it. + +## Paths + +Paths that start with `core/`, `stages/`, `references/`, `fhir/`, `flow/`, `ui/`, `templates/` or `scripts/` are relative to this skill's folder, the one that holds `SKILL.md`. Paths that start with `nhcx-package/` are in the NHCX package, fetched into the target project beside `nhcx-build/` (below). Paths that start with `nhcx-build/` are the workspace in the target project. + +## Getting the material + +Pins, payer fixtures and docs come from the NHCX package, published at https://github.com/nha-in/nhcx-package. `scripts/fetch-package.sh` downloads the latest release, unpacks it to `nhcx-package/` beside `nhcx-build/` and verifies its MANIFEST (pass a link or a local path to use a different build). `references/material.md` says what the package holds, gives the file of every pin by its label (`preauth/request` is `nhcx-package/fhir/B3/preauth-request.json`), and lists what it does not hold. Read it once, at stage 0. + +## What the skills produce + +Software that raises cashless claims on the National Health Claims Exchange (NHCX) with a private insurer and with PMJAY, in one of two shapes: + +| Mode | You start with | You end with | +| --- | --- | --- | +| `integrate` | A working hospital information system (HMIS, EMR, HIS, billing system) in any language | The same system, with a claims module that speaks NHCX through its transport, kept in sidecar tables and removable | +| `standalone` | Nothing | A self-contained claims desk: its own patients, admissions, documents and screens, speaking NHCX through a transport of its own | + +Every message goes through one transport, chosen at stage 1 from three (`references/transport-knowledge.md` section 1): + +| Transport | When | What the build does | +| --- | --- | --- | +| `existing` | Stage 0 found the app already speaks NHCX: its own client, a vendor gateway, an SDK | Wraps it behind 7.1's `send` and 7.3's door, and closes its gaps; never replaces it | +| `own` | The app has no NHCX integration, and the user has not asked for nhcx-adapter | Builds the protocol into the app from NHA's published chapters: the ABDM session token, the key and certificate, the participant record, the recipient's certificate, the JWE, the callback and its receipt | +| `adapter` | Only when the user asks for nhcx-adapter | Downloads it from https://github.com/nha-in/nhcx-adapter/releases and talks plain FHIR to it (`references/api-knowledge.md`) | + +Never propose nhcx-adapter; use it only when the user asks for it. Whichever the transport, the rest of the build sees the same two things: `send`, and a door that receives `{meta, jwe_headers, fhir}`. + +## The seven skills + +One skill per use case. Together they walk the whole flow in `flow/FLOW.md`; each one alone builds its slice. This folder builds only its own row. The others are named so that a verdict can say which skill owns a missing piece. + +| Skill | Flow steps | Legs | Use cases | Pins | +| --- | --- | --- | --- | --- | +| `nhcx-coverage` | F1, F2, F3 | policy search; `v1/coverageeligibility/check` purpose `discovery`, `validation`, `benefits` | A2, B1, D3 | `coverage/{discovery,validation,benefits}` | +| `nhcx-insurance` | F4, F7 | `v1/insuranceplan/request`; lines quoted from the plan | B2, D1 | `insurance` | +| `nhcx-preauth` | F5, F6, F8, F9, F9a, F9b for a `resubmit` payer, F9c, F9d, F9e | auth requirements; `v1/preauth/submit` 12, 19, 13, 131 and predetermination; cancel PC01 | B3, B8 cancel, B9, D2, D4 to D8 | `coverage/authrequirements`, `preauth/{request,enhancement,queryupdate,cancel}` | +| `nhcx-claim` | F10, F11 | `v1/claim/submit` 15; 161 (PMJAY) or 151 (generic); 16 (generic) | B5, D9, D10 | `claim/{request,queryupdate}` | +| `nhcx-communication` | F9b and the claim query for a `communication` payer, F12b | `v1/communication/request` in; `v1/communication/on_request` out | B4 | `communication/response`, and the `communication/request` reader | +| `nhcx-payment` | F12 | `v1/paymentnotice/request` in; `v1/paymentnotice/on_request` out on 17 or the notice's own id | B7, D13 | `payment/notice-ack` | +| `nhcx-reprocess` | F13 | `v1/task/submit`: reprocess and release on 36, status; 37 and the status Task read | A5, B8 reprocess, D11, D12 | `claim/{reprocess,release}` | + +`flow/flow.json` names the skills of every step in `skills`. Fifteen pins, each owned by exactly one skill, plus the communication request read as the sixteenth comparison. + +### The order they depend on + +The use cases depend on one another in the order the episode happens. A full build runs the seven skills top to bottom. Any one can run alone on an app that already has what it needs; stage 0 establishes whether it does, with the checks in this skill's `SKILL.md` under "Prerequisites". The other skills do not have to be installed for that check. + +| Skill | Needs | Because | +| --- | --- | --- | +| `nhcx-coverage` | nothing | It opens the episode | +| `nhcx-insurance` | coverage: an episode with an `eligible` verdict | The plan is fetched for an eligible episode's policy | +| `nhcx-preauth` | coverage (eligible, and its builder for auth requirements); insurance (plan ready, lines quoted) | Items, prices, documents and forms come from the plan; F9 holds `eligible` | +| `nhcx-claim` | preauth: an approved or partial pre-auth with its `preAuthRef`, the dossier, the Claim builder | The claim goes under the pre-auth's number, built by the same builder | +| `nhcx-communication` | preauth or claim: a leg the payer can ask about, with its bundle as sent | A query names a Claim; the reply lifts entries from the bundle sent | +| `nhcx-payment` | claim: a filed claim | A notice is matched by the claim number | +| `nhcx-reprocess` | claim: a decided claim; payment for a release; preauth for status on a pre-auth | A reprocess reopens a decided claim; a release follows a short payment | + +## The foundation + +Six modules carry every leg and belong to no one skill: 7.1 (the transport), 7.2 (storage), 7.3 (the callback door), 7.11 (state and payer adapters), 7.12 (the case screen shell) and 7.13 (the standalone shell). Every skill's stage 0 checks them. The first skill that finds one absent builds it; a skill that runs later on the same app finds it present and reuses it. `core/FOUNDATION.md` says how to recognise each and what makes it present. + +## What compliant means + +Every skill is held to the same points, for its own legs: + +1. Every hospital-side leg the skill owns (`references/flow-knowledge.md` section 1) is sent with its workflow id, and every payer answer on it is read. +2. Every bundle the skill sends matches its pin in `nhcx-package/fhir` byte for byte, `created` excepted. +3. The callback door answers 2xx fast, dedupes on `x-hcx-api_call_id`, archives before it applies, and matches by correlation id first. +4. No screen shows a decision the exchange has not sent, and nothing the exchange already said is retyped. +5. The offline tests pass, and the report says honestly which rungs of the test pyramid were climbed. +6. The software walks the flow in `flow/FLOW.md`, step for step: the same steps in the same order, the same tabs with the same names, the same guards, the same action labels. The flow is copied, never redesigned. +7. Nothing the app already did is built a second time. Every capability stage 0 found present is reused, and validated and tested like new code. + +## The flow + +An NHCX provider desk walks one path from policy search to settlement, and a build from these skills walks it. `flow/FLOW.md` is that path: thirteen steps with their branches, the case screen's eight tabs in order, the status line, the action labels the desk sees, the guards before every send, and what runs on every page load. `flow/flow.json` is the same, machine-readable, with step ids `F1` to `F13`. Read FLOW.md whole at stage 1; stage 4 copies the steps, stage 5 puts the screens on them, stage 7 implements them by id, stage 8 checks every step has a route. An agent that reorders, merges or renames these steps has left the skill. + +## The ladder + +Twelve stages, 0 to 11. Each has one file under `stages/`, reads the artefacts of the stages before it, writes into `nhcx-build/` in the target project, and ends at a gate. A gate is a list of conditions a reader can check without trusting you. Do not start a stage until the gate before it is closed, and never close a gate by asserting it; close it by pointing at the evidence. + +This skill runs every stage over its own slice. Stage 1 is shared with any other NHCX skill that runs on the same app: the first writes it and later ones confirm it. Parts of stages 3 to 6 are the episode's, not the skill's: the first skill to reach them writes those parts whole, and later skills build on them. + +| Stage | File | Scope | Writes | Gate closes when | +| --- | --- | --- | --- | --- | +| 0 | `stages/0-capability-check.md` | this skill | `nhcx-build/0-capability.md` section, `nhcx-build/capabilities.json` entries | Every own, foundation and prerequisite capability has a verdict with observed evidence | +| 1 | `stages/1-idea.md` | shared | `nhcx-build/1-idea.md` | The mode, the payers, the scope of every step with its skill, and the constraints are written and the user has agreed | +| 2 | `stages/2-planning.md` | this skill | `nhcx-build/2-planning.md` section, this skill's block in `nhcx-build/STATE.md` | Every later stage has a size and a proof; every module has its action from stage 0 | +| 3 | `stages/3-discovery.md` | shared rows; this skill's host facts | `nhcx-build/3-discovery.md` | Every host fact this skill needs is answered with proof, or marked as a gap | +| 4 | `stages/4-flow-and-data-mapping.md` | the flow and table homes episode-wide; this skill's bundles | `nhcx-build/4-flow-data-mapping.md`, `nhcx-build/mapping.json` | Every table has a home, every leg the four ids, every bundle of this skill a source map | +| 5 | `stages/5-screen-plan.md` | the case screen shell episode-wide; this skill's tabs | `nhcx-build/5-screen-plan.md`, `nhcx-build/screens.json` | Every value on this skill's screens names its message; the honesty rules hold | +| 6 | `stages/6-code-plan.md` | this skill's modules; the client and configuration episode-wide | `nhcx-build/6-code-plan.md`, `nhcx-build/modules.json` | Every module this skill touches has files, dependencies, a pin and an action | +| 7 | `stages/7-write-code/README.md` and `7.N-*.md` | what stage 0 found absent or partial | Code, plus `nhcx-build/7-modules/7.N.md` | Each module's "Done when" list is met, in order | +| 8 | `stages/8-validate-modules.md` | every module part this skill owns, reused ones included | `nhcx-build/8-validation.md`, `nhcx-build/8-validation/7.N.json` | Every row passes, or carries a named, accepted exception | +| 9 | `stages/9-write-tests.md` | this skill's pins, readers and matrix rows | Test code, plus `nhcx-build/9-tests.md` | Every row this skill owns has a test, or a written reason it cannot | +| 10 | `stages/10-run-tests.md` | this skill's tests | `nhcx-build/10-test-run.md` and the raw outputs | The offline rung passes; the higher rungs are run only when the user starts the services | +| 11 | `stages/11-build-report.md` | this skill | `nhcx-build/11-report.md` section | The report is written from the artefacts, names every gap, and a stranger could resume from it | + +Stage 7 is a module ladder of its own, 7.1 to 7.13. Each module file carries its own Build, Pseudo code, Validate and Tests sections, and names the skills that build it; stage 8 runs the Validate sections and stage 9 writes the Tests sections, so a module is never validated against a checklist written somewhere else. + +## The workspace + +Everything this skill writes lives in one folder in the target project, so the work can be resumed, reviewed and deleted as a unit. When several NHCX skills work on one app they share that folder, whichever skill folder each runs from: each adds its own section or entries and leaves the others alone. + +``` +nhcx-build/ + STATE.md the gate ledger: the shared rows, the foundation, one block per skill + capabilities.json every capability checked, its verdict and its evidence; read and written by every skill + 0-capability.md one section per skill; scratch checks under 0-capability/ + 1-idea.md shared + 2-planning.md one section per skill + 3-discovery.md shared; each row says which skill answered it + 4-flow-data-mapping.md the flow and table homes, then one section per skill; plus mapping.json + 5-screen-plan.md the case screen shell, then one section per skill; plus screens.json + 6-code-plan.md the client and configuration, then one section per skill; plus modules.json + 7-modules/7.1.md .. 7.13.md one record per module; a shared module has a part per skill + 8-validation.md one section per skill; plus 8-validation/7.N.json, each row tagged with its skill + 9-tests.md one section per skill + 10-test-run.md one section per skill; plus 10-test-run/-*.log + 11-report.md a summary across skills, then one section per skill + NOTES.md every place a skill was silent, ambiguous or wrong +``` + +`templates/` holds the skeleton of each artefact. Copy the skeleton, fill it, keep its headings: later stages find things by heading. + +## How to run a stage + +1. Read `nhcx-build/STATE.md`. If stage 1 in the Shared block is open, and this skill's stage 0 is closed, run stage 1. Otherwise find the first open gate in this skill's block. That is the stage to run; do not skip ahead and do not redo a closed stage unless the user asks. +2. Read the stage file. Read the artefacts it lists under Inputs, and this skill's `SKILL.md` row for the stage. Read the references it names, in the sections it names. +3. Do the work. Write the artefact from its template, in this skill's section. +4. Walk the gate. For each condition, write the evidence into STATE.md: a file path, a line, a command and its output. A condition with no evidence stays open. Every artefact that names a step, a tab or an action uses the ids and words from `flow/flow.json`. +5. If a gate needs the user (stage 0 when a prerequisite is missing; stage 1 always when it is first written; stage 10 rungs 3 and 4 always), stop and ask. Otherwise continue to the next stage. + +Resuming later is step 1 again. Nothing lives in your memory; everything lives in `nhcx-build/`. + +You may be asked to run one stage alone with the earlier artefacts already written. Treat those as closed; do not rewrite them. + +## Rules that hold throughout + +- Reading and offline commands only until stage 10 says otherwise. Never start a service or send live traffic unless the user asks. +- Never edit the files in `nhcx-package/`. They are the truth you are held to. +- Build only what stage 0 found absent or partial. A capability found present is reused through its existing code, never built a second time: two transports or two callback doors break the rule that one module sends and one receives. +- Present means a check was observed passing. Code that looks right is partial until its check has run. +- Never build another skill's capability inside this one. When a prerequisite is missing, stop and say which skill owns it. +- When this skill extends a module another skill built, it re-runs that skill's Validate rows for the module. The rows are in the module file, which every skill folder carries. +- This skill writes its own section of a shared artefact and leaves the other skills' sections alone. +- Never hard-code a document code, a package code or a questionnaire url. Take them from the payer's plan or auth-requirements answer. +- Every outbound leg stores three things from the transport's answer: `txn_id`, `correlation_id` and `api_call_id`. Every message is addressed to the policy's processor (`recipient_code`) and carries the beneficiary's ABHA. Every inbound message is matched by `x-hcx-correlation_id` first and by the claim number inside the bundle second. +- Take the decisions from the module files (Build, Rules, Pseudo code) and `fhir/FHIR.md`, and write them in the target's language and conventions. Never invent a shape the pins do not show. +- Write `nhcx-build/NOTES.md` as you go. A fact the skill does not give you is a gap to record, never a guess to bury in code. +- No em dashes anywhere you write. Short sentences. Tables for anything with more than three columns of fact. +- Do not claim a rung of the test pyramid was climbed when it was not. The report's value is its honesty. + +## Reference map + +| File | Holds | Read at | +| --- | --- | --- | +| `core/FOUNDATION.md` | The six foundation capabilities: how to recognise each, what makes it present, who builds it | Stage 0, stage 7 when building one | +| `references/flow-knowledge.md` | The episode and its legs, every workflow id, the two payer kinds, the classification rule, stage vocabulary, the use-case catalogue, rules no document states | Stages 1, 2, 4, 7.4 to 7.11 | +| `references/transport-knowledge.md` | The three transports and when each applies; the contract `send` and the door rely on; building the protocol yourself from NHA's chapters (token, key and certificate, participant record, policy lookup, recipient certificate, JWE, callback and receipt, status and `/v1/error`); wrapping an existing integration; getting nhcx-adapter when asked | Stages 0, 1, 4, 6, 7.1, 7.3 | +| `references/api-knowledge.md` | The nhcx-adapter contract, read only when the user chose the adapter: config, routes, envelope and answer, delivery, ledger, kit endpoints, curl | 7.1 and 7.3, adapter only | +| `references/fhir-knowledge.md` | Every bundle sent and received, element ids, HPIN, consent questionnaires, supportingInfo, LM100, ONS and DTM, the TaskBundle reply, where the pins live, the validator | Stages 4, 6, 7.4 to 7.10, 8 | +| `references/errors-and-debugging.md` | PAYR and ERR codes with meaning and fix, gateway errors, reading a ledger thread, correlation mistakes, redelivery, sandbox pace | Stages 8, 10, 11 | +| `references/testing-knowledge.md` | The test pyramid, the test-case matrix per use case, a skeleton offline test | Stages 2, 9, 10 | +| `fhir/FHIR.md` | The FHIR guide: every bundle sent and read, entries in pinned order, the code systems, pseudo code for each builder and reader, the refusal each rule guards against | Stages 0, 4, 6, 7.4 to 7.10, 8 | +| `ui/UI-GUIDE.md` | The screens: the two honesty rules, where every value comes from, a layout per screen, the state words, pseudo code for the status line, the timeline and the actions | Stages 5, 7.12, 7.13 | +| `flow/FLOW.md`, `flow/flow.json` | The one path an episode walks: steps F1 to F13 and their skills, the tab order, the action labels, the guards, the page-load polls | Stage 1 whole; stages 4, 5, 7, 8 by step id | +| `references/material.md` | Where the pins, fixtures and docs live: the NHCX package, the pin map, what the package lacks | Stage 0, and whenever a cited file is needed | + +## Keeping the seven copies in step + +Everything in this folder except `SKILL.md` is the same in all seven skill folders. A change to one of these files is made in all seven. `diff -r --exclude=SKILL.md` between any two skill folders prints nothing when they agree. + +## Deliverables + +- This skill's sections of `nhcx-build/`, every gate in its STATE.md block closed with evidence or open with a reason. +- Its verdicts in `capabilities.json`, each with the check that decided it. +- Schema additions for its legs (integrate) or its tables in the whole schema (standalone), under the target's conventions. +- Builders and readers for every leg it owns, each compared with its pin in the offline test. +- Its tabs and screens, deriving every state from received messages. +- Tests covering its rows of the matrix, a run record, and a report section a stranger could act on. diff --git a/plugins/nhcx/skills/nhcx-payment/fhir/FHIR.md b/plugins/nhcx/skills/nhcx-payment/fhir/FHIR.md new file mode 100644 index 000000000..90b85cbae --- /dev/null +++ b/plugins/nhcx/skills/nhcx-payment/fhir/FHIR.md @@ -0,0 +1,658 @@ +# NHCX FHIR: the bundles a hospital sends and reads + +Every bundle here is held to a pin in the NHCX package, under `nhcx-package/fhir/B*`. Read `../references/fhir-knowledge.md` for the why; this file is the how. The pseudo code is language-neutral: a `dict` is a JSON object, a `list` is a JSON array, and `ref(url)` is `{"reference": url}`. + +## 1. Conventions every bundle follows + +"Validator" below is the HL7 FHIR validator with the NRCeS `ndhm.in` IG, run as `../references/fhir-knowledge.md` section 11 describes. + +| Rule | Detail | Refusal if broken | +| --- | --- | --- | +| Bundle | `resourceType Bundle`, `type collection`, `id` fixed per shape, `meta.profile` = the NRCES bundle profile | validator error | +| Entries | Every entry has an absolute `fullUrl` under `https://nhcx.abdm.gov.in/...`; every `reference` resolves to a `fullUrl` in the same bundle | validator error, PAYR-10xx | +| Profiles | Every resource carries `meta.profile` = `https://nrces.in/ndhm/fhir/r4/StructureDefinition/` | validator warning | +| No timestamps on requests | No `meta.versionId`, `meta.lastUpdated`, bundle `timestamp` (the communication reply is the exception) | none, but the pin differs | +| Money | `{"value": n, "currency": "INR"}`; whole numbers as integers, never `3300.0` | pin differs | +| Instants | IST with `+05:30`, seconds precision | PAYR on dates | +| Identifiers | Typed with a `type.coding` from the NDHM identifier-type system or HL7 v2-0203, `system` where the pin has one | PAYR-1083 and kin | + +### Code systems, named once + +``` +NDHM = "https://nrces.in/ndhm/fhir/r4/CodeSystem/" +PROFILE = "https://nrces.in/ndhm/fhir/r4/StructureDefinition/" +BASE = "https://nhcx.abdm.gov.in" +HL7 = "http://terminology.hl7.org/CodeSystem/" +SNOMED = "http://snomed.info/sct" +ICD10 = "http://hl7.org/fhir/sid/icd-10" +HPR = "https://hpr.abdm.gov.in" + +ID_TYPE = NDHM + "ndhm-identifier-type-code" # PMJAY, ABHA, HPID, HPIN, CLN +V2_0203 = HL7 + "v2-0203" # MB, MD, NH, NPI, NIIP +V2_0360 = HL7 + "v2-0360" # qualification degrees +ORG_TYPE = HL7 + "organization-type" # prov, pay +ACT_CODE = HL7 + "v3-ActCode" # HIP +REL = HL7 + "subscriber-relationship" # self +PRIORITY = HL7 + "processpriority" # normal +CARE_ROLE = HL7 + "claimcareteamrole" # primary, assist +DX_TYPE = HL7 + "ex-diagnosistype" # admitting +DX_ONADM = HL7 + "ex-diagnosis-on-admission" # yes +FIN_TASK = HL7 + "financialtaskcode" # poll, cancel, reprocess, release, status +FIN_INPUT = HL7 + "financialtaskinputtype" # include +COMM_CAT = HL7 + "communication-category" # notification + +BENEFIT_CAT = NDHM + "ndhm-benefit-category" # Claim.item.category (specialty) +PROC_CODE = NDHM + "ndhm-procedure-code" # Claim.item.productOrService (package) +PROGRAM = NDHM + "ndhm-program-code" # AB-PMJAY +SI_CATEGORY = NDHM + "ndhm-supportinginfo-category" # INV, ONS, OTH, HDS, DIS, NMI, INF, STG +SI_CODE = NDHM + "ndhm-supportinginfo-code" # ADDD, EDT, PSP, DSDE, DTM, DTH, LAMA, DAMA, CQD, ODN +DOC_CODE = BASE + "/document-code" # the plan's MANDxxxx codes, else ODN +TASK_INPUT = NDHM + "ndhm-task-input-type-code" # policyNumber, providerId, claimNumber, intimationNumber, document +TASK_INPUT_X = BASE + "/task-input-type" # amount +TASK_OUTPUT = NDHM + "ndhm-task-output-type" # status +TASK_OUTVAL = NDHM + "ndhm-task-output-value" # paymentack +TASK_CODES = NDHM + "ndhm-task-codes" # deliver +REASON = NDHM + "ndhm-reason-code" # treatmentplanchanged, claimrejected, partialpayment, rejectiondisputed +CAT_CODE = BASE + "/category-code" # CoverageEligibilityRequest.item.category +PRODUCT_CODE = BASE + "/product-code" # CoverageEligibilityRequest.item.productOrService +PROC_TYPE = BASE + "/procedure-type" # conservative, medical, surgical +DOC_TYPE_EXT = settings.document_type_extension_url # on a Communication attachment; participant-defined (nhcx-package/docs/05-FHIR Reference/17-Communication.md). + # The communication/response pin carries its author's own url: the pin comparison sets this from the pin. +``` + +### Shared helpers + +``` +function cc(system, code, display=null): # CodeableConcept + coding = {"code": code}; if system: coding.system = system; if display: coding.display = display + return {"coding": [coding]} + +function typed_id(type_system, type_code, type_display, value, system=null): + out = {"type": cc(type_system, type_code, type_display), "value": value} + if system: out.system = system # put "system" before "value" as the pins do; canonical JSON sorts anyway + return out + +function entry(url, resource): return {"fullUrl": url, "resource": resource} + +function profile(name): return {"profile": [PROFILE + name]} + +function bundle(id, profile_name, entries): # profile_name: "ClaimBundle", "TaskBundle", "CoverageEligibilityRequestBundle" + return {"resourceType": "Bundle", "id": id, "meta": profile(profile_name), "type": "collection", "entry": entries} + +function organization(role, identifier_code, identifier_display, id_value, name, res_id=null): + o = {"resourceType": "Organization", "meta": profile("Organization"), + "identifier": [typed_id(V2_0203, identifier_code, identifier_display, id_value, BASE)], + "type": [cc(ORG_TYPE, role, "Healthcare Provider" if role == "prov" else "Payer")], "name": name} + if res_id: o.id = res_id + return o + +function provider_org(facility, res_id=null): return organization("prov", "NPI", "National provider identifier", facility.hfr_id, facility.name, res_id) +function payer_org(payer, res_id=null): return organization("pay", "NIIP", "National Insurance Payor Identifier (Payor)", strip_hcx(payer.participant_code), payer.name, res_id) +function strip_hcx(code): return code.split("@")[0] + +function money(v): return {"value": int(v) if v == int(v) else round(v, 2), "currency": "INR"} +``` + +## 2. Coverage eligibility request + +Pins: `coverage/{discovery,validation,benefits,authrequirements}`. Sent on `v1/coverageeligibility/check`, workflow id = the case number. Purposes: `discovery` (who covers this person), `validation` (is the policy in force), `benefits` (balances), `auth-requirements` (rule on the quoted items). + +Entries, in order: CoverageEligibilityRequest, Patient, provider Organization, payer Organization, Location, Coverage, PractitionerRole. + +``` +function build_coverage_request(d): + # d: purpose, member_id, policy_code (null on discovery), facility{hfr_id,name}, payer{participant_code,name}, created, items[] (benefits, auth-requirements only) + U = BASE + cer = {"resourceType": "CoverageEligibilityRequest", "meta": profile("CoverageEligibilityRequest"), + "identifier": [{"system": BASE}], "status": "active", + "priority": cc(PRIORITY, "normal", "Normal"), "purpose": [d.purpose], + "patient": ref(U + "/patient"), "created": d.created, + "enterer": ref(U + "/practitioner-role"), "provider": ref(U + "/provider"), + "insurer": ref(U + "/payer"), "facility": ref(U + "/location"), + "insurance": [{"focal": true, "coverage": ref(U + "/coverage")}]} + if d.purpose in ("benefits", "auth-requirements"): + cer.item = [eligibility_item(i) for i in d.items] + patient = {"resourceType": "Patient", "meta": profile("Patient"), + "identifier": [typed_id(ID_TYPE, "PMJAY", "Pradhan Mantri Jan Aarogya Yojana (PMJAY) ID", d.member_id), + typed_id(V2_0203, "MB", "Member Number", d.member_id)]} # no name, no demographics + coverage = {"resourceType": "Coverage", "meta": profile("Coverage"), + "identifier": [typed_id(V2_0203, "NH", "National Health Plan Identifier", d.policy_code or "NONE")], + "status": "active", "type": cc(ACT_CODE, "HIP", "health insurance plan policy"), + "subscriber": ref(U + "/patient"), "subscriberId": d.member_id, "beneficiary": ref(U + "/patient"), + "relationship": cc(REL, "self"), "payor": [ref(U + "/payer")]} + location = {"resourceType": "Location", "name": d.facility.name, "managingOrganization": ref(U + "/provider")} + role = {"resourceType": "PractitionerRole", "meta": profile("PractitionerRole"), + "code": [cc(SNOMED, "307988006", "Medical technician")]} + return bundle("coverage-" + d.purpose.replace("-", "") + "-request-generic", "CoverageEligibilityRequestBundle", [ + entry(U + "/coverage-eligibility/request", cer), entry(U + "/patient", patient), + entry(U + "/provider", provider_org(d.facility)), entry(U + "/payer", payer_org(d.payer)), + entry(U + "/location", location), entry(U + "/coverage", coverage), entry(U + "/practitioner-role", role)]) + +function eligibility_item(i): + # i: category{code,display}, code, display, quantity (integer), tiers[] {code, display} + out = {"category": cc(CAT_CODE, i.category.code, i.category.display), + "productOrService": cc(PRODUCT_CODE, i.code, i.display), + "quantity": {"value": int(i.quantity)}} + if i.tiers: out.modifier = [cc(null, t.code, t.display) for t in i.tiers] # no system on a tier + return out +``` + +Bundle ids: `coverage-discovery-request-generic`, `coverage-validation-request-generic`, `coverage-benefits-request-generic`, `coverage-authrequirements-request-generic`. + +### Reader: CoverageEligibilityResponse + +The payer echoes the request's entries and appends its own; take the last of each type. + +``` +function parse_validation_bundle(b): + resp = last(b, "CoverageEligibilityResponse"); pat = last(b, "Patient"); cov = last(b, "Coverage") + out = {"outcome": resp.outcome, "disposition": resp.disposition, "inforce": resp.insurance[0].inforce, + "auth_required": any(item.authorizationRequired for item in resp.insurance[0].item or []), + "allowed": null, "used": null} + for item in resp.insurance[0].item or []: + for ben in item.benefit or []: + if ben.allowedMoney and (out.allowed is null or ben.allowedMoney.value > out.allowed): + out.allowed = ben.allowedMoney.value; out.used = (ben.usedMoney or {}).value or 0 + out.patient = {"name": pat.name[0].text, "gender": pat.gender, "birthDate": pat.birthDate, + "abha": first_identifier(pat, "ABHA"), "photo": pat.photo[0].data if pat.photo else null} + out.coverage = {"class": cov.class[0].name if cov.class else null, "period": cov.period} + return out +# status: eligible if inforce else not-eligible; balance shown = allowed - used +``` + +### Reader: the auth-requirements ruling + +``` +function parse_auth_bundle(b): + resp = last(b, "CoverageEligibilityResponse"); items = []; requirements = [] + for item in resp.insurance[0].item or []: + items.append({"code": item.productOrService.coding[0].code, "authorised": item.authorizationRequired, + "excluded": item.excluded, "benefit": item.benefit[0] if item.benefit else null}) + for sup in item.authorizationSupporting or []: + text = sup.text or "" # the scheme overloads free text + r = {"line": item.productOrService.coding[0].code, "code": sup.coding[0].code if sup.coding else null, + "display": sup.coding[0].display if sup.coding else text} + if "fullUrl:" in text: r.kind = "form"; r.url = after("fullUrl:", text).strip(); r.stage = "pre" + else: r.kind = "document"; r.stage = "post" if "Type: post" in text else "pre" + r.at_preauth = (r.kind == "form") or (r.stage == "pre") + requirements.append(r) + return {"items": items, "requirements": requirements} +``` + +## 3. Insurance plan request + +Pin: `insurance`. Sent on `v1/insuranceplan/request`, workflow id = the case number. One entry. + +``` +function build_plan_request(policy_code, provider_id): + task = {"resourceType": "Task", "meta": profile("Task"), "status": "requested", "intent": "order", + "code": cc(FIN_TASK, "poll"), + "input": [{"type": cc(TASK_INPUT, "policyNumber"), "valueString": policy_code}, + {"type": cc(TASK_INPUT, "providerId"), "valueString": provider_id}]} + return bundle("insurance-request-generic", "TaskBundle", [entry(BASE + "/insurance/request", task)]) +# no id, no authoredOn, no requester; at least one input is mandatory +``` + +### Reader: the plan + +``` +function parse_plan_bundle(b): + plan = first(b, "InsurancePlan"); forms = {q.url: q for q in all(b, "Questionnaire")} + benefits = {} # keyed by package code + for p in plan.plan or []: # shape 1: package-based + for sc in p.specificCost or []: + specialty = sc.category.coding[0] + for ben in sc.benefit or []: + code = ben.type.coding[0].code; row = benefits.setdefault(code, new_benefit(code, ben.type.coding[0].display, specialty)) + for cost in ben.cost or []: + kind = cost.type.coding[0].code # Procedure | Implant | Stratification + if kind == "Procedure": row.rate = cost.value.value; row.kind = "Procedure" + else: row.extras.append({"kind": kind, "code": cost.qualifiers[0].coding[0].code, "display": cost.qualifiers[0].coding[0].display, "amount": cost.value.value}) + row.conditions.update(read_conditions(ben.extension)); row.requirements += read_requirements(ben.extension) + for cov in plan.coverage or []: # shape 2: coverage-based + for ben in cov.benefit or []: + code = ben.type.coding[0].code; row = benefits.setdefault(code, new_benefit(code, ben.type.coding[0].display, cov.type.coding[0])) + for lim in ben.limit or []: + if lim.code.coding[0].code == code: row.rate = lim.value.value + else: row.extras.append({"kind": "Stratification", "code": lim.code.coding[0].code, "display": lim.code.coding[0].display, "amount": lim.value.value}) + row.conditions.update(read_conditions(ben.extension)); row.requirements += read_requirements(ben.extension) + policy_requirements = read_requirements(plan.extension) # policy-wide: identity proof, consent forms + return {"plan": {"id": plan.id, "name": plan.name}, "benefits": list(benefits.values()), + "policy_requirements": policy_requirements, + "forms": [{"url": u, "title": q.title, "kind": "stg" if "/stgquestionnaire/" in u else "policy", + "questions": [{"linkId": it.linkId, "text": it.prefix or it.text, "type": it.type, + "options": [o.valueString or o.valueCoding.display for o in it.answerOption or []], + "default": first_selected(it)} for it in q.item]} for u, q in forms.items()]} + +function read_conditions(exts): # extension url family "...Claim-Condition": children named by their url tail + out = {} + for e in exts or []: + if "Claim-Condition" in e.url: + for child in e.extension or []: out[tail(child.url)] = child.valueString or child.valueBoolean or child.valueCodeableConcept.coding[0].code + return out + +function read_requirements(exts): # "...Claim-SupportingInfoRequirement": one nested requirement per document + out = [] + for e in exts or []: + if "Claim-SupportingInfoRequirement" in e.url: + for req in e.extension or []: + r = {} + for f in req.extension or []: + if tail(f.url) == "category": r.category = f.valueCodeableConcept.coding[0].code + if tail(f.url) == "code": r.code = f.valueCodeableConcept.coding[0].code; r.display = f.valueCodeableConcept.coding[0].display + if tail(f.url) == "documentationUrl": r.url = f.valueUri or f.valueString + out.append(r) + return out +``` + +## 4. The Claim bundle + +Pins: `preauth/request`, `preauth/enhancement`, `preauth/queryupdate`, `claim/request`, `claim/queryupdate`. One builder, three switches: `leg` (`preauth`, `claim`, `predetermination`), `flow` (`request`, `enhancement`, `queryupdate`), `use` (`preauthorization`, `claim`, `predetermination`). + +Entries, in order: Claim, Patient, provider Organization (id 1), payer Organization (id 2), Coverage (id 1), Practitioner (one per care team member), Procedure (one per package line), QuestionnaireResponse (one per answered form). + +``` +function claim_bundle(leg, use, d): + # d: flow, claim_no, created, admission{admitted_at, discharged_at, surgery_at, death_at, mode, stage}, + # patient{member_id, abha, name, phone, gender, birthDate}, facility, payer, policy_code, + # care_team[] {hpid, licence, hpin, name, qualification_code, qualification_display, specialty_snomed, specialty_display}, + # diagnoses[] {code, display}, lines[] (procedures and implants, each with tiers[]), documents[] {code, category, content_type, bytes, title}, + # forms[] {url, answers[] {linkId, type, value}}, program_code (AB-PMJAY or null), factor_rule (pmjay or null), + # preauth_ref (claim leg), summary{code, content_type, bytes, title} (claim leg), query_reply (queryupdate) + U = BASE; anchor = U + "/" + leg + "/" + d.flow + practitioners = [practitioner_resource(m, n + 1) for n, m in enumerate(d.care_team)] + procedures = [procedure_resource(line, n + 1, completed = (leg == "claim"), when = d.admission.surgery_at or d.admission.admitted_at) for n, line in enumerate(package_lines(d.lines))] + (qrs, form_refs) = questionnaire_responses(d.forms, d.created) + (si, si_refs) = supporting_info(d, leg, form_refs) + claim = {"resourceType": "Claim", "id": d.claim_no, "meta": profile("Claim"), + "identifier": [typed_id(ID_TYPE, "CLN", "Claim number", d.claim_no, BASE)], + "status": "active", "type": cc(SNOMED, "737481003", "Inpatient care management (procedure)"), "use": use, + "patient": ref(U + "/patient"), + "billablePeriod": {"start": d.admission.admitted_at, "end": d.admission.discharged_at or planned_end(d)}, + "created": d.created, "insurer": ref(U + "/payer"), "provider": ref(U + "/provider"), + "priority": cc(PRIORITY, "normal", "Normal"), + "careTeam": [{"sequence": n + 1, "provider": ref(practitioner_url(n)), + "role": cc(CARE_ROLE, "primary" if n == 0 else "assist", "Primary provider" if n == 0 else "Assisting Provider"), + "qualification": cc(SNOMED, m.specialty_snomed, m.specialty_display)} for n, m in enumerate(d.care_team)], + "supportingInfo": si, + "diagnosis": [{"sequence": n + 1, "diagnosisCodeableConcept": cc(ICD10, dx.code, dx.display), + "type": [cc(DX_TYPE, "admitting", "Admitting Diagnosis")], "onAdmission": cc(DX_ONADM, "yes", "Yes")} for n, dx in enumerate(d.diagnoses)], + "procedure": [{"id": "Procedure/" + str(n + 1), "sequence": n + 1, + "type": [cc(PROC_TYPE, line.procedure_type.lower(), line.procedure_type)], # from the plan's ProcedureType condition + "date": d.admission.surgery_at or d.admission.admitted_at, + "procedureReference": {"reference": U + "/procedure/" + str(n + 1), "display": line.display}} for n, line in enumerate(package_lines(d.lines))], + "insurance": [{"sequence": 1, "focal": true, "coverage": ref(U + "/coverage")}], + "item": claim_items(d, si_refs), + "total": money(sum(item.net.value for item in items))} + if leg == "claim": claim.insurance[0].preAuthRef = [d.preauth_ref] # the payer's ClaimResponse.preAuthRef + entries = [entry(anchor, claim), entry(U + "/patient", patient_resource(d.patient)), + entry(U + "/provider", provider_org(d.facility, "1")), entry(U + "/payer", payer_org(d.payer, "2")), + entry(U + "/coverage", coverage_resource(d.policy_code, d.patient.member_id))] + entries += [entry(practitioner_url(n), p) for n, p in enumerate(practitioners)] + entries += [entry(U + "/procedure/" + str(n + 1), p) for n, p in enumerate(procedures)] + entries += [entry(U + "/questionnaireresponse/" + str(n + 1), q) for n, q in enumerate(qrs)] + return bundle(leg + "-" + d.flow + "-request-generic", "ClaimBundle", entries) + # preauth-request-generic, preauth-enhancement-request-generic, preauth-queryupdate-request-generic, claim-request-generic, claim-queryupdate-request-generic + +function practitioner_url(n): return BASE + "/practitioner" + ("" if n == 0 else "/" + str(n + 1)) + +function patient_resource(p): + ids = [typed_id(ID_TYPE, "PMJAY", "Pradhan Mantri Jan Aarogya Yojana (PMJAY) ID", p.member_id)] + if p.abha: ids.append(typed_id(ID_TYPE, "ABHA", "Ayushman Bharat Health Account (ABHA) ID", p.abha)) + ids.append(typed_id(V2_0203, "MB", "Member Number", p.member_id)) + return {"resourceType": "Patient", "id": "1", "meta": profile("Patient"), "identifier": ids, + "name": [{"text": p.name}], "telecom": [{"system": "phone", "value": p.phone}], "gender": p.gender, "birthDate": p.birthDate} + +function practitioner_resource(m, n): + ids = [typed_id(ID_TYPE, "HPID", "Healthcare Professional ID (HPID)", m.hpid or m.hpin, BASE)] + if m.licence: ids.append(typed_id(V2_0203, "MD", "Medical License number", m.licence, BASE)) + ids.append(typed_id(ID_TYPE, "HPIN", "Health Practitioner ID issued by NDHM", m.hpin, HPR)) # PAYR-1083 without it + return {"resourceType": "Practitioner", "id": str(n), "meta": profile("Practitioner"), "identifier": ids, + "name": [{"text": m.name}], "qualification": [{"code": cc(V2_0360, m.qualification_code, m.qualification_display)}]} + +function coverage_resource(policy_code, member_id): + return {"resourceType": "Coverage", "id": "1", "meta": profile("Coverage"), + "identifier": [typed_id(V2_0203, "NH", "National Health Plan Identifier", policy_code)], + "status": "active", "type": cc(ACT_CODE, "HIP", "health insurance plan policy"), + "subscriber": ref(BASE + "/patient"), "subscriberId": member_id, "beneficiary": ref(BASE + "/patient"), + "relationship": cc(REL, "self"), "payor": [ref(BASE + "/payer")]} + +function procedure_resource(line, n, completed, when): + return {"resourceType": "Procedure", "id": str(n), "meta": profile("Procedure"), + "status": "completed" if completed else "preparation", + "code": {"coding": [{"system": SNOMED, "code": "71388002", "display": "Procedure"}], "text": line.display}, + "subject": ref(BASE + "/patient"), "performedDateTime": when} +``` + +### Items: one per procedure or implant, never per tier + +``` +function package_lines(lines): return [l for l in lines if l.kind in ("procedure", "implant")] # tiers ride on their parent + +function claim_items(d, si_refs): + groups = package_lines(d.lines); factors = procedure_factors(groups, d.factor_rule) + items = [] + for n, line in enumerate(groups): + tiers = [t for t in d.lines if t.kind == "tier" and t.parent_code == line.code] + net = line.amount + sum(t.amount for t in tiers) + item = {"id": "Item/" + str(n + 1), "sequence": n + 1, "careTeamSequence": [1], "diagnosisSequence": [1], + "procedureSequence": [n + 1], "informationSequence": si_refs, # every supportingInfo sequence + "category": cc(BENEFIT_CAT, line.category.code, line.category.display), + "productOrService": cc(PROC_CODE, line.code, line.display)} + if tiers: item.modifier = [cc(null, t.code, t.display) for t in tiers] + if d.program_code: item.programCode = [cc(PROGRAM, d.program_code, "Ayushman Bharat Pradhan Mantri Jan Arogya Yojana (AB-PMJAY)")] + item.servicedPeriod = {"start": day(d.admission.admitted_at), "end": day(d.admission.discharged_at or planned_end(d))} + item.quantity = {"value": int(line.quantity)} + item.unitPrice = money(net / line.quantity) + if factors: item.factor = factors[n] + item.net = money(net) + items.append(item) + return items + +function procedure_factors(groups, rule): + # PMJAY multiple-procedure rule: by cost rank, 1, 0.5, 0.25; a generic payer sends no factor + if rule != "pmjay" or len(groups) < 2: return null # the single-item pins carry factor 0.5 (their own contradiction); compare without it + ranked = sorted(range(len(groups)), key = lambda i: -groups[i].amount) + return {i: [1, 0.5, 0.25][min(rank, 2)] for rank, i in enumerate(ranked)} +``` + +### supportingInfo: the table, then the numbering + +``` +function supporting_info(d, leg, form_refs): + si = [] + for doc in d.documents: # one per attached file; never drop one + si.append({"category": cc(SI_CATEGORY, doc.category or "INV", display_for(doc.category or "INV")), + "code": cc(DOC_CODE, doc.code or "ODN", doc.title), # the plan's code, else ODN + "valueAttachment": {"contentType": doc.content_type, "data": base64(doc.bytes), "title": doc.title}}) + if leg == "claim": + si.append({"category": cc(SI_CATEGORY, "HDS", "Discharge summary"), "code": cc(DOC_CODE, d.summary.code or "HDS", d.summary.title), + "valueAttachment": {"contentType": d.summary.content_type, "data": base64(d.summary.bytes), "title": d.summary.title}}) + si.append(scalar("ONS", "ADDD", "Admission date -Discharge date", d.admission.admitted_at)) + si.append(scalar("OTH", "EDT", "EncounterDateTime", d.admission.admitted_at)) + if leg == "claim": + if d.admission.surgery_at: si.append(scalar("ONS", "PSP", "Procedure start", d.admission.surgery_at)) + si.append(scalar("ONS", "DSDE", "Discharge date", d.admission.death_at or d.admission.discharged_at)) + if d.admission.mode == "death": si.append(scalar("ONS", "DTM", "Date and time of death", d.admission.death_at)) # PAYR-1096 without it + code = {"normal": "DTH", "lama": "LAMA", "dama": "DAMA", "death": "DTM"}[d.admission.mode] + si.append(scalar("DIS", code, display_for(code), stage_words(d.admission.stage))) # "Before Surgery" | "During Surgery" | "After Surgery" + if d.flow == "queryupdate": + si.append(scalar("NMI", "CQD", "Claim query detail", d.query_reply)) # the desk's words; PMJAY reads its answer from here + for (form, url) in form_refs: # one per answered form + cat = "STG" if form.kind == "stg" else "INF"; code = "STG" if form.kind == "stg" else "ODN" + si.append({"category": cc(SI_CATEGORY, cat, display_for(cat)), "code": cc(SI_CODE, code, display_for(code)), "valueReference": ref(url)}) + for n, s in enumerate(si): # number once, after assembly: PAYR-1019 without sequence + s.id = "SupportingInformation/" + str(n + 1); s.sequence = n + 1 + reorder(s, ["id", "sequence", "category", "code", "value*"]) + return (si, [s.sequence for s in si]) + +function scalar(cat, code, display, value): + return {"category": cc(SI_CATEGORY, cat, display_for(cat)), "code": cc(SI_CODE, code, display), "valueString": value} +``` + +### Questionnaire responses + +``` +function questionnaire_responses(forms, authored): + qrs = []; refs = [] + for n, form in enumerate(forms): + url = BASE + "/questionnaireresponse/" + str(n + 1) + qr = {"resourceType": "QuestionnaireResponse", "id": str(n + 1), "meta": profile("QuestionnaireResponse"), + "questionnaire": form.url, "status": "completed", "subject": ref(BASE + "/patient"), "authored": authored, + "item": [{"linkId": a.linkId, "answer": [typed_answer(a)]} for a in form.answers]} + qrs.append(qr); refs.append((form, url)) + return (qrs, refs) + +function typed_answer(a): + switch a.type: + "string", "text", "choice": return {"valueString": a.value} + "date", "dateTime": return {"valueDateTime": a.value} + "boolean": return {"valueBoolean": a.value} + "integer": return {"valueInteger": int(a.value)} + "decimal": return {"valueDecimal": a.value} + "attachment": return {"valueAttachment": {"contentType": a.content_type, "data": base64(a.bytes), "title": a.title}} +``` + +### Which forms and documents ride + +``` +function required_forms(case, stage): # stage: preauth | claim + if case.ruling: forms = [r for r in case.ruling.requirements if r.kind == "form" and (stage == "preauth" or r.stage != "pre")] + else: forms = plan_stg_forms(case.plan, case.lines) if stage == "preauth" else [] + return forms + policy_forms(case.plan) # consent every leg: PAYR-1256 / PAYR-1363; STG: PAYR-1254 / PAYR-1365 + +function required_documents(case, stage): + if case.ruling: return [r for r in case.ruling.requirements if r.kind == "document" and (r.stage == "pre") == (stage == "preauth")] + wanted = plan_documents(case.plan, case.lines) + return wanted if stage == "preauth" else [w for w in wanted if not attached_at_preauth(case, w.code)] +``` + +### The legs, and the LAMA collapse + +``` +function lines_for(case, leg): + if leg == "claim" and case.admission.mode in ("lama", "dama") and case.admission.stage in ("before", "during"): + return [{"kind": "procedure", "code": "LM100", "display": "Left against medical advice", "quantity": 1, + "amount": plan_rate(case.plan, "LM100") or 0, "category": lm100_category(case.plan)}] # PAYR-1362 if the package stays + return case.lines # LM100 never on a pre-auth: PAYR-1270 +``` + +| Leg | flow | use | Procedure status | Workflow | Extra | +| --- | --- | --- | --- | --- | --- | +| Pre-auth | `request` | `preauthorization` | `preparation` | 12 | fresh 12 after a rejection too (PAYR-1214 on 121) | +| Enhancement | `enhancement` | `preauthorization` | `preparation` | 13 | every line, old and new, same claim number; factors 1 and 0.5 | +| Query answer | `queryupdate` | `preauthorization` | `preparation` | 19 (131 after an enhancement query) | `NMI/CQD`; new correlation id | +| Claim | `request` | `claim` | `completed` | 15 | discharge scalars, `HDS`, `preAuthRef`, under the pre-auth's number (ERR-PYR-CLM-007) | +| Claim query answer | `queryupdate` | `claim` | `completed` | 161 (PMJAY), 151 (generic) | as the claim plus `NMI/CQD` | +| Predetermination | `request` | `predetermination` | `preparation` | 12 on `v1/preauth/submit` | no state effects | + +## 5. Reader: ClaimResponse + +Fed by every answer on a pre-auth, enhancement, claim or predetermination thread. Entries: ClaimResponse, Patient, two Organizations, Coverage. + +``` +function parse_claim_response(b): + r = first(b, "ClaimResponse") + status_adj = first(a for a in r.adjudication or [] if a.category.coding[0].code == "status") + out = {"use": r.use, "outcome": r.outcome, "disposition": r.disposition, + "status_reason": status_adj.reason.coding[0].code.lower() if status_adj else null, # submitted|approved|queried|rejected|cancelled + "preauth_ref": r.preAuthRef if is_string(r.preAuthRef) else (r.preAuthRef[0] if r.preAuthRef else null), + "claim_no": r.identifier[0].value if r.identifier else null, + "totals": {t.category.coding[0].code: t.amount.value for t in r.total or []}, # by category, never by position + "items": [], "notes": [n.text for n in r.processNote or []]} + for it in r.item or []: + adj = {a.category.coding[0].code: a for a in it.adjudication or []} + out.items.append({"sequence": it.itemSequence, + "status": adj.status.reason.coding[0].code.lower() if adj.status else null, + "eligible": adj.eligible.amount.value if adj.eligible else null, + "submitted": adj.submitted.amount.value if adj.submitted else null, + "reason": adj.reason.reason.coding[0].display if adj.reason else "", # verbatim, pipe-delimited USER~datetime~type~comment~trust + "eligpercent": adj.eligpercent.value if adj.eligpercent else null, + "deductible": adj.deductible.amount.value if adj.deductible else null}) + return out + +function verdict_status(p): # copy exactly; never read outcome alone + if p.outcome == "queued" or p.status_reason == "submitted": return "submitting" + if p.status_reason == "cancelled": return "rejected" + if p.status_reason == "queried": return "queried" + if p.outcome == "error": return "rejected" + if p.outcome == "partial": return "partial" if p.status_reason == "approved" else "queried" + if p.outcome == "complete": return "approved" if p.status_reason in ("approved", null) else "queried" + return "queried" + +function apply_claim_response(leg, p, envelope): + leg.status = verdict_status(p) + if p.preauth_ref: leg.preauth_ref = p.preauth_ref # never overwrite a value with an empty one + leg.eligible_amount = p.totals.get("eligible") or p.totals.get("benefit") + leg.submitted_amount = p.totals.get("submitted") + leg.approved_amount = p.totals.get("benefit") # what the screen shows as the decision + leg.items_json = p.items; leg.query_note = join(p.notes + [i.reason for i in p.items if i.reason]) + leg.thread_correlation_id = envelope.jwe_headers["x-hcx-correlation_id"] + leg.answered_at = now() if leg.status != "submitting" else leg.answered_at +``` + +Payer workflow ids are labels for the timeline only: 20 received, 21 approved, 22 enhancement approved, 23 rejected, 24 queried, 25 claim received, 26 approved, 27 queried, 291 rejected. The bundle decides the state. + +## 6. Task bundles the hospital sends + +Pins: `preauth/cancel`, `claim/reprocess`, `claim/release`, `payment/notice-ack`. Sent on `v1/task/submit` (the payment acknowledgement on `v1/paymentnotice/on_request`). Entries: Task, provider Organization, payer Organization. + +``` +function task_bundle(id, anchor, task, facility, payer): + return bundle(id, "TaskBundle", [entry(BASE + anchor, task), entry(BASE + "/provider", provider_org(facility)), entry(BASE + "/payer", payer_org(payer))]) + +function base_task(code, status, authored_on, description): + return {"resourceType": "Task", "meta": profile("Task"), "status": status, "intent": "order", + "code": cc(FIN_TASK, code), "description": description, "authoredOn": authored_on, + "requester": ref(BASE + "/provider"), "owner": ref(BASE + "/payer")} + +function task_input(code, display, value): return {"type": cc(TASK_INPUT, code, display), "valueString": value} +function based_on(claim_no): return [{"identifier": typed_id(ID_TYPE, "CLN", "Claim number", claim_no, BASE), "display": "Claim " + claim_no}] + +function cancel_task(claim_no, reason, authored_on, facility, payer): # workflow PC01 + t = base_task("cancel", "requested", authored_on, "Cancel the preauthorization " + claim_no) + t.reasonCode = cc(REASON, reason.code, reason.display) # treatmentplanchanged, ... + t.input = [task_input("claimNumber", "ClaimNumber", claim_no), task_input("intimationNumber", "IntimationNumber", claim_no)] + return task_bundle("preauth-cancel-request-generic", "/preauth/cancel", t, facility, payer) + +function reprocess_task(claim_no, member_id, reason, description, documents, authored_on, facility, payer): # workflow 36 + t = base_task("reprocess", "requested", authored_on, description) + t.reasonCode = cc(REASON, reason.code, reason.display) # claimrejected | partialpayment | rejectiondisputed + t.basedOn = based_on(claim_no) + t.input = [task_input("claimNumber", "ClaimNumber", claim_no), task_input("intimationNumber", "IntimationNumber", claim_no)] + t.input += [{"type": cc(TASK_INPUT, "document", "Document"), "valueAttachment": {"contentType": d.content_type, "data": base64(d.bytes), "title": d.title}} for d in documents] + t.for = {"identifier": typed_id(ID_TYPE, "PMJAY", "Pradhan Mantri Jan Aarogya Yojana (PMJAY) ID", member_id)} # MB on a generic payer + return task_bundle("claim-reprocess-request-generic", "/claim/reprocess", t, facility, payer) + +function release_task(claim_no, amount, authored_on, facility, payer): # workflow 36 + t = base_task("release", "requested", authored_on, "Release the balance amount for claim " + claim_no) + t.reasonCode = cc(REASON, "partialpayment", "Reprocess request due to partial payment by payer") + t.basedOn = based_on(claim_no) + t.input = [task_input("claimNumber", "ClaimNumber", claim_no), {"type": cc(TASK_INPUT_X, "amount", "Amount"), "valueMoney": money(amount)}] + return task_bundle("claim-release-request-generic", "/claim/release", t, facility, payer) + +function status_task(claim_no, authored_on, facility, payer): # workflow = the leg's correlation id; PMJAY refuses (PAYR-1018) + t = base_task("status", "requested", authored_on, "Status of " + claim_no) + t.input = [task_input("claimNumber", "ClaimNumber", claim_no)] + return task_bundle("claim-status-request-generic", "/claim/status", t, facility, payer) + +function payment_ack(claim_no, authored_on, facility, payer): # workflow 17 (PMJAY) or the notice's own id; x-hcx-correlation_id = the notice's + t = base_task("status", "completed", authored_on, "Received the payment for claim " + claim_no) + t.output = [{"type": cc(TASK_OUTPUT, "status", "Status"), "valueCodeableConcept": cc(TASK_OUTVAL, "paymentack", "Payment is acknowledged")}, + {"type": cc(TASK_INPUT, "claimNumber", "ClaimNumber"), "valueString": claim_no}] + return task_bundle("payment-notice-ack-generic", "/payment/notice-ack", t, facility, payer) +``` + +The pins and the build both carry `intimationNumber`, so the offline comparison diffs the pins unchanged. + +### Readers: PC02, 37, status + +``` +function parse_task_answer(b): + t = first(b, "Task"); cr = first(b, "ClaimResponse") # a 37 may carry a ClaimResponse queued + outputs = {o.type.coding[0].code: o for o in t.output or []} + return {"status": t.status, "code": t.code.coding[0].code, + "claim_status": (outputs.get("claimStatus") or outputs.get("status") or {}).valueCodeableConcept.coding[0].code if outputs else null, + "description": t.description, "queued": cr is not null and cr.outcome == "queued"} +# PC02: pre-auth -> cancelled, episode gets a fresh claim number, the withdrawn one stays on the leg +# 37: enquiry row -> answered; a fresh verdict follows on the claim's own thread +``` + +## 7. Communication + +Pins: `communication/request` (the payer's TaskBundle, the reader's input) and `communication/response` (the hospital's reply). On `v1/communication/request` in, `v1/communication/on_request` out, with the request's correlation id and workflow id echoed. + +``` +function parse_communication_request(b): + t = first(b, "Task"); cr = first(b, "CommunicationRequest") + return {"task_status": t.status, "intent": t.intent, "reason": t.reasonCode.coding[0].code.lower() if t.reasonCode else null, + "request_id": cr.id, "request_url": fullurl_of(b, cr), + "questions": [p.contentString for p in cr.payload or [] if p.contentString], + "about_claim": (cr.basedOn or [{}])[0].display, "claim_no": claim_no_in(b)} + +function classify_communication(adapter, reason, intent): + if adapter.query_mode == "resubmit": return "notification" + if intent == "proposal": return "notification" + if intent == "order": return "query" + if reason in (null, "additionalinfo", "questionnaire", "query"): return "query" + return "notification" # tatquery, grievance, walletupdate, policychange, claimarbitration + +function build_acknowledgement_bundle(request_bundle, facility): # a notification, sent back at once + b = deepcopy(request_bundle); t = first(b, "Task"); t.status = "completed" + move_first(b, "Organization", where = provider) # provider Organization first + return b + +function build_communication_bundle(q, text, documents, sent_leg_bundle, facility, payer, now): + # q: the parsed request; sent_leg_bundle: the pre-auth or claim bundle as sent (its Claim, Patient, Organizations, Practitioner, Coverage are lifted) + task_id = uuid(); comm_id = uuid() + comm = {"resourceType": "Communication", "id": comm_id, "meta": profile("Communication"), + "identifier": [{"value": q.request_identifier}], "basedOn": [{"reference": q.request_url, "display": "CommunicationRequest"}], # never inResponseTo + "status": "completed", "category": [cc(COMM_CAT, "notification")], "priority": "routine", + "about": [{"reference": claim_anchor(sent_leg_bundle), "display": "Claim " + claim_no}], + "sender": {"reference": BASE + "/provider", "display": "Organization"}, "recipient": [{"reference": BASE + "/payer", "display": "Organization"}], + "payload": [{"contentString": text}] + [{"contentAttachment": {"contentType": d.content_type, "data": base64(d.bytes), "title": d.title}, + "extension": [{"url": DOC_TYPE_EXT, "valueString": d.code}]} for d in documents]} + task = {"resourceType": "Task", "id": task_id, "meta": profile("Task"), "status": "completed", "intent": "order", + "code": cc(TASK_CODES, "deliver"), "reasonCode": cc(null, q.reason or "additionalinfo", "Additional information requested"), + "authoredOn": now, "requester": {"reference": BASE + "/provider", "display": "Organization"}, "owner": {"reference": BASE + "/payer", "display": "Organization"}, + "input": [{"type": cc(FIN_INPUT, "include"), "valueReference": {"reference": "urn:uuid:" + comm_id, "display": "Communication"}}]} + entries = [entry("urn:uuid:" + task_id, task), entry("urn:uuid:" + comm_id, comm), entry(q.request_url, q.request_resource)] + entries += [entry(e.fullUrl, e.resource) for e in sent_leg_bundle.entry if e.resource.resourceType in ("Claim", "Patient", "Organization", "Practitioner", "Coverage")] + b = bundle("communication-response-generic", "TaskBundle", entries) + b.meta.lastUpdated = now; b.timestamp = now # the IG example carries both; the only request that does + return b +``` + +Excluded from the byte comparison of the reply: `meta.lastUpdated`, `timestamp`, `authoredOn`, the two generated uuids. + +## 8. Payment notice + +Read on `v1/paymentnotice/request`. Entries: Task, PaymentNotice, PaymentReconciliation, two Organizations. + +``` +function parse_payment_notice(b): + pn = first(b, "PaymentNotice"); pr = first(b, "PaymentReconciliation"); t = first(b, "Task") + out = {"claim_no": pn.identifier[0].value if pn.identifier else claim_no_in(b), + "amount": pn.amount.value, "payment_status": pn.paymentStatus.coding[0].code, # paid | cleared | ... + "payment_date": pn.paymentDate, "utr": null, "details": []} + if pr: + out.utr = pr.paymentIdentifier.value if pr.paymentIdentifier else null + out.gross = pr.paymentAmount.value if pr.paymentAmount else null + out.details = [{"type": d.type.coding[0].code, "amount": d.amount.value if d.amount else null} for d in pr.detail or []] # deductions, TDS + if not out.utr and pn.payment and pn.payment.identifier: out.utr = pn.payment.identifier.value + return out +# record: one claim_payment row keyed on the message's correlation id (unique), matched by claim_no; then acknowledge with payment_ack() +``` + +## 9. Validate before you send + +``` +function validate_bundle(b, pin): # the offline gate, module 7.7 Validate + assert canonical(strip(b, ["created"])) == canonical(strip(pin, ["created"])) # plus the per-shape exclusions above + urls = {e.fullUrl for e in b.entry} + for r in all_references(b): assert r in urls or r.startswith("urn:uuid:") + c = first(b, "Claim") + if c: + for it in c.item: assert it.id and it.sequence + for p in c.procedure: assert p.id and p.sequence + for n, s in enumerate(c.supportingInfo): assert s.id and s.sequence == n + 1 + for pr in all(b, "Practitioner"): assert any(i.type.coding[0].code == "HPIN" and i.system == HPR for i in pr.identifier) + assert c.total.value == sum(it.net.value for it in c.item) + assert not any(it.productOrService.coding[0].code == "LM100" for it in c.item) or c.use == "claim" + assert no literal in the builder matches r"MAND\d+|MG\d+|/questionnaire/" +``` + +| Symptom | Refusal | +| --- | --- | +| an item without `id` | PAYR-1027 | +| a supportingInfo without `sequence` | PAYR-1019 | +| a Practitioner without `HPIN` | PAYR-1083 | +| a death claim without `ONS/DTM` | PAYR-1096, PAYR-1503 | +| a LAMA claim before surgery still carrying the package | PAYR-1362 | +| `LM100` on a pre-auth | PAYR-1270 | +| the consent form unanswered | PAYR-1256 (pre-auth), PAYR-1363 (claim) | +| a package's STG form unanswered | PAYR-1254, PAYR-1365 | +| a claim under its own number | ERR-PYR-CLM-007 | +| 121 after a rejection | PAYR-1214 | +| 151, 19 or 16 on `v1/claim/submit` to PMJAY | PAYR-1321 | +| a document outside pdf, jpg, jpeg, png; a Task the sandbox does not take; a misspelt intimation input on a reprocess | PAYR-1008 | diff --git a/plugins/nhcx/skills/nhcx-payment/flow/FLOW.md b/plugins/nhcx/skills/nhcx-payment/flow/FLOW.md new file mode 100644 index 000000000..312668e67 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-payment/flow/FLOW.md @@ -0,0 +1,228 @@ +# The flow: the one path a claim episode walks + +This is the reference flow for an NHCX provider desk: these steps, in this order, with these guards and these words. A build from this skill walks the same path. It does not redesign it, reorder it, merge steps, or invent screens the path does not have. Stage 4 copies it, stage 5 puts screens on it, stage 7 implements it step by step, stage 8 checks every step exists, and test drivers check the same through `flow.json`. + +## The shape + +One episode is one case (`claim` row). It has one list screen, one "new case" screen and one case screen. The case screen has tabs in the order the episode happens, and above the tabs one status line and the actions the case is waiting for. Everything else (inbox, payments across cases) is a view over the same rows. + +Tabs on the case screen, in this order and with these names: + +| # | Tab key | Tab label | Opens when | +| --- | --- | --- | --- | +| 1 | `eligibility` | Eligibility | always | +| 2 | `plan` | Insurance plan | always (empty until the plan is fetched) | +| 3 | `lines` | Line items | always (quoting refused until the plan is `ready`) | +| 4 | `validate` | Validate | always (the ruling on the quoted set) | +| 5 | `preauth` | Pre-authorisation | once the coverage verdict is `eligible` | +| 6 | `communication` | Communication | always (the payer's questions on both legs) | +| 7 | `claim` | Claim | always; its submit opens once a pre-auth is approved or partial | +| 8 | `payments` | Payments | always | + +The episode may also render on one page, with the same sections in the same order. Either shape is fine; the order and the gating are not negotiable. + +## Which skill builds which step + +Seven skills build this flow, one slice each (`core/LADDER.md`). `flow.json` names them per step in `skills`, the first named being the one that owns the step. + +| Steps | Skill | +| --- | --- | +| F1, F2, F3 | `nhcx-coverage` | +| F4, F7 | `nhcx-insurance` | +| F5, F6, F8, F9, F9a, F9c, F9d, F9e; F9b for a `resubmit` payer (19, 131) | `nhcx-preauth` | +| F10, F11; the claim query answer for a `resubmit` payer (161) | `nhcx-claim` | +| F9b and the claim query for a `communication` payer; F12b | `nhcx-communication` | +| F12 | `nhcx-payment` | +| F13 | `nhcx-reprocess` | + +The case screen, its tabs, the status line and actions, and the page-load polls are the foundation's (`core/FOUNDATION.md`): the first skill lays them out whole, and each skill fills its own tabs. + +## The status line and the actions + +Above the tabs: `stage / sub-stage` from `case_stage` (module 7.11) and the list from `next_actions`, first item highlighted. The labels are these, verbatim: + +| Stage | Sub-stage | Action offered (label, tab) | +| --- | --- | --- | +| any | an open query exists | "Answer the payer (n)", `communication` (leads every list) | +| `eligibility` | `draft`, `error`, `not-eligible` | "Check the cover", `eligibility` | +| `eligibility` | `eligible`, no plan `ready` | "Fetch the package master", `plan` | +| `eligibility` | plan ready, no lines | "Quote the treatment", `lines` | +| `eligibility` | lines quoted | "Send the pre-authorisation", `preauth` | +| `preauth` or `enhancement` | `queried` | "Answer the query", `preauth` (resubmit payer) or "Answer the payer's query", `communication` (communication payer) | +| `preauth` | `draft`, `refused` | "Send the pre-authorisation", `preauth` | +| `preauth` | `rejected` | "Send a fresh pre-authorisation", `preauth` | +| `preauth` | `approved`, `partial`, lines added since | "Send the enhancement (n added)", `preauth` | +| `preauth` | `approved`, `partial`, not discharged | "Record the discharge", `claim` | +| `preauth` | `approved`, `partial`, discharged | "File the claim", `claim` | +| `preauth` | `requested`, `answered`, `resubmitted` | "With the payer; ask where it stands", `preauth` | +| `claim` | `queried` | "Answer the claim query", `claim` or "Answer the payer's query", `communication` | +| `claim` | `rejected`, `partial` | "Ask for a reprocess", `claim` | +| `claim` | `requested`, `answered`, `resubmitted` | "With the payer; ask where it stands", `claim` | +| `claim` | `refused` | "Send the claim again", `claim` (while a send kind remains) else "Ask for a reprocess" | +| `claim` | `approved` | "Await the payment notice", `payments` | +| `payment` | a notice unacknowledged | "Acknowledge the payment notice", `payments` | +| `payment` | all acknowledged | "Settled", `payments` | + +## The steps + +Each step: where it happens, what must hold, what the user does, what the system does (module in brackets), what goes on the wire, what is stored, where the case stands afterwards, and what the screen shows next. Ids are `F1` to `F13` with letters for branches; `flow.json` carries the same ids. + +### F1. Policy search + +- Screen: Cases list, "New case", `GET /claims/new`. +- Holds: nothing. +- User: picks an identifier type (`MemberId`, `AbhaNumber`, `MobileNo`) and a value, presses "Search policies". +- System [7.4]: `search_policies` through the transport: the participant service's `participant/get/policies`; normalises each row (`member_id`, `policy_code` from `productid`, `payer_code` from `payerid`, `recipient_code` from `processingid`, `product_name`). NHCX-1016 (nothing linked) is an empty list, not an error. +- Screen: a table, one row per policy: beneficiary, product and policy, payer, ABHA, mobile, a "Select" button. No name and no photo yet; the payer returns those at F3. + +### F2. Open the case + +- Screen: the same, "Select" on a row; `POST /claims`. +- System [7.4, 7.2]: `create_claim` snapshots the policy (`member_id`, `policy_code`, `payer_code`, `recipient_code`, `policy_json`), mints the claim number, stamps `eligibility / draft`. +- Redirect: the case screen, Eligibility tab, "Claim opened." +- Next action: "Check the cover". + +### F3. Check the cover (coverage eligibility) + +- Screen: Eligibility tab, card "Coverage eligibility check": purpose select (`validation` default, `benefits`, `discovery`), policy code and member id shown from the snapshot, "Send to payer". +- Holds: member id; policy code for `validation` and `benefits`. +- System [7.4]: `run_check(purpose)`, workflow id = the claim number, status `checking`; the page shows "Awaiting payer" and refreshes; the answer arrives by callback [7.3] or poll. +- Wire: `v1/coverageeligibility/check`; `on_check` back. +- Stored: `txn_id`, `correlation_id`, `api_call_id`; on the answer `inforce`, `outcome`, `disposition`, allowed and used amounts, the payer's `Patient` (name, gender, DOB, address, ABHA, photo), `Coverage` class and period. +- After: `eligibility / eligible` or `not-eligible` (or `error` with the payer's words). A `ProtocolResponse` or a 404 on `txn/related` settles as `error`, never spins. +- Screen: card "Payer verdict": Sum insured, Utilised, Wallet balance (allowed less used), Disposition verbatim, In force, Pre-authorisation required, Checked at, Correlation. Beneficiary card fills with the payer's demographics. "Check again" allowed from any settled state. +- Next action: "Fetch the package master". + +### F4. Fetch the package master (insurance plan) + +- Screen: Insurance plan tab, "Fetch the plan" (or "Refresh"). +- Holds: `eligible`. +- System [7.5]: `reuse_plan` first (same policy, provider, payer, status `ready`: zero sends); else `request_plan`, status `fetching`, workflow id = the claim number. +- Wire: `v1/insuranceplan/request`; `on_request` back with the InsurancePlan and Questionnaires. +- Stored: `claim_plan` (`ready`, `empty` or `error`), `claim_plan_benefit` per package, `claim_plan_form` per url. Both published shapes merged on package code. +- Screen: a search over the master (name or code, specialty filter, procedure or implant), one row per package with rate, kind, "View"; a package view with rate, implants approved, tiers, conditions, documents wanted, the forms those point at as questions; an "All forms" page. Policy-wide requirements shown above the table. +- Next action: "Quote the treatment". + +### F5. Link the admission (integrate) or capture it (standalone) + +- Screen: Pre-authorisation tab, card "Link the admission" (opens once `eligible`). +- Holds: `eligible`. +- Integrate: list every current inpatient stay of the patient whose ABHA matches the payer's (digits only); "Link" stores `patient_id` and `encounter_id`, defaults the admission date from the encounter. Linking before `eligible` and to a stay that is not a current IPD admission is refused. "Unlink" keeps the draft. +- Standalone [7.13]: register the patient (from the payer's demographics) and admit them here; the same two keys are stored. +- Screen after: card "Linked admission" with ward, bed, admitted at, consultant. + +### F6. The dossier (pre-auth capture) + +- Screen: Pre-authorisation tab, once linked: the form, saved in one transaction by `save_preauth` [7.7 inputs]. +- Captured: admission date (required) and provisional discharge date (not before admission); ICD-10 diagnoses (at least one; read off the admission when it recorded them, else a picker); the treating doctor (the admission's consultant, else a picker; must have an HPIN); package case or non-package case toggle; documents (pdf, jpg, jpeg, png, each recorded against the payer requirement code it answers, else `ODN`). +- Estimated amount: always recomputed server-side from the lines (F7), never from the form. +- Guards: saving a package case with no line quoted is refused. + +### F7. Quote the treatment (lines from the plan) + +- Screen: Line items tab, "Choose line items", `GET /claims//lines`. Three parts: what is quoted (editable quantities, running total, "remove"); what the payer says goes with it (implants approved for the quoted procedures, the tiers each offers; anything already quoted drops out); the whole master to search. +- Holds: plan `ready`. Quoting anything before that is refused. +- System [7.5]: `add_line(kind, code, parent_code)`; price read from the plan at add time; `amount = rate x quantity` server-side; a tier is added through the procedure that offers it and carries `parent_code`. Refused: a code the plan lacks, a tier the procedure does not offer, a duplicate, a zero quantity. +- Forms: the chosen lines pull in the questionnaires the plan attaches (STG per package, policy forms always); they render on the Pre-authorisation tab and are answered there (`save_answers`, one row per question, file answers upload a document). +- Next action: "Send the pre-authorisation". + +### F8. Validate the set (auth requirements) + +- Screen: Validate tab, "Ask the payer" (also run silently before F9). +- Holds: at least one line. +- System [7.6]: `ensure_auth_requirements`: fingerprint the quoted set; send only when the fingerprint is new; never wait for the answer. +- Wire: `v1/coverageeligibility/check` with purpose `auth-requirements` and the items; `on_check` back (the PMJAY sandbox rarely answers). +- Stored: `claim_auth` (`checking` then `ready`), items authorised or excluded, requirements (document or form, code, url, stage `pre` or `post`, `at_preauth`). +- Screen: the ruling per line, the documents and forms it wants for each leg; the pre-auth and claim tabs read it to build their document and form cards. Without a ruling they fall back to the plan's list. + +### F9. Send the pre-authorisation + +- Screen: Pre-authorisation tab, card "Submit": what will be sent (lines, forms answered, documents attached, the total), "Send to payer". +- Holds (all before any HTTP call): `eligible`; an admission linked; an admission date; at least one diagnosis; at least one care team member with an HPIN; at least one line; every required form answered; every document the ruling or plan asks for at pre-auth attached. +- System [7.7]: `submit_preauth`: `preauth_send_kind` picks `preauth` (12); builds the Claim bundle (`preauth`, `request`); status `submitting`, `submission_kind`, `workflow_id`; stores the three ids; `thread_correlation_id` untouched until the payer answers. +- Wire: `v1/preauth/submit`, workflow 12. +- After: `preauth / requested`. +- Screen: "Awaiting payer", the timeline row for the send, Refresh. Next action: "With the payer; ask where it stands". + +#### F9a. The payer answers + +- Callback [7.3] or poll: first the acknowledgement (workflow 20, `outcome queued`, reason `submitted`): recorded, `preauth_ref` kept, the leg stays `submitting`. Then the decision on the same correlation id: `verdict_status` [7.8]. +- After: `approved` (21), `partial` (approved for less), `queried` (24), `rejected` (23). Never read `outcome` alone. +- Screen: Decision, Payer reference (`preAuthRef`), Approved amount (`total[benefit]`), Eligible amount, the item verdicts table (eligible, status, reason verbatim, eligible %, quantity), process notes verbatim. A door refusal shows as a flag with the payer's code and text, the thread restored. +- Next action per the table above. + +#### F9b. Answer a query + +- Resubmit payer (PMJAY): the query is inside the ClaimResponse (`query_note`). Screen: Pre-authorisation tab, the payer's words, a reply box, "Submit again". System: `submit_preauth(reply)` with kind `preauth_query_response` (19; 131 after an enhancement query), flow `queryupdate`, `NMI/CQD` = the reply, a new correlation id. After: `answered`, then the decision. +- Communication payer (generic): the query is a CommunicationRequest on a new thread, filed in `claim_query` (F12 inbox). Screen: Communication tab, the questions verbatim, a reply box, documents to attach (existing or new, each under the payer's code else `ODN`), "Send the reply". System [7.10]: `answer_query`: the TaskBundle reply on `v1/communication/on_request` with the request's correlation id and workflow id. The leg stays `queried` until the decision arrives on its own thread. An empty reply is refused before any HTTP call. + +#### F9c. Enhancement + +- Screen: Line items tab, add a line after a decision; the Pre-authorisation card shows "enhancement pending (n added)"; "Submit enhancement". +- Holds: `approved` or `partial`; no request in flight. +- System: `submit_preauth` with kind `enhancement` (13; `enhancement_resubmit` 131 on a query): the whole bundle again, every line old and new, same claim number, factors 1 and 0.5. After: `enhancement / requested`, then 22 (or 21 from the SHA), 231, 241. + +#### F9d. Cancel + +- Screen: Pre-authorisation tab, "Withdraw": a reason picker (the seven documented reasons) and a note, required for Other. Hidden once a claim has been raised; refused on a `rejected` pre-auth and twice. +- System [7.9]: `cancel_preauth`: Task `cancel`, workflow PC01, on its own thread (`cancel_correlation_id`), `cancelling`. +- After PC02: `cancelled`; the episode gets a fresh claim number, the withdrawn one stays on the leg. + +#### F9e. Predetermination (a quote) + +- Screen: Pre-authorisation tab, "Ask for a quote". +- System [7.7]: the very bundle F9 would send with `use predetermination`, on `v1/preauth/submit`, workflow 12, its own row (`asking` then `answered`). Nothing on the pre-auth changes. + +### F10. Record the discharge + +- Screen: Claim tab, card "Discharge": mode (Normal, LAMA, DAMA, Death), stage (Before, During, After surgery), discharge date and time, surgery date and time, death date and time (death only). +- Holds: a pre-auth `approved` or `partial`. +- Stored: on `claim_submission` (`draft`) or the encounter. +- Screen after: the claim card opens; for LAMA or DAMA before or during surgery it says the approved packages are voided and the claim will carry `LM100` only. +- Next action: "File the claim". + +### F11. File the claim + +- Screen: Claim tab, cards "Documents for the claim" (what the ruling deferred to this stage, plus the discharge summary, always), "Forms for the claim" (the consent again, and what the ruling deferred), "Everything attached for the claim" (any further pdf or image), "Submit the claim". +- Holds: discharge recorded; the discharge summary attached; every claim-stage form answered; amount not above the approved amount. +- System [7.7]: `submit_claim`: `claim_send_kind` (`claim` 15; `claim_query_response` 161 PMJAY or 151 generic; `claim_resubmit` 16 generic only); the Claim bundle (`claim`, `request`) under the pre-auth's claim number with `preAuthRef`, procedures `completed`, discharge scalars, `HDS`, `DIS`; `LM100` collapse when it applies. +- Wire: `v1/claim/submit`. +- After: `claim / requested`; then 25 (ack), 26 `approved`, 27 `queried`, 291 `rejected`, read as F9a. +- Screen: as the pre-auth card: decision, amounts, item verdicts with `deductible`, notes verbatim. + +#### F11, continued: claim query and reprocess + +- Query: as F9b, on the claim (161 or the Communication reply). +- Rejected or partial: "Ask for a reprocess" (F13). There is no claim resubmit on PMJAY. + +### F12. Payments + +- The payer starts it: `v1/paymentnotice/request` arrives on a new thread, matched by the claim number inside (a `CLN` identifier, then any untyped identifier on the notice, the reconciliation, the Task; never the bundle id), looked up against `claim_no` and every leg's `claim_ref`. +- System [7.10]: `record_payment`: one `claim_payment` row per notice, deduped on the notice's correlation id; details from the PaymentReconciliation; a payer that reuses the notice id updates the row. Then, at once and automatically, `acknowledge_payment`: Task `status` `completed`, output `paymentack`, to the notice's own sender, its correlation id echoed, workflow 17 (PMJAY) or the notice's own (generic). A failed acknowledgement is kept on the row; the notice is still recorded and the callback still answered 2xx. +- After: `payment / noticed` or `paid`. Paid is counted once per UTR, newest notice winning; an initiated notice without a UTR shows "Initiated, UTR awaited" and is not money received. +- Screen: Payments tab, one card per notice: status, amount, UTR as text, the breakdown, "Acknowledged at" or "Send the acknowledgement again". Across cases: the payments view. +- Next action: "Acknowledge the payment notice" while one is pending, else "Settled". + +### F12b. The inbox + +- Every CommunicationRequest is classified [7.10]: query, notification or note. Notifications are acknowledged at once (the payer's bundle back, Task `completed`) and the case left alone. Queries are filed `open` and lead every action list until answered (F9b). Notes are shown, never acted on. +- Screen: Communication tab on the case; the inbox view across cases, by kind and reason. + +### F13. The small exchanges + +- Status: "Ask where it stands" on the pre-auth and claim cards, while awaiting and after a decision; Task `status`, workflow = the leg's correlation id (fallback 13); not offered to a payer whose adapter refuses it (PMJAY, PAYR-1018). The answer fills the enquiry row; the leg is unchanged. +- Reprocess: on a decided claim not paid in full, "Send reprocess request" with a coded reason (`claimrejected`, `partialpayment`, `rejectiondisputed`), words, and documents; Task `reprocess`, workflow 36. The payer's `completed` Task (37) reopens the claim: the submission goes back to `requested` and the new verdict lands on the claim's own thread. +- Release: once part of an approved claim is paid, "Ask for the balance" with the amount owed; Task `release`, reason `partialpayment`, `valueMoney`, workflow 36. +- Each ask is its own `claim_enquiry` row on its own thread, shown on the card it belongs to, newest first. + +## What runs on every page load of the case + +In this order, before rendering, each bounded to one poll and a short timeout, never a send: coverage (`checking`), plan (`fetching`), ruling (`checking`), claim (`submitting`), predeterminations (`asking`), pre-auth (`submitting` or `cancelling`), enquiries (`asking`). Then the beneficiary card, the policy card, the verdict card, the status line and actions, the tabs. A "Refresh" button reloads the same tab. + +## What is not in the flow + +- No status control anywhere. Stage and sub-stage are derived. +- No manual acknowledgement of a payment notice as the only path; it goes automatically and the screen shows that it went. +- No "chase" button without the status exchange behind it. +- No separate discharge submission on PMJAY; the discharge rides on the claim. +- No claim resubmit on PMJAY; a decided claim is reprocessed. diff --git a/plugins/nhcx/skills/nhcx-payment/flow/flow.json b/plugins/nhcx/skills/nhcx-payment/flow/flow.json new file mode 100644 index 000000000..315d1a4b8 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-payment/flow/flow.json @@ -0,0 +1,818 @@ +{ + "source": "flow/FLOW.md", + "tabs": [ + { + "key": "eligibility", + "label": "Eligibility", + "opens": "always" + }, + { + "key": "plan", + "label": "Insurance plan", + "opens": "always" + }, + { + "key": "lines", + "label": "Line items", + "opens": "always; quoting refused until the plan is ready" + }, + { + "key": "validate", + "label": "Validate", + "opens": "always" + }, + { + "key": "preauth", + "label": "Pre-authorisation", + "opens": "coverage verdict eligible" + }, + { + "key": "communication", + "label": "Communication", + "opens": "always" + }, + { + "key": "claim", + "label": "Claim", + "opens": "always; submit once the pre-auth is approved or partial" + }, + { + "key": "payments", + "label": "Payments", + "opens": "always" + } + ], + "stages": [ + "eligibility", + "preauth", + "enhancement", + "claim", + "payment" + ], + "sub_stages": [ + "draft", + "checking", + "eligible", + "not-eligible", + "requested", + "resubmitted", + "answered", + "queried", + "approved", + "partial", + "rejected", + "cancelling", + "cancelled", + "refused", + "noticed", + "paid" + ], + "next_actions": [ + { + "when": "an open query exists", + "label": "Answer the payer (n)", + "tab": "communication", + "leads": true + }, + { + "stage": "eligibility", + "sub_stage": [ + "draft", + "error", + "not-eligible" + ], + "label": "Check the cover", + "tab": "eligibility" + }, + { + "stage": "eligibility", + "when": "no plan ready", + "label": "Fetch the package master", + "tab": "plan" + }, + { + "stage": "eligibility", + "when": "no lines", + "label": "Quote the treatment", + "tab": "lines" + }, + { + "stage": "eligibility", + "when": "lines quoted", + "label": "Send the pre-authorisation", + "tab": "preauth" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "queried" + ], + "label": "Answer the query", + "tab": "preauth", + "payer": "resubmit" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "queried" + ], + "label": "Answer the payer's query", + "tab": "communication", + "payer": "communication" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "draft", + "refused" + ], + "label": "Send the pre-authorisation", + "tab": "preauth" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "rejected" + ], + "label": "Send a fresh pre-authorisation", + "tab": "preauth" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "approved", + "partial" + ], + "when": "lines added since", + "label": "Send the enhancement (n added)", + "tab": "preauth" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "approved", + "partial" + ], + "when": "not discharged", + "label": "Record the discharge", + "tab": "claim" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "approved", + "partial" + ], + "when": "discharged", + "label": "File the claim", + "tab": "claim" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "requested", + "answered", + "resubmitted" + ], + "label": "With the payer; ask where it stands", + "tab": "preauth" + }, + { + "stage": "claim", + "sub_stage": [ + "queried" + ], + "label": "Answer the claim query", + "tab": "claim", + "payer": "resubmit" + }, + { + "stage": "claim", + "sub_stage": [ + "queried" + ], + "label": "Answer the payer's query", + "tab": "communication", + "payer": "communication" + }, + { + "stage": "claim", + "sub_stage": [ + "rejected", + "partial" + ], + "label": "Ask for a reprocess", + "tab": "claim" + }, + { + "stage": "claim", + "sub_stage": [ + "requested", + "answered", + "resubmitted" + ], + "label": "With the payer; ask where it stands", + "tab": "claim" + }, + { + "stage": "claim", + "sub_stage": [ + "refused" + ], + "label": "Send the claim again", + "tab": "claim", + "when": "a send kind remains, else Ask for a reprocess" + }, + { + "stage": "claim", + "sub_stage": [ + "approved" + ], + "label": "Await the payment notice", + "tab": "payments" + }, + { + "stage": "payment", + "when": "a notice unacknowledged", + "label": "Acknowledge the payment notice", + "tab": "payments" + }, + { + "stage": "payment", + "when": "all acknowledged", + "label": "Settled", + "tab": "payments" + } + ], + "steps": [ + { + "id": "F1", + "name": "Policy search", + "screen": "new case", + "tab": null, + "routes": [ + "GET /claims/new" + ], + "module": "7.4", + "skills": ["nhcx-coverage"], + "holds": [], + "user": "Search policies", + "sends": { + "path": "participant/get/policies", + "kind": "registry REST" + }, + "stores": [], + "after": null, + "shows": "one row per policy with Select" + }, + { + "id": "F2", + "name": "Open the case", + "screen": "new case", + "tab": null, + "routes": [ + "POST /claims" + ], + "module": "7.4", + "skills": ["nhcx-coverage"], + "holds": [], + "user": "Select", + "sends": null, + "stores": [ + "claim: member_id, policy_code, payer_code, recipient_code, policy_json, claim_no" + ], + "after": { + "stage": "eligibility", + "sub_stage": "draft" + }, + "next_action": "Check the cover" + }, + { + "id": "F3", + "name": "Check the cover", + "screen": "case", + "tab": "eligibility", + "routes": [ + "POST /claims//check" + ], + "module": "7.4", + "skills": ["nhcx-coverage"], + "holds": [ + "member id", + "policy code for validation and benefits" + ], + "user": "purpose, Send to payer", + "sends": { + "path": "v1/coverageeligibility/check", + "workflow": "", + "reply": "on_check" + }, + "stores": [ + "txn_id", + "correlation_id", + "api_call_id", + "inforce", + "outcome", + "disposition", + "allowed_amount", + "used_amount", + "patient demographics", + "coverage class and period" + ], + "after": { + "stage": "eligibility", + "sub_stage": "eligible|not-eligible|error" + }, + "shows": "Payer verdict: sum insured, utilised, wallet balance, disposition verbatim", + "next_action": "Fetch the package master" + }, + { + "id": "F4", + "name": "Fetch the package master", + "screen": "case", + "tab": "plan", + "routes": [ + "POST /claims//plan", + "GET /claims//plan/", + "GET /claims//plan/forms" + ], + "module": "7.5", + "skills": ["nhcx-insurance"], + "holds": [ + "eligible" + ], + "user": "Fetch the plan (reuse first)", + "sends": { + "path": "v1/insuranceplan/request", + "workflow": "", + "reply": "on_request" + }, + "stores": [ + "claim_plan", + "claim_plan_benefit", + "claim_plan_form" + ], + "after": { + "plan": "ready|empty|error" + }, + "shows": "searchable master, package view, all forms", + "next_action": "Quote the treatment" + }, + { + "id": "F5", + "name": "Link or capture the admission", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//link", + "POST /claims//unlink" + ], + "module": "7.13 or the HMIS", + "skills": ["nhcx-preauth"], + "holds": [ + "eligible" + ], + "user": "Link the admission", + "sends": null, + "stores": [ + "claim.patient_id", + "claim.encounter_id", + "admission date default" + ], + "after": null + }, + { + "id": "F6", + "name": "The dossier", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//preauth", + "POST /claims//documents", + "POST /claims//documents/required" + ], + "module": "7.7 inputs", + "skills": ["nhcx-preauth"], + "holds": [ + "linked" + ], + "user": "Save the dossier", + "sends": null, + "stores": [ + "claim_diagnosis", + "claim_care_team", + "claim_document (code, stage)", + "claim_item" + ], + "guards": [ + "admission date required", + "at least one diagnosis", + "doctor with HPIN", + "package case needs a line" + ] + }, + { + "id": "F7", + "name": "Quote the treatment", + "screen": "lines", + "tab": "lines", + "routes": [ + "GET /claims//lines", + "POST /claims//lines", + "POST /claims//lines/quantities", + "POST /claims//lines//delete", + "POST /claims//forms" + ], + "module": "7.5", + "skills": ["nhcx-insurance"], + "holds": [ + "plan ready" + ], + "user": "add procedure, implant or tier; quantities; answer the forms the lines pull in", + "sends": null, + "stores": [ + "claim_line (rate from the plan, parent_code on a tier)", + "claim_form_answer" + ], + "guards": [ + "code not in plan", + "tier not offered by the procedure", + "duplicate", + "zero quantity" + ], + "next_action": "Send the pre-authorisation" + }, + { + "id": "F8", + "name": "Validate the set", + "screen": "case", + "tab": "validate", + "routes": [ + "POST /claims//auth" + ], + "module": "7.6", + "skills": ["nhcx-preauth"], + "holds": [ + "at least one line" + ], + "user": "Ask the payer (validate)", + "sends": { + "path": "v1/coverageeligibility/check", + "purpose": "auth-requirements", + "workflow": "", + "reply": "on_check", + "awaited": false + }, + "stores": [ + "claim_auth (fingerprint)", + "claim_auth_item", + "claim_auth_requirement" + ], + "after": { + "auth": "checking|ready" + } + }, + { + "id": "F9", + "name": "Send the pre-authorisation", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//submit" + ], + "module": "7.7", + "skills": ["nhcx-preauth"], + "holds": [ + "eligible", + "linked", + "admission date", + "diagnosis", + "care team with HPIN", + "a line", + "required forms answered", + "required documents attached" + ], + "user": "Send to payer", + "sends": { + "path": "v1/preauth/submit", + "workflow": "12", + "kind": "preauth", + "reply": "on_submit 20 then 21|23|24" + }, + "stores": [ + "claim_preauth: submitting, submission_kind, workflow_id, txn_id, correlation_id, api_call_id, request_json" + ], + "after": { + "stage": "preauth", + "sub_stage": "requested" + }, + "next_action": "With the payer; ask where it stands" + }, + { + "id": "F9a", + "name": "The payer answers", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /nhcx/callback/v1/preauth/on_submit" + ], + "module": "7.8", + "skills": ["nhcx-preauth"], + "holds": [], + "user": null, + "reads": "20 queued (stay submitting, keep preauth_ref) then the decision via verdict_status", + "stores": [ + "status", + "preauth_ref", + "approved_amount", + "eligible_amount", + "items_json", + "query_note", + "thread_correlation_id" + ], + "after": { + "stage": "preauth", + "sub_stage": "approved|partial|queried|rejected" + }, + "shows": "decision, payer reference, approved amount, item verdicts, notes verbatim; door refusal as a flag" + }, + { + "id": "F9b", + "name": "Answer a query", + "screen": "case", + "tab": "preauth or communication", + "routes": [ + "POST /claims//submit (reply)", + "POST /claims//queries//reply" + ], + "module": "7.7 or 7.10", + "skills": ["nhcx-preauth", "nhcx-communication"], + "holds": [ + "queried" + ], + "user": "reply text and documents", + "sends": { + "resubmit": { + "path": "v1/preauth/submit", + "workflow": "19 or 131", + "flow": "queryupdate", + "new_thread": true + }, + "communication": { + "path": "v1/communication/on_request", + "workflow": "", + "correlation_id": "" + } + }, + "after": { + "stage": "preauth", + "sub_stage": "answered (resubmit) or queried until the decision (communication)" + } + }, + { + "id": "F9c", + "name": "Enhancement", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//submit" + ], + "module": "7.7", + "skills": ["nhcx-preauth"], + "holds": [ + "approved or partial", + "lines added", + "no request in flight" + ], + "user": "Submit enhancement", + "sends": { + "path": "v1/preauth/submit", + "workflow": "13 or 131", + "flow": "enhancement", + "whole_bundle": true + }, + "after": { + "stage": "enhancement", + "sub_stage": "requested" + } + }, + { + "id": "F9d", + "name": "Cancel", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//cancel" + ], + "module": "7.9", + "skills": ["nhcx-preauth"], + "holds": [ + "not rejected", + "not cancelled", + "no claim raised" + ], + "user": "Withdraw the pre-authorisation", + "sends": { + "path": "v1/task/submit", + "workflow": "PC01", + "task": "cancel", + "own_thread": true + }, + "after": { + "stage": "preauth", + "sub_stage": "cancelling then cancelled; fresh claim number" + } + }, + { + "id": "F9e", + "name": "Predetermination", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//predetermination" + ], + "module": "7.7", + "skills": ["nhcx-preauth"], + "holds": [ + "as F9" + ], + "user": "Ask for a quote", + "sends": { + "path": "v1/preauth/submit", + "workflow": "12", + "use": "predetermination" + }, + "after": { + "predetermination": "asking then answered; the pre-auth unchanged" + } + }, + { + "id": "F10", + "name": "Record the discharge", + "screen": "case", + "tab": "claim", + "routes": [ + "POST /claims//discharge" + ], + "module": "7.7 inputs", + "skills": ["nhcx-claim"], + "holds": [ + "approved or partial" + ], + "user": "mode (normal, lama, dama, death), stage, discharge, surgery and death times", + "sends": null, + "stores": [ + "claim_submission draft: discharge_mode, discharge_stage, dates" + ], + "next_action": "File the claim" + }, + { + "id": "F11", + "name": "File the claim", + "screen": "case", + "tab": "claim", + "routes": [ + "POST /claims//claim", + "POST /claims//claim/documents" + ], + "module": "7.7", + "skills": ["nhcx-claim", "nhcx-communication"], + "holds": [ + "discharge recorded", + "discharge summary attached", + "claim-stage forms answered", + "amount not above approved" + ], + "user": "Submit the claim", + "sends": { + "path": "v1/claim/submit", + "workflow": "15 (161 or 151 query answer; 16 generic resubmit)", + "kind": "claim", + "under": "the pre-auth's claim number", + "reply": "on_submit 25 then 26|27|291" + }, + "after": { + "stage": "claim", + "sub_stage": "requested then approved|queried|rejected|partial" + } + }, + { + "id": "F12", + "name": "Payments", + "screen": "case", + "tab": "payments", + "routes": [ + "POST /nhcx/callback/v1/paymentnotice/request", + "POST /claims//payments//ack", + "GET /claims/payments" + ], + "module": "7.10", + "skills": ["nhcx-payment"], + "holds": [], + "user": null, + "reads": "PaymentNotice matched by claim number; deduped on its correlation id", + "sends": { + "path": "v1/paymentnotice/on_request", + "workflow": "17 (PMJAY) or the notice's own", + "correlation_id": "", + "to": "the notice's sender", + "automatic": true + }, + "after": { + "stage": "payment", + "sub_stage": "noticed|paid" + }, + "next_action": "Acknowledge the payment notice, then Settled" + }, + { + "id": "F12b", + "name": "The inbox", + "screen": "inbox", + "tab": "communication", + "routes": [ + "POST /nhcx/callback/v1/communication/request", + "GET /claims/inbox", + "POST /claims//queries//acknowledge" + ], + "module": "7.10", + "skills": ["nhcx-communication"], + "holds": [], + "reads": "classify: query | notification | note", + "sends": { + "notification": { + "path": "v1/communication/on_request", + "automatic": true + } + }, + "after": { + "query": "open, leads every action list" + } + }, + { + "id": "F13", + "name": "Status, reprocess, release", + "screen": "case", + "tab": "preauth or claim", + "routes": [ + "POST /claims//status", + "POST /claims//reprocess", + "POST /claims//release" + ], + "module": "7.9", + "skills": ["nhcx-reprocess"], + "holds": [ + "status: payer allows it", + "reprocess: claim decided and not paid in full", + "release: part paid" + ], + "sends": { + "path": "v1/task/submit", + "workflow": "leg correlation id (status) or 36", + "own_thread": true + }, + "after": { + "enquiry": "asking then answered|error; a reprocess reopens the claim to requested" + } + } + ], + "page_load_polls": [ + "coverage checking", + "plan fetching", + "ruling checking", + "claim submitting", + "predeterminations asking", + "preauth submitting or cancelling", + "enquiries asking" + ], + "not_in_the_flow": [ + "a status control", + "a manual-only payment acknowledgement", + "a chase button without the status exchange", + "a separate discharge submission on PMJAY", + "a claim resubmit on PMJAY" + ] +} \ No newline at end of file diff --git a/plugins/nhcx/skills/nhcx-payment/references/api-knowledge.md b/plugins/nhcx/skills/nhcx-payment/references/api-knowledge.md new file mode 100644 index 000000000..3b07e901d --- /dev/null +++ b/plugins/nhcx/skills/nhcx-payment/references/api-knowledge.md @@ -0,0 +1,400 @@ +# API knowledge: the nhcx-adapter contract (optional transport) and the HMIS endpoints that face it + +Read this file only when the transport is nhcx-adapter, and use nhcx-adapter only when the user has asked for it (`references/transport-knowledge.md` section 1). Otherwise the build reaches NHCX through the app's existing integration or its own transport, and `references/transport-knowledge.md` sections 3 and 4 replace everything here. + +This file describes nhcx-adapter (https://github.com/nha-in/nhcx-adapter) as its release ships it, and the HMIS side a build needs to face it. A release carries the binary, `config.sample.json`, `serve.sh`, `stop.sh`, `update.sh` and `README.md`. `nhcx-package/docs/02-Getting Started/10-NHCX Adapter.md` covers the same adapter. When a detail matters, check the release README and `config.sample.json` for the version you run. + +## 1. What the adapter is + +One binary, one `config.json`, no database. You POST plain FHIR to it. It mints the protocol ids, fetches the recipient's certificate, encrypts a compact JWE, posts to the NHCX gateway, and records the exchange in a file ledger. NHCX callbacks reach it encrypted; it decrypts them and POSTs plain FHIR to your HMIS. Both directions are synchronous; there is no queue (release README, "How it works"). + +The same binary can front several participants at once. Inbound, `x-hcx-recipient_code` picks the profile whose key decrypts and whose callback receives. Outbound, `x-hcx-sender_code` picks who sends (release README, "Hosting several participants"). Encrypting for a code the same adapter holds is allowed. So one adapter can host a hospital and a test payer together, and a test between them needs no second gateway. + +## 2. Configuration + +File: `config.sample.json` in the release. `${NAME}` reads an environment variable; `@file` reads a file next to the config. Unknown keys are rejected. + +| Key | Default | What it does | +| --- | --- | --- | +| `env` | `sandbox` | `sandbox` or `production`. Picks the gateway (`https://apisbx.abdm.gov.in/hcx/v1` or `https://apis.abdm.gov.in/hcx/v1`), registry, session endpoint and `X-CM-ID` (`sbx` or `abdm`). | +| `listen` | `127.0.0.1:8090` | The HTTP listener. | +| `publicUrl` | empty | How NHCX reaches the adapter. Register `/in` as the participant's `endpoint_url`. | +| `apiKey` | `${NHCX_ADAPTER_API_KEY}` | The key your HMIS presents on `/out`, `/fhir/out`, `/ledger*`, `/token`. Demanded in production, honoured but not demanded in sandbox. `requireApiKey: true` closes a sandbox adapter. | +| `participant.participantId` | none; the sample carries an example code | Your registry code. `@hcx` is added if missing. | +| `participant.clientId`, `clientSecret` | `${NHCX_CLIENT_ID}`, `${NHCX_CLIENT_SECRET}` | ABDM credentials that mint the session token. | +| `participant.privateKey` | `@private_key.pem` | The RSA key of your registered certificate. | +| `participants[]` | `[]` | Further hosted identities. Each needs only `participantId` and `callback`; the rest is inherited. | +| `callback.url` | `http://127.0.0.1:8765/nhcx/callback` in the sample | Where decrypted messages are POSTed. | +| `callback.appendPath` | `true` | Appends the NHCX path: `.../callback` receives `v1/preauth/on_submit` at `.../callback/v1/preauth/on_submit`. | +| `callback.timeoutSeconds` | `20` | One delivery. NHCX wants its 202 within 30 seconds. | +| `callback.apiKey` | empty | Sent to your HMIS as `Authorization: Bearer `. | +| `callback.routes` | `{}` | Per-path overrides, used exactly as written: `{"v1/preauth/on_submit": "http://preauth-svc/hook"}`. | +| `callback.also` | absent | Extra targets for the same delivery (two systems behind one participant code). Every target must accept or NHCX redelivers to all. | +| `ledger.enabled`, `ledger.dir`, `ledger.retentionDays`, `ledger.storeBodies` | `true`, `data/ledger`, `30`, `true` | The traffic ledger. A hand-written config that leaves out `retentionDays` keeps every day. | +| `maxBodyBytes` | 8 MiB in the v1.0.1 README | Caps request bodies on both surfaces. A PMJAY package master is far larger: set 100 MiB (`104857600`) explicitly. | +| `panel.password`, `panel.path` | empty, `/panel` | The browser console; off until a password is set. | +| `auth.mode`, `auth.tokenTtlSeconds` | `sessions`, `1200` | How the ABDM token is obtained. | + +Minimal working config for one hospital: + +```json +{ + "env": "sandbox", + "listen": "127.0.0.1:8090", + "publicUrl": "https:///in", + "apiKey": "${NHCX_ADAPTER_API_KEY}", + "participant": { + "participantId": "@hcx", + "clientId": "${NHCX_CLIENT_ID}", + "clientSecret": "${NHCX_CLIENT_SECRET}", + "privateKey": "@private_key.pem" + }, + "callback": { "url": "http://127.0.0.1:/nhcx/callback", "appendPath": true, "apiKey": "" } +} +``` + +Start it with `./nhcx-adapter serve`, or `./serve.sh` from the release archive; `./stop.sh` stops a background server. It checks token, participant record, certificate and registered endpoint first and offers to fix each in a terminal (release README, "Startup checks"). `./nhcx-adapter check --no-tui` is the same as a health gate. `serve --no-tui --skip-checks` starts it with no prompts and no checks, for a script that has already checked. + +## 3. Routes + +| Route | Auth | Does | +| --- | --- | --- | +| `POST /out/{path...}` | API key | Send. `path` is the NHCX API path, `v1/preauth/submit`. | +| `POST /fhir/out/{path...}` | API key | Same handler, hcxkit's prefix. The client in section 11 sends here. | +| `POST /in/{path...}` | none | NHCX delivers here. Register `/in`. | +| `POST /v1/{path...}` | none | Alias of `/in` for a registry `endpoint_url` of `/`. | +| `GET /ledger` | API key | Newest first. Filters: `direction, entity, kind, status, sender, recipient, participant, correlation_id, workflow_id, since, until, before, limit` (1 to 500). `since` and `until` take RFC 3339, a date, or a duration such as `24h`. | +| `GET /ledger/stats` | API key | Counts by direction, status, entity. | +| `GET /ledger/thread/{cid}` | API key | Every message on one correlation id plus the derived state. | +| `GET /ledger/{id}` | API key | One message in full, bundle included. | +| `GET /token`, `POST /token/refresh` | API key | The ABDM session token, for calls the adapter does not make (registry, PMJAY payer service). `?participant=` for a hosted identity. | +| `GET /healthz`, `GET /readyz` | none | Liveness; readiness is 503 until a token is held. | +| `GET /panel` | its own password | Operator console: Live, Ledger, Send, Lookup, Setup. | +| `/internal/*` | none | hcxkit-compatible console API, section 8. | + +API key check: `Authorization: Bearer ` first, then `X-Api-Key: `. Constant-time compare. A miss answers `401 {"ok":false,"error":{"code":"UNAUTHORIZED","message":"missing or invalid API key"}}`. + +## 4. The outbound envelope + +The body must be a JSON object. Header precedence, lowest to highest: + +1. HTTP request headers named `x-hcx-*`. +2. The `jwe_headers` object (hcxkit spelling). +3. Top-level `x-hcx-*` keys. +4. Top-level short aliases: `sender`, `recipient`, `correlation_id`, `request_id`, `api_call_id`, `workflow_id`, `status`. + +The payload is `fhir`, else `payload`, else the body itself when it carries `resourceType`. Otherwise `400 INVALID_ENVELOPE`. + +The protected header names: + +``` +x-hcx-api_call_id x-hcx-request_id x-hcx-correlation_id x-hcx-timestamp +x-hcx-status x-hcx-sender_code x-hcx-recipient_code x-hcx-workflow_id +``` + +Completion rules: + +- Sender and recipient codes get `@hcx` appended if missing. +- `api_call_id`, `request_id`, `correlation_id` are kept only when they are plain 8-4-4-4-12 UUIDs; anything else is replaced with a fresh UUID. So a response must carry the request's `correlation_id` as a UUID or the thread is lost. +- `x-hcx-status` defaults to `request.initiated`, or `response.complete` when the last path segment starts with `on_`. +- `x-hcx-timestamp` defaults to now as `YYYY-MM-DDThh:mm:ss±hhmm`. The zone has no colon: `+0530`, not `+05:30`. +- An empty `x-hcx-workflow_id` is dropped, not sent. +- On an `on_` path with no usable correlation id, the adapter threads the message to the newest inbound request of that entity from that recipient. Do not rely on it; send the id. + +What a hospital sends on a normal leg: + +```json +{ + "jwe_headers": { + "x-hcx-sender_code": "@hcx", + "x-hcx-recipient_code": "@hcx", + "x-hcx-workflow_id": "12" + }, + "fhir": { "resourceType": "Bundle", "type": "collection", "...": "..." } +} +``` + +Add `"x-hcx-correlation_id": ""` only on the two reply legs: the communication reply on `v1/communication/on_request` and the payment acknowledgement on `v1/paymentnotice/on_request`. + +## 5. The outbound answer + +The HTTP status is the NHCX gateway's own. Body: + +```json +{ + "ok": true, + "path": "v1/preauth/submit", + "url": "https://apisbx.abdm.gov.in/hcx/v1/preauth/submit", + "headers": { "x-hcx-correlation_id": "...", "x-hcx-api_call_id": "...", "x-hcx-request_id": "...", "x-hcx-workflow_id": "12", "x-hcx-status": "request.initiated", "x-hcx-timestamp": "...", "x-hcx-sender_code": "...", "x-hcx-recipient_code": "..." }, + "gateway_status": 202, + "response": { "...": "the NHCX 202 body" }, + "duration_ms": 412, + "ledger_id": "7UMV0007", + "txn_id": "7UMV0007", + "correlation_id": "...", + "request_id": "..." +} +``` + +Store three things on the leg: `txn_id` (the ledger id), `correlation_id` (the thread), and `headers["x-hcx-api_call_id"]`. Store them on every send. + +Local failures come back as `{"ok": false, "error": {"code", "message", "retryable"}, "request_id", "upstream_status", "upstream_body"}` with these statuses: `400` for `INVALID_ENVELOPE`, `INVALID_PAYLOAD`, `INVALID_BODY`, `INVALID_JWE`, `NO_PATH`, `NO_RECIPIENT`, `WRONG_RECIPIENT`, `BODY_READ`; `401` for the API key; `413` `BODY_TOO_LARGE`; `422` for `DECRYPT_FAILED`, `CERT_NOT_FOUND`, `SELF_ENCRYPTION_KEY`; `502` for any code starting `CALLBACK_`, `GATEWAY_`, `CERT_FETCH_`, `TOKEN_`; `501` `LEDGER_DISABLED`. A gateway refusal is recorded in the ledger as `rejected` with `GATEWAY_HTTP_`. + +## 6. The inbound callback your HMIS receives + +The adapter POSTs to `callback.url` plus the NHCX path. Body: + +```json +{ + "meta": { + "type": "in", + "payloadType": "fhir", + "path": "v1/preauth/on_submit", + "ip": "1.2.3.4", + "time": "", + "redelivery": false, + "participant": "@hcx" + }, + "jwe_headers": { + "alg": "RSA-OAEP-256", "enc": "A256GCM", + "x-hcx-api_call_id": "...", "x-hcx-correlation_id": "...", "x-hcx-request_id": "...", + "x-hcx-sender_code": "@hcx", "x-hcx-recipient_code": "@hcx", + "x-hcx-status": "response.partial", "x-hcx-timestamp": "...", "x-hcx-workflow_id": "20" + }, + "fhir": { "resourceType": "Bundle", "...": "..." } +} +``` + +`payloadType` is `fhir` for a bundle and `protocol` for a ProtocolResponse. A ProtocolResponse is a refusal. Then `fhir` is the plain JSON body with `type: "ProtocolResponse"`, `x-hcx-status: response.error` and `x-hcx-error_details` at its top level. + +HTTP headers on the delivery: + +| Header | Value | +| --- | --- | +| `X-Nhcx-Path` | `v1/preauth/on_submit` | +| `X-Nhcx-Payload-Kind` | `fhir` or `protocol` | +| `X-Nhcx-Correlation-Id` | the thread | +| `X-Nhcx-Api-Call-Id` | this delivery's id, stable across redeliveries | +| `X-Nhcx-Redelivery` | `true` when the ledger already holds this api_call_id (absent otherwise) | +| `X-Nhcx-Participant` | the hosted identity it was addressed to | +| `X-Hcxkit-Txn-Id` | equals `x-hcx-api_call_id` (what a kit-style backend dedupes on) | +| `X-Hcxkit-Type` | entity: `coverage`, `insurance`, `preauth`, `claim`, `task`, `payment`, `communication`, `status` | +| `X-Hcxkit-Flow` | `request` for an arriving response, `on_request` for an arriving request (inverted on purpose) | +| `X-Hcxkit-Payload-Kind` | same as `X-Nhcx-Payload-Kind` | +| `Authorization` | `Bearer ` when configured | + +Contract: answer any 2xx quickly. The adapter then answers NHCX with the 202 acceptance body and an `X-Nhcx-Ledger-Id` header: + +```json +{ + "timestamp": "11/09/2026 10:00:00:123", + "api_call_id": "...", "correlation_id": "...", + "result": { "sender_code": "...", "recipient_code": "...", "entity_type": "preauth", "protocol_status": "request.queued" }, + "error": { "code": "", "message": "" } +} +``` + +A non-2xx from your HMIS becomes `CALLBACK_HTTP_` and NHCX redelivers. NHCX makes five attempts, then drops the correlation id. Your handler must therefore be idempotent on `x-hcx-api_call_id`. Do not do slow work inside the callback: store the envelope, answer 200, apply it after. Apply a delivery on a context detached from the incoming request, so a gateway that hangs up cannot roll the write back. + +The HMIS callback handler: + +- Routes `POST /callback`, `POST /callback/` and `POST /nhcx/callback`. +- Takes an optional shared secret on the query string (`?token=`). +- Reads `X-Hcxkit-Type`, `X-Hcxkit-Flow` and `X-Hcxkit-Payload-Kind`. +- Archives the envelope before applying it. +- Answers `400` for an unreadable body, because redelivery cannot help. Anything unexpected becomes a 500, so the adapter retries. +- Returns `{"status": "settled" | "unmatched" | "ignored"}`. +- Routes by correlation id, never by path. + +## 7. The ledger + +Layout: `ledger.dir//.json`, one file per message, plus `/index.jsonl` with one summary line per message. Ids are eight base32 characters (alphabet `0-9A-V`), a day prefix and a counter that restarts each day: `7UMV0001` is the first message of its day. Pruned hourly by `retentionDays`. + +Entry fields: `id, direction (out|in), created_at, path, entity, action, kind (request|response), format (fhir|protocol|json), sender, recipient, correlation_id, api_call_id, request_id, workflow_id, hcx_status, status, error{code,message}, redelivery, duration_ms, peer{url,status_code,response}, also[], headers{}, fhir{}, fhir_summary{resource_type,bundle_type,entries,resource_types,focus,identifier,patient,outcome}`. + +`status` values: outbound `accepted`, `rejected`, `failed`; inbound `delivered`, `delivery_failed`, `rejected`. + +Thread: `{correlation_id, entity, workflow_id, counterparty, role (initiator|responder), state, started, updated, messages[]}`. `state` is derived by walking the messages in order: + +- `awaiting_response`: you sent a request. +- `awaiting_our_response`: a request reached you. +- `partial`: a `response.partial` arrived. +- `completed`: a response closed it. +- `error`: a rejection, a failed send or delivery, a protocol message, or an `error` status. +- `unknown`. + +Two ledger behaviours you rely on. An outbound `on_` response with no `correlation_id` is threaded to the newest matching inbound request. An inbound whose `api_call_id` was seen before is flagged `redelivery: true`. + +CLI, same data, no server needed for `follow`: + +```sh +nhcx-adapter ledger list --since 24h --entity preauth --status rejected +nhcx-adapter ledger follow --direction in +nhcx-adapter ledger show 7UMV0007 +nhcx-adapter ledger thread +nhcx-adapter ledger stats +nhcx-adapter decrypt --file body.json +nhcx-adapter cert +nhcx-adapter send --path v1/preauth/submit --recipient --file bundle.json +``` + +## 8. hcxkit-compatible endpoints + +A client written against hcxkit polls the adapter for the other side's answer instead of only waiting for its callback. The adapter serves the sliver of hcxkit's `/internal` API that such a client needs. None of these need the API key. Keep the adapter's port off any network you do not control (`nhcx-package/docs/02-Getting Started/10-NHCX Adapter.md`, "Before you expose it"). + +| Route | Body | Answers | +| --- | --- | --- | +| `GET /internal/config/get` | none | `{participant{participantId,name,callbackUrl}, participants[], CMID, env, urls{nhcx,participant,sessions}}` | +| `POST /internal/participants/search` | `{"participant_code": ""}` | `{participants:[registry record + participant_code, participant_name, endpoint_url, status, roles]}`; an unknown code is `{participants: []}` | +| `POST /internal/txn/related` | `{"txnId": ""}` | every ledger row on the same correlation id, both directions, as `{id, direction, status, sender, recipient, correlation_id, api_call_id, type, flow, created_at}`; `404 TXN_NOT_FOUND` when the ledger no longer holds it | +| `POST /internal/txn/fhir` | `{"txnId": ""}` | `{meta{type,payloadType,path,time}, jwe_headers, fhir}`, the same envelope shape a delivery carries | +| `POST /internal/txn/dispatch` | `{"txnId": ""}` | `{txnId, status}` with `dispatch_failed` for a failed or rejected send, `dispatched` for accepted or delivered, plus `errorCode`, `errorMessage` | +| `GET /internal/txn/list?limit=200` | none | the recent ledger, newest first, same row shape | +| `POST /internal/policies/search` | `{"identifiertype": "MemberId", "MobileNo" or "AbhaNumber", "identifiervalue": "..."}` (also `mobile`, `abhaNo`) | the ABDM registry's `participant/get/policies` answer, status passed through; "No policies found" is an error the caller reads as empty | +| `POST /internal/policies/abha/link`, `.../delink` | forwarded verbatim | registry answer | +| `POST /internal/participants/list` | forwarded verbatim | registry roster | +| `POST /internal/participants/certs` | `{"participantid": ""}` | `{participant_code, encryption_cert}` | +| `GET /internal/participants/saved` | none | the configured profiles | + +The polling pattern: + +1. After a send, call `/internal/txn/related` with the stored `txn_id`. +2. Take the inbound rows on the thread that were not sent by you. Keep only rows addressed to the participant the send came from. +3. Fetch each with `/internal/txn/fhir`, newest first. +4. Take the first whose bundle carries the resource the reply is made of (ClaimResponse, CoverageEligibilityResponse, InsurancePlan, Task). +5. Apply it through the same code path the callback uses. Dedupe on `x-hcx-api_call_id`. + +A `404` from `txn/related` means the ledger was reset. Settle the leg as an error instead of spinning. + +## 9. curl examples + +Set these once. The address is the adapter's default `listen`: + +```sh +export ADAPTER=http://127.0.0.1:8090 +export KEY= +export ME=@hcx +export PAYER=@hcx +``` + +Liveness and readiness: + +```sh +curl -s $ADAPTER/healthz +curl -s $ADAPTER/readyz +``` + +Send a coverage eligibility check. Write the envelope to a file first. The bundle is the package's validation request, `nhcx-package/fhir/B1/validation.json`, with your own identifiers substituted. Run this from the project root that holds `nhcx-package/`: + +```sh +python3 - <<'EOF' +import json, os +bundle = json.load(open("nhcx-package/fhir/B1/validation.json")) +env = {"jwe_headers": {"x-hcx-sender_code": os.environ["ME"], + "x-hcx-recipient_code": os.environ["PAYER"], + "x-hcx-workflow_id": ""}, + "fhir": bundle} +json.dump(env, open("/tmp/coverage-out.json", "w")) +EOF +curl -s $ADAPTER/fhir/out/v1/coverageeligibility/check \ + -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \ + --data-binary @/tmp/coverage-out.json +``` + +Read the answer back from the ledger with the `correlation_id` from that response: + +```sh +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger/thread/" +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger?direction=in&entity=coverageeligibility&since=1h" +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger/" +``` + +Same thread through the kit endpoints (no key): + +```sh +curl -s $ADAPTER/internal/txn/related -H 'Content-Type: application/json' -d '{"txnId":""}' +curl -s $ADAPTER/internal/txn/fhir -H 'Content-Type: application/json' -d '{"txnId":""}' +``` + +A session token for the PMJAY payer service or a registry call: + +```sh +curl -s -H "Authorization: Bearer $KEY" $ADAPTER/token +``` + +Simulate a delivery to your own callback while the adapter is not involved (useful for the callback handler's unit test). This is the exact shape the adapter posts. Wrap the package's bare payer bundle, here the pre-auth approval `nhcx-package/fhir/C5/C5-approved-wf21.json`, as `{"meta":{...},"jwe_headers":{...},"fhir":}` first: + +```sh +python3 - <<'EOF' +import json +bundle = json.load(open("nhcx-package/fhir/C5/C5-approved-wf21.json")) +env = {"meta": {"type": "in", "payloadType": "fhir", "path": "v1/preauth/on_submit"}, + "jwe_headers": {"x-hcx-correlation_id": "", "x-hcx-api_call_id": "", + "x-hcx-sender_code": "@hcx", + "x-hcx-recipient_code": "@hcx", + "x-hcx-status": "response.complete", "x-hcx-workflow_id": "21"}, + "fhir": bundle} +json.dump(env, open("/tmp/delivery.json", "w")) +EOF +curl -s -X POST "http://127.0.0.1:/nhcx/callback/v1/preauth/on_submit" \ + -H 'Content-Type: application/json' -H 'X-Nhcx-Path: v1/preauth/on_submit' \ + -H 'X-Nhcx-Payload-Kind: fhir' -H 'X-Nhcx-Correlation-Id: ' -H 'X-Nhcx-Api-Call-Id: ' \ + -H 'X-Hcxkit-Txn-Id: ' -H 'X-Hcxkit-Type: preauth' -H 'X-Hcxkit-Flow: request' -H 'X-Hcxkit-Payload-Kind: fhir' \ + -H 'Authorization: Bearer ' \ + --data-binary @/tmp/delivery.json +``` + +## 10. The HMIS-side endpoints a build exposes + +Use these as the model for what your HMIS needs. `` is the claim episode id. + +| Method | Path | Purpose | Leg | +| --- | --- | --- | --- | +| GET | `/claims`, `/claims/new`, `/claims/` | list, policy search, detail | none | +| POST | `/claims` | open an episode from a chosen policy | none | +| GET | `/claims//state` | the whole episode as JSON after the page-load polls | none | +| POST | `/claims//check` | coverage eligibility (validation, benefits, discovery) | `v1/coverageeligibility/check` | +| POST | `/claims//plan` | fetch or refresh the package master | `v1/insuranceplan/request` | +| GET | `/claims//plan/forms`, `.../forms/`, `.../plan/` | questionnaires and one package | none | +| POST | `/claims//link`, `/unlink` | attach or detach the admission | none | +| POST | `/claims//preauth` | save the dossier draft | none | +| GET, POST | `/claims//lines`, `.../lines/quantities`, `.../lines//delete` | procedure, implant and tier lines | none | +| POST | `/claims//forms` | save questionnaire answers | none | +| POST | `/claims//auth` | auth-requirements ruling | `v1/coverageeligibility/check` | +| POST | `/claims//submit` | pre-auth 12, query answer 19, enhancement 13, enhancement answer 131 | `v1/preauth/submit` | +| POST | `/claims//predetermination` | a quote | `v1/preauth/submit` | +| POST | `/claims//cancel` | cancel Task PC01 | `v1/task/submit` | +| POST | `/claims//status` | status enquiry Task | `v1/task/submit` | +| POST | `/claims//reprocess`, `/release` | reprocess or balance release, 36 | `v1/task/submit` | +| POST | `/claims//queries//reply`, `.../acknowledge` | communication reply or notification acknowledgement | `v1/communication/on_request` | +| POST | `/claims//discharge` | record how the stay ended | none | +| POST | `/claims//claim` | claim 15, query answer 161 or 151, resubmit 16 | `v1/claim/submit` | +| POST | `/claims//claim/documents`, `/documents`, `/documents/required`, `.../delete` | attachments | none | +| GET | `/claims//documents/` | view an attachment | none | +| POST | `/claims//payments//ack` | resend a payment acknowledgement | `v1/paymentnotice/on_request` | +| POST | `/v1/` under the registered `endpoint_url` (own transport), or `/callback`, `/callback/`, `/nhcx/callback` (nhcx-adapter) | a delivery | inbound | + +The HMIS configuration a build needs: + +- The transport's settings: for nhcx-adapter, its base URL (it listens on `127.0.0.1:8090` by default) and API key; for your own transport, the ABDM client id and secret, the private key, and the sessions, NHCX and registry addresses (`references/transport-knowledge.md` section 3). +- The payer's participant code (`1518@hcx` for the PMJAY SHA Himachal Pradesh sandbox) and the payer's name. +- The callback shared secret. +- A workflow-id override table, JSON, that overrides the per-payer table key by key, for example `cancel=122`. +- A map from payer code to payer adapter, for example `1518=pmjay,=generic`. +- The archive folder for cases, and a switch to turn the archive off. + +The sender code is not an environment variable. It is the facility's participant code, held in the HMIS's own settings. + +## 11. What the adapter client looks like in code + +The whole client is one function, `_api(path, payload, timeout, method, claim_id, use_case)`. It builds the URL from the base, adds `Authorization: Bearer` when a key is set, POSTs JSON, raises `GatewayError(message, status)` on any non-2xx or network failure, decodes JSON, and archives the envelope beside the case when `claim_id` is given. Every send in the module goes through it, which is what lets a test replace it with a stub: + +```python +posted = {} +def _ack(path, payload=None, **kw): + posted["path"], posted["payload"] = path, payload + return {"txn_id": "01PLAN", "correlation_id": "corr-plan-1"} +claims._api = _ack +``` + +Give your HMIS the same single door. diff --git a/plugins/nhcx/skills/nhcx-payment/references/errors-and-debugging.md b/plugins/nhcx/skills/nhcx-payment/references/errors-and-debugging.md new file mode 100644 index 000000000..9be844d82 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-payment/references/errors-and-debugging.md @@ -0,0 +1,167 @@ +# Errors and debugging + +Sources: + +- `nhcx-package/nhcx-error.yaml`: every NHCX, PAYR and ERR-PYR code, with the standard and reference payer readings side by side. +- `nhcx-package/docs/06-Reference/01-Error Codes.md`: the same codes as tables. +- `nhcx-package/docs/01-Overview/04-JWE, Status and Errors.md`, "Codes met live". +- `nhcx-package/docs/03-Building a Provider/11-PMJAY Sandbox Run.md`: one full case run, refusal by refusal. +- `nhcx-package/docs/06-Reference/02-Troubleshooting.md`. +- The nhcx-adapter release README, "Troubleshooting". + +The live readings are from runs against the PMJAY SHA Himachal Pradesh sandbox payer (`1518@hcx`). + +## 1. Where an error comes from + +Three places refuse a message, and the family of the code says which (`nhcx-error.yaml`, `spaces`): + +| Family | Who refused | How you hear it | +| --- | --- | --- | +| Gateway answers to your own send (`400`, `401`) | the exchange, before the message goes further | the HTTP answer to your POST on `/v1/...`; a `401` is an expired token or a missing `Bearer` | +| A delivery your key cannot open (own transport) | your receiving end | the JWE will not decrypt: the certificate on your participant record is not the key you hold | +| Adapter codes (`INVALID_ENVELOPE`, `CERT_NOT_FOUND`, `CALLBACK_HTTP_500`), nhcx-adapter only | nhcx-adapter, before or after the wire | the HTTP answer to your `/fhir/out` call, `{"ok": false, "error": {...}}` | +| `NHCX-*` | the exchange; the message never reached the payer | the HTTP answer to your call (`gateway_status` 4xx with `upstream_body`), or a `ProtocolResponse` delivered to your callback later | +| `PAYR-*`, `ERR-PYR-*` | the payer; the message reached it | a `ProtocolResponse` on your callback with `x-hcx-status: response.error` and `x-hcx-error_details {code, message}`, on the request's correlation id | + +A `ProtocolResponse` is plain JSON, not a bundle. The exchange delivers it with `type: ProtocolResponse` and the `x-hcx-` fields in the clear; nhcx-adapter passes it on with `X-Nhcx-Payload-Kind: protocol` and `fhir` set to the body. Read `fhir.type == "ProtocolResponse"` and `fhir["x-hcx-error_details"]`. Settle the leg as refused at the door with the payer's words, and keep the thread the payer last answered on. + +PAYR numbers are not globally unique. The same number means different things on different sheets (`nhcx-error.yaml` lists them under `collisions`), and the live sandbox reuses several with a meaning the published sheet does not give. Match on the message text and log both. + +## 2. PAYR and ERR codes met live + +The published text is from `nhcx-package/nhcx-error.yaml`. Where the standard and reference payer sheets collide, both readings are given. The live text and the fix are from the sandbox runs. + +| Code | Published text | Live text | What it means | Fix | +| --- | --- | --- | --- | --- | +| PAYR-1008 | Invalid FHIR bundle received (reference payer); Eligible coverage amount is insufficient (standard) | "Invalid content type" or "Invalid input, code and reason code" or "Invalid Base64" | Three faults on one code: a document outside pdf, jpg, jpeg, png and fhir+json; a Task code paired with a reason the scheme does not accept (every `status`, `reprocess`, `release` Task on the sandbox, and a reprocess with the intimation input misspelt); an attachment it will not decode | Check the content type. For a Task, the sandbox takes only one financial task code, `cancel` (`11-PMJAY Sandbox Run.md`, "What the sandbox will not take"). Spell the reprocess input `intimationNumber` | +| PAYR-1018 | Time limit for submission expired (standard); No task reason code received (reference payer) | asks for a `Task.reasonCode` on a status enquiry | The status Task is refused as incomplete; with a reason it is refused with PAYR-1008 | Do not offer a status enquiry on PMJAY; switch it off in the PMJAY payer adapter | +| PAYR-1019 | Requested additional information was not received in time (standard); Invalid sequence received in supporting info element (reference payer) | "Invalid sequence received in supporting info element" | A `supportingInfo` entry with no `sequence` | Number the whole list once it is assembled | +| PAYR-1027 | (item error family) | "Invalid item id found for item in claim component" | `Claim.item` has no element `id` (`Item/1`). Nothing to do with the package code | Put `id` on every item, procedure and supportingInfo | +| PAYR-1083 | (practitioner family) | "No HPR details found for the practitioner ... category code as HPIN" | The Practitioner carries no identifier typed `HPIN` | Add the `HPIN` identifier under `https://hpr.abdm.gov.in` | +| PAYR-1096, PAYR-1503 | (supporting-info value-type family) | the death date is missing | A death claim without the `ONS`/`DTM` entry | Add `ONS`/`DTM` with the death instant and answer the plan's death forms | +| PAYR-1214 | No previous preauthorization approved record found for the resubmission request | same | A 121 after a rejection | Send a fresh 12 | +| PAYR-1238 | Beneficiary is having an active preauthorization request at this hospital with reference number ... | same; the reference ends in the SHA's case id | Scheme rule, not a bundle fault: one live pre-auth per beneficiary per hospital. Perversely the first sign the bundle is right, because validation runs first | Cancel the other case (PC01) or let it be rejected; sweep before a run | +| PAYR-1245 | Rule failure | "Only one conservative procedure can be booked for a case" | The master's `ProcedureType`; an enhancement on a conservative case must add a medical package | Pick a package whose `ProcedureType` is medical | +| PAYR-1254, PAYR-1365 | Response for STG Questionnaire id ... is mandatory for procedure code ... | same | A package's treatment-guideline questionnaire unanswered | Answer every `/stgquestionnaire/` form the plan attaches to the quoted packages | +| PAYR-1256, PAYR-1363 | Response for Authentication Consent Questionnaire is missing | same | The plan's consent questionnaire unanswered where no biometric token was taken; 1256 on the pre-auth, 1363 on the claim | Answer the policy-level consent form on both legs | +| PAYR-1270 | Item LM100 is not applicable for preauthorization request | same | `LM100` on a pre-auth | Only a LAMA or DAMA claim before or during surgery carries it | +| PAYR-1321 | Error occurred while processing the request due to invalid workflow id | same | 151, 19 or 16 on `v1/claim/submit` | Answer a claim query on 161; never resubmit a decided claim, reprocess it | +| PAYR-1322 | No active case found for the given case number | "Active instance found for case number" | A request is already open on that case; the scheme takes one at a time | Wait about 30 seconds after a decision, then send again; up to three tries | +| PAYR-1362 | No procedure with code LM100 received with 'Requested' status | same | A LAMA or DAMA claim before or during surgery that still carries the package | Collapse the claim to one `LM100` line | +| PAYR-1367, PAYR-1368 | No biometric records found ... / units of cycle information received | same | A cyclic package (dialysis) claimed without a biometric record per cycle and cycle information | Do not claim a cyclic package unless the HMIS can produce both | +| PAYR-1401 | policy not allowed for the hospital | same | The plan was asked for under a policy the hospital is not empanelled under | Ask under the beneficiary's own policy code from the policy search | +| PAYR-1406 | Existing request with correlation id ... is in progress | same | A second plan request while one is still being served | Wait 15 to 60 minutes; reuse the master you hold | +| ERR-PYR-CLM-007 | on none of the published sheets; `nhcx-error.yaml` lists it as observed live | "No prior preauthorization or claim record found for case number" | The claim was sent under a number of its own instead of the pre-auth's | Send the claim under the pre-auth's claim number | + +Refusals arrive in order: the SHA validates the bundle first and applies the scheme's rules only to a bundle that passed. A refusal in the `PAYR-102x` block is structural, so check ids and sequences before values. + +## 3. Gateway protocol errors + +From `nhcx-package/nhcx-error.yaml` (the gateway space) and the live notes: + +| Code | Message | When you meet it | Fix | +| --- | --- | --- | --- | +| NHCX-1006 | Duplicate request. Request with same correlation id already exist | A request sent again on a correlation id the exchange already holds | Mint a fresh correlation id for every request; only a response echoes one | +| NHCX-1010 | No Data with given Correlation id for call back request | A response sent on a thread the exchange has retired: the request was redelivered five times without a 2xx, or the id was never a request | Acknowledge inbound requests at once; a payer that decides minutes later sends `outcome queued` first | +| NHCX-1012 | No records found with the requested api caller id | The sandbox's own `v1/status` route, whatever id you pass | Ask status as a Task on `v1/task/submit` | +| NHCX-1015 | Invalid response received from receiver (published); the registry answers "You are not authorized to update/modify details" | Updating a participant's endpoint or certificate with a client id that did not create it | Use the creator's credentials or the NHCX participant portal (nhcx-adapter release README, "Troubleshooting") | +| NHCX-1016 | Invalid Api Action / no policies found (the registry, on a policy search) | A policy search that finds nothing | Read it as an empty result | +| NHCX-1018 | Invalid ABHA number received | An ABHA not in `XX-XXXX-XXXX-XXXX` form on the envelope | Format it, or omit the header | + +With nhcx-adapter as the transport, its local codes and their HTTP statuses are in `api-knowledge.md` section 5. The ones you will meet first: + +- `CERT_NOT_FOUND`: the recipient has no certificate on the registry; nothing to fix locally. +- `SELF_ENCRYPTION_KEY`: the registry handed out your own certificate for another code; run `nhcx-adapter cert --refresh`. +- `DECRYPT_FAILED` on `/in`: your registered certificate is not the key you hold; run `nhcx-adapter check`. +- `WRONG_RECIPIENT` on `/in`: a message for a participant this adapter does not hold. +- `CALLBACK_HTTP_` and `CALLBACK_UNREACHABLE`: your HMIS refused or was down; NHCX will redeliver up to five times. +- `TOKEN_HTTP_401`: wrong `clientId` or `clientSecret`, or sandbox credentials against production. + +## 4. Reading a ledger thread + +The per-case archive is the first place to look, with any transport: every message sent and received, by correlation id, in `//transactions.txt` (step 4). With nhcx-adapter as the transport, its ledger also holds what reached it but not your HMIS; the commands below read it. + +Step 1. Find the thread. From the leg row's `correlation_id`, or from the case number in a summary: + +```sh +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger/thread/" | python3 -m json.tool +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger?since=2h&direction=in&limit=100" | python3 -c 'import json,sys; [print(r["id"], r["created_at"][11:19], r["direction"], r["path"], r["workflow_id"], r["hcx_status"], r["status"], r.get("fhir_summary",{}).get("outcome")) for r in json.load(sys.stdin)["items"]]' +nhcx-adapter ledger thread # no server needed +``` + +Step 2. Read the derived `state`: + +| state | Meaning | What to do | +| --- | --- | --- | +| `awaiting_response` | You sent a request and nothing came back | Wait; on the SHA a decision needs the desk. Check `peer.status_code` on the outbound row is 202 | +| `partial` | A `response.partial` arrived (20, 25, or the SHA's 37) | The payer has it. The decision comes on the same thread | +| `completed` | A `response.complete` arrived | The leg should be settled in the HMIS. If it is not, the callback failed or the reader misread it | +| `awaiting_our_response` | A request reached you (a CommunicationRequest, a payment notice) | Your reply is due on this correlation id | +| `error` | A rejection, a failed send or delivery, or a protocol message | Open the message with `error` or `format: protocol` | + +Step 3. Read one message in full, bundle included: + +```sh +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger/" | python3 -m json.tool | less +``` + +On an inbound row, `peer.status_code` is what your callback answered and `peer.response` is its body. A `delivery_failed` row with a 500 is your handler raising. On an outbound row, `peer.status_code` is the gateway's answer and `peer.response` its body. A `rejected` row carries `GATEWAY_HTTP_` and the NHCX error in `peer.response`. + +Step 4. Compare with the HMIS's own archive for the case, `//transactions.txt`. Each line names the workflow id, correlation id, api call id, ledger id and file. + +- A message in the ledger and not in the archive is a callback that failed. +- A message in the archive marked `outcome=unmatched` is one the HMIS could not tie to a case: the correlation id is on no leg row, and the bundle names no claim number the HMIS knows. +- A message in neither is a send that never left; look at the HMIS's error on the leg row. + +Files, when the server is down: `//.json`, and `index.jsonl` in the same folder for the summaries. `ledger.dir` is `data/ledger` by default. + +## 5. Correlation mistakes + +Each of these was made once in a real build. + +- Answering on the wrong thread. A communication reply or a payment acknowledgement must carry the request's `x-hcx-correlation_id`; every other leg must not carry one. A PMJAY query answer (19, 131, 161) goes on a new correlation id; a same-thread answer is swallowed without a refusal. +- Sending a non-UUID correlation id. nhcx-adapter replaces anything that is not an 8-4-4-4-12 UUID with a fresh one, so the thread is silently lost; store what the transport returned, not what you sent. With your own transport, a request's correlation id is its own `api_call_id` and an answer echoes the request's. +- Matching by path or by header type. Route an inbound message by its correlation id first, then by the claim number inside the bundle. With nhcx-adapter, the `X-Hcxkit-Flow` header is inverted on purpose and must not be a filter. +- Closing a thread on the first reply. The acknowledgement and the decision share one correlation id; a settled-status guard throws the approval away. +- Losing the thread after a refusal at the door. A send refused with a ProtocolResponse went out under a correlation id the payer never took in. The case still lives on the thread the payer last answered; keep it as `thread_correlation_id`. +- Reusing a correlation id after an error. The exchange retires it; the next attempt needs a fresh one. +- Forgetting the workflow id on a reply. Some payers match the payment acknowledgement on the notice's own workflow id; PMJAY wants 17. + +## 6. Redelivery and deduplication + +NHCX redelivers an unacknowledged message up to five times and then drops the correlation id. The SHA redelivers a large plan answer on its own, two or three times about a minute apart, under the same `x-hcx-api_call_id`. A case archive showed it as three lines on one api call id. With `callback.also` configured, one delivery reaches every target, and a refusal by any one of them makes NHCX redeliver to all. + +So: + +- Dedupe on `x-hcx-api_call_id` (with nhcx-adapter, `X-Hcxkit-Txn-Id` carries the same value). Either store the last applied `api_call_id` on the leg row and ignore a repeat, or keep an inbound ledger keyed on it and answer `duplicate`. A payer that omits the id is deduped on identical outcome and adjudication. +- Dedupe payment notices and communication requests on their correlation id, with a unique index on each table. +- Answer 2xx before doing slow work. The exchange allows 30 seconds for the 202 receipt (nhcx-adapter gives your HMIS 20 of them, `callback.timeoutSeconds`); anything slower is a failed delivery. +- Un-record a delivery whose application failed for a passing reason (database away), so the redelivery is not waved off as a duplicate. +- With nhcx-adapter, treat `X-Nhcx-Redelivery: true` as a hint, not a rule: the ledger flag is per adapter process and is lost on a ledger reset. + +## 7. A send reported as failed can still have landed + +Seen live on the sandbox three times in one night. A pre-authorisation went out through nhcx-adapter, the connection dropped after the request had been written, and it answered the hospital `GATEWAY_UNREACHABLE` with HTTP 502. NHCX had taken the message: the SHA acknowledged it four seconds later on the correlation the adapter had minted. A hospital that treats that 502 as "not sent" sends again. The scheme refuses the duplicate (ERR-PYR-PRE-030 "Active instance found for case number", PAYR-1238 for a fresh pre-auth), and a live case stands at the payer that the hospital has no record of. + +So: + +- nhcx-adapter's failure body names the ids the message went out under: `ledger_id`, `txn_id`, `correlation_id`, `api_call_id`, `request_id` and the `headers` map. Keep them. With your own transport the ids are the ones you minted before sealing: store them before the POST, so a failed POST still has a thread to look for. +- Record the failed leg under that correlation, not as nothing. Carry the ids on the client's error and write them onto the leg row. +- When an answer arrives on a failed leg's correlation, revive it: the leg becomes a sent leg, the record moves from draft to with-the-payer, and the desk is not offered a second send. A protocol error answer revives nothing. +- Anything that creates a record before it sends must name that record in the refusal, or the record is orphaned where nobody can see it. An enhancement handler returns the child it raised alongside the gateway's words. + +## 8. Sandbox pace rules + +What the SHA Himachal Pradesh sandbox (`1518@hcx`) did across the runs. `nhcx-package/docs/03-Building a Provider/11-PMJAY Sandbox Run.md` records one such run in order. + +- One live pre-authorisation per beneficiary per hospital (PAYR-1238). Every HMIS that shares the facility's participant code shares the limit, so sweep before a run: withdraw every approved case without a claim, then wait ten seconds. +- One request at a time per case (PAYR-1322). About 30 seconds between a decision and the next leg; an enhancement refused with "Active instance" is resent up to three times. +- Decisions are taken on the NHCX Payer Service desk, not on the exchange (`nhcx-package/docs/03-Building a Provider/12-PMJAY Adjudication APIs.md`). A case has to be driven through roles: PPD-Trust decides a pre-auth; a claim walks CEX-Trust, CPD-Trust, the Medical Audit Committee, ACO-Trust, SHA-Trust and the Claim Review Committee. The desk answers "Event Meta Log not found" or "Case not found" until the exchange has delivered the request; retry every six seconds, up to 150 seconds. A decision the desk accepts is sometimes never sent; taken again a minute later it is answered in seconds, so decide up to four rounds of 90 seconds. +- An enhancement's query has to be taken a minute after the acknowledgement. +- A claim episode with a query answered and the roles walked takes about ten minutes. Run cases one at a time and allow 20 minutes per case. +- The plan answer arrives in pieces over a minute and is redelivered; expect the same api call id three times. +- The beneficiary registry behind the ABDM session refuses a search now and then while a token refreshes. Retry the search up to four times, 30 seconds apart. +- The sandbox approves a claim query answer at zero with "No query response comments received" when the `CQD` reply is missing, and sometimes even when it is present. Report it; do not assert on the amount. +- The status Task is refused on this sandbox: without a `Task.reasonCode` it answers PAYR-1018, with any reason code PAYR-1008. PMJAY decides on its own desk and answers no status enquiry, so do not offer one for it. Record the refusal on the enquiry row and move on. +- The reprocess Task is taken only under the standard's spelling, `intimationNumber`. Use that spelling on every Task (cancel included); the package's bundles carry it too. The SHA answers workflow 37, "Arbitration claim submission process completed successfully". +- A test payer you run yourself has none of these limits; six use cases ran in under four minutes against one. diff --git a/plugins/nhcx/skills/nhcx-payment/references/fhir-knowledge.md b/plugins/nhcx/skills/nhcx-payment/references/fhir-knowledge.md new file mode 100644 index 000000000..08ffbb6c6 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-payment/references/fhir-knowledge.md @@ -0,0 +1,206 @@ +# FHIR knowledge: every bundle sent and received + +Sources: the bundles under `nhcx-package/fhir` (the hospital pins in `B1` to `B9`, the payer answers in `C3` to `C11`, the live PMJAY hospital captures in `D1` to `D13`) and the chapters under `nhcx-package/docs/05-FHIR Reference`. Get the package as `references/material.md` says. + +## 1. Where the examples live + +| Set | Path | What it is | +| --- | --- | --- | +| Pinned hospital bundles | `nhcx-package/fhir/B1` to `B9`, the lower-case files (`B3/preauth-request.json`) | One bundle per message a hospital sends, written to the specification with placeholders. A build is held to these byte for byte. The pin map is in `references/material.md`. | +| Payer answers | `nhcx-package/fhir/C3` to `C11` | One file per message the payer sends: the generic answer and, where one exists, its `-pmjay` twin. Feed these into your readers. | +| Live hospital captures | `nhcx-package/fhir/D1` to `D13` (PMJAY) and the capitalised B files such as `B3/B3-request.json` (generic) | Bundles taken from the sandbox wire, with the beneficiary's identifiers replaced | +| The catalogue | `nhcx-package/fhir/index.yaml` | For each file: direction, side, scheme (`generic` or `pmjay`), workflow id, focal resource, origin. Origin `example` means placeholders, not a payload; `wire` means a capture. | +| The NRCeS IG's own example | `nhcx-package/fhir/B4/communication-request.json` | The communication TaskBundle for the payer's request comes from the IG | +| Your build's archive | `//NNN--.json` and `transactions.txt` (modules 7.1 and 7.3) | Every envelope one episode sent and received, in order | +| Chapters | `nhcx-package/docs/05-FHIR Reference/*.md` | Element by element: `08-Preauthorisation Request.md`, `12-Claim Request.md`, `13-Claim Response.md`, `17-Communication.md`, `15-Cancel, Reprocess and Shortfall.md`, `16-Payment Notice and Acknowledgement.md`, `06-Insurance Plan Response, Package-Based.md`, `19-Codes and Value Sets.md` | + +Pins, by leg. Paths are under `nhcx-package/fhir/`. + +| Leg | Provider pin | Payer answer or capture | +| --- | --- | --- | +| Coverage eligibility | `B1/discovery.json`, `B1/validation.json`, `B1/benefits.json`, `B1/auth-requirements.json` | `C3/validation-response.json`, `C3/discovery-response.json`, `C3/benefits-response.json`, `C3/C3-response-generic.json`; PMJAY `C3/coverage-eligibility.json`, `C3/C3-benefits-pmjay.json`, `C3/C3-response-pmjay.json` | +| Insurance plan | `B2/insurance-plan-request.json` | `C4/C4-response-pmjay.json` (package-based, abridged), `C4/C4-response-generic.json` (coverage-based) | +| Pre-auth 12, enhancement 13, query answer 19 or 131 | `B3/preauth-request.json`, `B3/preauth-enhancement.json`, `B3/preauth-queryupdate.json` | `C5/C5-received-wf20.json`, `C5/C5-approved-wf21.json`, `C5/preauth-queried.json`, `C5/C5-rejected-wf23.json`, `C5/C5-enhancement-approved-wf22.json`; PMJAY the `-pmjay` twins and `C5/C5-queried-wf24.json` | +| Cancel PC01 | `B3/preauth-cancel.json` | `C10/C10-cancelled-wfPC02.json`, `C10/C10-cancelled-wfPC02-pmjay.json` | +| Claim 15, query answer 161 | `B5/claim-request.json`, `B5/claim-queryupdate.json` | `C7/C7-received-wf25.json`, `C7/C7-approved-wf26.json`, `C7/claim-queried.json`, `C7/C7-rejected-wf291.json`; PMJAY the `-pmjay` twins, `C7/C7-approved-deduction-wf26-pmjay.json` and `C7/C7-queried-wf27.json` | +| Reprocess 36, release 36 | `B5/claim-reprocess.json`, `B5/claim-release.json` | `C10/C10-arbitration-wf37.json`, `C10/C10-arbitration-wf37-pmjay.json` | +| Payment acknowledgement | `B7/payment-notice-ack.json` | The notice you answer: `C9/C9-notice-wf30.json`; PMJAY `C9/payment-notice.json`, `C9/C9-notice-tds-wf30-pmjay.json` | +| Communication reply | `B4/communication-response.json` | `B4/communication-request.json` (the query you answer; the IG's example), `C6/C6-preauth-query-wf24.json` and `C6/C6-claim-query-wf27.json` (live, generic), `C6/C6-notification-wfN02.json` (PMJAY) | +| Status enquiry | None. The published call carries no bundle (`nhcx-package/docs/05-FHIR Reference/18-Predetermination, Status and Search.md`). | None captured | + +## 2. Conventions every hospital bundle follows + +From `nhcx-package/docs/05-FHIR Reference/01-Bundles and Conventions.md` and the pins: + +- `Bundle.type` is `collection`; `Bundle.meta.profile` names the NRCES bundle profile (`ClaimBundle`, `TaskBundle`, `CoverageEligibilityRequestBundle`); every resource names its own profile under `https://nrces.in/ndhm/fhir/r4/StructureDefinition/`. +- Every entry has an absolute `fullUrl` under one base, `https://nhcx.abdm.gov.in/...`, and every reference resolves to another entry. A thing that is genuinely not in the bundle is named by identifier, not by a URL. The chapter's rule 3 also accepts `urn:uuid:` references; parse both. +- `Bundle.id` is fixed per shape: `coverage-validation-request-generic`, `preauth-request-generic`, `preauth-enhancement-request-generic`, `claim-queryupdate-request-generic`, `preauth-cancel-request-generic`. +- No `meta.versionId`, no `meta.lastUpdated`, no bundle `timestamp` on a request. The communication reply and acknowledgement are the exception: the IG example carries `meta.lastUpdated` and `timestamp`, and the build writes them. +- Money carries `currency: INR`; the total equals the sum of the item nets; whole numbers are written as integers. +- Instants are IST with `+05:30`. The four coverage pins in `B1` stamp `created` at `+05:00`, so leave `created` out of the byte comparison. + +## 3. Coverage eligibility request + +Builder: `build_coverage_request`. Seven entries, in this order and at these urls: + +1. `CoverageEligibilityRequest` at `/coverage-eligibility/request`: `identifier: [{system: https://nhcx.abdm.gov.in}]`, `status active`, `priority normal`, `purpose: []`, `patient`, `created`, `enterer` (the PractitionerRole), `provider`, `insurer`, `facility` (the Location), `insurance: [{focal: true, coverage}]`, and `item[]` on `benefits` and `auth-requirements`. +2. `Patient` at `/patient`: identifiers typed `PMJAY` (NDHM identifier-type system) and `MB` (v2-0203), both the member id. Nothing else; demographics are the payer's to return. +3. `Organization` provider at `/provider`: identifier `NPI` under `https://nhcx.abdm.gov.in` = the facility's registry id (HFR id); `type prov`; `name`. +4. `Organization` payer at `/payer`: identifier `NIIP` = the participant code without `@hcx` (`1518`); `type pay`. +5. `Location` at `/location`: `name`, `managingOrganization` the provider. +6. `Coverage` at `/coverage`: identifier `NH` = the policy code, or `NONE` on a discovery; `status active`; `type HIP`; `subscriber`, `beneficiary`, `subscriberId` = member id; `relationship self`; `payor`. +7. `PractitionerRole` at `/practitioner-role`: `code` SNOMED `307988006` Medical technician. + +Items (`eligibility_item`): `category` under `https://nhcx.abdm.gov.in/category-code` (the specialty), `productOrService` under `https://nhcx.abdm.gov.in/product-code` (the package), `quantity.value` as an integer, and each ward tier quoted through the package as a `modifier` coding with code and display and no system. No money, no diagnosis, no sequence. + +The four purposes differ only in `purpose`, the Coverage identifier and whether `item` is present. + +Reader (`parse_validation_bundle`): the payer echoes the request's entries and appends its own, so take the last `CoverageEligibilityResponse`, `Patient` and `Coverage`. Read `insurance[0].inforce`, `outcome`, `disposition`, `item[].authorizationRequired`, the largest `benefit[].allowedMoney` with its `usedMoney`, the Patient's name, gender, birth date, address, `ABHA` identifier and photo, the Coverage's `class[0].name` and `period`. The SHA answers on workflow id `5` (`nhcx-package/fhir/C3/C3-response-pmjay.json`). + +Auth-requirements reader (`parse_auth_bundle`, with `supporting_entry`; examples `C3/C3-response-generic.json` and `C3/C3-response-pmjay.json`): one `insurance[0].item` per line quoted, each with `authorizationRequired`, `excluded`, `benefit[0]` and `authorizationSupporting[]`. Each supporting entry is a CodeableConcept whose `text` is free text the scheme overloads: `fullUrl: ` marks a form to answer; `Type: pre` or `Type: post` says which leg a document is due at; `Procedure Code: X` says for which line. The space after the colon is sometimes missing; match both. A form is always wanted at pre-auth; a document only when its stage is `pre`. + +## 4. Insurance plan request and the plan + +Request (`build_plan_request`): a `TaskBundle` with one entry, a `Task` at `https://nhcx.abdm.gov.in/insurance/request`: `status requested`, `intent order`, `code poll` on the HL7 financial task code system, inputs typed `policyNumber` and `providerId` under the NDHM task-input code system. No id, no timestamp, no requester. At least one input is mandatory. Bundle id `insurance-request-generic`. + +Answer: an `InsurancePlanBundle` with one `InsurancePlan`, an `Organization`, and one `Questionnaire` per form the plan names (the same form repeated once per benefit that needs it; collect by `url`). The parser (`parse_plan_bundle`) reads both published shapes and merges them on package code: + +- `plan[].specificCost[].category` (the specialty) then `benefit[].type` (the package) then `cost[]`: the cost typed `Procedure` is the package rate; `Stratification` and `Implant` costs are money paid over the rate, named by their `qualifiers[0]`. +- `coverage[].benefit[].limit[]`: the limit whose code is the package's own is the rate; the rest (STRAT codes, implants) are tiers. +- Extensions on the plan, the coverage and each benefit, matched by a squashed url family: `Claim-Condition` children name conditions (`ProcedureType`, `IsDayCare`, and so on); `Claim-SupportingInfoRequirement` children are one nested requirement per document, each with `category`, `code` (`MAND0409` and the like) and `documentationUrl` pointing at a Questionnaire. Requirements on the `InsurancePlan` resource itself are policy-wide (proof of identity, the consent forms). +- A `Questionnaire` under `/questionnaire/` is a policy form; under `/stgquestionnaire/` a treatment-guideline checklist. Questions live on `item.prefix` far more often than `item.text`; answer options are plain strings; `initialSelected` is the payer's default. + +Store it once per facility and policy and copy it onto later episodes (`reuse_plan`). The PMJAY master runs to tens of megabytes; the validator cannot check it whole. + +## 5. The Claim bundle: pre-authorisation, enhancement, query answer, claim, predetermination + +One document for every leg (`claim_bundle`). Entries, in order and at these urls: + +1. `Claim` at `https://nhcx.abdm.gov.in//`: leg `preauth`, `claim` or `predetermination`; flow `request`, `enhancement` or `queryupdate`. +2. `Patient` at `/patient`, `id 1`: identifiers `PMJAY` (member id), `ABHA` (when known), `MB` (member id); `name.text`, `telecom`, `gender`, `birthDate`. +3. `Organization` provider at `/provider`, `id 1`; `Organization` payer at `/payer`, `id 2` (as in section 3). +4. `Coverage` at `/coverage`, `id 1`: `NH` identifier = policy code, `subscriberId` = member id. +5. `Practitioner` at `/practitioner` (the second and later at `/practitioner/2` and so on), `id n`: identifiers `HPID` under `https://nhcx.abdm.gov.in`, `MD` (licence) when known, and `HPIN` under `https://hpr.abdm.gov.in`. PMJAY looks the practitioner up by the `HPIN` typed identifier and refuses a bundle without one with PAYR-1083. `qualification.code` under HL7 v2-0360 with the table's own display (`degree_coding`). +6. `Procedure` at `/procedure/n`, `id n`, one per package: `status preparation` before treatment, `completed` on the claim; `code` SNOMED `71388002` with `text` = the package display; `performedDateTime`. +7. `QuestionnaireResponse` at `/questionnaireresponse/n`, one per answered form: `questionnaire` = the plan's Questionnaire url, `status completed`, `subject` the Patient, `authored`, `item[].answer[]` typed by the question (`valueString`, `valueDateTime`, `valueBoolean`, `valueInteger`, `valueDecimal`, `valueAttachment`). + +The Claim itself: + +- `id` = the claim number; `identifier[0]` typed `CLN` under `https://nhcx.abdm.gov.in` = the claim number. Element ids on every list the payer indexes: `item[].id = Item/n`, `procedure[].id = Procedure/n`, `supportingInfo[].id = SupportingInformation/n`. PAYR-1027 is an item without one. +- `status active`, `type` SNOMED `737481003` inpatient care, `use` = `preauthorization`, `claim` or `predetermination`, `billablePeriod`, `created`, `insurer`, `provider`, `priority normal`. +- `careTeam[]`: sequence, provider reference, role `primary` for the first and `assist` after, `qualification` SNOMED specialty. +- `diagnosis[]`: ICD-10 under `http://hl7.org/fhir/sid/icd-10`, type `admitting`, `onAdmission yes`. +- `procedure[]`: sequence, `type` under `https://nhcx.abdm.gov.in/procedure-type` = the plan's `ProcedureType` condition lower-cased (`conservative`, `medical`, `surgical`), `date`, `procedureReference` with the package display. +- `insurance[0]`: `sequence 1`, `focal true`, `coverage`; on the claim `preAuthRef: [""]`. The pin carries the pre-auth's own claim number there (`B5/claim-request.json` quotes `B3/preauth-request.json`'s claim id). The build carries the payer's `ClaimResponse.preAuthRef`, which the live capture `nhcx-package/fhir/D9/D9-request.json` shows as `2026091110000810`. +- `item[]` (`claim_items`): one per procedure or implant, never per tier. `sequence`, `careTeamSequence`, `diagnosisSequence`, `procedureSequence` (its own Procedure), `informationSequence` (every supportingInfo), `category` under `ndhm-benefit-category` (the specialty), `productOrService` under `ndhm-procedure-code` (the package), `modifier[]` one coding per ward tier with code and display and no system, `programCode` `AB-PMJAY` under `ndhm-program-code` for PMJAY and none for a generic payer, `servicedPeriod` as dates, `quantity`, `unitPrice` = net divided by quantity, `factor` from the scheme's multiple-procedure rule (1, 0.5, 0.25 by cost rank; PMJAY only), `net` = the line plus its tiers. +- `total` = the sum of the nets. + +supportingInfo (`supporting_info`), every entry numbered once the list is assembled (PAYR-1019 is an entry without `sequence`): + +| When | category | code | value | +| --- | --- | --- | --- | +| every leg, one per attached document | `INV` (or the document's own category) under `ndhm-supportinginfo-category` | the plan's requirement code (`MAND0408`) under `https://nhcx.abdm.gov.in/document-code`, else `ODN` | `valueAttachment {contentType, data, title}` | +| every leg | `ONS` | `ADDD` | `valueString` admission instant | +| every leg | `OTH` | `EDT` | `valueString` admission instant | +| claim | `HDS` | the plan's summary code (`MAND0006` in the pin) else `HDS` | `valueAttachment` the discharge summary | +| claim, when a surgery time is known | `ONS` | `PSP` | `valueString` surgery instant | +| claim | `ONS` | `DSDE` | `valueString` discharge instant, or the death instant | +| claim, death only | `ONS` | `DTM` | `valueString` death instant (PAYR-1096 and PAYR-1503 without it) | +| claim | `DIS` | `DTH`, `LAMA`, `DAMA` or `DTM` | `valueString` the stage: `Before Surgery`, `During Surgery`, `After Surgery` | +| query answer (flow `queryupdate`) | `NMI` | `CQD` | `valueString` the desk's reply. The SHA reads its query response comments from here; an answer without one is decided as if none was given | +| every leg, one per answered form | `INF` (or `STG` for a treatment guideline) | `ODN` (or `STG`) | `valueReference` to the QuestionnaireResponse entry | + +Which forms ride (`required_forms`): with an auth-requirements ruling, the forms it named for the leg; without one, at pre-auth every guideline form the plan attaches to the quoted packages; and on both legs every policy-level form. The scheme refuses a pre-auth that answers neither biometrically nor with its Authentication Consent questionnaire (PAYR-1256, PAYR-1271), a claim without the consent answered again at discharge (PAYR-1363, PAYR-1364), and a package without its STG questionnaire (PAYR-1254, PAYR-1365). The live D4 capture carries two policy questionnaires; the live D9 claim carries four, including the Discharge Consent (`nhcx-package/fhir/D9/D9-request.json`). + +Which documents ride (`required_documents`, `preauth_documents`): the ruling's list for the leg, else the plan's list for the quoted packages at pre-auth and whatever was not attached there at the claim. A file attached against a requirement carries that requirement's code; a file nobody asked for carries `ODN`. Never drop one. Content types the scheme takes: pdf, jpg, jpeg, png (PAYR-1008 otherwise). + +The legs differ in these ways only: + +| Leg | flow | use | Procedure status | Extra | +| --- | --- | --- | --- | --- | +| Pre-auth 12 | `request` | `preauthorization` | `preparation` | | +| Enhancement 13 | `enhancement` | `preauthorization` | `preparation` | every line, old and new, under the same claim number; the costlier package at factor 1 and the other at 0.5 (the live capture `nhcx-package/fhir/D6/D6-enhancement.json` carries the two lines at 1 and 0.5) | +| Query answer 19 or 131 | `queryupdate` | `preauthorization` | `preparation` | the `NMI`/`CQD` reply | +| Claim 15 | `request` | `claim` | `completed` | discharge scalars, summary, `preAuthRef`, the claim under the pre-auth's number (ERR-PYR-CLM-007) | +| Claim query answer 161 | `queryupdate` | `claim` | `completed` | as the claim, plus `NMI`/`CQD` | +| Predetermination | `request` | `predetermination` | `preparation` | sent on `v1/preauth/submit` with workflow 12 | + +LAMA and DAMA before or during surgery (`claim_lines`): the claim carries one item, procedure `LM100` at the plan's rate (the sandbox prices it at zero), no tier, and the payer disqualifies every approved item (PAYR-1362 if the package is still there). After surgery the package stands and `LM100` is not used. PAYR-1270 is `LM100` on a pre-auth. + +## 6. The ClaimResponse you read + +Shape (`nhcx-package/docs/01-Overview/07-Payer Flexibility.md`, "Answer detail"): `ClaimResponse`, `Patient`, the two `Organization` entries, `Coverage`, in that order. Fields to read (`parse_claim_response`): + +- `use`: `preauthorization` or `claim`; a bundle with none is whatever you sent on that thread. +- `outcome`: `queued` (acknowledgement), `partial` (queried, or approved for less), `complete`, `error` (rejected). +- `adjudication[]` at claim level: the entry whose `category` is `status` carries `reason.coding.code`: `submitted`, `approved`, `queried`, `rejected`, `cancelled`. +- `preAuthRef`: the payer's case number; see `flow-knowledge.md` section 3 for which answers carry it. +- `identifier[0].value`: your claim number, echoed on every answer. +- `total[]`: a repeating list by `category`, never positional: `benefit` (granted this round), `eligible` (what the case stands at), `submitted`; PMJAY adds `tax` and `incentive`. +- `item[].adjudication[]` by category: `eligible` (amount), `status` (reason `Approved`, `Queried`, `Rejected`), `reason` (the desk's remark, pipe-delimited `USER~datetime~type~comment~trust`, kept verbatim), `eligpercent`, `eligquant`, `deductible` with its reason after a claim. +- `processNote[].text`. +- `type` is present only on the pre-auth acknowledgement (SNOMED `737481003`). + +The status rule (`verdict_status`): `queued` or reason `submitted` is still `submitting`; reason `cancelled` is `rejected`; reason `queried` is `queried`; outcome `error` is `rejected`; outcome `partial` is `partial` only with reason `approved`, else `queried`; outcome `complete` is `approved` with reason `approved` or none, else `queried`. Never read `outcome` alone. + +## 7. Task bundles the hospital sends + +A `TaskBundle` with the `Task` at `https://nhcx.abdm.gov.in//` followed by the provider and payer Organizations. The Task: `status requested` (`completed` on an acknowledgement), `intent order`, `code` on the HL7 financial task code system with no display, `description`, `authoredOn`, `requester` the provider, `owner` the payer. + +| Task | code | reasonCode (NDHM reason code system) | inputs | Other | +| --- | --- | --- | --- | --- | +| Cancel PC01 | `cancel` | one of `treatmentplanchanged`, `patientrequest`, `financialconstraints`, `alternativetreatment`, `duplicateclaim`, `administrativeerror`, `other` (with `other` the description is the only justification) | `claimNumber`, `intimationNumber` (both typed under `ndhm-task-input-type-code`) | anchor `/preauth/cancel` | +| Reprocess 36 | `reprocess` | `claimrejected`, `partialpayment` or `rejectiondisputed` with the reference's displays | `claimNumber`, `intimationNumber` (the standard's spelling), one `document` input per attachment as `valueAttachment` | `basedOn[0].identifier` typed `CLN`; `for.identifier` typed `PMJAY` on the scheme, `MB` elsewhere; anchor `/claim/reprocess` | +| Release 36 | `release` | `partialpayment` | `claimNumber`, `amount` as `valueMoney` under `https://nhcx.abdm.gov.in/task-input-type` | `basedOn` as above; anchor `/claim/release` | +| Status | `status` | none | `claimNumber` | anchor `//status`; not in the package, whose status call carries no bundle (`18-Predetermination, Status and Search.md`); refused by PMJAY | +| Payment acknowledgement 17 | `status`, `status completed` | none | none; `output[]`: `status` = `paymentack` under the NDHM task-output systems, and `claimNumber` | anchor `/payment/notice-ack` | + +The spelling rule: the input is `intimationNumber`, the standard's spelling, on every Task. A reprocess under any other spelling is refused with PAYR-1008 (proven live; `nhcx-package/docs/01-Overview/07-Payer Flexibility.md`, "One spelling on the Task"). The pinned cancel and reprocess Tasks carry the same spelling, so the offline comparison diffs them unchanged. + +## 8. Task answers you read + +`parse_task_response`: find the `Task`, then follow each `output[].valueReference` to the entry it names; when that is a `ClaimResponse`, read it with the same parser as a verdict. + +- PC02 (`nhcx-package/fhir/C10/C10-cancelled-wfPC02.json`): Task `completed`, code `approve`, `output[0]` an `include` reference to a `ClaimResponse` with adjudication reason `cancelled`, `use preauthorization`. Accept the cancel when the Task status is `completed` or `accepted` and the outcome is not `error`. Retire the claim number after an accepted cancel. +- 37 (`nhcx-package/fhir/C10/C10-arbitration-wf37.json`): Task `accepted`, code `approve`, a `ClaimResponse` with outcome `queued`, `use claim`. Put the claim leg back to `submitting`; the new verdict comes on the claim's own thread. +- A status answer: none captured in the package. A generic payer that answers a status Task sends a Task `completed`, code `status`, `output[]` with `claimNumber` and a `claimStatus` string; PMJAY refuses the enquiry instead. + +## 9. The communication loop + +The query, generic payer (`nhcx-package/fhir/C6/C6-preauth-query-wf24.json`; the IG's example at `nhcx-package/fhir/B4/communication-request.json`): a `TaskBundle` with a `Task` `poll`, `requested`, `intent order`, `reasonCode additionalinfo`, one `include` input pointing at the `CommunicationRequest`; the request with `identifier` (the claim number), `basedOn` the Claim, `payload[].contentString` one per ask, `reasonCode[].text` repeating them; then the Claim, Patient, the two Organizations, Practitioner and Coverage. It arrives on `v1/communication/request` on a new correlation id, with the queried leg's correlation id in `x-hcx-workflow_id` when the payer sends one. + +The notification, PMJAY (`nhcx-package/fhir/C6/C6-notification-wfN02.json`): a Task `poll`, `completed`, `intent proposal`, reason `information` under `http://terminology.hl7.org/CodeSystem/communication-category`, a `CommunicationRequest` with one `contentString`, and the two Organizations. + +Reader (`parse_communication_request`): the first `CommunicationRequest`; the claim numbers it names in `about[]`, `basedOn[]` and `identifier[]`; the asks from `payload[].contentString`, else `reasonCode[].text`, else the Task's `description`; the Task's `intent` and `reasonCode`. Match the claim by those numbers first, then by a request id already held, then by the correlation id of one of your sends, then by the workflow id as a thread. + +The reply (`build_communication_bundle`; pin `nhcx-package/fhir/B4/communication-response.json`): a `TaskBundle` with `meta.lastUpdated`, `identifier` under the payer system, `timestamp`, and entries in this order: + +1. `Task` at `urn:uuid:`: `status completed`, `intent order`, `code deliver` under `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-codes`, `authoredOn`, `requester` the provider, `owner` the payer, one `input` typed `include` (HL7 financialtaskinputtype) pointing at the Communication, `reasonCode` echoed from the request's Task when it carried one. +2. `Communication` at `urn:uuid:`: `identifier` echoed from the request, `basedOn: [{reference: }]`, `about: [{reference: }]`, `status completed`, `category notification`, `priority routine`, `recipient` the payer, `sender` the provider, `payload[]`: a `contentString` for the text, then one `contentAttachment {contentType, title, creation, data}` per document, each with an `extension` carrying the document code. The extension url is participant-defined (`17-Communication.md`): write it under your own system and keep one url. `inResponseTo` is never set: FHIR allows only a Communication there and the validator refuses a request. +3. The `CommunicationRequest` echoed as it arrived. +4. The case as the payer holds it, lifted from the queried leg's own bundle: `Claim`, `Patient`, provider `Organization`, payer `Organization`, `Practitioner`, `Coverage`. + +Envelope for the reply: `x-hcx-correlation_id` = the request's, `x-hcx-workflow_id` = the request's, else the queried leg's correlation id, else the claim number; sender and recipient swapped. + +The acknowledgement of a notification: the payer's own bundle sent back with `Task.status` set to `completed`, its intent and reason as sent, the provider Organization ahead of the payer's, a fresh `timestamp`. A request that came without a Task gets one built round it, coded `poll`, intent `proposal`, pointing at the request. The package's `B4/communication-acknowledgement.json` is a different shape: a `status` Task, `completed`, with a `status` output and the two Organizations, and no CommunicationRequest. + +## 10. The payment notice you read and the acknowledgement you send + +Notice (`nhcx-package/fhir/C9/C9-notice-wf30.json`; PMJAY `C9/payment-notice.json` and `C9/C9-notice-tds-wf30-pmjay.json`): a Task `deliver`, `requested`, with a `status` input; a `PaymentNotice` with a `CLN` identifier (the claim number), `amount`, `paymentStatus paid`; a `PaymentReconciliation` with the same identifier, `disposition`, `paymentDate`, `paymentAmount`, `paymentIdentifier` typed `UTR`, and `detail[]` lines (`RF` and `Payment` in `payment-notice.json`; `TDS` and `Payment` in the other two); the two Organizations. It arrives on `v1/paymentnotice/request` on a new thread, workflow 30, 31 or 33. + +Reader (`parse_payment_notice`): the claim number from the `CLN` identifier on the notice, the reconciliation, the Task, or the first entry's untyped identifier, never from the bundle identifier; the amount from the notice or `paymentAmount`; the UTR; the details. Dedupe on the notice's correlation id; a second notice with the same `PaymentNotice.id` updates the first (`record_payment`). Count money once per UTR (`paid_total`). + +Acknowledgement: the Task in section 7, sent on `v1/paymentnotice/on_request` to whoever sent the notice (not always the claim's payer), with `x-hcx-correlation_id` = the notice's and `x-hcx-workflow_id` = `17` for PMJAY or the notice's own id for a generic payer. + +## 11. Validating a bundle + +The package ships no validator. Use the HL7 FHIR validator (`validator_cli.jar`, from HL7) with the NRCeS IG package `ndhm.in`, version 6.5.0. A bundle refused with PAYR-1004 or PAYR-1008 goes through the validator before anything else (`nhcx-package/docs/06-Reference/02-Troubleshooting.md`). The rules it checks against are in `nhcx-package/docs/05-FHIR Reference/01-Bundles and Conventions.md`. + +```sh +java -Xmx4g -jar validator_cli.jar \ + -version 4.0.1 -ig -tx n/a -output result.json +``` + +Pass every file in one call; starting the JVM is the slow part. `-tx n/a` keeps the terminology checks offline; drop it to add them. A bundle passes when the output holds no issue of severity error or fatal. + +The provider pins carry 0 to 13 errors each and the SHA accepted every one as it stands. An error that says "a code the profile does not define" is the scheme's own vocabulary, not a fault to fix. A warning is advice. diff --git a/plugins/nhcx/skills/nhcx-payment/references/flow-knowledge.md b/plugins/nhcx/skills/nhcx-payment/references/flow-knowledge.md new file mode 100644 index 000000000..098cd9dbc --- /dev/null +++ b/plugins/nhcx/skills/nhcx-payment/references/flow-knowledge.md @@ -0,0 +1,206 @@ +# Flow knowledge: the claim episode, its workflow ids, the two payer kinds, the use cases + +Sources: the NHCX package, fetched by `scripts/fetch-package.sh` into `nhcx-package/` beside `nhcx-build/`. That means the overview chapters under `nhcx-package/docs/01-Overview`, the workflow sheet `nhcx-package/workflow.yaml`, the use-case catalogue `nhcx-package/usecases.yaml`, and the payer bundles under `nhcx-package/fhir/C3` to `nhcx-package/fhir/C11`. The published chapters live under `nhcx-package/docs/01-Overview`, `nhcx-package/docs/05-FHIR Reference` and `nhcx-package/docs/03-Building a Provider`. Everything else here was learnt live on the NHCX sandbox. + +## 1. The episode + +One hospital admission that an insurer pays for is one claim episode. Store it as one record with a claim number. Any number works if it is unique per hospital, short, sortable, and fits the payer's `CLN` identifier. The episode has these legs, each a separate exchange with its own correlation id: + +| Order | Leg | You send | Payer answers | Thread | +| --- | --- | --- | --- | --- | +| 1 | Policy lookup | The participant service's `participant/get/policies`, through the transport; the recipient of every later leg is the policy's `processingid` | synchronous JSON | none, plain REST | +| 2 | Coverage eligibility | `v1/coverageeligibility/check`, purpose `discovery`, `validation` or `benefits` | `on_check` | new per check | +| 3 | Insurance plan (package master) | `v1/insuranceplan/request` | `on_request` | new; one plan per facility and policy | +| 4 | Auth requirements | `v1/coverageeligibility/check`, purpose `auth-requirements`, with items | `on_check` (the PMJAY sandbox rarely answers; `nhcx-package/fhir/C3/C3-response-pmjay.json` is an SHA ruling, `C3/C3-response-generic.json` a generic one) | new per procedure set | +| 5 | Pre-authorisation | `v1/preauth/submit` wf 12 | `on_submit` 20 first, then 21, 23 or 24 | new; the acknowledgement comes first on the same thread | +| 5a | Pre-auth query answer | `v1/preauth/submit` wf 19 (PMJAY) or `v1/communication/on_request` (generic) | 21 or 23 | new (PMJAY) or the request's (generic) | +| 5b | Enhancement | `v1/preauth/submit` wf 13, the whole pre-auth again with the added line | 20 then 22, 231 or 241 (the SHA sandbox has also answered with 21) | new | +| 5c | Enhancement query answer | `v1/preauth/submit` wf 131 | 22 or 231 | new | +| 5d | Cancel | `v1/task/submit` wf PC01 | `task/on_submit` PC02 | new | +| 5e | Predetermination | `v1/preauth/submit`, `Claim.use = predetermination`, wf 12 | `on_submit` | new | +| 6 | Claim | `v1/claim/submit` wf 15, `Claim.use = claim`, under the pre-auth's number | 25 then 26, 27 or 291 | new | +| 6a | Claim query answer | `v1/claim/submit` wf 161 (PMJAY) or `v1/communication/on_request` (generic) | 26 or 291 | new (PMJAY) or the request's (generic) | +| 6b | Reprocess or release | `v1/task/submit` wf 36 | `task/on_submit` 37, then a fresh verdict on the claim's thread | new | +| 7 | Payment notice | the payer sends `v1/paymentnotice/request` wf 30 (31, 33) | you answer `v1/paymentnotice/on_request` wf 17 (PMJAY) or the notice's own id (generic) | the notice's | +| any | Status enquiry | `v1/task/submit`, Task code `status` | `task/on_submit` (generic); PMJAY refuses it | new | +| any | Communication | the payer sends `v1/communication/request` | you answer `v1/communication/on_request` | the request's | + +The payer's acknowledgement is `x-hcx-status: response.partial` and the decision is `response.complete`, on the same correlation id (`nhcx-package/docs/01-Overview/07-Payer Flexibility.md`, "Answer detail"). Read the acknowledgement as "the payer has it", never as a decision. Map `ClaimResponse.outcome` `queued`, or an adjudication reason `submitted`, to leg status `submitting` (`verdict_status`). + +## 2. Every workflow id + +The hospital's table. PMJAY and a generic payer differ in three rows: `claim_query_response`, `claim_resubmit` and `payment_ack`. + +| Kind | PMJAY | Generic | Path | Note | +| --- | --- | --- | --- | --- | +| `preauth` | `12` | `12` | `v1/preauth/submit` | A new pre-auth. Also a fresh request after a rejection: PMJAY refuses 121 there with PAYR-1214. | +| `preauth_resubmit` | `121` | `121` | `v1/preauth/submit` | Kept in the table. `preauth_send_kind` never picks it after a rejection. | +| `preauth_query_response` | `19` | `19` | `v1/preauth/submit` | The answer to a 24. A generic payer asks by communication instead, so this is a PMJAY leg. | +| `enhancement` | `13` | `13` | `v1/preauth/submit` | The whole pre-auth again under the parent's number, plus the added line. | +| `enhancement_resubmit` | `131` | `131` | `v1/preauth/submit` | The answer to a 241. | +| `cancel` | `PC01` | `PC01` | `v1/task/submit` | Task code `cancel`. The handbook's section 8.6 says 122 (`nhcx-package/docs/01-Overview/06-Workflow Codes.md`, "Reconciled Discrepancies and Authority Rules", takes PC01). If a payer insists on 122, override it per payer in configuration. | +| `claim` | `15` | `15` | `v1/claim/submit` | The final bill. | +| `claim_query_response` | `161` | `151` | `v1/claim/submit` | PMJAY refuses 151, 19 and 16 with PAYR-1321; 161 is taken. | +| `claim_resubmit` | none | `16` | `v1/claim/submit` | PMJAY has no claim resubmit. A decided claim goes back only as a reprocess. | +| `payment_ack` | `17` | none (echo the notice's own id) | `v1/paymentnotice/on_request` | `None` in the table means "echo". | +| `reprocess` | `36` | `36` | `v1/task/submit` | Task code `reprocess`; acknowledged on 37. | +| `release` | `36` | `36` | `v1/task/submit` | Task code `release`, reason `partialpayment`, an `amount` input. | +| status enquiry | the leg's correlation id, fallback `13` | same | `v1/task/submit` | The fallback id is `13`. The NHCX sandbox refuses `v1/status` with NHCX-1012. | +| coverage, plan, auth requirements | your case number | your case number | see section 1 | The sheet lists no code. Send the episode's case number. | + +The payer's ids you must branch on (`nhcx-package/workflow.yaml`, `nhcx-package/docs/01-Overview/06-Workflow Codes.md`), with what the sandbox actually sent: + +| Id | Meaning | Status word | +| --- | --- | --- | +| `20` | Pre-auth or enhancement received | `response.partial` | +| `21` | Pre-auth approved | `response.complete` | +| `22` | Enhancement approved. A generic payer sends 22. The SHA sandbox has answered an enhancement with 21, and `nhcx-package/fhir/C5/C5-enhancement-approved-wf22-pmjay.json` is an SHA answer on 22. Accept both. | `response.complete` | +| `23` | Pre-auth rejected | `response.complete` | +| `231` | Enhancement denied | `response.complete` | +| `24` | Pre-auth queried | the sheet says `request.initiated`; the SHA sent `response.complete` | +| `241` | Enhancement queried | as 24 | +| `25` | Claim received | `response.partial` | +| `26` | Claim approved | `response.complete` | +| `27` | Claim queried | as 24 | +| `28`, `29` | Claim in process, forwarded | `response.partial` | +| `291` | Claim rejected | `response.complete` | +| `251`, `252`, `253`, `254` | Reprocess received, approved, rejected, queried | listed; both live payers answer a 36 with 37 instead | +| `37` | Arbitration acknowledged (the reprocess taken) | `response.complete` (the SHA sent `response.partial`) | +| `PC02` | Cancellation done | `response.complete` | +| `30`, `31`, `33` | Payment initiated, processed, settled with UTR | `request.initiated`, new thread | +| `5` | The SHA's coverage eligibility and plan answers | `response.complete` (`nhcx-package/fhir/index.yaml` gives 5 for `C3/C3-response-pmjay.json` and `C4/C4-response-pmjay.json`) | +| `N02` | Notification to a provider (a PMJAY CommunicationRequest) | `request.initiated` | + +Other codes exist (10, 11, 14, 141, 18, 45 to 47, 181, 491, 34, 35, 38, 39, G11 to G13, RP1 to RP3, DC01, DC02, N01, N03, N04, the R-series). A hospital build sends none of them. See `nhcx-package/docs/01-Overview/06-Workflow Codes.md` for the full sheet and the seven codes the handbook and the sheet publish differently. + +## 3. Two kinds of payer + +Read `nhcx-package/docs/01-Overview/07-Payer Flexibility.md` in full. A generic payer is any payer on the exchange, IRDAI-regulated insurers and TPAs included (`nhcx-package/fhir/README.md`). The rule, as coded: + +| | PMJAY (`query_mode: resubmit`) | Generic (`query_mode: communication`) | +| --- | --- | --- | +| The query arrives as | a `ClaimResponse` on the case's own thread, `outcome: partial`, item status `Queried`, wf 24, 241 or 27 | a `CommunicationRequest` TaskBundle on `v1/communication/request`, on a new thread, wf 24, 241 or 27 | +| The answer | the whole bundle again on `v1/preauth/submit` or `v1/claim/submit`, wf 19, 131 or 161, a new correlation id, the reply text on the `NMI`/`CQD` supportingInfo entry | a Communication TaskBundle on `v1/communication/on_request`, the request's correlation id and workflow id echoed | +| A `CommunicationRequest` from this payer | always a notification: acknowledge and leave the case alone | classified (below) | + +Where the payer's case number arrives. The package files are under `nhcx-package/fhir/`; the rule is in `07-Payer Flexibility.md`, "When the case number arrives". + +| Answer | PMJAY | Generic | +| --- | --- | --- | +| 20 on a fresh pre-auth | The package says none, and `C5/C5-received-wf20-pmjay.json` carries none. A live SHA 20 has also carried the path form, `PMJAY/HP/S/2024/R2/`. Handle both. | present (`C5/C5-received-wf20.json`) | +| 20 on an enhancement | none; keep the parent's | present | +| 21, 23, 24 | the bare number (`C5/C5-approved-wf21-pmjay.json`, `C5/C5-rejected-wf23-pmjay.json`, `C5/C5-queried-wf24.json`) | present (`C5/C5-approved-wf21.json`, `C5/C5-rejected-wf23.json`) | +| 25 | the path form (`C7/C7-received-wf25-pmjay.json`) | present (`C7/C7-received-wf25.json`) | +| 26, 27, 291, PC02, 37 | none | none | + +So the brief's rule holds with care. A generic payer's `response.partial` acknowledgement carries the payer's case number. PMJAY's 25 carries it; its 20 may not. Read `ClaimResponse.preAuthRef` on every answer. Keep a value and never overwrite it with an empty one (`apply_preauth`). The bare number is what the payer service desk wants; the path form ends in it. + +`query_mode` lives on the payer adapter. Choose the adapter by the payer's participant code through configuration: `1518@hcx` is PMJAY, and an unmapped code is generic. + +### The classification rule + +`classify_communication(adapter, reason, intent)` applies these, in order: + +1. If the payer's `query_mode` is `resubmit`: notification. +2. Else if `Task.intent` is `proposal`: notification. If `order`: query. +3. Else look at `Task.reasonCode`: absent, `additionalinfo`, `questionnaire` or `query` is a query; anything else (`tatquery`, `grievance`, `walletupdate`, `policychange`, `claimarbitration`) is a notification. Fold `claimArbitartion` into `claimarbitration`. +4. A bare `Communication` with no `CommunicationRequest` is a note: recorded, shown, never acted on. + +Acknowledge a notification at once. Send the payer's own bundle back with `Task.status` flipped to `completed`, the reason echoed and the provider Organization first. File a query open for the desk, and answer it later with the TaskBundle reply (see `fhir-knowledge.md`). The reply names the request in `Communication.basedOn`, never `inResponseTo`. + +The live shapes. A generic payer's query (`nhcx-package/fhir/C6/C6-preauth-query-wf24.json`) carries a Task `poll`, `requested`, `intent order`, reason `additionalinfo`, and a CommunicationRequest with one `contentString` per ask and `basedOn` the Claim. PMJAY's notification (`nhcx-package/fhir/C6/C6-notification-wfN02.json`) carries a Task `poll`, `completed`, `intent proposal`, reason `information` under the HL7 communication-category system. + +## 4. Stage, sub-stage, next actions + +Stamp two words onto the episode after every leg write (`stamp_case`), and compute a next-action list from them. Copy the vocabulary; it is what a desk needs to see. + +Stages: `eligibility`, `preauth`, `enhancement`, `claim`, `payment`. + +Sub-stages: `draft`, `checking`, `eligible`, `not-eligible`, `requested`, `resubmitted`, `answered`, `queried`, `approved`, `partial`, `rejected`, `cancelling`, `cancelled`, `refused`, `noticed`, `paid`. + +How a send kind maps to a sub-stage: `preauth`, `claim`, `enhancement` set `requested`; `*_resubmit` sets `resubmitted`; `*_query_response` and `enhancement_resubmit` set `answered`. `requested`, `answered` and `resubmitted` mean "with the payer". + +Derivation (`case_stage`): a payment notice wins, then the filed claim, then the pre-auth (stage `enhancement` if the last submission kind was an enhancement), then a saved draft, then the eligibility status. An open communication query on a leg that is with the payer flips the sub-stage to `queried`, because a generic payer's query never touches the leg row. + +Next actions (`next_actions`) are `{label, tab, tone}`; the first is what the case waits for. Rules worth copying: + +- An unanswered query always leads with "Answer the payer (n)". +- The leg's own reply box is offered only for a `resubmit` payer. A `communication` payer's desk is sent to the communication tab. +- A claim refused at the door offers "send again" while `claim_send_kind` still yields a kind, else "Ask for a reprocess". +- After a rejection the pre-auth offers a fresh 12, not 121. + +## 5. Rules the exchange enforces that no document states + +Each was found live on the sandbox. + +- Acknowledge or lose the thread. NHCX redelivers an unanswered submission, then drops it and retires the correlation id; a verdict sent later is refused with NHCX-1010. Both live payers answer twice on one correlation: `outcome: queued` first, the decision after. Your reader must not close a thread on the first reply. +- One message is taken once. The SHA redelivers the same `api_call_id` two or three times, about a minute apart, and a transport can fan one delivery out to several receivers (nhcx-adapter's `callback.also`). Dedupe on `x-hcx-api_call_id`. +- One live pre-auth per beneficiary per hospital (PAYR-1238). Clear it with PC01 or a rejection (`nhcx-package/docs/03-Building a Provider/11-PMJAY Sandbox Run.md`, "PAYR-1238 An active preauthorisation exists"). Sweep live pre-auths before a test run. +- One request at a time per case (PAYR-1322, "Active instance found"). Wait about 30 seconds after a decision before the next leg. When a refusal says "Active instance", wait and resend, up to three times. +- One plan per facility and policy. Key it on policy code, provider id and payer. Copy the held master onto a new episode instead of asking again (`reuse_plan`). A PMJAY master runs to tens of megabytes; one fetched live was 56 MB. +- Never drop a document. A file nobody asked for by name goes under `ODN`, "other document". A file attached against a requirement carries that requirement's code (`attach_required_document`). Take the code list from the plan, not from a constant. +- Ask the auth-requirements check, never await it (`ensure_auth_requirements`). Fingerprint the quoted set (`procedure_set`) so an unchanged set is not asked twice. Send the quantity as a whole number. +- Tiers are modifiers, not lines. A ward or ICU tier rides on `Claim.item.modifier` under its procedure, and that item's `net` carries both. +- The claim goes under the pre-auth's number (ERR-PYR-CLM-007), and PMJAY bills the package alone at the whole amount (`11-PMJAY Sandbox Run.md`, "ERR-PYR-CLM-007" and "What the package master decides"). +- Answers to a PMJAY query go on a new correlation id (`07-Payer Flexibility.md`, "On the claim thread"). A same-thread answer is swallowed: no acknowledgement, no refusal, and the desk dies on the old id. +- Cancel retires the number. Give the episode a fresh claim number after an accepted PC01, and keep the withdrawn one on the leg. +- A send refused at the door keeps the case on the thread the payer last answered. An enhancement refused at the door leaves the pre-auth approved. + +## 6. The use-case catalogue + +Codes and titles are quoted from `nhcx-package/usecases.yaml`, rendered as `nhcx-package/docs/01-Overview/05-NHCX Use Cases.md`. "Proves" is what a test run must show for each one. "Package file" is the provider bundle the package holds for it, under `nhcx-package/fhir/`. + +### A: shared + +| Code | Title | What it proves | +| --- | --- | --- | +| A1 | Get participant list | You can find the payer's code in the registry (the participant service's `fetch/participants/list`). | +| A2 | Get policy | You can find a beneficiary's policy and the processor code that becomes `x-hcx-recipient_code` (the participant service's `participant/get/policies`). | +| A3 | Get public key | The transport fetches the recipient's certificate (`fetch/certs`) and caches it. | +| A4 | Get auth token | The transport holds an ABDM session token (the gateway's sessions call) and refreshes it. | +| A5 | Get status | A status Task on `v1/task/submit` gets a Task back (generic), or a PAYR-1018 then PAYR-1008 refusal (PMJAY). The package holds no bundle for A5 (`nhcx-package/fhir/README.md`). | +| A6 | Receive errors | Your callback accepts a `ProtocolResponse` on any path and answers 2xx. | + +### B: hospital on the generic network + +| Code | Title | Workflow | Proves | Package file | +| --- | --- | --- | --- | --- | +| B1 | Check coverage eligibility | none | The check goes out; `inforce` and the wallet come back. | `B1/B1-check.json` | +| B2 | Request insurance plan | none | The package master lands and is stored once per policy. | `B2/B2-request.json` | +| B3 | Submit pre-authorisation | 12, 13 | Sent, acknowledged on 20, decided on 21 or 23; an enhancement on 13 decided on 22. | `B3/B3-request.json`, `B3/B3-enhancement.json` | +| B4 | Respond to a communication | 24, 27 echoed | A CommunicationRequest is classified and the TaskBundle reply goes on the request's thread. | `B4/B4-preauth-query-answer.json`, `B4/B4-claim-query-answer.json` | +| B5 | Submit claim | 15 | The claim under the pre-auth's number, acknowledged 25, decided 26 or 291. | `B5/B5-request.json` | +| B6 | Search claims | none | Not built by these skills. | `B6/claim-search.json` (example) | +| B7 | Acknowledge payment notice | 30 echoed | The notice is filed by claim number, deduped by correlation id, acknowledged on `on_request`. | `B7/B7-acknowledgement.json` | +| B8 | Reprocess or cancel | 36, PC01 | A decided claim is reopened (37 then a new verdict); a live pre-auth is withdrawn (PC02). | `B8/B8-reprocess.json`, `B8/B8-cancel.json` | +| B9 | Submit predetermination | 12 | A quote comes back as a ClaimResponse; nothing else changes. | `B9/predetermination-request.json` (example); the answer is `C11/predetermination-response.json` | + +### C: payer answering (for reference; you build the reader, not the sender) + +C3 coverage answer, C4 plan answer, C5 pre-auth answers (20, 21, 22, 23, 24, 231, 241), C6 communication (24, 241, 27, N02), C7 claim answers (25, 26, 27, 28, 29, 291), C9 payment notice (30, 31, 33), C10 Task answers (PC02, 37, 251 to 254), C11 predetermination. Reader inputs: `nhcx-package/fhir/C3` to `nhcx-package/fhir/C11`. The files ending `-pmjay` are the SHA's own; the rest are the generic payer's. `nhcx-package/fhir/index.yaml` gives each file's scheme, workflow id and origin. The PMJAY captures have the beneficiary's identifiers replaced. + +### D: hospital on PMJAY + +| Code | Title | Workflow | Proves | Package file | +| --- | --- | --- | --- | --- | +| D1 | Fetch the insurance plan | none | The scheme's master, both `coverage[]` and `specificCost[]`, nested document requirements, questionnaires. | `D1/D1-request.json` | +| D2 | Authenticate the beneficiary | not NHCX | Biometric token or the consent questionnaire fallback. | none | +| D3 | Check coverage eligibility | none | The wallet answer on wf 5. | `D3/D3-check.json` | +| D4 | Submit pre-authorisation | 12 | Element ids, HPIN, consent QuestionnaireResponse, documents from the master; acknowledged 20, decided 21 or 23 with `preAuthRef`. | `D4/D4-request.json` | +| D5 | Resubmit pre-authorisation | 121 | Not reachable on the sandbox after a rejection (PAYR-1214); send a fresh 12. | none | +| D6 | Raise an enhancement | 13, 131 | A second package (medical, not conservative: PAYR-1245) under the parent's number; a 241 answered on 131. | `D6/D6-enhancement.json`, `D6/D6-enhancement-query-answer.json` | +| D7 | Answer a pre-authorisation query | 19 | The 24 answered as a fresh submit with `CQD` reply text, new correlation id, then 21. | `D7/D7-query-answer.json` | +| D8 | Cancel pre-authorisation | PC01 | Task `cancel` with `claimNumber` and `intimationNumber`; PC02 back. | `D8/D8-cancel.json` | +| D9 | Submit claim | 15 | Under the pre-auth's number, the package alone, discharge scalars, Discharge Consent answered, PDF documents; 25 then 26. | `D9/D9-request.json` | +| D10 | Answer a claim query | 161 | The 27 answered on 161 with a written reply; the sandbox approves at zero. | `D10/D10-query-answer.json` | +| D11 | Reprocess a rejected claim | 36 | Task `reprocess`, reason `claimrejected`, second input spelled `intimationNumber` on every Task (a reprocess under any other spelling is refused PAYR-1008). The SHA answers 37, "Arbitration claim submission process completed successfully", and reopens the case; a generic payer answers 37 too. | `D11/D11-reprocess.json` | +| D12 | Claim a shortfall | 36 | Task `reprocess` with `partialpayment` after a settled payment. Out of reach on the sandbox: its finance side issues the notice on its own schedule, and the combination is refused before notice 33 is acknowledged (`11-PMJAY Sandbox Run.md`, "What the sandbox will not take"). | none | +| D13 | Acknowledge the payment notice | 17 | Notice 30 filed and acknowledged on `on_request` with 17. | `D13/D13-acknowledgement.json` | + +Discharge variants the D9 claim must cover, each proven on the sandbox: normal after surgery; LAMA and DAMA before, during and after surgery; death before, during and after surgery. Before or during surgery, LAMA and DAMA collapse the claim to one `LM100` line; a death carries `ONS`/`DTM`. `nhcx-package/docs/03-Building a Provider/08-PMJAY Provider.md` states the LAMA and DAMA rule. + +## 7. What each payer sends back, in order + +A pre-authorisation on the SHA sandbox: 20 (`queued`, `response.partial`, `ClaimResponse.type` present only here, as in `nhcx-package/fhir/C5/C5-received-wf20-pmjay.json`), then 24 (query) or 21 or 23. A claim: 25, then 27 or 26 or 291. A cancel: PC02 as a Task `completed`, code `approve`, `output[0]` an `include` reference to a ClaimResponse whose adjudication reason is `cancelled` (`C10/C10-cancelled-wfPC02-pmjay.json`). A reprocess: 37 as a Task `accepted` with a `queued` ClaimResponse (`C10/C10-arbitration-wf37-pmjay.json`), then 26 or 291 on the claim's thread. A payment: 30 on a new thread with a Task `deliver`, a `PaymentNotice` and a `PaymentReconciliation` (`C9/payment-notice.json`). + +A generic payer sends the same ids with the generic differences: 22 for an enhancement, `preAuthRef` on every acknowledgement and every pre-auth decision, queries as CommunicationRequests, `response.complete` on 37. Its files are the ones without `-pmjay` under `nhcx-package/fhir/C5`, `C6`, `C7`, `C9` and `C10`. diff --git a/plugins/nhcx/skills/nhcx-payment/references/material.md b/plugins/nhcx/skills/nhcx-payment/references/material.md new file mode 100644 index 000000000..d8882931d --- /dev/null +++ b/plugins/nhcx/skills/nhcx-payment/references/material.md @@ -0,0 +1,120 @@ +# Material: where the pins, fixtures and docs live + +The stage and module files cite pins, payer fixtures and chapters. All of them come from one source, the NHCX package. This file says how to get it, what it holds, and which package file each citation means. + +## The package + +| Source | Has | Get it | +| --- | --- | --- | +| The NHCX package (`nhcx-package/`) | The docs, every API as a request, the FHIR bundles (the fifteen hospital pins, the payer answers, the live PMJAY captures with identifiers replaced), the field mappings per use case, `workflow.yaml`, `usecases.yaml`, `nhcx-error.yaml`, `baseurl.yaml`, a `MANIFEST` with a sha256 per file | `scripts/fetch-package.sh`, or by hand (below) | +| nhcx-adapter (optional: only when the user asks for it) | The binary, `config.sample.json`, `serve.sh`, `README.md` | The latest release of https://github.com/nha-in/nhcx-adapter, downloaded only when the user chose it (`references/transport-knowledge.md` section 5). Its contract is in `references/api-knowledge.md`. | + +By default `scripts/fetch-package.sh` takes the build attached to the latest GitHub release of `nha-in/nhcx-package`. It checks the download against the sha256 the release records. To use a different build, pass a link or a local path: `scripts/fetch-package.sh `. + +By hand: download the `nhcx-package-v.zip` asset from https://github.com/nha-in/nhcx-package/releases/latest. Unzip it beside `nhcx-build/`. It unpacks to `nhcx-package/`. + +Where the web is off, copy the package in. Do not try to fetch it. + +After unpacking, check it. `nhcx-package/MANIFEST` names the version and lists every file with its size and sha256. Verify at least the pins you will be held to. + +What the package holds: + +| Path | What it is | +| --- | --- | +| `nhcx-package/fhir/B1` to `B9` | Hospital bundles. Lower-case files (`preauth-request.json`) are the pins, written to the specification with placeholders. Capitalised files (`B3-request.json`) are live captures. | +| `nhcx-package/fhir/C3` to `C11` | Payer answers. A generic file and, where one exists, its `-pmjay` twin. | +| `nhcx-package/fhir/D1` to `D13` | Live PMJAY hospital captures, identifiers replaced | +| `nhcx-package/fhir/index.yaml` | The catalogue: for each file its direction, side, scheme (`generic` or `pmjay`), workflow id, focal resource, origin (`wire` or `example`) | +| `nhcx-package/docs/` | The chapters, `01-Overview` to `07-Go Live` | +| `nhcx-package/mappings/.yaml` | Field mappings per bundle; `A1.yaml` is the master dictionary | +| `nhcx-package/apis/` | Every API as a request (a Bruno collection) | +| `nhcx-package/workflow.yaml`, `usecases.yaml`, `nhcx-error.yaml`, `baseurl.yaml` | Workflow ids, use cases, error codes, base URLs | +| `nhcx-package/MANIFEST` | Version, and a size and sha256 per file | + +## The pin map + +Every hospital-side pin, and its file in the package. The fifteen hospital-built pins are the bytes a build is held to (canonical JSON). The last row is a payer's message, the reader's input. + +| Pin | Package | Module | +| --- | --- | --- | +| `coverage/discovery` | `nhcx-package/fhir/B1/discovery.json` | 7.4 | +| `coverage/validation` | `nhcx-package/fhir/B1/validation.json` | 7.4 | +| `coverage/benefits` | `nhcx-package/fhir/B1/benefits.json` | 7.4 | +| `coverage/authrequirements` | `nhcx-package/fhir/B1/auth-requirements.json` | 7.6 | +| `insurance` | `nhcx-package/fhir/B2/insurance-plan-request.json` | 7.5 | +| `preauth/request` | `nhcx-package/fhir/B3/preauth-request.json` | 7.7 | +| `preauth/enhancement` | `nhcx-package/fhir/B3/preauth-enhancement.json` | 7.7 | +| `preauth/queryupdate` | `nhcx-package/fhir/B3/preauth-queryupdate.json` | 7.7 | +| `preauth/cancel` | `nhcx-package/fhir/B3/preauth-cancel.json` | 7.9 | +| `claim/request` | `nhcx-package/fhir/B5/claim-request.json` | 7.7 | +| `claim/queryupdate` | `nhcx-package/fhir/B5/claim-queryupdate.json` | 7.7 | +| `claim/reprocess` | `nhcx-package/fhir/B5/claim-reprocess.json` | 7.9 | +| `claim/release` | `nhcx-package/fhir/B5/claim-release.json` | 7.9 | +| `communication/response` | `nhcx-package/fhir/B4/communication-response.json` | 7.10 | +| `payment/notice-ack` | `nhcx-package/fhir/B7/payment-notice-ack.json` | 7.10 | +| `communication/request` (a payer's message, the reader's input) | `nhcx-package/fhir/B4/communication-request.json`. It is the NRCeS IG's own example, with the Patient's name, identifier, birth date and phone replaced. | 7.10 | + +## The payer fixtures + +What the readers are fed. `generic` is what any payer on the exchange sends, IRDAI-regulated insurers and TPAs included. `pmjay` is the SHA's own message, a live capture with the beneficiary's identifiers replaced. Some identifiers are absent from the PMJAY files: `C5-received-wf20-pmjay.json` carries no `preAuthRef`. Read a value from the file before you assert it. Paths are under `nhcx-package/fhir/`. + +| Answer | Generic | PMJAY | Reader | +| --- | --- | --- | --- | +| Coverage, validation | `C3/validation-response.json` | `C3/coverage-eligibility.json` | 7.4 | +| Coverage, discovery | `C3/discovery-response.json` | none | 7.4 | +| Coverage, benefits | `C3/benefits-response.json` | `C3/C3-benefits-pmjay.json` | 7.4 | +| Coverage, auth-requirements | `C3/C3-response-generic.json` | `C3/C3-response-pmjay.json` (workflow 5) | 7.6 | +| Insurance plan | `C4/C4-response-generic.json` (coverage-based) | `C4/C4-response-pmjay.json` (package-based) | 7.5 | +| Pre-auth received 20 | `C5/C5-received-wf20.json` | `C5/C5-received-wf20-pmjay.json` | 7.8 | +| Pre-auth approved 21 | `C5/C5-approved-wf21.json` | `C5/C5-approved-wf21-pmjay.json` | 7.8 | +| Enhancement approved 22 | `C5/C5-enhancement-approved-wf22.json` | `C5/C5-enhancement-approved-wf22-pmjay.json` | 7.8 | +| Pre-auth rejected 23 | `C5/C5-rejected-wf23.json` | `C5/C5-rejected-wf23-pmjay.json` | 7.8 | +| Pre-auth queried 24 | `C5/preauth-queried.json` | `C5/C5-queried-wf24.json` | 7.8 | +| Claim received 25 | `C7/C7-received-wf25.json` | `C7/C7-received-wf25-pmjay.json` | 7.8 | +| Claim approved 26 | `C7/C7-approved-wf26.json` | `C7/C7-approved-wf26-pmjay.json`, `C7/C7-approved-deduction-wf26-pmjay.json` | 7.8 | +| Claim queried 27 | `C7/claim-queried.json` | `C7/C7-queried-wf27.json` | 7.8 | +| Claim rejected 291 | `C7/C7-rejected-wf291.json` | `C7/C7-rejected-wf291-pmjay.json` | 7.8 | +| Cancellation done PC02 | `C10/C10-cancelled-wfPC02.json` | `C10/C10-cancelled-wfPC02-pmjay.json` | 7.9 | +| Arbitration acknowledged 37 | `C10/C10-arbitration-wf37.json` | `C10/C10-arbitration-wf37-pmjay.json` | 7.9 | +| Query on the communication API, 24 and 27 | `C6/C6-preauth-query-wf24.json`, `C6/C6-claim-query-wf27.json` | none | 7.10 | +| Notification N02 | none | `C6/C6-notification-wfN02.json` | 7.10 | +| The query the reply answers | `B4/communication-request.json` (the IG's example) | none | 7.10 | +| Payment notice 30 | `C9/C9-notice-wf30.json` | `C9/payment-notice.json`, `C9/C9-notice-tds-wf30-pmjay.json` | 7.10 | +| Predetermination | `B9/predetermination-request.json` (the request), `C11/predetermination-response.json` | none | 7.7, 7.8 | + +`nhcx-package/fhir/index.yaml` catalogues every file: direction, side, scheme, workflow id, focal resource, origin (`wire` or `example`). An `example` file is placeholders written to the specification, not a payload. + +## The live hospital captures + +What a hospital actually sent, as the payer accepted it. The module files quote these shapes. Paths are under `nhcx-package/fhir/`. + +| Scheme | Files | +| --- | --- | +| PMJAY | `D1/D1-request.json` (plan), `D3/D3-check.json` (auth-requirements), `D4/D4-request.json` (pre-auth 12), `D6/D6-enhancement.json` (13), `D6/D6-enhancement-query-answer.json` (131), `D7/D7-query-answer.json` (19), `D8/D8-cancel.json` (PC01), `D9/D9-request.json` (claim 15), `D10/D10-query-answer.json` (161), `D11/D11-reprocess.json` (36), `D13/D13-acknowledgement.json` (17) | +| Generic | `B1/B1-check.json`, `B2/B2-request.json`, `B3/B3-request.json`, `B3/B3-enhancement.json`, `B4/B4-preauth-query-answer.json`, `B4/B4-claim-query-answer.json`, `B5/B5-request.json`, `B7/B7-acknowledgement.json`, `B8/B8-cancel.json`, `B8/B8-reprocess.json` | + +## The docs and the data files + +| Cited | Package | +| --- | --- | +| a chapter | `nhcx-package/docs/`, from `01-Overview` to `07-Go Live` | +| workflow ids (`references/flow-knowledge.md` section 2) | `nhcx-package/workflow.yaml`, the maintained source; rendered as `nhcx-package/docs/01-Overview/06-Workflow Codes.md` | +| use cases (`flow-knowledge.md` section 6) | `nhcx-package/usecases.yaml`; rendered as `nhcx-package/docs/01-Overview/05-NHCX Use Cases.md` | +| PAYR and ERR codes (`references/errors-and-debugging.md`) | `nhcx-package/nhcx-error.yaml` | +| field mappings per bundle (stage 4) | `nhcx-package/mappings/.yaml`; `A1.yaml` is the master dictionary | +| base URLs, sandbox and production | `nhcx-package/baseurl.yaml` | +| every API as a request | `nhcx-package/apis/` (a Bruno collection) | +| the bundle catalogue | `nhcx-package/fhir/index.yaml` | + +## What the package does not hold + +| Missing | Without it | +| --- | --- | +| A status-enquiry answer | None captured. The published status call carries no bundle either way (`nhcx-package/docs/05-FHIR Reference/18-Predetermination, Status and Search.md`). | +| A validator wrapper | Run the HL7 FHIR validator directly, as `references/fhir-knowledge.md` section 11 describes | +| Reference application source | The decisions are written into the module files and the references. Build from them. Record in `NOTES.md` where you would have wanted more. | +| End-to-end drivers and checkers | Write the stage 10 driver against your own build's state address | + +## Which is newer + +Where the references and the package disagree, the package is newer for the published facts (workflow ids, error text, base URLs). The references are newer for what was seen live (which ids a payer actually sent, which refusals mean what). Say which you followed in `NOTES.md`. diff --git a/plugins/nhcx/skills/nhcx-payment/references/testing-knowledge.md b/plugins/nhcx/skills/nhcx-payment/references/testing-knowledge.md new file mode 100644 index 000000000..4a24d7946 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-payment/references/testing-knowledge.md @@ -0,0 +1,405 @@ +# Testing knowledge + +Sources: the NHCX package, fetched by `scripts/fetch-package.sh` into `nhcx-package/` beside `nhcx-build/`. That means the pins and payer fixtures under `nhcx-package/fhir` (catalogued in `nhcx-package/fhir/index.yaml`), the use-case catalogue `nhcx-package/usecases.yaml`, and the chapters named below. Also what live runs on the NHCX sandbox taught. + +## 1. The pyramid + +| Rung | What it proves | Needs | How | +| --- | --- | --- | --- | +| 1. Offline | Every builder equals its pin (`created` excepted); every reader settles the right state from a payer fixture; the state machine refuses what it should | nothing running; a throwaway database; the transport's send stubbed; `nhcx-package/` | one suite in one process (sections 2 to 4) | +| 2. Validator | Every built bundle validates against the NRCeS profiles with no error you cannot explain | Java, the HL7 FHIR validator, the bundles your tests wrote | section 5 | +| 3. A generic payer on the sandbox | Every leg over the real exchange with a payer whose desk you can drive; queries as CommunicationRequests; payment released | the transport on the sandbox (your app's own, or nhcx-adapter when the user chose it), a generic payer you can drive, the sandbox reaching your callback | section 6 | +| 4. Live PMJAY sandbox | `1518@hcx`: the scheme's own refusals and rules, decisions taken on the payer service desk | the sandbox, a real beneficiary, patience | section 6 | + +Climb in order. Rungs 1 and 2 need no service and no consent. Rungs 3 and 4 put traffic on the live NHCX sandbox, and only the user starts them. + +## 2. Writing rung 1 for a new HMIS + +Build one suite with this shape, whatever the language: + +- One process, one seeded database under a temporary path, sections in the order the episode runs. `section(name)` starts a group; `check(label, condition, detail)` records one assertion and never raises. The run exits non-zero at the end if anything failed. +- The transport's `send` is one function, and the test replaces it. Every send goes through it; the test assigns a stub that records the path, recipient, workflow id, correlation id and bundle, and returns `{"txn_id": ..., "correlation_id": ..., "api_call_id": ...}`. Restore the real one in `finally`. The receiving end is tested apart from the door: for your own transport, seal a payer bundle with a test key pair, POST it, and check the 202 receipt and the envelope the door receives. +- Call the callback handler directly with an envelope, not over HTTP: `receive({"jwe_headers": {...}, "fhir": bundle}, "", "", "fhir")`. The return value is one of `settled`, `unmatched`, `ignored`. Feed it the payer bundles under `nhcx-package/fhir/C3` to `nhcx-package/fhir/C11`, both the generic files and the `-pmjay` ones. The auth-requirements rulings are `C3/C3-response-generic.json` (one line, 10 supporting entries) and `C3/C3-response-pmjay.json` (two lines, 22 entries). +- The pin comparison builds each bundle from the pin's own data and compares canonical JSON (`json.dumps(bundle, sort_keys=True)`) against the pin. The data is all in `nhcx-package/fhir/B3/preauth-request.json`: member `MD5SLS4X5`, policy `PMJAY/HP/S/G`, provider `IN1910000151`, payer `1518@hcx`, package `MG0111A` with tier `STRAT006b`, the four `MAND` documents. Drop from both sides only `created`. The bundle id and every entry's `fullUrl` are fixed strings in the pins (`preauth-request-generic`, `https://nhcx.abdm.gov.in/preauth/request`), and the build produces them as they are. +- The single-item pins carry `factor 0.5`. That contradicts the rule their own enhancement follows (`nhcx-package/fhir/B3/preauth-enhancement.json`: the costlier line 1, the next 0.5), so compare those with `factor` removed. Compare the cancel and reprocess pins as they are; they carry `intimationNumber`, the spelling the build sends. +- Read every expected value in a reader check from the fixture you feed: `preAuthRef`, amounts, claim numbers, the UTR. The PMJAY captures have the beneficiary's identifiers replaced, and some fields are absent (`C5/C5-received-wf20-pmjay.json` carries no `preAuthRef`). A typed literal tests your memory, not the reader. +- Negative checks are half the value. A code the plan does not carry is refused. A send while the leg is with the payer is refused. A redelivered api call id is ignored. A claim refused at the door goes back to `queried` with the question restored. A cancel while the payer holds the case is accepted, and a cancel of a rejected one is refused. +- Put the regression sections near the bottom. Each is a defect that reached working code, named after what went wrong. Add one each time the sandbox teaches you something. + +In a language whose JSON encoder does not sort keys, decode into a map and encode again before comparing, so key order cannot fail a check. Where a byte comparison is too strict, as with the wire captures, compare element by element. + +## 3. The test-case matrix + +One row per hospital-side use case. Preconditions are the state the HMIS must be in. The action is what the desk or the test does. The expected wire is what must go out and come back; the per-case archive shows it (and the adapter's ledger, when it is the transport). The expected state is what the HMIS must hold afterwards. Codes are those of `nhcx-package/usecases.yaml`. Workflow ids are the PMJAY table unless the row says generic. + +| Use case | Preconditions | Action | Expected wire | Expected state | +| --- | --- | --- | --- | --- | +| A5 Get status (generic) | A pre-auth or claim leg with the payer; a generic payer | Ask status for the leg | `v1/task/submit`, Task `status` with `claimNumber`, workflow = the leg's correlation id; a Task back with `claimStatus` | An enquiry row `answered` with the status word; the leg unchanged | +| A5 Get status (PMJAY) | as above; PMJAY | Ask status | the same Task; a ProtocolResponse PAYR-1018 (no reason) or PAYR-1008 (with one) | The enquiry row `error` with the payer's words; nothing else changes | +| B1 Check coverage eligibility | A patient with a member id and policy from the policy search; facility HFR id and participant code set | Validate, then discover | `v1/coverageeligibility/check` twice, new correlation each, workflow = the case number; `on_check` with the request echoed and a `CoverageEligibilityResponse` | `claim.status eligible`, `inforce 1`, allowed and used amounts, the payer's Patient demographics | +| B2 Request insurance plan | Eligible; no master held for this facility and policy | Fetch the plan | `v1/insuranceplan/request`, a Task `poll` with `policyNumber` and `providerId`; `on_request` with the InsurancePlan and Questionnaires | `claim_plan.status ready`, benefits with rates, tiers, requirements, forms by url; a second episode on the same policy copies it without a send | +| B3 Submit pre-authorisation | Plan ready; lines quoted from it; dossier saved; admission linked; documents and forms for the pre-auth stage attached | Submit | `v1/coverageeligibility/check` purpose `auth-requirements` first (sent, not awaited), then `v1/preauth/submit` workflow 12 equal to the pin but for identifiers; `on_submit` 20 (`queued`, `response.partial`) then 21 | `claim_preauth.status submitting` after the 20 with `preauth_ref` kept, `approved` after the 21 with `approved_amount`; stage `preauth`, sub-stage `approved` | +| B3 Auth-requirements ruling | The check sent with the pre-auth; the payer answers it | Nothing; read on arrival | inbound `on_check`, a CoverageEligibilityResponse with purpose `auth-requirements`, one `insurance[0].item` per quoted line with `authorizationRequired`, `excluded` and `authorizationSupporting[]` (`C3/C3-response-generic.json`, `C3/C3-response-pmjay.json`) | each quoted line holds its ruling and what is due at pre-auth (a form always, a document only when its `Type` is `pre`); the pre-auth leg unchanged | +| B3 Enhancement | Approved; a line added since (`enhancement_lines` non-empty) | Submit again | `v1/preauth/submit` workflow 13, every line old and new, factors 1 and 0.5; 20 then 22 (generic); the SHA has answered 21 or 22 | `submission_kind enhancement`, `enhancement_no 1`, `preauth_ref` kept, then `approved`; stage `enhancement` | +| B4 Respond to a communication (generic) | A pre-auth or claim with the payer; the payer sends a CommunicationRequest on a new thread | The desk replies with text and a document | inbound `v1/communication/request` with Task `poll`, reason `additionalinfo`; outbound `v1/communication/on_request` with the request's correlation id and workflow id, a TaskBundle: Task `deliver`, Communication `basedOn` the request, the request echoed, the case entries | `claim_query` row `kind query`, `status open` then `answered` with `reply_json`; the leg row untouched; sub-stage `queried` while open | +| B4 Notification | Any leg; the payer sends a CommunicationRequest with intent `proposal` or reason `tatquery` | Nothing; it is acknowledged on arrival | outbound `v1/communication/on_request` at once, the payer's bundle with `Task.status completed`, provider Organization first | `claim_query` row `kind notification`, `status acknowledged`; the case's stage unchanged | +| B5 Submit claim | Approved pre-auth; discharge recorded with mode and stage; claim-stage documents and forms attached | Submit the claim | `v1/claim/submit` workflow 15, `use claim`, `preAuthRef`, the discharge scalars, the summary; 25 (`queued`) then 26 | `claim_submission.status submitting` then `approved` with amounts and item verdicts; stage `claim` | +| B7 Acknowledge payment notice (generic) | An approved claim; the payer's desk releases payment | Nothing; acknowledged on arrival | inbound `v1/paymentnotice/request` workflow 30 on a new thread; outbound `v1/paymentnotice/on_request` with the notice's correlation id and its own workflow id echoed, Task `status completed` with `paymentack` | `claim_payment` row with amount, UTR, `ack_status sent`; stage `payment`, sub-stage `paid`; a redelivery of the notice is `ignored` | +| B8 Cancel | A pre-auth `submitting`, `approved`, `partial` or `queried` | Cancel with a reason | `v1/task/submit` workflow PC01, Task `cancel`, inputs `claimNumber` and `intimationNumber`; `task/on_submit` PC02 with a ClaimResponse adjudicated `cancelled` | `claim_preauth.status cancelling` then `cancelled`; the episode gets a fresh claim number, the old one stays on `claim_ref`; a cancel of a `rejected` pre-auth is refused before sending | +| B8 Reprocess (generic) | A claim `rejected` or `partial` | Reprocess with reason `claimrejected` and a document | `v1/task/submit` workflow 36, Task `reprocess`, `intimationNumber`, `basedOn` CLN, `document` inputs, `for` the member; 37 (Task `accepted`, ClaimResponse `queued`); then 26 on the claim's thread | The enquiry row `answered` with `reopened`; `claim_submission` back to `submitting`, then `approved` | +| B9 Submit predetermination | Eligible; dossier saved | Ask for a quote | `v1/preauth/submit` workflow 12 with `use predetermination`; a ClaimResponse back | A `claim_predetermination` row `answered` with `allowed_amount`; the pre-auth row untouched | +| D1 Fetch the insurance plan | Eligible on PMJAY | Fetch | as B2; the answer on workflow 5, both `specificCost[]` and `coverage[]`, nested document requirements, `/questionnaire/` and `/stgquestionnaire/` forms | as B2, with `ProcedureType` conditions and the consent forms among the policy documents | +| D2 Authenticate the beneficiary | A policy from the BIS | Not NHCX; take the consent questionnaire path | none | The consent form answered for the pre-auth stage | +| D3 Check coverage eligibility | as B1 with member `MD5SLS4X5` style ids | Validate | as B1; the answer on workflow 5 with the wallet | as B1 | +| D4 Submit pre-authorisation | as B3, plus: HPIN on the doctor, `Item/n` ids, consent and STG forms answered, documents under the plan's `MAND` codes | Submit | `v1/preauth/submit` workflow 12; 20 with the path-form `preAuthRef` or none (flow-knowledge.md section 3), then 21 with the bare number | as B3; `preauth_ref` = the bare case number after the 21 | +| D5 Resubmit pre-authorisation | A pre-auth `rejected` | Submit again | a fresh 12, never 121 | a new `submitting` round; 121 would be PAYR-1214 | +| D6 Raise an enhancement | Approved; a medical package added (not conservative) | Submit | workflow 13; 20 without `preAuthRef` (keep the parent's); 241 arrives as a ClaimResponse `partial` on the case thread; the desk answers on 131 with a `CQD` reply; then approved | `enhancement_no 1`; `queried` then `answered` then `approved`; a second conservative package would be PAYR-1245 | +| D7 Answer a pre-authorisation query | The 24 arrived as a ClaimResponse `partial`, item status `Queried` | The desk writes a reply and submits again | `v1/preauth/submit` workflow 19, flow `queryupdate`, `NMI`/`CQD` carrying the words, a new correlation id; 20 then 21 | `submission_kind preauth_query_response`, `query_note` holding the payer's question, then `approved`; an empty reply is refused before sending | +| D8 Cancel pre-authorisation | as B8 on PMJAY | Cancel | as B8 | as B8 | +| D9 Submit claim | as B5, plus: the claim under the pre-auth's claim number, the package alone at the whole amount, Discharge Consent answered, PDF documents | Submit | `v1/claim/submit` workflow 15; 25 with `preAuthRef` as a path; then 26 | as B5; item verdicts with `eligible`, `status Approved` | +| D9 LAMA or DAMA before or during surgery | Discharge mode `lama` or `dama`, stage `Before Surgery` or `During Surgery` | Submit the claim | one item `LM100`, no tier, `DIS` = `LAMA` or `DAMA` with the stage | approved; the package would be PAYR-1362 | +| D9 Death | Discharge mode `death` with a date and time | Submit the claim | `ONS`/`DTM` and `DSDE` with the death instant, `DIS`/`DTM`, the death forms | approved; without `DTM` PAYR-1096 | +| D10 Answer a claim query | The 27 arrived as a ClaimResponse `partial` | The desk writes a reply and submits again | `v1/claim/submit` workflow 161, `NMI`/`CQD`, a new correlation id; 25 then 26 | `submission_kind claim_query_response`, then `approved`, possibly at zero | +| D11 Reprocess a rejected claim | A claim `rejected` | Reprocess | as B8 reprocess; on the sandbox a ProtocolResponse PAYR-1008 | the enquiry row `error` with the refusal; on a generic payer as B8 | +| D12 Claim a shortfall | A settled payment short of the approved amount | Release with `partialpayment` and the amount | `v1/task/submit` workflow 36, Task `release`, `valueMoney` | an enquiry row; out of reach on the sandbox | +| D13 Acknowledge the payment notice | An approved claim; the SHA's finance side sends 30 | Nothing; acknowledged on arrival | outbound `v1/paymentnotice/on_request` with workflow 17, the notice's correlation id, to the notice's sender | as B7 | + +Cross-cutting rows every matrix needs: + +| Case | Action | Expected | +| --- | --- | --- | +| Redelivery | Deliver the same envelope twice | the second returns `ignored`; state unchanged | +| Unmatched | Deliver an answer on an unknown correlation id | `unmatched`; archived under `unmatched`; nothing changes | +| Refusal at the door | Deliver a ProtocolResponse on a leg's thread | the leg `error` (or `queried` restored for a query answer, `approved` restored for an enhancement) with the payer's words; `correlation_id` restored to `thread_correlation_id` | +| Ledger reset (nhcx-adapter only) | The adapter answers 404 on `txn/related` | the leg `error` with "send again"; no spinning | +| Stage after every write | Any of the above | `stage` and `sub_stage` on the episode agree with `case_stage` recomputed from the legs | + +## 4. A skeleton offline test + +Replace the placeholders marked `` with your HMIS's own. Every pin and payer answer is loaded from the package. + +```python +#!/usr/bin/env python3 +"""Offline NHCX checks for : builders against the package pins, readers against the payer fixtures. + + NHCX_PACKAGE=nhcx-package python3 nhcx_offline_test.py # exit 0 when every check passes +""" +from __future__ import annotations + +import copy +import json +import os +import tempfile + +PKG = os.environ.get("NHCX_PACKAGE", "nhcx-package") +GENERIC_PAYER = "" + +os.environ[""] = os.path.join(tempfile.mkdtemp(prefix="nhcx-test-"), "t.db") + +import as nhcx # noqa: E402 the module that owns transport, build_*, receive + +failures = 0 +current = "general" +tally: dict[str, list[int]] = {} + + +def section(name: str) -> None: + global current + current = name + tally.setdefault(name, [0, 0]) + print(f"\n-- {name} " + "-" * max(3, 60 - len(name))) + + +def check(label: str, condition: bool, detail: str = "") -> None: + global failures + tally.setdefault(current, [0, 0]) + tally[current][0 if condition else 1] += 1 + if not condition: + failures += 1 + print(f"[{' ok ' if condition else ' FAIL '}] {label}" + (f" ({detail})" if detail else "")) + + +def pin(rel: str) -> dict: + """A bundle from the package by its path under fhir/, e.g. pin("B3/preauth-request.json").""" + with open(os.path.join(PKG, "fhir", rel), encoding="utf-8") as fh: + return json.load(fh) + + +def resource(bundle: dict, kind: str) -> dict: + return next(e["resource"] for e in bundle["entry"] if e["resource"]["resourceType"] == kind) + + +def task_input(task: dict, code: str): + return next(i.get("valueString") for i in task.get("input", []) if i["type"]["coding"][0]["code"] == code) + + +def total(claim_response: dict, category: str): + return next((t["amount"].get("value") for t in claim_response.get("total", []) + if t["category"]["coding"][0]["code"] == category), None) + + +def normalised(bundle: dict, factor: bool = True) -> dict: + """Drop only `created`, which a builder stamps when it sends; with factor=False, the Claim items' factor too.""" + out = copy.deepcopy(bundle) + + def walk(node): + if isinstance(node, dict): + node.pop("created", None) + for value in node.values(): + walk(value) + elif isinstance(node, list): + for value in node: + walk(value) + + walk(out) + if not factor: + for entry in out["entry"]: + if entry["resource"]["resourceType"] == "Claim": + for item in entry["resource"].get("item", []): + item.pop("factor", None) + return out + + +def canonical(bundle: dict, factor: bool = True) -> str: + return json.dumps(normalised(bundle, factor), sort_keys=True, ensure_ascii=False) + + +def same(label: str, ours: dict, want: dict, factor: bool = True) -> None: + a, b = canonical(ours, factor), canonical(want, factor) + check(label, a == b, "" if a == b else a[:300]) + + +# The package pins' own data: nhcx-package/fhir/B3/preauth-request.json and B1/*.json. +# Every builder is fed this and must produce the pin. +REF = { + "claim_no": "VB26AA2600001", "member_id": "MD5SLS4X5", "policy": "PMJAY/HP/S/G", + "provider": {"id": "IN1910000151", "name": "Facility Name"}, + "payer": {"code": "1518@hcx", "id": "1518", "name": "Insurance Company"}, + "patient": {"name": "Patient Name", "gender": "male", "dob": "2004-09-18", + "phone": "9999999999", "abha": "91718280654077", "member_id": "MD5SLS4X5"}, + "practitioner": {"name": "Practitioner Name", "hpr_id": "982374978-2343", "license_no": "MCI-12345", + "qualification": "Doctor of Medicine", "qualification_code": "MD", + "specialty": "General medicine", "specialty_code": "394802001"}, + "diagnosis": {"code": "A97", "display": "Dengue"}, + "item": {"code": "MG0111A", "display": "Pleural Effusion", "category_code": "MG", + "category_display": "General Medicine", "quantity": 1, "unit_price": 3300, "net": 3300, + "kind": "Procedure", "procedure_type": "conservative"}, + "tier": {"code": "STRAT006b", "display": "HDU", "kind": "Stratification", "parent_code": "MG0111A"}, + # The benefits and auth-requirements pins quote a different package. + "coverage_item": {"code": "MG004C", "display": "Dengue shock syndrome (Dengue fever)", + "category_code": "MG", "category_display": "General Medicine", "quantity": 1, + "tier": {"code": "STRAT006c", "display": "ICU - Without Ventilator"}}, +} + + +def main() -> int: + section("coverage eligibility: ours is the pin") + for purpose, rel in (("discovery", "B1/discovery.json"), ("validation", "B1/validation.json"), + ("benefits", "B1/benefits.json"), ("auth-requirements", "B1/auth-requirements.json")): + want = pin(rel) + ours = nhcx.build_coverage_request((purpose, want)) + same(f"coverage {purpose}", ours, want) + + section("insurance plan request: ours is the pin") + same("plan request", nhcx.build_plan_request(REF["policy"], REF["provider"]["id"]), + pin("B2/insurance-plan-request.json")) + + section("claim bundles: ours is the pin") + ref_pa = pin("B3/preauth-request.json") + ref_pdf = next(si["valueAttachment"]["data"] for si in resource(ref_pa, "Claim")["supportingInfo"] + if "valueAttachment" in si) + dossier = (REF, ref_pdf, ref_pa) + same("preauth request", nhcx.build_preauth_bundle(dossier, flow="request"), ref_pa, factor=False) + ref_qu = pin("B3/preauth-queryupdate.json") + reply = next(si["valueString"] for si in resource(ref_qu, "Claim")["supportingInfo"] + if si["category"]["coding"][0]["code"] == "NMI") + same("preauth query update", + nhcx.build_preauth_bundle(dossier, flow="queryupdate", query_response=reply), + ref_qu, factor=False) + ref_cancel = pin("B3/preauth-cancel.json") + cancel = resource(ref_cancel, "Task") + reason = cancel["reasonCode"]["coding"][0] + same("preauth cancel", + nhcx.build_cancel_task(task_input(cancel, "claimNumber"), (reason["code"], reason["display"]), + cancel["authoredOn"], REF["provider"], REF["payer"]), + ref_cancel) + ref_ack = pin("B7/payment-notice-ack.json") + ack = resource(ref_ack, "Task") + acked_claim = next(o["valueString"] for o in ack["output"] if "valueString" in o) + same("payment acknowledgement", + nhcx.build_payment_ack(acked_claim, ack["authoredOn"], REF["provider"], REF["payer"]), + ref_ack) + + section("the transport is the one door, and it can be stubbed") + posted: list[dict] = [] + real_send = nhcx.transport.send + + def submitted(payer: str, corr: str): + def _send(path, bundle, recipient, workflow_id, correlation_id=None, **kw): + posted.append({"path": path, "recipient": recipient, "workflow_id": workflow_id, + "correlation_id": correlation_id, "bundle": bundle}) + return {"txn_id": "01TEST", "correlation_id": corr, "api_call_id": "acid-" + corr} + + seeded = (payer) # eligible, plan ready, lines quoted, dossier saved + nhcx.transport.send = _send + try: + nhcx.submit_preauth(seeded) + finally: + nhcx.transport.send = real_send + return seeded + + episode = submitted(REF["payer"]["code"], "corr-preauth-1") + sent = posted[-1] + leg = nhcx.preauth(episode) + check("the pre-auth goes out on the preauth route under workflow 12", + sent["path"] == "v1/preauth/submit" and str(sent["workflow_id"]) == "12") + check("no correlation id is passed on a request", sent["correlation_id"] is None) + check("the leg waits with the transport's ids", + leg["status"] == "submitting" and leg["txn_id"] == "01TEST" and leg["correlation_id"] == "corr-preauth-1") + + section("readers: the payer answers settle the right state") + + def deliver(bundle: dict, acid: str, workflow: str, status: str = "response.complete", + corr: str = "corr-preauth-1", sender: str = "1518@hcx") -> str: + return nhcx.receive({"jwe_headers": {"x-hcx-correlation_id": corr, + "x-hcx-api_call_id": acid, + "x-hcx-sender_code": sender, + "x-hcx-status": status, "x-hcx-workflow_id": workflow}, + "fhir": bundle}, "preauth", "request", "fhir") + + received = pin("C5/C5-received-wf20-pmjay.json") + before = nhcx.preauth(episode)["preauth_ref"] + check("the PMJAY acknowledgement leaves the leg waiting", + deliver(received, "acid-20", "20", "response.partial") == "settled" + and nhcx.preauth(episode)["status"] == "submitting") + check("an acknowledgement without preAuthRef overwrites nothing", + not resource(received, "ClaimResponse").get("preAuthRef") + and nhcx.preauth(episode)["preauth_ref"] == before) + check("the same api call id delivered again is ignored", + deliver(received, "acid-20", "20", "response.partial") == "ignored") + approval = pin("C5/C5-approved-wf21-pmjay.json") + approved = resource(approval, "ClaimResponse") + check("the approval settles the leg on the same thread with the payer's case number", + deliver(approval, "acid-21", "21") == "settled" + and nhcx.preauth(episode)["status"] == "approved" + and nhcx.preauth(episode)["approved_amount"] == total(approved, "benefit") + and nhcx.preauth(episode)["preauth_ref"] == approved["preAuthRef"]) + stage, sub_stage = nhcx.case_stage(episode) + check("the episode is stamped preauth / approved", (stage, sub_stage) == ("preauth", "approved")) + + other = submitted(GENERIC_PAYER, "corr-preauth-2") + generic = pin("C5/C5-received-wf20.json") + check("a generic payer's acknowledgement carries the case number, and it is kept", + deliver(generic, "acid-20g", "20", "response.partial", corr="corr-preauth-2", + sender=GENERIC_PAYER) == "settled" + and nhcx.preauth(other)["status"] == "submitting" + and nhcx.preauth(other)["preauth_ref"] == resource(generic, "ClaimResponse")["preAuthRef"]) + + section("auth requirements: the payer's ruling is read line by line") + for rel in ("C3/C3-response-generic.json", "C3/C3-response-pmjay.json"): + ruling = pin(rel) + answer = [e["resource"] for e in ruling["entry"] + if e["resource"]["resourceType"] == "CoverageEligibilityResponse"][-1] + want = {i["productOrService"]["coding"][0]["code"]: i.get("authorizationRequired") + for i in answer["insurance"][0]["item"]} + got = nhcx.parse_auth_bundle(ruling) # {procedure code: {"required": bool, "supporting": [...]}} + check(f"{rel}: one ruling per quoted line, required as the payer says", + {code: line["required"] for code, line in got.items()} == want) + + section("the query loop") + queried = pin("C5/C5-queried-wf24.json") + check("a PMJAY query is the leg queried, with the payer's words and case number kept", + deliver(queried, "acid-24", "24") == "settled" + and nhcx.preauth(episode)["status"] == "queried" + and bool(nhcx.preauth(episode)["query_note"]) + and nhcx.preauth(episode)["preauth_ref"] == resource(queried, "ClaimResponse")["preAuthRef"]) + try: + nhcx.submit_preauth(episode, reply="") + check("an empty reply is refused before sending", False) + except ValueError: + check("an empty reply is refused before sending", True) + check("a generic payer's CommunicationRequest is classified a query", + nhcx.classify_communication(nhcx.GENERIC_ADAPTER, "additionalinfo", "order") == "query" + and nhcx.classify_communication(nhcx.PMJAY_ADAPTER, "additionalinfo", "order") == "notification" + and nhcx.classify_communication(nhcx.GENERIC_ADAPTER, "tatquery", None) == "notification") + + section("refusal at the door") + refusal = {"type": "ProtocolResponse", "x-hcx-status": "response.error", + "x-hcx-correlation_id": "corr-preauth-1", + "x-hcx-error_details": {"code": "PAYR-1238", "message": "Beneficiary is having an active preauthorization request"}} + (episode) + check("a ProtocolResponse settles the leg as refused with the payer's words", + nhcx.receive({"jwe_headers": {"x-hcx-correlation_id": "corr-preauth-1"}, "fhir": refusal}, + "preauth", "request", "protocol") == "settled" + and nhcx.preauth(episode)["status"] == "error" + and "PAYR-1238" in (nhcx.preauth(episode)["error_message"] or "")) + + section("tasks and payment") + cancelled = pin("C10/C10-cancelled-wfPC02-pmjay.json") + verdict = resource(cancelled, "ClaimResponse")["adjudication"][0]["reason"]["coding"][0]["code"] + check("PC02 is read as an accepted cancellation", + nhcx.parse_task_response(cancelled)["adjudication"] == verdict == "cancelled") + arbitration = pin("C10/C10-arbitration-wf37-pmjay.json") + check("37 is read as the reprocess taken", + nhcx.parse_task_response(arbitration)["task_status"] == resource(arbitration, "Task")["status"]) + paid = pin("C9/payment-notice.json") + pn, pr = resource(paid, "PaymentNotice"), resource(paid, "PaymentReconciliation") + notice = nhcx.parse_payment_notice(paid) + check("the payment notice names the claim, the amount and the UTR", + notice["claim_ref"] == pn["identifier"][0]["value"] + and notice["amount"] == pn["amount"]["value"] + and notice["utr"] == pr["paymentIdentifier"]["value"]) + + print("\n" + "=" * 64) + total_checks = sum(ok + bad for ok, bad in tally.values()) + for name, (ok, bad) in tally.items(): + print(f" {name:44s} {ok:3d} passed {bad:2d} failed [{'FAIL' if bad else 'ok'}]") + print("=" * 64) + if failures: + print(f"{failures} of {total_checks} check(s) FAILED") + return 1 + print(f"all {total_checks} checks passed") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) +``` + +What each placeholder must do: + +- `` names the variable your HMIS reads its database path from, so the suite runs on a throwaway file. +- `` is the module that owns `transport`, the builders and `receive`. +- `` is the participant code of a generic payer (``) that your configuration maps to `query_mode: communication`. +- `` returns the dict your coverage builder takes, filled from `REF`. The discovery pin carries policy `NONE`. The benefits and auth-requirements pins quote `REF["coverage_item"]`. Copy the Location and PractitionerRole from the pin it is given. +- `` returns whatever your claim builder takes. That is the claim number, the item, the tier, the program `AB-PMJAY` and factors `(1, 0.5, 0.25)`. Add the four `MAND` documents (`MAND0408`, `MAND0455`, `MAND0409`, `MAND0570`, each with the pin's PDF), and copy the stay and procedure dates from the pin it is given. +- `` takes a payer code and inserts an eligible episode for that payer, with the plan and lines seeded straight into the database. +- `` puts the pre-auth row back to `submitting` on `corr-preauth-1`. + +Run the suite from the folder that holds `nhcx-package/`, or set `NHCX_PACKAGE` to its path. + +## 5. Running rung 2 + +Have your tests and live runs write every bundle they build into one archive folder. The package ships no validator. Run the HL7 FHIR validator with the NRCeS IG `ndhm.in` on the whole folder in one call, with the command and flags in `references/fhir-knowledge.md` section 11. + +Read the results in three piles. "A code the profile does not define" is the scheme's vocabulary, and it is expected. "A required element is missing" and "an id or value the base rules refuse" are yours to fix. Warnings are advice; the sandbox accepted every pin as it stands. Skip the package master; it exhausts the validator's memory. A live PAYR-1004 or PAYR-1008 is the first reason to run this rung again (`nhcx-package/docs/06-Reference/02-Troubleshooting.md`). + +## 6. Running rungs 3 and 4 + +Only the user runs these. Prepare what they start and the driver, then stop and ask. + +What the user starts: + +1. The transport. Your own or the app's existing one needs a participant record carrying its certificate and a public HTTPS `endpoint_url` the exchange can reach (`references/transport-knowledge.md` section 3). nhcx-adapter, only when the user chose it, comes from its release: `config.sample.json` filled in, started with `serve.sh`. +2. Your HMIS, reachable by the exchange through that transport. +3. For rung 3, a generic payer on the sandbox whose desk you can drive (``), mapped to `query_mode: communication`. For rung 4, nothing more: the PMJAY payer is `1518@hcx`, and its decisions are taken on the payer service desk. + +The driver is a script or a browser spec. It walks the matrix rows through the app's JSON state address or its own screens, one episode per test, in series, with a 20 minute timeout per episode. + +- Before a PMJAY run, sweep every live pre-auth for the beneficiaries the tests use. Cancel it on PC01, or have the desk reject it. Otherwise the first pre-auth is refused with PAYR-1238. +- One request at a time per case. Wait about 30 seconds after a decision before the next leg. On "Active instance found" (PAYR-1322), wait and resend, up to three times. +- Wait on the case's own state, never on a fixed sleep or a checklist. +- Log every verdict the sandbox gives, with its workflow id and words, so a refusal is a finding, not a mystery. +- Expect about four minutes for the rung 3 matrix and about ten minutes per episode on PMJAY. + +After the run, package its bundles by correlation id from the per-case archive: every message sent and received, filed under its case. With nhcx-adapter as the transport, `nhcx-adapter ledger thread ` gives the same conversation, with bodies only while `ledger.storeBodies` is true (`nhcx-package/docs/02-Getting Started/10-NHCX Adapter.md`). File each thread under its use case. diff --git a/plugins/nhcx/skills/nhcx-payment/references/transport-knowledge.md b/plugins/nhcx/skills/nhcx-payment/references/transport-knowledge.md new file mode 100644 index 000000000..a0838b9cd --- /dev/null +++ b/plugins/nhcx/skills/nhcx-payment/references/transport-knowledge.md @@ -0,0 +1,283 @@ +# Transport knowledge: how the build reaches NHCX + +Every NHCX message is a FHIR bundle sealed in a JWE, sent with an ABDM session token, and answered later on the sender's own callback. Something has to do that work. This file says which of three things does it for a build, what the rest of the build expects from it, and how to build it yourself. + +Section 3 is drawn from NHA's published chapters: `nhcx-package/docs/02-Getting Started` (01 to 09, and 11), `nhcx-package/docs/01-Overview/04-JWE, Status and Errors.md` and `nhcx-package/docs/06-Reference/03-Envelope Fields.md`. Open them when a detail matters. Where they and this summary differ, they win. + +## 1. Three transports + +| Transport | Choose it when | The build | +| --- | --- | --- | +| `existing` | Stage 0 found the app already speaks NHCX: its own client that seals and posts JWEs, a vendor gateway or middleware, an HCX SDK, callbacks under `/v1/...` | Keeps it. Wraps it behind the contract in section 2 and closes the gaps section 4 lists. Never replaces a working one. | +| `own` | The app has no NHCX integration, and the user has not asked for nhcx-adapter. This is the default. | Builds the protocol into the app (section 3): the session token, the key and certificate, the participant record, the recipient's certificate, sealing and sending, the callback and its receipt. | +| `adapter` | Only when the user asks for nhcx-adapter, by name or by asking for "the adapter" | Downloads it (section 5) and talks plain FHIR to it. `references/api-knowledge.md` is its contract. | + +The rules: + +- Never propose nhcx-adapter, and never choose it because it is easier. Use it only when the user has asked for it, and write their words into `nhcx-build/1-idea.md`. +- An app with an NHCX integration of its own keeps it, even when it is partial. Extend it; never put a second transport beside it. +- The choice is made once per app, at stage 1, from stage 0's verdict on `foundation.transport`. Every skill after the first reads it from `1-idea.md`. + +## 2. The contract every transport meets + +The rest of the build (modules 7.2 to 7.13) never sees the transport, only these functions: + +| Function | Takes | Gives | Notes | +| --- | --- | --- | --- | +| `send(path, bundle, recipient, workflow_id, correlation_id = null, ben_abha_id = null, claim_no, usecase)` | The NHCX path (`v1/preauth/submit`), the bundle, the recipient's participant code, the workflow id; a correlation id only when answering (the communication reply, the payment acknowledgement); the beneficiary's ABHA, else the episode's by `claim_no` | `{txn_id, correlation_id, api_call_id, raw}` | Raises `TransportError(code, message, protocol_response, retryable)` on a refusal. Archives the outbound message. Every leg stores the three ids. | +| The receiving end | A delivery from the exchange (`own`, `existing`) or from nhcx-adapter | Calls 7.3's `receive(envelope)` with `{meta: {path, payloadType, redelivery}, jwe_headers: {every x-hcx- field}, fhir: }`; `payloadType` is `fhir`, `protocol` or `error` | Answers the sender as its transport requires (section 3.9 for `own`). The door does the rest. | +| `policies(id_type, value)` | `AbhaNumber`, `MemberId` or `MobileNo`, and the value | The participant service's answer, raw | Module 7.4 normalises it (section 3.6). | +| `participants(role)` | `PAYER`, `PROVIDER` or `TPA` | The registry's list | Cached for the day. | +| `token()` | nothing | The ABDM session token | For calls the transport does not make itself, such as the PMJAY payer service. | +| `thread(correlation_id)`, `fetch_missed(txn_id)` | | The messages on one thread; a missed answer | Only nhcx-adapter keeps a ledger to answer these. With `own` and `existing`, `thread` reads the per-case archive and `fetch_missed` answers `unavailable`; a lost answer surfaces through `/v1/error` and the status exchange instead (section 3.10). | + +Two values every transport needs from the build, both from the policy lookup (section 3.6). The recipient is the policy's `processingid`, kept on the episode as `recipient_code`. The insurer is its `payerid`, kept as `payer_code`: it goes inside the bundle and chooses the payer adapter (module 7.11). And every message carries the beneficiary's ABHA number in `x-hcx-ben-abha-id`. + +A test replaces `send` with a stub of the same signature (stage 9). Nothing else in the build changes for a test. + +## 3. Building it yourself (`own`) + +Seven things, in this order (`01-The Base Framework.md`): a token, a key and certificate, a participant record, the payer and policy lookups, the recipient's certificate, sealing and sending, and the callback. The last two are the ones every message uses. + +### 3.1 Before you start + +| Need | Why | +| --- | --- | +| The facility's HFR id | The registry that vouches for a hospital | +| ABDM sandbox client id and secret, Milestone 1 completed | NHCX uses the same credentials; there is no separate login | +| A public HTTPS server in India with a domain name | The exchange calls your callback; it will not call an IP address or a port number | +| `openssl` where the private key will live | The key pair | +| A JOSE library | RSA-OAEP-256 with A256GCM: `jose` on Node, `jwcrypto` on Python, Nimbus on Java, `jose-jwt` on .NET | + +Ask the user for the credentials. Never write them, the token or the private key into code, a log or `nhcx-build/`. + +### 3.2 Addresses and headers + +From `nhcx-package/baseurl.yaml`: + +| Service | Sandbox | Production | +| --- | --- | --- | +| ABDM session token | `https://dev.abdm.gov.in/api/hiecm/gateway/v3/sessions` | `https://apis.abdm.gov.in` plus the same path; confirm it in the onboarding letter | +| NHCX exchange, every use-case call under `/v1` | `https://apisbx.abdm.gov.in/hcx` | Shared by NHA after sandbox exit | +| Participant service | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice` | `https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice` | + +Keep every address in configuration. Every call to the participant service and the use-case endpoints carries `Accept: application/json`, `Content-Type: application/json` and `bearer_auth: Bearer `. The header is `bearer_auth`, not `Authorization`; some NHA pages write `Authorization`, so send both with the same value. + +### 3.3 The session token + +`POST` to the sessions address with three headers, none optional: `REQUEST-ID` (a fresh UUID on every call), `TIMESTAMP` (UTC with milliseconds and a trailing `Z`, from the system clock) and `X-CM-ID` (`sbx` on the sandbox, `abdm` in production). The body is `{"clientId", "clientSecret", "grantType": "client_credentials"}`. The answer carries `accessToken` and `expiresIn`. + +- NHA's documents give its life as 300, 1200 and 6000 seconds. Rely on none: keep the token and when you got it, and fetch a new one when it is a few minutes old. +- On any `401`, get a new token and retry that call once. Never retry with the same token. +- Put `Bearer` and a space before the token. Without it, `401`. + +`03-Session Token.md` also shows the two timestamp shapes in ten languages: the gateway's UTC `...975Z`, the exchange's `+05:30`. + +### 3.4 Your key and certificate + +```bash +openssl genpkey -algorithm RSA -out private.key -pkeyopt rsa_keygen_bits:2048 +openssl req -new -key private.key -out request.csr +openssl x509 -req -in request.csr -signkey private.key -out certificate.crt -days 365 +base64 -w 0 certificate.crt > certificate.b64 # macOS: base64 -i certificate.crt -o certificate.b64 +``` + +`private.key` never leaves the server that receives callbacks. `certificate.b64` goes on the participant record as `encryption_cert`. Note the expiry: a lapsed certificate stops every sender. Replace it yearly (`04-Your Certificate.md`). + +### 3.5 The participant record + +On the sandbox, `POST /participant/create` with: + +| Field | Value | +| --- | --- | +| `linked_registry_codes` | `["10001"]` (HFR) | +| `registryid` | Your ABDM client id on the sandbox; the HFR id in production | +| `roles` | `["10001"]` (provider) | +| `participant_name`, `scheme_code`, `state`, `district`, `primaryEmail`, `phone`, `primaryMobile` | The facility's | +| `encryption_cert` | The base64 certificate | +| `endpoint_url` | The base of your callback server | + +The answer is your `participant_code`: the `x-hcx-sender_code` on everything you send. `participant/update` changes the certificate or the address. Production takes four steps with a passcode to the mobile on the HFR record (`v2/participant/create`, `validate`, `v2/participant/update`, `update/validate`), and `v2/update/cert` rotates only the certificate (`05-Creating and Updating a Participant.md`). + +The exchange appends the use-case path to `endpoint_url`: a pre-auth decision arrives at `/v1/preauth/on_submit`. Only the client id that created the record may change it; any other gets NHCX-1015. + +This is the user's onboarding, not the build's. The build writes the script or the settings screen; the user runs it with their credentials. Check it worked by fetching your own certificate back (section 3.7). + +### 3.6 The payer and the policy + +- Payers: `POST /fetch/participants/list` with `role` (`PAYER`, `PROVIDER`, `TPA`), `fromdate` and `todate` (`dd/MM/yyyy`), and optionally `entitytype` (`Gov`). There is no server-side search by name: fetch, filter locally, and cache for the day. +- Policies: `POST /participant/get/policies` with `identifiertype` and `identifiervalue`. Try `AbhaNumber` (no hyphens), then `MemberId`, then `MobileNo`, and stop at the first that returns a policy. Each policy carries `payerid`, `processingid`, `memberid`, `productid` and `productname`. The published answer is a sketch: read a real one before writing the parser, and keep it raw on the episode. +- Send to the processor. `processingid` is the envelope's recipient and whose certificate seals the message; `payerid` is the insurer named inside the bundle. They are the same when the insurer processes its own claims and differ when a TPA does. Addressing the `payerid` is the portal's seventh most common mistake. A policy with no `processingid` cannot be addressed: stop and say so (`06-Finding Participants and Policies.md`). + +### 3.7 The recipient's certificate + +`POST /fetch/certs` with `{"participantid": ""}`. The answer is PEM text: usually an X.509 certificate, sometimes a bare SPKI public key (anything under about 400 bytes). Load it as a certificate and take its key; if that fails, load it as a key. NHA does not publish the JSON envelope around it, so read one real answer first. Cache by participant code for 24 hours, and refresh early when the other side stops being able to open your messages (`07-Fetching a Recipient Certificate.md`). + +### 3.8 Sealing and sending + +The protected header (`08-Building and Sending a JWE.md`, `06-Reference/03-Envelope Fields.md`): + +| Field | Value | +| --- | --- | +| `alg`, `enc` | `RSA-OAEP-256`, `A256GCM`; not `RSA-OAEP` | +| `x-hcx-sender_code` | Your participant code | +| `x-hcx-recipient_code` | The policy's `processingid` on a request; the request's sender on an answer | +| `x-hcx-api_call_id` | A fresh UUID on every message, answers included | +| `x-hcx-request_id` | A UUID per request; optional, send it | +| `x-hcx-correlation_id` | On a request, this message's own `api_call_id`. On an answer, the request's `correlation_id`, so the two ids differ on an answer | +| `x-hcx-workflow_id` | The step code (`references/flow-knowledge.md` section 2). Optional in the specification, but payers key on it: send it wherever the sheet gives one | +| `x-hcx-timestamp` | ISO 8601 with `+05:30`, no milliseconds, from the system clock | +| `x-hcx-status` | `request.initiated` on a request; `response.complete` on an answer (an `on_` path) | +| `x-hcx-ben-abha-id` | The beneficiary's ABHA number without hyphens. Mandatory on every exchange | +| `x-hcx-use_case` | Optional: `New`, `Enhancement` or `Resubmit` on a pre-auth; `New` or `Resubmit` on a claim | + +Seal with the JOSE library: the bundle as plaintext, the recipient's public key, the header above as the protected header, compact serialisation (five parts, four dots). POST `{"payload": ""}` to `/v1/` with the headers of section 3.2. The sandbox collection also repeats the `x-hcx-` fields as HTTP headers; send them both ways. + +What comes back: + +| Answer | Means | The build | +| --- | --- | --- | +| `202` with a receipt (`protocol_status: request.queued`) | The envelope was valid and is queued. It is not the decision | Store `api_call_id` and `correlation_id`, and the archive id as `txn_id`; the leg waits | +| `400` | The envelope failed validation | Raise with the gateway's body; nothing went to the payer | +| `401` | The token expired, or `Bearer` is missing | New token, retry once | +| A connection dropped after the request was written | Unknown: it may have landed | Do not resend at once (`references/errors-and-debugging.md` section 7) | + +A correlation id that failed at the gateway is retired. The next attempt needs a fresh `api_call_id` and a fresh `correlation_id` (`01-Overview/04-JWE, Status and Errors.md`). + +### 3.9 Receiving + +Host these under `endpoint_url` (`09-Receiving a Callback.md`): `/v1/coverageeligibility/on_check`, `/v1/insuranceplan/on_request`, `/v1/preauth/on_submit`, `/v1/claim/on_submit`, `/v1/predetermination/on_submit`, `/v1/search/on_submit`, `/v1/communication/request`, `/v1/paymentnotice/request`, `/v1/task/on_submit`, `/v1/on_status` and `/v1/error`. Build one handler. The path gives the receipt's `entity_type`; the correlation id routes everything else (module 7.3). + +- The address: a domain over HTTPS with TLS 1.2 or newer, hosted in India, reachable from the exchange's outbound addresses `3.109.99.210`, `13.126.152.0` and `13.200.129.223`. +- The body: `{"type": "JWEPayload", "payload": ""}`; or, when the recipient refused your message, `{"type": "ProtocolResponse", "x-hcx-...": ..., "x-hcx-status": "response.error", "x-hcx-error_details": {code, message, trace}}` with the fields in the clear. `/v1/error` carries neither: it is a plain report of a request the exchange gave up on after five attempts. Store it whole and do not parse it against a fixed schema. +- Open a `JWEPayload` with your private key: the protected header comes out in the clear and the bundle is the plaintext. A failure to decrypt means the message was sealed for a certificate that is not the one on your participant record. +- Answer every delivery with `202` and the receipt within 30 seconds, `/v1/error` and unrecognised messages included. Not `200`, and not an empty body: + + ```json + {"timestamp": "dd/MM/yyyy HH:mm:ss:SSS", "api_call_id": "", "correlation_id": "", + "result": {"sender_code": "", "recipient_code": "", "entity_type": "preauth", "protocol_status": "request.queued"}, + "error": {"code": "", "message": ""}} + ``` + + `entity_type` is the path's second-to-last segment, or the last where that is `v1`, with `on_` stripped. +- Hand the door `{meta: {path, payloadType, redelivery}, jwe_headers, fhir}`: `payloadType` `fhir` with the bundle, `protocol` with the ProtocolResponse body as `fhir`, `error` with the `/v1/error` report. The door dedupes on `x-hcx-api_call_id`, archives, matches and applies, fast and with no outbound calls, so the receipt still goes inside the 30 seconds. +- The exchange signs its calls to you with a JWT (RS256; claims `jti`, `iss`, `sub`, `iat`, `exp`). No published source gives the NHCX public key or the header the token arrives in. Build the check with the key in configuration. While no key is configured, log that at every start, accept calls only from the three addresses above, and ask NHA for the key at onboarding. Never leave the check off silently. + +### 3.10 Status and the error endpoint + +- `/v1/status` asks the exchange what became of a message you sent. The payload is empty; `x-hcx-correlation_id` is that message's `api_call_id`. The answer arrives on `/v1/on_status` with `request.queued`, `request.dispatched` or `request.stopped` (redelivery exhausted; the correlation is retired). Call it when a case has been quiet longer than the payer's turnaround, never on a timer (`11-Status and Search.md`). `references/flow-knowledge.md` section 2 records what the sandbox did with it; keep the path configurable. This is not the claim's status Task of module 7.9. +- `/v1/error` is how you learn a request died. Without it a lost message is silent. + +With no ledger to poll, these two, the per-case archive and the receipts are what an `own` transport has. A leg with no answer stays waiting; it never turns into an error on a timer. + +### 3.11 Proving it + +The sandbox's dummy payer answers when you trigger it. Send it a bundle, then `POST https://apisbx.abdm.gov.in/pmjay/sbxhcx/dummyhcxpayer/process/request` with `{"action": "Approve" | "Reject" | "Query", "method": "Preauth" | "Claim", "correlationId": ""}`. Its answer reaching your `/v1/preauth/on_submit`, sealed or as a ProtocolResponse, proves the token, the participant record, the address, the sealing and the opening together (`09-Receiving a Callback.md`, "Closing the loop"). This is live traffic: stage 10, rung 3, started by the user. + +### 3.12 Pseudo code + +``` +settings.nhcx = {sessions, base, registry, cm_id, client_id, client_secret, # from configuration, never from code + private_key, signing_key} # signing_key empty until onboarding gives it + +function token(): + if cache.token and age(cache.at) < 240s: return cache.token + r = http_post(settings.nhcx.sessions, json = {clientId: settings.nhcx.client_id, clientSecret: settings.nhcx.client_secret, + grantType: "client_credentials"}, + headers = {"REQUEST-ID": uuid4(), "TIMESTAMP": utc_millis_z(), "X-CM-ID": settings.nhcx.cm_id}) + cache = {token: r.json().accessToken, at: now()} + return cache.token + +function authed_post(url, body, extra_headers = {}): + for attempt in (1, 2): + t = token() + r = http_post(url, json = body, timeout = 90, + headers = {"Accept": "application/json", "Content-Type": "application/json", + "bearer_auth": "Bearer " + t, "Authorization": "Bearer " + t} + extra_headers) + if r.status != 401: return r + cache.token = null # one retry, with a fresh token + return r + +function registry(path, body): return authed_post(settings.nhcx.registry + "/" + path, body) + +function recipient_key(code): # cached for 24 hours + if certs[code] and age(certs[code].at) < 24h: return certs[code].key + pem = pem_in(registry("fetch/certs", {participantid: code}).json()) # read one real answer first + key = try_certificate(pem).public_key() or load_public_key(pem) # X.509 first, bare SPKI second + certs[code] = {key, at: now()} + return key + +function send(path, bundle, recipient, workflow_id, correlation_id = null, ben_abha_id = null, claim_no = null, usecase = ""): + abha = digits(ben_abha_id or ben_abha(claim_no)) + if not recipient or not workflow_id or not abha: raise ValueError("recipient, workflow id and beneficiary ABHA are required") + answer = path.split("/")[-1].startswith("on_") + api_call_id = uuid4() + header = {"alg": "RSA-OAEP-256", "enc": "A256GCM", + "x-hcx-sender_code": with_hcx(settings.participant_code), "x-hcx-recipient_code": with_hcx(recipient), + "x-hcx-api_call_id": api_call_id, "x-hcx-request_id": uuid4(), + "x-hcx-correlation_id": correlation_id if answer else api_call_id, + "x-hcx-workflow_id": str(workflow_id), "x-hcx-timestamp": now_ist_seconds(), + "x-hcx-status": "response.complete" if answer else "request.initiated", + "x-hcx-ben-abha-id": abha} + jwe = jose_encrypt_compact(to_json(bundle), recipient_key(with_hcx(recipient)), protected = header) + r = authed_post(settings.nhcx.base + "/" + path, {"payload": jwe}, extra_headers = without(header, "alg", "enc")) + txn = archive.record(claim_no, usecase, "out", {path, header, bundle, status: r.status, response: r.text}) + if r.status >= 300: + raise TransportError(code = "GATEWAY_HTTP_" + r.status, message = r.text, retryable = r.status >= 500) + return {txn_id: txn, correlation_id: header["x-hcx-correlation_id"], api_call_id: api_call_id, raw: r.json()} + +route POST /v1/ # under endpoint_url; exempt from session auth and CSRF; the exchange's addresses only +function inbound(request, path): + verify_nhcx_jwt(request, settings.nhcx.signing_key) # when the key is configured; else logged at start, never silent + body = parse_json_or_null(request.body) + if path == "error": + env = {meta: {path: "v1/error", payloadType: "error"}, jwe_headers: {}, fhir: body} + elif body and body.type == "ProtocolResponse": + env = {meta: {path: "v1/" + path, payloadType: "protocol"}, jwe_headers: x_hcx_fields(body), fhir: body} + else: + try: header, plaintext = jose_decrypt_compact(body.payload, settings.nhcx.private_key) + except: archive.record(null, "undecryptable", "in", request.body); return 202, receipt({}, path, error = "DECRYPT_FAILED") + env = {meta: {path: "v1/" + path, payloadType: "fhir"}, jwe_headers: header, fhir: parse_json(plaintext)} + receive(env) # module 7.3: dedupe, archive, match, apply; fast, no sends + return 202, receipt(env.jwe_headers, path) # within 30 seconds + +function receipt(h, path, error = ""): + return {"timestamp": now_ist("dd/MM/yyyy HH:mm:ss:SSS"), + "api_call_id": h["x-hcx-api_call_id"], "correlation_id": h["x-hcx-correlation_id"], + "result": {"sender_code": h["x-hcx-sender_code"], "recipient_code": h["x-hcx-recipient_code"], + "entity_type": entity_type(path), "protocol_status": "request.queued"}, + "error": {"code": error, "message": ""}} + +function entity_type(path): # "v1/preauth/on_submit" -> "preauth"; "v1/on_status" -> "status" + parts = ("v1/" + path).split("/"); seg = parts[-2] if parts[-2] != "v1" else parts[-1] + return seg.removeprefix("on_") +``` + +## 4. Using an existing integration (`existing`) + +How stage 0 recognises one: `x-hcx-`, `JWEPayload`, `RSA-OAEP-256`, `A256GCM`, a JOSE library among the dependencies, `bearer_auth`, a sessions URL on the ABDM gateway, `participanthcxservice`, `fetch/certs`, `participant/get/policies`, routes ending in `on_submit`, `on_check` or `on_request`, a vendor's NHCX or HCX client library, a separate gateway service the app calls. + +What it must do, checked by running it offline with the network stubbed and a test key pair for the seal: + +| Contract item (section 2) | Look at | Common gap | +| --- | --- | --- | +| `send` emits the protected header of section 3.8 | What it seals or posts | No `x-hcx-ben-abha-id`; a request correlation id that is not its own `api_call_id`; UTC timestamps; `RSA-OAEP` | +| The recipient | Who it addresses | The `payerid` instead of the `processingid` | +| The three ids back to the caller | Its return value | Only a success flag; the ids stay inside it | +| Receiving: a `202` receipt within 30 seconds on every path, `/v1/error` included | Its callback handler | `200` or an empty body; no `/v1/error`; slow work before answering | +| Handing on the header and the bundle | What it gives the app | The bundle without the header; no ProtocolResponse path | +| Dedupe on `x-hcx-api_call_id` | Its store | None | +| A record of every message | Its logs | Bodies not kept | + +The build wraps it. 7.1's `send` calls the existing client and returns the three ids. The existing callback handler, after its receipt, calls 7.3's `receive` with the envelope of section 2. Each gap is closed in the existing code, in its style (stage 7, action `extend`). The existing transport is not rewritten, and no second one is added beside it. If it cannot be made to hand on the ids or the header, record `partial` and ask the user whether to extend it further or, with their agreement, build `own` in its place. + +## 5. nhcx-adapter, only when asked + +nhcx-adapter is NHA's optional single binary that does section 3 for you (`nhcx-package/docs/02-Getting Started/10-NHCX Adapter.md`, titled "Optional"). Use it only when the user has asked for it. Then: + +1. Get it, with the user's go-ahead, from https://github.com/nha-in/nhcx-adapter/releases (the latest). Each release carries one archive per platform, `nhcx-adapter___.tar.gz` (darwin, linux, windows, freebsd; amd64, arm64, 386), holding the binary, `config.sample.json`, `serve.sh`, `stop.sh`, `update.sh` and `README.md`. Put it in a folder of the user's, not in the skill. +2. Its contract is `references/api-knowledge.md`: configuration (section 2), routes (3), the outbound envelope and answer (4, 5), the delivery your HMIS receives (6), the ledger (7), the kit endpoints (8). +3. Onboarding is sections 3.1 to 3.5 again: credentials, a key, a participant record, a public address. The adapter can generate and register the key itself (`config init`, `cert generate`, its startup checks). +4. It does not queue or retry, does not build or validate bundles, and does not verify who sent an inbound message beyond decrypting it. Its `/internal/*` routes have no authentication: bind it to loopback. + +How it maps onto section 2: `send` POSTs `{jwe_headers, fhir}` to `/fhir/out/`; the receiving end is the HMIS route the adapter posts to (`api-knowledge.md` section 6); `policies` is `/internal/policies/search`; `thread` and `fetch_missed` are its ledger and `/internal/txn/*`. diff --git a/plugins/nhcx/skills/nhcx-payment/scripts/fetch-package.sh b/plugins/nhcx/skills/nhcx-payment/scripts/fetch-package.sh new file mode 100755 index 000000000..efbafa50b --- /dev/null +++ b/plugins/nhcx/skills/nhcx-payment/scripts/fetch-package.sh @@ -0,0 +1,122 @@ +#!/usr/bin/env bash +# Fetch the NHCX package and unpack it beside nhcx-build/ as nhcx-package/. +# +# scripts/fetch-package.sh [url-or-path] [target-dir] +# +# With no [url-or-path] (or "latest"), the zip is the build attached to the latest +# release of https://github.com/nha-in/nhcx-package (the nhcx-package-v.zip +# asset); its sha256 is checked against the digest GitHub records for the asset. +# Otherwise [url-or-path] is a link to the zip or a local path to it. +# [target-dir] defaults to the current directory. The zip unpacks to /nhcx-package/. +# +# Afterwards MANIFEST is checked: every file it lists must exist with the sha256 +# it records. Nothing is deleted; an existing nhcx-package/ is replaced. +set -euo pipefail + +repo="nha-in/nhcx-package" +src="${1:-latest}" +target="${2:-.}" +if [[ "$src" == "-h" || "$src" == "--help" ]]; then + echo "usage: $0 [latest|url-or-path-to-package.zip] [target-dir]" >&2 + exit 2 +fi + +download() { # + if command -v curl >/dev/null 2>&1; then + curl -fsSL -o "$2" "$1" + elif command -v wget >/dev/null 2>&1; then + wget -qO "$2" "$1" + else + echo "neither curl nor wget is available" >&2 + exit 1 + fi +} + +mkdir -p "$target" +tmp="$(mktemp -d)" +zip="$tmp/package.zip" +want_sha="" + +if [[ "$src" == "latest" ]]; then + # Ask the releases API for the latest release's zip asset and its digest. + api="https://api.github.com/repos/$repo/releases/latest" + if download "$api" "$tmp/release.json" 2>/dev/null; then + read -r tag url want_sha < <(python3 - "$tmp/release.json" <<'PY' +import json, sys +rel = json.load(open(sys.argv[1], encoding="utf-8")) +assets = [a for a in rel.get("assets", []) + if a["name"].startswith("nhcx-package") and a["name"].endswith(".zip")] +if not assets: + sys.exit(f"release {rel.get('tag_name')} has no nhcx-package*.zip asset") +a = assets[0] +digest = a.get("digest") or "" +print(rel["tag_name"], a["browser_download_url"], + digest.split(":", 1)[1] if digest.startswith("sha256:") else "") +PY + ) + else + # API unreachable or rate limited: read the tag off the releases/latest redirect + # and build the asset name from it. No digest to check in this case. + tag="$(curl -fsSIL -o /dev/null -w '%{url_effective}' "https://github.com/$repo/releases/latest")" + tag="${tag##*/}" + if [[ -z "$tag" || "$tag" == "latest" ]]; then + echo "could not resolve the latest release of $repo" >&2 + exit 1 + fi + url="https://github.com/$repo/releases/download/$tag/nhcx-package-v$tag.zip" + fi + echo "fetching $repo release $tag: $url" + download "$url" "$zip" + if [[ -n "$want_sha" ]]; then + got_sha="$(python3 -c 'import hashlib,sys; print(hashlib.sha256(open(sys.argv[1],"rb").read()).hexdigest())' "$zip")" + if [[ "$got_sha" != "$want_sha" ]]; then + echo "sha256 mismatch for $url: got $got_sha, release says $want_sha" >&2 + exit 1 + fi + fi +elif [[ -f "$src" ]]; then + cp "$src" "$zip" +else + download "$src" "$zip" +fi + +rm -rf "$target/nhcx-package" +unzip -q "$zip" -d "$target" +if [[ ! -f "$target/nhcx-package/MANIFEST" ]]; then + echo "unpacked, but $target/nhcx-package/MANIFEST is missing; is this the NHCX package?" >&2 + exit 1 +fi + +# Verify every file the MANIFEST lists. The MANIFEST is YAML; its file entries +# carry path, bytes and sha256 on separate lines. +python3 - "$target/nhcx-package" <<'PY' +import hashlib, os, re, sys +root = sys.argv[1] +text = open(os.path.join(root, "MANIFEST"), encoding="utf-8").read() +# Only the `files:` section lists a sha256 per path; the `contents:` summary above it +# lists directories. Parse entry by entry so a directory entry never borrows the next +# file's hash. +files_section = text.split("\nfiles:\n", 1)[1] if "\nfiles:\n" in text else "" +entries = [] +for chunk in re.split(r"\n\s*-\s+path:\s*", "\n" + files_section)[1:]: + path = chunk.split("\n", 1)[0].strip() + m = re.search(r"^\s+sha256:\s*([0-9a-f]{64})", chunk, re.M) + if path and m: + entries.append((path, m.group(1))) +bad = [] +for path, want in entries: + p = os.path.join(root, path) + if not os.path.isfile(p): + bad.append(f"missing {path}") + continue + got = hashlib.sha256(open(p, "rb").read()).hexdigest() + if got != want: + bad.append(f"sha256 mismatch {path}") +print(f"nhcx-package: {len(entries)} file(s) listed, {len(bad)} problem(s)") +for b in bad[:20]: + print(" " + b) +sys.exit(1 if bad else 0) +PY + +rm -rf "$tmp" +echo "ready: $target/nhcx-package (see references/material.md for the path map)" diff --git a/plugins/nhcx/skills/nhcx-payment/stages/0-capability-check.md b/plugins/nhcx/skills/nhcx-payment/stages/0-capability-check.md new file mode 100644 index 000000000..8186c3288 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-payment/stages/0-capability-check.md @@ -0,0 +1,92 @@ +# Stage 0: capability check + +Purpose: before anything is planned, find out what the app already does. For this skill's own capabilities, for the foundation it stands on, and for what it needs from the use cases before it, write one verdict each with the evidence that decides it. The verdicts decide what the later stages reuse, extend, build or wait for. Nothing is built twice, and nothing is reused on faith. + +## Inputs + +- This skill's `SKILL.md`, section "Capability check": its own capabilities (what to look for, what makes each present), and its prerequisites with the check that proves each present. The skills that own the prerequisites do not need to be installed; their checks are in this skill's `SKILL.md`. +- `core/FOUNDATION.md`: the six foundation capabilities. +- `nhcx-build/capabilities.json` and `nhcx-build/0-capability.md`, if another NHCX skill already ran on this app. +- The target: the codebase (integrate), or the folder where the standalone app lives or will live. +- The pins and payer fixtures each check names, in `nhcx-package/`. If it is not beside `nhcx-build/`, fetch it now (`scripts/fetch-package.sh`); `references/material.md` names each pin's file. + +## The verdicts + +| Verdict | Means | What happens next | +| --- | --- | --- | +| `present` | Located, and its check was run and observed passing | Reuse. Stage 7 builds nothing for it. Stage 8 still runs its Validate rows; stage 9 still tests it. | +| `partial` | Located, but its check fails; or it covers some legs or branches and not others; or it was located and could not be run | Extend. Stage 7 builds the difference, in the existing code. | +| `absent` | Searched for as the skill says and not found | Build. Stage 7 builds it. | +| `unknown` | Could not be searched: no code is reachable | Planned as absent; stage 0 runs again when the code is reachable. | +| `not applicable` | The mode or the scope excludes it: 7.13 in integrate mode, a leg the user marked out | Nothing. | + +For a prerequisite, a verdict of `absent` or `unknown` is a stop: see step 5. + +Present is a claim about behaviour. Code that looks right is `partial` until its check has run. + +## Do + +### 1. Find the target + +Integrate: the codebase root, its language and framework, enough to search and to run code offline (stage 3 does the full survey). Standalone: the app folder. If it is empty and no other NHCX skill has built anything there, every capability is `absent` and this stage is short. Write which in one line. + +If `nhcx-build/capabilities.json` exists, read it. A verdict another skill recorded is a lead, not a result. If the code changed since its date (the version control log says), run its check again; otherwise carry it forward with its evidence and date. + +### 2. Locate + +For each capability in the three lists (own, foundation, prerequisites), search for the markers: NHCX paths such as `v1/preauth/submit`, resource names such as `CoverageEligibilityRequest`, workflow ids as strings, table and column names. `SKILL.md` lists them for its own capabilities; for a prerequisite, the marker is what its check names. Record every hit as `path:line`. A hit in a comment, a dead branch or a test fixture is not the capability; say so. + +Look also for the same job done another way: a pre-auth sent to a TPA portal, an eligibility check recorded from a phone call, a payment keyed in from a bank statement. That is a host capability that stages 3 and 4 may link to. The NHCX capability is still `absent`. + +### 3. Check + +For every capability located, run the check `SKILL.md` names, offline: + +- a builder: feed it the pin's own data and compare its output with the pin (canonical JSON, `created` excluded, and only the exclusions the module names); +- a reader: feed it the payer fixture and read the state it settles; +- a sender: call it with the 7.1 stub, or a stub of the app's own client, and read what it posted; +- the door: call the handler with an envelope; +- a screen: render it on a seeded state and read the text. + +Use the app's own test runner where it can host the check, else a one-off script under `nhcx-build/0-capability/`. Nothing leaves the machine. + +Where the existing code cannot be called without the network or a running service, record `partial` with `not run: `. Never `present`. + +### 4. Decide + +One verdict per capability, with where (the paths), how (the command), observed (the output, or the first lines of the diff), and the action: reuse, extend, build or wait. For `partial`, name the difference: which pin fails and at which element, which branch is missing (a PMJAY query answer on 19 but none on 131), which column is missing. + +### 5. When a prerequisite is missing + +A prerequisite is a capability another skill owns that this skill's legs cannot run without. `SKILL.md` lists them with their checks. If one is `absent` or `unknown`: + +1. Stop and tell the user which capability is missing, which skill owns it, and what this skill cannot do without it. +2. Offer the two ways on: run the owning skill first (installing it if it is not beside this one; it is the default); or continue with this skill's offline work only (builders, readers and tests against seeded rows), with the live legs marked `later` in stage 1 and the dependency written in `NOTES.md`. +3. Never build another skill's capability inside this one. It would be built without that skill's checks. + +A `partial` prerequisite does not stop the skill. Its gap goes into stage 2's risk table. + +## Write + +- `nhcx-build/capabilities.json` from `templates/capabilities.json`: one entry per capability, keyed by id, with `skill`, `module`, `verdict`, `located`, `how`, `observed`, `action`, `checked_by` and `date`. Update the entries this skill checked; leave the others. +- `nhcx-build/0-capability.md` from `templates/0-capability.md`: a section headed with this skill's name, holding the three tables (own, foundation, prerequisites) and the summary line. +- The scratch checks under `nhcx-build/0-capability/`, kept: stage 8 runs them again. +- This skill's block in `nhcx-build/STATE.md` (create the file from `templates/STATE.md` if it does not exist), with stage 0's row closed and its evidence. + +## Gate + +- [ ] Every capability in this skill's list, every foundation capability, and every prerequisite has a verdict. +- [ ] Every `present` names the command run and its observed output. None rests on reading alone. +- [ ] Every `partial` names the difference. +- [ ] Every `absent` names what was searched for, so a reader can repeat the search. +- [ ] A missing prerequisite was put to the user, and the answer is recorded. +- [ ] `capabilities.json` parses and holds this skill's entries. + +## Common mistakes + +- Marking a capability present because its endpoint name appears in the code. The pin decides. +- Rebuilding a working NHCX transport or callback door because this skill did not write it. An app that already seals, sends and receives NHCX messages keeps its own; the verdict says reuse. +- Proposing nhcx-adapter for an app that lacks a transport. The transport is then `own`; the adapter is used only when the user asks for it. +- Treating a legacy TPA workflow as the NHCX capability. It is a host capability; the NHCX one is absent. +- Checking against the live sandbox. Stage 0 is offline; the live rungs are stage 10's, and the user's. +- Carrying another skill's verdict forward after the code changed. diff --git a/plugins/nhcx/skills/nhcx-payment/stages/1-idea.md b/plugins/nhcx/skills/nhcx-payment/stages/1-idea.md new file mode 100644 index 000000000..b9f391316 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-payment/stages/1-idea.md @@ -0,0 +1,80 @@ +# Stage 1: the idea + +Purpose: agree with the user what is being built before anything is designed. One page, shared by the seven skills. Wrong answers here cost the most later, so this is the one stage that always ends with a question to the user when it is first written. + +The first skill to reach this stage writes `1-idea.md` whole: the mode, the payers, the constraints, and a scope row for every step of the flow, each naming the skill that owns it. A later skill reads the page, confirms that the mode and the payers still hold, and marks its own rows. It asks the user only when it would change a row or an answer. + +## Inputs + +- This skill's section of `nhcx-build/0-capability.md`: what the app already does. A leg found present is still in scope: it is validated and tested, not rebuilt. Say so in the scope table's reason column. A prerequisite the user chose to wait for makes this skill's live legs `later`. +- `flow/FLOW.md`, whole. The build walks this path; the scope table below marks its steps in, later or out, and nothing else. `flow/flow.json` names the skills of each step in `skills`. +- What the user said. If they pasted a brief, quote it in the artefact. +- `references/flow-knowledge.md` sections 1, 3 and 6: the legs, the two payer kinds, the use-case catalogue. Read them so the scope table below uses the catalogue's codes. + +## Do + +Decide five things, in this order. A later skill confirms the first two and the fourth, and does the third for its own rows. + +### 1. Mode + +| Signal | Mode | +| --- | --- | +| A codebase, a database, a running system is named | `integrate` | +| "from scratch", "standalone", "a claims app", no existing system | `standalone` | +| Unclear | Ask. Do not guess; the two modes diverge at stage 3. | + +### 2. Payers + +Which participant codes the software will talk to, and which kind each is: + +| Payer | Participant code | Kind | Query mode | +| --- | --- | --- | --- | +| PMJAY (SHA Himachal Pradesh, sandbox) | `1518@hcx` | scheme | `resubmit` | +| A generic sandbox payer you can drive, for testing | from the participant registry | generic | `communication` | +| Any other insurer | from the registry | generic unless told otherwise | `communication` | + +Both kinds are in scope by default. A build that targets only one still keeps the payer adapter switch (module 7.11), because the second is one config line away. + +### 3. Scope of legs + +Copy the steps of `flow/flow.json` (F1 to F13 with their branches) into a scope table, with the skill that owns each (`skills`), and mark each `in`, `later` or `out`, with a reason; add the catalogue code from `flow-knowledge.md` section 6 beside each. The default scope for a first release is every hospital-side leg in `flow-knowledge.md` section 1. Cutting a leg is the user's call; propose it, do not decide it. Legs that are commonly `later`: predetermination, status enquiry (PMJAY refuses it), release of a shortfall (out of reach on the sandbox). + +A later skill changes only its own rows. + +### 4. Constraints + +Ask the codebase, not the user, where you can: + +- Language and framework (integrate: whatever the HMIS uses; standalone: Python standard library unless the user names another, because the module files' pseudo code maps onto it directly). +- The transport (`references/transport-knowledge.md` section 1): `existing` when stage 0 found the app already speaks NHCX; else `own`, built into the app from NHA's protocol; `adapter` (nhcx-adapter) only when the user has asked for it, their words quoted. Never propose the adapter. +- The inbound path. For `own`: a public HTTPS domain in India, registered as the participant's `endpoint_url` and reachable from the exchange. For `existing`: the app's own callback. For `adapter`: whether the app can receive the adapter's POST; if not, polling the adapter's ledger is the only inbound path. Write it down now. +- What onboarding needs from the user: the ABDM sandbox client id and secret (Milestone 1), the facility's HFR id, and a participant record carrying the build's certificate and callback address. +- Document storage: blob, filesystem, object store. +- Whether a background worker exists. Without one, polls happen on the request path. +- Anything the user forbids: new dependencies, schema changes to existing tables, a build step. + +### 5. Definition of done + +Write the compliance points from `core/LADDER.md` as they apply to this build, and the highest rung of the test pyramid the user wants climbed before handover (`references/testing-knowledge.md` section 1). The offline rung is never optional. + +## Write + +`nhcx-build/1-idea.md` from `templates/1-idea.md`. Keep the headings. Under two pages. A later skill edits only its scope rows and adds a line under "Agreed". + +## Gate + +- [ ] Mode is `integrate` or `standalone`, and the reason is one sentence. +- [ ] Every payer has a participant code and a query mode. +- [ ] The scope table has every step of the flow and every catalogue row, each with its skill, marked in, later or out. +- [ ] Constraints name the language, the transport (existing, own, or nhcx-adapter because the user asked for it), the inbound path and the document store. +- [ ] Definition of done names the target rung. +- [ ] The user has read the page and agreed, or a written brief stands in for the user. A later skill that changed nothing records that it confirmed the page. + +Record the gate in the Shared block of `nhcx-build/STATE.md`. + +## Common mistakes + +- Choosing `standalone` because the HMIS is unfamiliar. Unfamiliar is what stage 3 is for. +- Leaving PMJAY out because the user only named an insurer. PMJAY is the payer that refuses most; a build that handles it handles the rest. +- Dropping a leg from scope because stage 0 found it present. It stays in: present capabilities are validated and tested. +- Writing design here. Tables, screens and modules belong to stages 4 to 6. diff --git a/plugins/nhcx/skills/nhcx-payment/stages/10-run-tests.md b/plugins/nhcx/skills/nhcx-payment/stages/10-run-tests.md new file mode 100644 index 000000000..e7e5d8d32 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-payment/stages/10-run-tests.md @@ -0,0 +1,59 @@ +# Stage 10: run the tests + +Purpose: climb the pyramid as far as the user asked in stage 1, for this skill's rows, and record every rung honestly. Rung 1 you run yourself. Rungs 2 to 4 need services or live payers, and only the user starts those. + +## Inputs + +- `nhcx-build/1-idea.md` (the target rung), `nhcx-build/9-tests.md` (the run command, this skill's rows) +- This skill's `SKILL.md`: its stage 10 row (which matrix rows each rung walks) +- `references/testing-knowledge.md` sections 1, 5 and 6 +- `references/errors-and-debugging.md` sections 4 to 8 (reading the ledger, sandbox pace) + +## The rungs + +| Rung | What | Who starts it | Record | +| --- | --- | --- | --- | +| 1 Offline | The suite from stage 9, against the pins and fixtures, no network | you | the full output | +| 2 Validator | The HL7 FHIR validator on every bundle this skill builds, run as `references/fhir-knowledge.md` section 11 says | you, if Java and the validator are installed | one table: bundle, errors, warnings | +| 3 Generic payer | The transport on the sandbox (the app's own, or nhcx-adapter when the user chose it) and a generic sandbox payer whose desk you can drive; this skill's legs, every query as a CommunicationRequest, payment from its desk | the user | the ledger thread per leg, the state address after each | +| 4 PMJAY sandbox | SHA Himachal Pradesh, `1518@hcx`; sweep live pre-auths first; one request at a time per case, 30 seconds between; decisions on the payer service desk | the user | the ledger, the archive folder, every refusal verbatim | + +## Do + +### Rung 1 + +Run the command from `nhcx-build/9-tests.md`: the whole suite, not only this skill's tests, because a skill that extended a shared module can break another skill's test. Save the whole output to `nhcx-build/10-test-run/-rung1.log`. In `integrate` mode also run the HMIS's own suite and save it. A failure goes back to stage 7 (the module) or stage 9 (the test); record the fix and the re-run. Do not edit a test to make it pass unless the test was wrong, and say so. + +### Rung 2 + +If the validator runs, validate every bundle this skill's tests built (write them to a folder from the tests). Warnings are advice; the sandbox accepted every pin as it stands. Errors are findings. If it does not run, write `not run` and why. + +### Rungs 3 and 4 + +Prepare, do not run: + +1. The commands the user runs: the HMIS with its public callback (`own` or `existing`), nhcx-adapter with its filled config only when the user chose it, and the payer (rung 3). For `own`, the sandbox's dummy payer proves the loop first (`references/transport-knowledge.md` section 3.11). Write them into this skill's section of `nhcx-build/10-test-run.md` under "Runbook". +2. The driver: a script or a spec that walks this skill's matrix rows through the JSON state address, waiting on the case's own state and never on a fixed sleep, logging every verdict the payer gives. The earlier legs a row needs (an eligible case, an approved pre-auth) are reached by the earlier skills' drivers or through the app's own screens. +3. The sweep for rung 4: cancel or let expire every live pre-auth for the beneficiaries the tests use (PAYR-1238 otherwise). +4. Then stop and ask the user to start the services. When they have, run the driver, save its log, and package the run's bundles by correlation id from the per-case archive (or the adapter's ledger, when it is the transport). + +While a live run is going: one request at a time per case; wait about 30 seconds after a decision; on "Active instance found" wait and resend up to three times; on a refusal read the ledger thread before touching the code. + +## Write + +This skill's section of `nhcx-build/10-test-run.md` from `templates/10-test-run.md`: per rung, `passed`, `failed`, `not run` with the reason, the log path, and the findings (each a line: what, where, the PAYR or rule, the fix or the open question). The raw logs under `nhcx-build/10-test-run/`, named for the skill. + +## Gate + +- [ ] This skill's rung 1 log exists and shows every test in the suite passing, or the failures are listed as findings with a stage to return to. +- [ ] In `integrate` mode the HMIS's own suite log exists and passes. +- [ ] Rung 2 has a table or `not run` with a reason. +- [ ] Rungs 3 and 4 have a runbook and a driver for this skill's rows, and either a log or `not run: user has not started the services`. +- [ ] No rung is marked passed without a log. + +## Common mistakes + +- Starting a service yourself: the app's public callback, or nhcx-adapter. Only the user does. +- Running only this skill's tests at rung 1. A shared module may have broken another skill's. +- Sleeping a fixed time in a driver. Wait on the state address. +- Reading a refusal as a code bug before reading the ledger thread. Half of them are scheme rules (flow-knowledge section 5). diff --git a/plugins/nhcx/skills/nhcx-payment/stages/11-build-report.md b/plugins/nhcx/skills/nhcx-payment/stages/11-build-report.md new file mode 100644 index 000000000..4ea8a0806 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-payment/stages/11-build-report.md @@ -0,0 +1,64 @@ +# Stage 11: the report + +Purpose: one document a stranger can pick up to know what was built, what was found already there, what was proven, what was not, and what to do next. Written from the artefacts in `nhcx-build/`, not from memory. Its value is its honesty. + +`11-report.md` has a summary across the skills at the top and one section per skill below it. This skill writes its section and updates its row of the summary. + +## Inputs + +- Everything in `nhcx-build/`, `STATE.md` first, `NOTES.md` last +- This skill's sections of `0-capability.md`, `8-validation.md` and `10-test-run.md` + +## Do + +### 1. Read STATE.md + +Every gate row in this skill's block, and the foundation rows it built, with their evidence. A gate without evidence is reported as open, whatever you remember. + +### 2. Write this skill's section + +From `templates/11-report.md`, in this order: + +| Section | Holds | +| --- | --- | +| Capabilities | Every capability in this skill's section of `0-capability.md`: its verdict at stage 0, what was done (reused, extended, built), and its evidence after stage 8 | +| What was built | Each module part this skill built or extended, with its files and its record (`7-modules/7.N.md`) | +| Compliance | The seven points from `core/LADDER.md` for this skill's legs, each with the evidence path (the pin comparisons, the door tests, the screen tests, the rung logs) | +| The test pyramid | Per rung: passed, failed, not run, the log | +| Findings | Every failure from stages 8 and 10 with its resolution or its open state | +| Gaps | This skill's entries in `NOTES.md` folded in: what the skills did not say, what the docs did not say, what the sandbox did that no document states | +| Exceptions | Every accepted exception from stage 8 and the user's agreement | +| Runbook | How to start it, how to run the suite, how to run rungs 3 and 4, what to sweep first, where the archive and the ledger are | +| Next | The `later` legs from stage 1, the open gates, the rungs not climbed, and the skill to run next in the order `core/LADDER.md` gives | + +Then update this skill's row in the summary table: stages closed, rung reached, what it reused, extended and built, what is open. Mode, payers and "today a user can" are for the whole build; bring them up to date. + +### 3. Check the report against the rules + +- Every claim of "passes" has a log or a record path beside it. +- Every rung not run says so. +- Every capability reported as reused has its stage 8 evidence, not only stage 0's. +- No em dashes, short sentences, tables for facts. +- A stranger with this report and the target project could resume at the first open gate. + +## Write + +This skill's section of `nhcx-build/11-report.md`, and its summary row. Update `STATE.md` with the final gate. + +## Gate + +- [ ] Every section in the template is present in this skill's section. +- [ ] Every capability in this skill's section of `0-capability.md` appears under Capabilities. +- [ ] Every module part this skill touched appears in "What was built" or, if reused, under Capabilities. +- [ ] Every compliance point names evidence. +- [ ] The pyramid table matches this skill's section of `10-test-run.md`. +- [ ] This skill's entries in `NOTES.md` are folded into "Gaps" in full. +- [ ] The runbook has the start commands, the test command and the sweep. +- [ ] The summary table has this skill's row. + +## Common mistakes + +- Reporting the rung the user asked for as reached because the offline rung passed. +- Reporting a reused capability as working on the strength of stage 0 alone. +- Dropping a finding that was fixed. Fixed findings are the most useful part of the report for the next build. +- Writing the report before stage 10's logs exist. diff --git a/plugins/nhcx/skills/nhcx-payment/stages/2-planning.md b/plugins/nhcx/skills/nhcx-payment/stages/2-planning.md new file mode 100644 index 000000000..06c405cdc --- /dev/null +++ b/plugins/nhcx/skills/nhcx-payment/stages/2-planning.md @@ -0,0 +1,67 @@ +# Stage 2: planning + +Purpose: turn the idea and the capability check into this skill's schedule of gates, and add its block to the ledger every later stage writes to. This is bookkeeping, and it is short. + +## Inputs + +- `nhcx-build/1-idea.md` +- This skill's section of `nhcx-build/0-capability.md`: the verdict of every capability it owns or stands on +- `core/LADDER.md`, "The ladder"; this skill's `SKILL.md`, "The ladder, for this skill" +- `references/testing-knowledge.md` section 1 (the pyramid) and section 3 (the matrix), so the acceptance tests below are the matrix's rows and not invented ones + +## Do + +### 1. Size each stage + +For every stage 3 to 11, write one row for this skill: what it produces for this build, how big it is (small, medium, large), and what proves it done. "What proves it done" is the stage's gate, restated for this skill. + +For stage 7, list the modules this skill's `SKILL.md` names and the foundation modules, each with its verdict from stage 0 turned into an action: + +| Verdict | Action in stage 7 | +| --- | --- | +| `present` | reuse: nothing built; validated in stage 8, tested in stage 9 | +| `partial` | extend: the difference, in the existing code | +| `absent`, `unknown` | build | +| `not applicable` | nothing | + +Module 7.13 depends on the mode: + +| Module | integrate | standalone | +| --- | --- | --- | +| 7.1 to 7.12 | yes | yes | +| 7.13 standalone shell | no | yes | + +Module 7.12 (screens) is smaller in `integrate` mode when the HMIS already has patients, admissions and documents; the plan says which existing screens gain a panel and which are new. + +### 2. Order and dependencies + +The ladder is sequential by stage. Inside stage 7, foundation modules come first, then this skill's modules in the order of `stages/7-write-code/README.md`; the plan may not reorder them, because each module's validation assumes the ones before it exist. + +### 3. Risks + +Copy into a risk table the rules from `references/flow-knowledge.md` section 5 that touch this skill's legs; its `SKILL.md` names them in its stage 2 row. Each rule is a way the build fails live even when the offline tests pass. When this skill builds or extends a foundation module, add the foundation's rules too: acknowledge or lose the thread; one message is taken once (dedupe on `x-hcx-api_call_id`). Add every `partial` prerequisite from stage 0, and the build's own risks: a missing HPIN on the practitioner table, no inbound route to the HMIS, a plan master too large for the database column, a callback behind auth middleware. + +### 4. What the user must do + +List every point where the ladder stops for the user: agreeing stage 1, running an owning skill first when a prerequisite is missing, supplying participant credentials (the ABDM client id and secret), registering the participant's certificate and callback address, starting the services for stage 10 rungs 3 and 4 (the app's public callback, or nhcx-adapter when the user chose it), sweeping live pre-auths before a PMJAY run. + +## Write + +- This skill's section of `nhcx-build/2-planning.md`, from `templates/2-planning.md`. +- This skill's block in `nhcx-build/STATE.md` (created at stage 0 from `templates/STATE.md`), with a row per stage and a row per module part, each module row carrying its action. +- `nhcx-build/NOTES.md`, empty but for its heading, if it does not exist. + +## Gate + +- [ ] Every stage 3 to 11 has a row with a size and a proof, for this skill. +- [ ] Every module this skill touches, and every foundation module, has its verdict and its action; 7.13 is marked by mode. +- [ ] The risk table holds every rule this skill's `SKILL.md` names for stage 2, and the foundation's rules when this skill builds or extends a foundation module. +- [ ] The user-action list names the credentials and the service starts. +- [ ] STATE.md has this skill's block with a row per stage and per module part. + +## Common mistakes + +- Estimating in days. Estimate in size; the user turns size into time. +- Planning to skip stage 8 or 9 "for the first pass". They are what makes the report true. +- Planning to rebuild a capability stage 0 found present. +- Reordering modules so screens come first. Screens derive from messages; without readers there is nothing to derive from. diff --git a/plugins/nhcx/skills/nhcx-payment/stages/3-discovery.md b/plugins/nhcx/skills/nhcx-payment/stages/3-discovery.md new file mode 100644 index 000000000..9feb26eca --- /dev/null +++ b/plugins/nhcx/skills/nhcx-payment/stages/3-discovery.md @@ -0,0 +1,97 @@ +# Stage 3: discovery + +Purpose: find the surface you will build on. In `integrate` mode that is the HMIS; in `standalone` mode it is the runtime, the storage and the deployment target the user has chosen. Every answer names the file, table or endpoint that proves it. An answer without proof is a gap. + +`3-discovery.md` is shared by the seven skills: one row per concern, each naming the skill that answered it. This skill answers the rows its `SKILL.md` lists under "Host facts", and the framework and runtime rows if no skill has. A row an earlier skill answered with proof is reused; check it again only if the code changed since. + +Stage 0 looked for NHCX capabilities. This stage looks at the host: where patients, admissions, doctors, documents and bills live. + +## Inputs + +- `nhcx-build/1-idea.md`, `nhcx-build/2-planning.md`, this skill's section of `nhcx-build/0-capability.md` +- This skill's `SKILL.md`, "Host facts" +- The target codebase (integrate) or the chosen runtime (standalone) +- `stages/7-write-code/7.2-storage.md` (the claim tables) and `stages/7-write-code/7.13-standalone-shell.md` (patient, encounter, practitioner, document), as the shape to compare against + +## Do + +Answer in writing every question below that this skill's host facts name, plus the framework and runtime questions when they are not yet answered. Reading only; change nothing. + +### Framework and runtime + +| Question | Why it matters | +| --- | --- | +| Language, web framework, ORM, database engine, migration tool | Where a new table goes and how it is created | +| How configuration is read (env, file, database) | Where the transport's settings live: the participant code, and the client id and secret and the private key (`own`), or the adapter URL and key (`adapter`) | +| How the app exposes an HTTP endpoint an outside process can POST to; which auth middleware must be exempted | The callback door, module 7.3 | +| Background worker or scheduler, or none | Whether polls run on the request path or in a worker | +| How the app serves a page and what the screen conventions are | Module 7.12 must match them | +| How tests are run and where they live | Stage 9 must match them | + +### Patients + +| Question | Why it matters | +| --- | --- | +| The patient table, its primary key, the unique identifier (MRN) | `claim.patient_id` | +| Where name, gender, date of birth, phone, ABHA number live | The Patient resource in every bundle | +| Where a scheme member id (PMJAY id) and a policy code can be stored, per patient or per visit | The Coverage resource; the policy search result | + +### Admissions and encounters + +| Question | Why it matters | +| --- | --- | +| The inpatient encounter table: admission time, discharge time, ward or bed, admitting doctor, status | `billablePeriod`, `ONS/ADDD`, the care team | +| How discharge is recorded, and whether it can carry a mode (normal, LAMA, DAMA, death) and a stage (before, during, after surgery) | `DIS` and `DSDE` on the claim; the LM100 collapse | +| Diagnoses: SNOMED, ICD-10 or free text | The payer needs ICD-10 with a display | +| Procedures or surgeries, and whether a surgery time is recorded | `ONS/PSP` | + +### Billing + +| Question | Why it matters | +| --- | --- | +| Billing lines: code, quantity, unit price, net; which charge master | Lines are quoted from the payer's plan, not the HMIS master, but the two must be reconcilable | +| Whether a line can be tagged with a payer package code and a category | `claim_line` | +| Invoices and receipts: where a settlement amount and a UTR go | Payment notices, module 7.10 | + +### Documents + +| Question | Why it matters | +| --- | --- | +| Where PDFs and images live (blob column, filesystem, object store) | `valueAttachment` needs the bytes and the content type | +| Whether a file can be tagged with a payer document code and a stage (pre-auth or claim) | The plan's requirement codes; never `ODN` for a file that was asked for by name | +| Accepted content types | The scheme takes pdf, jpg, jpeg, png only (PAYR-1008) | + +### Doctors + +| Question | Why it matters | +| --- | --- | +| The practitioner table; an HPR id (HPIN); a licence number; a qualification string | PMJAY refuses a pre-auth without an HPIN typed identifier (PAYR-1083) | + +### Facility + +| Question | Why it matters | +| --- | --- | +| The facility's HFR id, name, phone; its NHCX participant code | The provider Organization; the sender code | + +### Standalone mode + +The same questions, answered for the runtime the user chose. Where the answer is "nothing exists yet", write what module 7.13 will create: `patient`, `encounter`, `practitioner`, `document`, `settings`. A standalone app still has to hold every fact the questions ask for; it simply has to capture it itself. + +## Write + +`nhcx-build/3-discovery.md` from `templates/3-discovery.md`: one table, concern by concern, columns `Concern | Where it lives (proof) | Gap | Answered by`. A gap is what stage 4 fills. Add rows; do not rewrite another skill's rows. + +## Gate + +- [ ] Every host fact this skill's `SKILL.md` names has a row, and so does every framework and runtime question. +- [ ] Every row that is not a gap names a file path, a table, or an endpoint. +- [ ] When this skill builds or extends the callback door, the callback route is answered: which URL, which middleware to exempt, or "no inbound route, poll only". +- [ ] When this skill's bundles carry a Practitioner, the HPIN question is answered; if the practitioner table has no HPR id, the gap says so. +- [ ] When this skill attaches documents, the document store is answered with content-type handling. + +## Common mistakes + +- Answering from the framework's documentation instead of the codebase. The proof column is the codebase. +- Skipping the discharge-mode question. A death claim without `DTM` is refused (PAYR-1096); the HMIS must be able to say the patient died and when. +- Treating "no background worker" as a blocker. Without one, polls run on the request path; it is a design input, not a stop. +- Answering every concern for every skill. Answer the ones this skill needs; the next skill adds its own. diff --git a/plugins/nhcx/skills/nhcx-payment/stages/4-flow-and-data-mapping.md b/plugins/nhcx/skills/nhcx-payment/stages/4-flow-and-data-mapping.md new file mode 100644 index 000000000..bf51c7991 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-payment/stages/4-flow-and-data-mapping.md @@ -0,0 +1,92 @@ +# Stage 4: flow and data mapping + +Purpose: decide where every fact the exchange needs comes from and where every fact the exchange returns goes, leg by leg. This is the design stage with the most rows; get it right and stages 6 and 7 are transcription. + +Two parts of this stage belong to the episode, not to one skill: the flow table (section 1) and the home of every table (section 2), with the matching order (section 4). The first skill to run this stage writes them whole, so every later skill builds on one design; a later skill checks them and adds only what its gaps need. The field mapping (section 3) is this skill's own bundles only. + +## Inputs + +- `nhcx-build/1-idea.md` (scope), `nhcx-build/3-discovery.md` (the surface and its gaps), this skill's section of `nhcx-build/0-capability.md` (what exists already) +- This skill's `SKILL.md`: its steps, legs, bundles and tables +- `flow/FLOW.md` and `flow/flow.json`: the steps this build implements. They are copied, not redesigned. +- `references/flow-knowledge.md` sections 1, 2, 4 and 5 +- `references/transport-knowledge.md` section 2 (what a send returns, what arrives at the door) +- `references/fhir-knowledge.md` sections 3 to 10 (what each bundle needs); `fhir/FHIR.md` for the exact elements, as the builders' data dictionaries name them +- `stages/7-write-code/7.2-storage.md`: the claim tables and the columns each must hold + +## Do + +### 1. The flow, for this build + +The first skill copies every step of `flow/flow.json` into the flow table, in order, with its id and its skills, and adds two columns for this build: the HMIS event it hangs off (admission, discharge, a desk action) and the mark from stage 1 (`in`, `later`, `out`). The steps, their order, their tabs, their guards and their action labels are the flow's; this build adds where each fact comes from, nothing else. Then note the payer branches as the flow has them (F9b, F11, F12: `19`/`131`/`161` resubmits against a Communication reply; `17` against an echoed id). The stage and sub-stage vocabulary is copied as is; do not rename it. + +Write the step ids into `mapping.json` under `flow.steps` and the eight tabs, in order and with their labels, under `flow.tabs`. + +A later skill checks its own steps' rows and fills their HMIS event where the first skill left it open. + +### 2. The episode tables + +The first skill gives every table below a home, not only its own. The home is one decision for the episode (sidecar tables, or columns on the HMIS's tables), and a skill that chose differently later would split the design. It writes the columns each table must hold, and the legs' columns under `legs`. Later skills read the homes and add only the columns their gaps need. + +For each table below, decide one of three homes and write it down: + +| Home | When | +| --- | --- | +| A new sidecar table keyed on the HMIS's own ids | Default. Keeps the HMIS schema untouched and the integration removable. | +| Columns added to an existing HMIS table | Only for a scalar the HMIS already half-holds (a member id on the visit, an HPIN on the doctor) | +| An existing table used as is (`existing`) | Only when it already holds every column named below. This is the home of a capability stage 0 found present: record its real name and its columns, and a gap for each column it lacks | + +| Table | Why it exists | Must hold | +| --- | --- | --- | +| `claim` | The episode: beneficiary, policy, payer, eligibility verdict, link to the admission, pre-auth draft, stage and sub-stage | claim number, member id, policy code, payer participant code, patient and encounter keys, `txn_id`, `correlation_id`, `stage`, `sub_stage` | +| `claim_plan`, `claim_plan_benefit`, `claim_plan_form` | The payer's package master, flattened; one per facility and policy, copied onto later episodes | packages with rate, kind, conditions, extras (tiers, implants), document requirements; questionnaires by url | +| `claim_auth`, `claim_auth_item`, `claim_auth_requirement` | The auth-requirements ruling on the quoted set | per line: authorised, excluded; per requirement: kind (document or form), code, url, stage | +| `claim_line` | What is quoted: procedures, implants, ward tiers with a parent procedure | code, kind, quantity, unit price, amount, parent code | +| `claim_form_answer` | Answers to the plan's questionnaires | url, linkId, answer, stage | +| `claim_preauth` | The pre-auth leg, one row rewritten each round (12, 19, 13, 131) | status, `txn_id`, `correlation_id`, `thread_correlation_id`, `api_call_id`, `preauth_ref`, `submission_kind`, `workflow_id`, request and response json, cancel fields | +| `claim_submission` | The claim leg plus the discharge | discharge mode, stage, dates; the same exchange columns as the pre-auth | +| `claim_query` | Every CommunicationRequest or Communication from the payer, classified | `correlation_id` (unique), request id, kind, reason code, status, reply fields | +| `claim_payment`, `claim_payment_detail` | Payment notices, matched by claim number, deduped by correlation id | amount, UTR, payment status, ack fields | +| `claim_enquiry` | Status, reprocess and release Tasks, one row per ask | kind, `correlation_id`, answer | +| `claim_predetermination` | A quote, one row per ask | as a pre-auth, without state effects | +| `claim_document` | Attachments with the payer's code, category and stage | bytes or a pointer, content type, code, stage | +| `claim_diagnosis`, `claim_care_team`, `claim_item` | ICD-10 codes, doctors, non-package items | as named | + +The rule that never bends: every leg row holds `txn_id`, `correlation_id` and `api_call_id` from the transport's answer, and `thread_correlation_id` separately, because a send refused at the door must not lose the thread the payer last answered on. + +### 3. Field mapping, per bundle + +For each bundle this skill sends (its `SKILL.md` lists them; `fhir-knowledge.md` sections 3, 4, 5, 7, 9, 10), one table: `FHIR element | Source (table.column or constant or payer answer) | Transform | Gap`. Do not fill values; name sources. The elements that are always mapped from a payer answer and never from the HMIS: package codes and rates (the plan), document codes and questionnaire urls (the plan or the ruling), `preAuthRef` (the ClaimResponse), the payer's own case number. + +For each bundle this skill reads (sections 6, 8, 9, 10 and the coverage answer in section 3), one table: `FHIR element | Destination | Rule`. The status rule for a ClaimResponse is `verdict_status`, copied verbatim; never read `outcome` alone. + +Where stage 0 found a builder or reader present, map what it does today, and name each element where it differs from the pin as a gap. + +### 4. Inbound matching + +Written once, by the first skill. Write the matching order as a numbered list: `x-hcx-correlation_id` against every leg table; then the claim number inside the bundle; then unmatched, archived, 2xx returned. Write the dedupe key: `x-hcx-api_call_id`. Write the archive path: `//NNN--.json` plus `transactions.txt`. A later skill adds its leg tables to the correlation order. + +## Write + +- `nhcx-build/4-flow-data-mapping.md` from `templates/4-flow-data-mapping.md`. The first skill writes the flow table, the table homes and the matching order at the top; each skill writes a section headed with its name holding its field mappings. +- `nhcx-build/mapping.json` in the shape of `templates/mapping.json`. The first skill writes `flow`, `episode`, `tables`, `legs` and `inbound` whole; every skill adds its bundles under `bundles`, each entry with `"skill"`. Stage 6 reads it. + +## Gate + +- [ ] The flow table has every step of `flow/flow.json`, in its order, with its id, its skills and an in/later/out mark; `mapping.json` `flow.steps` lists every id and `flow.tabs` the eight tabs verbatim. +- [ ] Every table above has a home in `mapping.json` under `tables`. +- [ ] Every leg table's columns in `mapping.json` include `txn_id`, `correlation_id`, `api_call_id` and `thread_correlation_id`. +- [ ] `mapping.json` `episode.columns` includes `stage` and `sub_stage`. +- [ ] Every bundle this skill sends has a source table; every element with no source is listed as a gap, not omitted. +- [ ] Where this skill's bundles carry a Practitioner, the HPIN element's source is named (or its gap is). +- [ ] Every capability stage 0 found present is mapped to what exists, with its differences from the pin as gaps. +- [ ] The matching order, the dedupe key and the archive path are written. + +## Common mistakes + +- Redesigning the flow: merging tabs, adding a "status" step, moving the discharge out of the claim tab. The flow is the reference flow; copy it. +- Giving homes only to this skill's tables when it is the first to run the stage. The next skill would choose differently. +- Mapping package rates to the HMIS charge master. Prices come from the plan; the master is for reconciliation. +- One `correlation_id` column on the episode instead of one per leg. Each leg is its own thread. +- Forgetting `thread_correlation_id`. It is the difference between a recoverable door refusal and a dead case. +- Mapping `Patient` demographics on the coverage request. Only the member id goes out; the payer returns the rest. diff --git a/plugins/nhcx/skills/nhcx-payment/stages/5-screen-plan.md b/plugins/nhcx/skills/nhcx-payment/stages/5-screen-plan.md new file mode 100644 index 000000000..9ec0d8bc2 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-payment/stages/5-screen-plan.md @@ -0,0 +1,74 @@ +# Stage 5: screen plan + +Purpose: decide the screens, and for every value on every screen, the received message it is derived from. The two honesty rules are the whole point of this stage, and a reviewer tests them before anything else. + +The case screen is the episode's (`foundation.screens`): its eight tabs, the status line and actions, the JSON state address and the cases list. The first skill to run this stage lays them out whole, every tab present with its opening condition. Each skill then plans the values and actions of its own tabs and screens, which its `SKILL.md` lists. + +## Inputs + +- `nhcx-build/1-idea.md`, `nhcx-build/3-discovery.md` (screen conventions), `nhcx-build/4-flow-data-mapping.md` +- This skill's `SKILL.md`: its tabs, its screens, its next actions +- `flow/FLOW.md` ("The shape", "The status line and the actions", every step's Screen line) and `flow/flow.json`: the screens are put on these steps, not invented. +- `references/flow-knowledge.md` section 4 (stage, sub-stage, next actions) +- `ui/UI-GUIDE.md`: the screens, a layout per screen, where every value comes from, the state words. Read it whole before planning. +- `nhcx-package/docs/03-Building a Provider/09-UI Guide.md` (the published source of the guide) + +## The two rules + +1. No screen shows a decision the exchange has not sent. Every state on every screen is derived from a stored message. A case with a request sent and no answer back reads as waiting, never approved, never rejected. That case exists only because module 7.3 kept a record of what was sent, so the screen must be able to render a leg with a request and no response. +2. Nothing the exchange already knows is typed. Payer names, policies, balances, package rates, the payer's own wording, `preAuthRef`, the approved amount, the UTR are rendered from the message that carried them. A package rate is never an editable field. + +## Do + +### 1. The screen list + +The case screen carries the eight tabs of `flow.json` `tabs`, in that order, with those labels, opening under those conditions. The status line and the action list above the tabs use the labels of `flow.json` `next_actions` verbatim. Then, minimum, once every skill has run: + +| Screen | Who | Shows | Derived from | Planned by | +| --- | --- | --- | --- | --- | +| Cases list | billing clerk | every episode, its stage and sub-stage, what it waits for | `claim.stage`, `sub_stage`, `next_actions` | the first skill | +| Case | everyone | the timeline of legs, the payer's answer verbatim, the actions open now | every leg row and its archived messages | the first skill; each skill its tabs | +| Inbox | desk | payer messages routed by kind: query, notification, note | `claim_query` | `nhcx-communication` | +| Payments | accounts | notices, deductions, UTR, reconciliation | `claim_payment`, `claim_payment_detail` | `nhcx-payment` | +| Find and cover | registration clerk | policy search, eligibility verdict, register or link | the policy search answer and the `on_check` bundle | `nhcx-coverage` | +| Plan | doctor | specialty, package, add-ons, tiers, the documents and forms the plan wants | `claim_plan_*`, `claim_auth_*` | `nhcx-insurance`, with the ruling from `nhcx-preauth` | + +`integrate` mode adds a panel to the HMIS's own admission screen linking the admission to its episode. `standalone` mode adds the capture screens module 7.13 describes (patient, admission, discharge, documents, settings). + +Where stage 0 found a screen present, plan what it shows today against the rules, and list every value that breaks one as a gap. + +### 2. Per screen, per value + +For every value on this skill's screens, one row: `Value | Message and element | Empty state`. The empty state is what the screen shows before the message arrives (for a decision: "waiting"; for a rate: nothing, the field does not exist yet). A value whose source is "the user types it" is allowed only for things the exchange cannot know: the discharge mode and dates, the desk's reply to a query, the documents, the questionnaire answers, the chosen lines. + +### 3. Actions + +Every action is one step of `flow.json` and carries its id in `step`. For every action this skill's screens offer, the leg it sends, the sub-stage that must hold for it to be offered, and the sub-stage it moves to. Take the offered-when rules from `next_actions` in flow-knowledge section 4: an unanswered query always leads; the reply box is offered only to a `resubmit` payer; after a rejection the pre-auth offers a fresh 12, not 121. + +### 4. Addresses and conventions + +Write the route for each screen in the HMIS's own style (from stage 3). The state of a case must also be readable as JSON at one address, because stage 10 drives the screens through it (for example `GET /claims//state`). Each skill adds its legs to what the address returns. + +## Write + +- `nhcx-build/5-screen-plan.md` from `templates/5-screen-plan.md`: the shell at the top (first skill), then a section per skill. +- `nhcx-build/screens.json` in the shape of `templates/screens.json`: the first skill writes `rules`, `tabs`, `state_address`, the cases list and the case screen; each skill adds its screens and actions. + +## Gate + +- [ ] `screens.json` `tabs` lists the eight tabs of `flow.json` in order with the same keys and labels. +- [ ] Every user-driven step this skill owns (its steps among F1 to F13, except F9a, F12 and F12b, which the payer starts) appears as an action with its `step` id, and every action's `label` is one of `flow.json` `next_actions` or the step's own button. +- [ ] `screens.json` holds the cases list, the case screen, and every screen this skill plans, each with a route (plus 7.13's in standalone mode). +- [ ] Every screen this skill plans has a `values` list and every value names a message element or is marked `typed` with a reason from the allowed list. +- [ ] Every decision-bearing value has an empty state of waiting. +- [ ] No `values` entry marks a rate, a payer name, a `preAuthRef` or a UTR as typed. +- [ ] Every action names its leg, its offered-when sub-stage and its resulting sub-stage. +- [ ] A JSON state address exists for a case. + +## Common mistakes + +- A status dropdown on the case. Status is derived; there is no dropdown. +- Showing `preAuthRef` from the pre-auth's own claim number. It comes from the ClaimResponse. +- Designing the desk's reply box for a `communication` payer on the leg. It belongs on the inbox item. +- Laying out only this skill's tab when it is the first to run the stage. The shell has all eight. +- Screens that need JavaScript. Forms post and the page re-renders; that is enough. diff --git a/plugins/nhcx/skills/nhcx-payment/stages/6-code-plan.md b/plugins/nhcx/skills/nhcx-payment/stages/6-code-plan.md new file mode 100644 index 000000000..2167000f1 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-payment/stages/6-code-plan.md @@ -0,0 +1,68 @@ +# Stage 6: code plan + +Purpose: turn the mapping, the screen plan and the capability verdicts into a list of modules with files, dependencies, the pin each is held to, and what this skill does to each. Stage 7 builds this list in order; stage 8 validates it in order. + +The transport's shape, the configuration, the archive and the test placement (sections 2 to 5) are the episode's: the first skill to run this stage writes them, and later skills use them. + +## Inputs + +- `nhcx-build/3-discovery.md`, `nhcx-build/4-flow-data-mapping.md`, `mapping.json`, `nhcx-build/5-screen-plan.md`, `screens.json` +- This skill's section of `nhcx-build/0-capability.md` and `nhcx-build/2-planning.md` (the action per module) +- `stages/7-write-code/README.md` and every `7.N-*.md` this skill touches: the module ladder is fixed; the plan decides the files +- `references/fhir-knowledge.md` section 1: where the pins live +- `fhir/FHIR.md`: the builders and readers the modules 7.4 to 7.10 implement, so the plan names them + +## Do + +### 1. Place each module + +For each module this skill touches (its `SKILL.md` lists them) and each foundation module it builds or extends, write: + +| Field | Meaning | +| --- | --- | +| `skills` | A map from skill to action: `build`, `extend` or `reuse`. A module another skill already placed keeps its entry; add this skill and its action | +| `files` | The files it creates or changes, in the target's layout and naming (from stage 3). For a reused or extended module, the files that exist | +| `depends_on` | The modules that must exist first; the ladder's order is the floor, the plan may add more | +| `held_to` | The pin in `nhcx-package/fhir` (its file, from `references/material.md`), the payer fixture, or the rule (for modules with no bundle) | +| `copy_from` | What the module follows: its own Pseudo code section and the `fhir/FHIR.md` section it names | +| `tables` | The tables from `mapping.json` it reads and writes | +| `screens` | The screens from `screens.json` it serves (7.12 and 7.13 only) | + +`modules.json` holds one entry per module, in ladder order (7.1 to 7.13), whichever skill adds it. + +### 2. The transport's shape + +Decide once, and every module uses it: the transport kind from stage 1, and the functions of the contract in `references/transport-knowledge.md` section 2: `send`, the receiving end that hands the door a normalised envelope, `policies`, `participants`, `token`, and `thread` and `fetch_missed` where the kind has them. Name them here so 7.4 to 7.10 call the same thing. A stub of `send`, recording the path, recipient, workflow id, correlation id and bundle and returning `{"txn_id", "correlation_id", "api_call_id"}`, is what stage 9 injects. When stage 0 found an existing transport, name its functions and what wraps them. + +### 3. Configuration + +List every setting and where it lives (from stage 3): the transport kind, participant code, facility HFR id and name, cases directory, per-payer overrides for workflow ids, and the transport's own. For `own`: the ABDM client id and secret, the private key, the sessions, NHCX and registry addresses, and the NHCX signing key once onboarding gives it. For `adapter`: its URL, API key and callback secret. For `existing`: whatever its client reads. Name the environment variables or config keys in the target's convention. + +### 4. The archive + +The per-case archive path from stage 4, and which module writes it (7.3 for inbound, 7.1 for outbound). + +### 5. Test placement + +Where the offline test lives (from stage 3's "how tests are run"), and how the pin comparison is wired: canonical JSON, `created` excluded, one comparison per pin. + +## Write + +- `nhcx-build/6-code-plan.md` from `templates/6-code-plan.md`: the episode sections once, the modules table, and this skill's section. +- `nhcx-build/modules.json` in the shape of `templates/modules.json`. + +## Gate + +- [ ] `modules.json` has an entry, in ladder order, for every module this skill touches and every foundation module (7.13 in standalone mode). +- [ ] Every entry this skill touches has non-empty `files`, `depends_on` (7.1 may be empty), `held_to` and `copy_from`, and this skill in `skills` with its action. +- [ ] Every pin this skill owns appears in some module's `held_to`. +- [ ] The transport kind and its functions are named. +- [ ] The configuration list includes the transport kind, the participant code, the cases directory, and every setting the chosen transport needs. +- [ ] The test file's location and the pin comparison rule are written. + +## Common mistakes + +- Splitting the claim bundle builder across modules by leg, or by skill. One builder, one `leg` and `flow` argument, is what the pins expect; `nhcx-claim` extends what `nhcx-preauth` built. +- Planning a second transport for the reply legs. Same function; the reply legs add `x-hcx-correlation_id` to the headers. +- Planning new files for a module stage 0 found present. +- Planning the screens before the readers exist in the dependency list. diff --git a/plugins/nhcx/skills/nhcx-payment/stages/7-write-code/7.1-config-and-transport.md b/plugins/nhcx/skills/nhcx-payment/stages/7-write-code/7.1-config-and-transport.md new file mode 100644 index 000000000..2ad046569 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-payment/stages/7-write-code/7.1-config-and-transport.md @@ -0,0 +1,131 @@ +# Module 7.1: configuration and the NHCX transport + +Purpose: the one path every message leaves by, whichever transport carries it. The settings, the transport chosen at stage 1 behind one `send`, the policy lookup, and the outbound half of the per-case archive. + +Skills: the foundation (`core/FOUNDATION.md`). Built whole by the first skill whose stage 0 finds it absent; every skill sends through it. + +## Depends on + +Nothing. First module. + +## Inputs + +- `nhcx-build/1-idea.md`: the transport, `existing`, `own`, or `adapter` because the user asked for it +- `nhcx-build/6-code-plan.md` sections 2 to 4 (the transport's functions, the configuration keys, the archive path) +- `references/transport-knowledge.md` section 2 (the contract), and section 3 (`own`), 4 (`existing`) or 5 (`adapter`) for the kind chosen +- With `adapter` only: `references/api-knowledge.md` sections 2 to 5, 7, 8 and 11 + +## Build + +### Settings + +Read from the target's configuration mechanism (stage 3). + +| Setting | Transport | Meaning | +| --- | --- | --- | +| transport kind | all | `existing`, `own` or `adapter` | +| participant code | all | The hospital's, with `@hcx`: `x-hcx-sender_code` | +| facility HFR id, name, phone | all | The provider Organization | +| cases directory | all | The per-case archive root | +| per-payer workflow id overrides | all | Optional, for a payer that insists on a code the table does not carry (`cancel` as 122) | +| ABDM client id and secret | own | The session token (`transport-knowledge.md` section 3.3) | +| private key | own | The PEM behind the certificate on the participant record, read from a file or a secret store | +| sessions, NHCX and registry addresses, `X-CM-ID` | own | From `nhcx-package/baseurl.yaml`; the sandbox by default | +| NHCX signing key | own | For the exchange's JWT on inbound calls. Empty until onboarding gives it, and logged while empty | +| adapter URL, adapter API key, callback secret | adapter | `references/api-knowledge.md` section 2. Also fill the adapter's `config.sample.json` into `nhcx-build/adapter.config.json`, secrets as `${ENV}` placeholders | +| whatever the existing client reads | existing | Named here, not duplicated | + +Secrets are read from configuration: never in code, never in `nhcx-build/`. + +### The transport + +One `send` with the signature in `transport-knowledge.md` section 2, and beside it `policies`, `participants`, `token`, `thread` and `fetch_missed`. What sits under them depends on the kind: + +| Kind | `send` | `policies`, `participants`, `token` | `thread`, `fetch_missed` | +| --- | --- | --- | --- | +| `own` | Seal and post (`transport-knowledge.md` sections 3.3 to 3.8): the token, the recipient's certificate, the protected header, a compact JWE, `{"payload"}` to `/v1/`, a `401` retried once | The participant service directly (sections 3.6 and 3.7) | `thread` reads the per-case archive; `fetch_missed` answers `unavailable` | +| `existing` | Calls the app's own client and maps its answer onto `{txn_id, correlation_id, api_call_id}` (section 4) | The app's own calls, or the participant service directly | What the app keeps; else as `own` | +| `adapter` | POSTs `{jwe_headers, fhir}` to `/fhir/out/` with the bearer key (`api-knowledge.md` sections 4 and 5) | `/internal/policies/search`, `/internal/participants/list`, `/token` | The adapter's ledger and `/internal/txn/*` (`api-knowledge.md` sections 7 and 8) | + +Common to every kind: + +1. A send without a recipient, a workflow id or the beneficiary's ABHA is refused before anything goes on the wire. +2. The recipient is the policy's processor: `recipient_of(row)` is `claim.recipient_code`, else `claim.payer_code` for an episode opened before the processor was kept. +3. A correlation id is passed only on the two answer legs, the communication reply and the payment acknowledgement. On a request the transport mints it (`own`: the message's own `api_call_id`). +4. A refusal raises `TransportError(code, message, protocol_response, retryable)`: the gateway's status and body (`own`), the adapter's `error.code` and `upstream_body` (`adapter`), or the existing client's error. A ProtocolResponse inside it is a refusal at the door; the caller records the payer's words. +5. The outbound message is archived before `send` returns: `//NNN--out.json` with what was sent and what came back, and a `transactions.txt` line (sequence, time, direction, path, workflow id, correlation id, api call id, txn id, outcome). With `own`, the archive entry is the `txn_id`. +6. The caller stores `txn_id`, `correlation_id` and `api_call_id` on the leg. + +## Rules + +- Use nhcx-adapter only when the user asked for it; `1-idea.md` records their words. Never propose it. +- Keep an existing NHCX integration and wrap it. Never put a second transport beside it. +- Seal and open JWEs only for `own`, and only with a JOSE library: `RSA-OAEP-256`, `A256GCM`, compact serialisation. Never hand-roll the cryptography. +- The workflow id goes out on every leg that has one; `x-hcx-ben-abha-id` goes out on every message. +- The sandbox refuses sends faster than one per 30 seconds per case (PAYR-1322). The transport does not throttle; the caller does. Say so in the docstring. +- The private key never leaves the server that receives callbacks, and never enters a log. + +## Validate + +- [ ] A send with no recipient, no workflow id or no beneficiary ABHA is refused before anything goes on the wire. +- [ ] The protected header of a send carries every mandatory field under the protocol's rules: sender and recipient with `@hcx`, a fresh `api_call_id`, a `correlation_id` equal to the `api_call_id` on a request and to the request's on an answer, the workflow id, `x-hcx-timestamp` in ISO 8601 with `+05:30`, `x-hcx-status` `request.initiated` or `response.complete`, and `x-hcx-ben-abha-id`. Observed on what the transport emits: the JWE header opened with a test key pair (`own`), the posted `jwe_headers` with the adapter's completion rules (`adapter`), the existing client's output (`existing`). +- [ ] The recipient is the episode's `recipient_code`, the policy's `processingid`, whenever the episode has one. +- [ ] A refusal raises `TransportError` carrying the code and the words the exchange or the adapter gave. With `own`, a `401` is retried once with a fresh token, and a second `401` raises. +- [ ] The archive file and the `transactions.txt` line exist after a send, with the sequence number zero-padded to three digits. +- [ ] Secrets are read from configuration, not present in code or in `nhcx-build/`. +- [ ] With `own`: a bundle sealed for a test certificate opens with its private key to the same bytes and the same protected header; the token is reused while fresh and fetched again when stale; a recipient's certificate is fetched once and then read from the cache. + +## Tests + +- Stub the HTTP layer and assert the URL, the headers and the body of one send with and one without a correlation id: `bearer_auth` and `{"payload"}` for `own`; the bearer key and `{jwe_headers, fhir}` for `adapter`. +- `own`: seal with a test key pair and open it again; check the header fields above; a `401` then a `202` sends twice with two tokens; a certificate in SPKI form loads as well as an X.509 one. +- `adapter`: a `502` with a ProtocolResponse `upstream_body` raises an error whose text carries the payer's `x-hcx-error_details` message; a `404` from `txn/related` is terminal, not retried. +- The archive sequence increments across two sends on one case. + +## Pseudo code + +The `own` transport's token, certificate cache, sealing and receiving end: `references/transport-knowledge.md` section 3.12. The adapter client: `references/api-knowledge.md` section 11. What every kind shares: + +``` +settings = { + transport: env("NHCX_TRANSPORT", "own"), # own | existing | adapter; adapter only when the user asked for it + participant_code: env("NHCX_PARTICIPANT_CODE"), # "@hcx" + facility: {hfr_id: env("NHCX_HFR_ID"), name: env("NHCX_FACILITY_NAME"), phone: ...}, + cases_dir: env("NHCX_CASES_DIR", "data/cases"), + workflow_overrides: parse_json(env("NHCX_WORKFLOW_IDS", "{}")), # {"1518@hcx": {"cancel": "122"}} + nhcx: {sessions: env("NHCX_SESSIONS_URL", "https://dev.abdm.gov.in/api/hiecm/gateway/v3/sessions"), # own + base: env("NHCX_BASE_URL", "https://apisbx.abdm.gov.in/hcx"), + registry: env("NHCX_REGISTRY_URL", "https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice"), + cm_id: env("NHCX_CM_ID", "sbx"), + client_id: env("NHCX_CLIENT_ID"), client_secret: env("NHCX_CLIENT_SECRET"), + private_key: read_secret(env("NHCX_PRIVATE_KEY_FILE")), signing_key: env("NHCX_SIGNING_KEY", "")}, + adapter: {url: env("NHCX_ADAPTER_URL"), api_key: env("NHCX_ADAPTER_API_KEY"), # adapter only + callback_secret: env("NHCX_CALLBACK_SECRET")}, +} + +transport = {"own": OwnTransport, "existing": ExistingTransport, "adapter": AdapterTransport}[settings.transport]() +# each offers send, policies, participants, token, thread, fetch_missed (transport-knowledge.md section 2) + +function recipient_of(row): return row.recipient_code or row.payer_code + +function ben_abha(claim_no): # the payer's Patient from the coverage answer, else the HMIS patient + row = claim_by_no(claim_no) + return digits(abha_in(row.patient_json) or patient(row.patient_id).abha) + +function with_hcx(code): return code if code.endswith("@hcx") else code + "@hcx" + +# the archive, outbound half; 7.3 writes the inbound half through the same function +function archive.record(claim_no, usecase, direction, payload): + folder = settings.cases_dir + "/" + (claim_no or "unmatched"); mkdir(folder) + n = next_sequence(folder) # 001, 002, ... + write(folder + f"/{n:03d}-{usecase}-{direction}.json", pretty(payload)) + append(folder + "/transactions.txt", f"{n:03d} {now()} {direction} {payload.path} wf={payload.workflow_id} " + f"cid={payload.correlation_id} acid={payload.api_call_id} txn={payload.txn_id} {payload.outcome}") + return f"{claim_no or 'unmatched'}/{n:03d}" +``` + +## Done when + +- Validate passes for the transport chosen. +- `own`: the onboarding the user must do is written into `nhcx-build/7-modules/7.1.md`: the credentials, the key and certificate, the participant record, the `endpoint_url`, and the NHCX signing key to ask NHA for. `adapter`: `nhcx-build/adapter.config.json` exists with placeholders. `existing`: the wrapper and every gap it closed are listed. +- `nhcx-build/7-modules/7.1.md` is written. diff --git a/plugins/nhcx/skills/nhcx-payment/stages/7-write-code/7.10-communication-and-payment.md b/plugins/nhcx/skills/nhcx-payment/stages/7-write-code/7.10-communication-and-payment.md new file mode 100644 index 000000000..271d56732 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-payment/stages/7-write-code/7.10-communication-and-payment.md @@ -0,0 +1,124 @@ +# Module 7.10: communication and payment + +Purpose: the two legs the payer starts. A CommunicationRequest is classified as a query, a notification or a note and answered accordingly; a PaymentNotice is recorded, matched to its claim, and acknowledged. + +Skills: `nhcx-communication` (classification, the notification acknowledgement, the reply) and `nhcx-payment` (the payment notice and its acknowledgement). Validate rows 1, 3, 4 and 5 are the communication half's; rows 2, 6 and 7 the payment half's; row 8 is both. + +## Depends on + +7.1 to 7.3, 7.7, 7.11 (for the payer's query mode; build 7.11's adapter table first if not yet). + +## Inputs + +- `references/flow-knowledge.md` section 3 (the two payer kinds, the classification rule) and section 1 rows "Payment notice" and "Communication" +- `references/fhir-knowledge.md` sections 9 and 10 +- Pins: `nhcx-package/fhir/B4/communication-request.json` (the payer's message), `B4/communication-response.json` (the reply), `nhcx-package/fhir/B7/payment-notice-ack.json` +- Payer messages: `nhcx-package/fhir/C6/C6-preauth-query-wf24.json` and `C6/C6-claim-query-wf27.json` (generic queries), `C6/C6-notification-wfN02.json` (PMJAY notification), `nhcx-package/fhir/C9/*.json` (payment notices) + +## Build + +### Classification + +`classify_communication(adapter, reason_code, intent) -> kind`, in order: a `resubmit` payer's request is a notification; `intent proposal` is a notification, `order` a query; then `reasonCode`: absent, `additionalinfo`, `questionnaire`, `query` is a query, anything else (`tatquery`, `grievance`, `walletupdate`, `policychange`, `claimarbitration`, with `claimArbitartion` folded in) a notification. A bare `Communication` with no request is a note: recorded, shown, never acted on. + +### Receiving + +`parse_communication_request(bundle)`: the Task's status, intent, reason; the CommunicationRequest's id, `basedOn` (the Claim), one question per `payload[].contentString`; the leg asked about (from the Claim's `use` or the `basedOn` identifier). Store a `claim_query` row keyed on the message's correlation id with `kind`, `stage`, `questions_json`, status `open`. + +### Acknowledging a notification + +`build_acknowledgement_bundle(query_id)`: the payer's own bundle sent back with `Task.status` flipped to `completed`, the reason echoed and the provider Organization first, on `v1/communication/on_request` with the request's correlation id and workflow id echoed in `jwe_headers`. Sent by `acknowledge_notification` from outside the callback (the desk's next request, or a worker). Status `acknowledged`. + +### Answering a query (communication payer) + +`build_communication_bundle(query_id, text, document_ids)`: a TaskBundle with a Task `deliver`, `completed`, including the Communication; the Communication `basedOn` the request (never `inResponseTo`) and `about` the Claim, its text a `contentString`, each document a `contentAttachment` under the document-type extension (its url is participant-defined: read it from configuration; the pin comparison takes the pin's own url); the CommunicationRequest echoed; then the Claim, Patient, provider Organization, payer Organization, Practitioner and Coverage lifted from the queried leg's bundle as sent. This bundle carries `meta.lastUpdated` and `timestamp` (the IG example does). Sent on `v1/communication/on_request` with the request's correlation id and workflow id. Status `answered`. + +For a `resubmit` payer the answer is not here: it is 7.7's query answer on a fresh thread. The inbox item for a PMJAY query is the leg's `query_note`, and its reply box calls `submit_preauth` or `submit_claim` with the reply. + +### Payment notice + +`parse_payment_notice(bundle)`: `PaymentNotice.amount`, `paymentStatus`, `paymentDate`, the `request` reference's identifier (the claim number), `payment` identifier (the UTR when settled), the `PaymentReconciliation` details when present. `record_payment` matches the claim number, dedupes on the correlation id, stores `claim_payment` and `claim_payment_detail`, and stamps the episode `payment`/`noticed` or `paid`. + +### Payment acknowledgement + +`build_payment_ack(payment_id)`: a TaskBundle in the shape of `B7/payment-notice-ack.json`, sent on `v1/paymentnotice/on_request` with the notice's correlation id and, for PMJAY, workflow `17`; for a generic payer the notice's own workflow id echoed (`None` in the adapter table means echo). Sent by `acknowledge_payment` from outside the callback. `ack_status` `sent` or `error`. + +## Rules + +- The reply names the request in `Communication.basedOn`, never `inResponseTo`. +- A `resubmit` payer's CommunicationRequest is always a notification, whatever it says. +- A notification is acknowledged at once and the case is left alone. +- The acknowledgement and the reply are the only two sends that carry `x-hcx-correlation_id` (with the payment acknowledgement). + +## Validate + +- [ ] `B4/communication-response.json` pin: the builder fed the request pin (`B4/communication-request.json`) and the pre-auth pin (`B3/preauth-request.json`) produces the response pin byte for byte (`meta.lastUpdated`, `timestamp` and `authoredOn` excluded). +- [ ] `B7/payment-notice-ack.json` pin comparison passes. +- [ ] Classification: the generic query (`C6/C6-preauth-query-wf24.json`: `intent order`, `additionalinfo`) is a query; the PMJAY notification (`C6/C6-notification-wfN02.json`: `intent proposal`, `information`) is a notification; the same PMJAY bundle under a `communication` adapter with `intent order` is a query; a bare Communication is a note. +- [ ] The reply's `Communication.basedOn` names the request and `inResponseTo` is absent. +- [ ] The acknowledgement and the reply carry `x-hcx-correlation_id` equal to the request's; the workflow id is echoed. +- [ ] Two deliveries of one notice create one `claim_payment` row. +- [ ] The PMJAY acknowledgement carries workflow `17`; the generic one echoes the notice's. +- [ ] No send happens inside the callback (7.1 stub sees zero sends during receipt). + +## Tests + +- The two pin comparisons. +- Classification table as a parametrised test. +- B6, B7, C6, D8, D13 and the notification rows from the matrix. + +## Pseudo code + +Classification, the acknowledgement, the reply and the payment reader: `fhir/FHIR.md` sections 7 and 8. Wiring: + +``` +APPLY["inbound_request"] = function (row, env): + kind = resource_types(env.fhir) + if "PaymentNotice" in kind: record_payment(row, env) + elif "CommunicationRequest" in kind: receive_communication(row, env) + elif "Communication" in kind: record_note(row, env) # a bare Communication: shown, never acted on + +function receive_communication(row, env): + p = fhir.parse_communication_request(env.fhir); adapter = payers.for_claim(row) + kind = fhir.classify_communication(adapter, p.reason, p.intent) + q = insert("claim_query", {claim_id: row.id, correlation_id: env.jwe_headers["x-hcx-correlation_id"], request_id: p.request_id, + workflow_id: env.jwe_headers["x-hcx-workflow_id"], sender_code: env.jwe_headers["x-hcx-sender_code"], + kind, stage: leg_asked_about(row, p), reason_code: p.reason, intent: p.intent, questions_json: p.questions, + request_json: env.fhir, status: "open", received_at: now()}) + if kind == "notification": enqueue(acknowledge_notification, q.id) # sent outside the callback + +function acknowledge_notification(query_id): + q = query(query_id); row = claim(q.claim_id) + bundle = fhir.build_acknowledgement_bundle(q.request_json, settings.facility) + r = transport.send("v1/communication/on_request", bundle, q.sender_code, workflow_id = q.workflow_id, correlation_id = q.correlation_id, claim_no = row.claim_no, usecase = "communication-ack") + update(q, {status: "acknowledged", reply_txn_id: r.txn_id, reply_api_call_id: r.api_call_id, replied_at: now()}) + +function answer_query(query_id, text, document_ids): # communication payer + q = query(query_id); row = claim(q.claim_id) + if payers.for_claim(row).query_mode == "resubmit": return submit_preauth(row.id, reply = text) if q.stage == "preauth" else submit_claim(row.id, reply = text) + sent = (preauth(row.id) if q.stage == "preauth" else submission(row.id)).request_json + bundle = fhir.build_communication_bundle(q, text, [doc_with_bytes(i) for i in document_ids], sent, settings.facility, payer_of(row), now_ist()) + r = transport.send("v1/communication/on_request", bundle, q.sender_code, workflow_id = q.workflow_id, correlation_id = q.correlation_id, claim_no = row.claim_no, usecase = "communication-reply") + update(q, {status: "answered", reply_text: text, reply_document_ids: document_ids, reply_txn_id: r.txn_id, replied_at: now()}); stamp_case(row.id) + +function record_payment(row, env): + p = fhir.parse_payment_notice(env.fhir) + pay = insert_or_ignore("claim_payment", {claim_id: row.id, correlation_id: env.jwe_headers["x-hcx-correlation_id"], workflow_id: env.jwe_headers["x-hcx-workflow_id"], + sender_code: env.jwe_headers["x-hcx-sender_code"], amount: p.amount, payment_status: p.payment_status, payment_date: p.payment_date, + utr: p.utr, notice_json: env.fhir, ack_status: "pending", received_at: now()}) + if not pay: return # the unique constraint caught a redelivery + for d in p.details: insert("claim_payment_detail", {payment_id: pay.id, type: d.type, amount: d.amount}) + enqueue(acknowledge_payment, pay.id) + +function acknowledge_payment(payment_id): + pay = payment(payment_id); row = claim(pay.claim_id); adapter = payers.for_claim(row) + bundle = fhir.payment_ack(submission(row.id).claim_ref or row.claim_no, now_ist(), settings.facility, payer_of(row)) + wf = adapter.workflow_ids.payment_ack or pay.workflow_id # 17 for PMJAY; echo for a generic payer + r = transport.send("v1/paymentnotice/on_request", bundle, pay.sender_code, workflow_id = wf, correlation_id = pay.correlation_id, claim_no = row.claim_no, usecase = "payment-ack") + update(pay, {ack_status: "sent", ack_txn_id: r.txn_id, ack_api_call_id: r.api_call_id, acked_at: now()}); stamp_case(row.id) +``` + +## Done when + +- Validate passes. +- `nhcx-build/7-modules/7.10.md` is written. diff --git a/plugins/nhcx/skills/nhcx-payment/stages/7-write-code/7.11-state-and-payer-adapters.md b/plugins/nhcx/skills/nhcx-payment/stages/7-write-code/7.11-state-and-payer-adapters.md new file mode 100644 index 000000000..94fbfc313 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-payment/stages/7-write-code/7.11-state-and-payer-adapters.md @@ -0,0 +1,145 @@ +# Module 7.11: state and payer adapters + +Purpose: two small tables of truth the whole build reads. The payer adapter says how a payer behaves; the stage machine says where an episode stands and what it waits for. + +Skills: the foundation (`core/FOUNDATION.md`). The first skill builds the payer adapter table whole; each skill adds the `case_stage` branches and the `next_actions` rows for its own legs. + +## Depends on + +7.2. (7.7 to 7.10 call it; build the adapter table as early as 7.4 needs the participant codes.) + +## Inputs + +- `references/flow-knowledge.md` sections 2, 3 and 4, whole +- `nhcx-build/1-idea.md` (the payers in scope) + +## Build + +### The payer adapter + +A table keyed by participant code (normalised: `1518` and `1518@hcx` are one key), each entry holding: + +| Field | PMJAY | Generic | +| --- | --- | --- | +| `query_mode` | `resubmit` | `communication` | +| `workflow_ids` | the PMJAY column of flow-knowledge section 2 | the generic column; `payment_ack` is `None` (echo) | +| `program_code` | `AB-PMJAY` | none | +| `auth_requirements` | asked | asked | +| `status_enquiry` | refused; do not offer | offered | +| `claim_resubmit` | none; reprocess only | `16` | +| `payer_system` | the identifier system for the payer Organization | same | + +`adapter_for(participant_code)` returns the entry or the generic default. `for_claim(row)` reads the episode's payer code. Overrides from configuration (7.1) merge on top, per payer, so a payer that insists on `cancel` as 122 is one config line. + +### Stage and sub-stage + +Stages: `eligibility`, `preauth`, `enhancement`, `claim`, `payment`. Sub-stages: `draft`, `checking`, `eligible`, `not-eligible`, `requested`, `resubmitted`, `answered`, `queried`, `approved`, `partial`, `rejected`, `cancelling`, `cancelled`, `refused`, `noticed`, `paid`. Send kind to sub-stage: `preauth`, `claim`, `enhancement` set `requested`; `*_resubmit` sets `resubmitted`; `*_query_response` and `enhancement_resubmit` set `answered`. `requested`, `answered`, `resubmitted` mean "with the payer". + +`case_stage(row, ...) -> (stage, sub_stage)`: a payment notice wins, then the filed claim, then the pre-auth (stage `enhancement` if the last submission kind was one), then a saved draft, then the eligibility status. An open communication query on a leg that is with the payer flips the sub-stage to `queried`. + +`stamp_case(claim_id)`: recompute and write both onto the episode. Called after every leg write by 7.3, 7.4 to 7.10. + +### Next actions + +The table in `flow/FLOW.md` ("The status line and the actions") and `flow/flow.json` `next_actions` is the specification; the labels are used verbatim. + +`next_actions(claim_id) -> [{label, tab, tone}]`, first is what the case waits for: an unanswered query always leads with "Answer the payer (n)"; the leg's own reply box only for a `resubmit` payer, a `communication` payer is sent to the inbox; a claim refused at the door offers "send again" while `claim_send_kind` still yields a kind, else "Ask for a reprocess"; after a rejection the pre-auth offers a fresh 12; a payer whose adapter refuses status enquiry never gets a "Ask status" action. + +## Rules + +- An unmapped payer is generic. +- The two words are derived, never set by a screen. +- Stamp after every write. A test that checks state after every step is what makes stage 8 possible. + +## Validate + +- [ ] `adapter_for("1518@hcx")` and `adapter_for("1518")` return the PMJAY entry; an unknown code returns generic. +- [ ] The PMJAY `workflow_ids` table equals flow-knowledge section 2's PMJAY column for every kind listed; the generic table has `payment_ack` as echo and `claim_query_response` as `151`. +- [ ] A configuration override for one kind changes only that kind. +- [ ] `case_stage` on each seeded state (draft; checking; eligible; pre-auth submitting; approved; queried by communication; enhancement requested; claim submitting; payment noticed; paid) returns the expected pair (write the table in the test). +- [ ] `next_actions` leads with the query when one is open; offers no status enquiry for PMJAY; offers a fresh 12 after a rejection. +- [ ] For every row of `flow.json` `next_actions`, the seeded state yields that label, character for character. +- [ ] After every leg write in 7.4 to 7.10, `claim.stage` and `sub_stage` equal `case_stage` recomputed. + +## Tests + +- A parametrised table for `case_stage`. +- A parametrised table for `next_actions`. +- The adapter lookups and the override. + +## Pseudo code + +``` +QUERY_MODE_RESUBMIT = "resubmit"; QUERY_MODE_COMMUNICATION = "communication" + +PMJAY = {"name": "PMJAY", "query_mode": QUERY_MODE_RESUBMIT, "program_code": "AB-PMJAY", "auth_requirements": true, + "status_enquiry": false, "payer_system": "https://nhcx.abdm.gov.in", + "workflow_ids": {"preauth": "12", "preauth_resubmit": "121", "preauth_query_response": "19", "enhancement": "13", "enhancement_resubmit": "131", + "cancel": "PC01", "claim": "15", "claim_query_response": "161", "claim_resubmit": null, "payment_ack": "17", "reprocess": "36", "release": "36"}} +GENERIC = {"name": "generic", "query_mode": QUERY_MODE_COMMUNICATION, "program_code": null, "auth_requirements": true, "status_enquiry": true, + "payer_system": "https://nhcx.abdm.gov.in", + "workflow_ids": {... as PMJAY except "claim_query_response": "151", "claim_resubmit": "16", "payment_ack": null}} # null = echo the notice's id +ADAPTERS = {"1518": PMJAY} # keyed without @hcx + +function adapter_for(participant_code): + key = (participant_code or "").split("@")[0] + base = deepcopy(ADAPTERS.get(key, GENERIC)) + for (k, v) in settings.workflow_overrides.get(with_hcx(key), {}): base.workflow_ids[k] = v + return base + +function for_claim(row): return adapter_for(row.payer_code) + +STAGES = ["eligibility", "preauth", "enhancement", "claim", "payment"] +KIND_TO_SUB = {"preauth": "requested", "claim": "requested", "enhancement": "requested", "preauth_resubmit": "resubmitted", "claim_resubmit": "resubmitted", + "preauth_query_response": "answered", "claim_query_response": "answered", "enhancement_resubmit": "answered"} +WITH_PAYER = {"requested", "answered", "resubmitted"} + +function leg_sub_stage(leg): + if leg.status == "submitting": return KIND_TO_SUB.get(leg.submission_kind, "requested") + return {"approved": "approved", "partial": "partial", "queried": "queried", "rejected": "rejected", "error": "refused", + "cancelling": "cancelling", "cancelled": "cancelled", "draft": "draft"}.get(leg.status, leg.status) + +function case_stage(row): + paid = sum(p.amount for p in payments(row.id) if p.payment_status in ("paid", "cleared")) + if payments(row.id): return ("payment", "paid" if paid > 0 else "noticed") + cs = submission(row.id) + if cs and cs.status != "draft": + sub = leg_sub_stage(cs) + if sub in WITH_PAYER and "claim" in open_query_stages(row): sub = "queried" + return ("claim", sub) + pa = preauth(row.id) + if pa and pa.status != "draft": + stage = "enhancement" if pa.submission_kind in ("enhancement", "enhancement_resubmit") else "preauth" + sub = leg_sub_stage(pa) + if sub in WITH_PAYER and "preauth" in open_query_stages(row): sub = "queried" + return (stage, sub) + if pa: return ("preauth", "draft") + return ("eligibility", {"checking": "checking", "eligible": "eligible", "not-eligible": "not-eligible"}.get(row.status, "draft")) + +function stamp_case(claim_id): (s, sub) = case_stage(claim(claim_id)); update(claim(claim_id), {stage: s, sub_stage: sub}) + +function next_actions(claim_id): + row = claim(claim_id); adapter = for_claim(row); out = []; pa = preauth(claim_id); cs = submission(claim_id) + open_q = open_queries(claim_id) + if open_q: out.append({label: f"Answer the payer ({len(open_q)})", tab: "communication" if adapter.query_mode == "communication" else ("claim" if open_q[0].stage == "claim" else "preauth"), tone: "primary"}) + if row.status in ("draft", "not-eligible", "error"): out.append({label: "Check cover", tab: "cover", tone: "primary"}) + elif not row.plan_id: out.append({label: "Fetch the plan", tab: "plan", tone: "primary"}) + elif not pa or pa.status == "draft": out.append({label: "Submit the pre-authorisation", tab: "preauth", tone: "primary"}) + elif pa.status == "queried" and adapter.query_mode == "resubmit": out.append({label: "Answer the query", tab: "preauth", tone: "primary"}) + elif pa.status == "rejected": out.append({label: "Send a fresh pre-authorisation", tab: "preauth", tone: "primary"}) # 12, never 121 + elif pa.status == "error": out.append({label: "Send again", tab: "preauth", tone: "warn"}) + elif pa.status in ("approved", "partial") and (not cs or cs.status == "draft"): + out.append({label: "Discharge and claim", tab: "claim", tone: "primary"}) + if enhancement_lines(claim_id): out.append({label: "Send the enhancement", tab: "lines", tone: "default"}) + out.append({label: "Cancel the pre-authorisation", tab: "preauth", tone: "danger"}) + elif cs and cs.status == "error": out.append({label: "Send again" if claim_send_kind(claim_id) else "Ask for a reprocess", tab: "claim", tone: "warn"}) + elif cs and cs.status == "rejected": out.append({label: "Ask for a reprocess", tab: "claim", tone: "warn"}) + for p in payments(claim_id): if p.ack_status != "sent": out.append({label: "Acknowledge the payment", tab: "payments", tone: "default"}) + if adapter.status_enquiry and (pa or cs): out.append({label: "Ask status", tab: "enquiries", tone: "default"}) + return out +``` + +## Done when + +- Validate passes. +- `nhcx-build/7-modules/7.11.md` is written. diff --git a/plugins/nhcx/skills/nhcx-payment/stages/7-write-code/7.12-screens.md b/plugins/nhcx/skills/nhcx-payment/stages/7-write-code/7.12-screens.md new file mode 100644 index 000000000..130115d38 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-payment/stages/7-write-code/7.12-screens.md @@ -0,0 +1,124 @@ +# Module 7.12: screens + +Purpose: the screens in `screens.json`, built the way the target builds screens, every value derived from a stored message, plus the JSON state address a driver reads. + +Skills: the foundation (`core/FOUNDATION.md`) builds the case screen shell: all eight tabs, the status line, the state address, the page-load polls, the cases list. Each skill fills its own tabs and screens, and adds its legs to the state address. + +## Depends on + +7.1 to 7.11. Screens come last because they render what the readers stored. + +## Inputs + +- `nhcx-build/5-screen-plan.md`, `nhcx-build/screens.json` +- `nhcx-build/3-discovery.md` (screen conventions, helpers, styling) +- `nhcx-package/docs/03-Building a Provider/09-UI Guide.md` +- `ui/UI-GUIDE.md` for the route shape, the state address and the helper vocabulary; two or three route modules of the target for its conventions + +## Build + +### The case screen walks the flow + +Tabs in the order and with the labels of `flow.json` `tabs`; the Pre-authorisation tab appears once the verdict is `eligible`. Above the tabs the status line and the actions from 7.11. Each step F1 to F13 has its control on the tab the flow names, offered only when the step's `holds` hold. The page-load polls run in the order `flow.json` `page_load_polls` gives, bounded, before rendering. + +### Every screen in `screens.json` + +For each screen: the route, the handler, the render. Each value in the screen's `values` list is rendered from the element it names; the empty state is what shows before the message arrived. A decision-bearing value with no message renders as waiting. There is no status control anywhere. + +### The case screen + +The timeline: one row per leg row and per archived message, in time order, with direction, path, workflow id label (7.8's labels), status word, and the payer's words verbatim (`disposition`, item remarks, process notes, `x-hcx-error_details` on a refusal). The actions open now are `next_actions` from 7.11, rendered as buttons that post to the senders; the first action is highlighted. Each pane (cover, plan, lines, forms, documents, pre-auth, communication, claim, payments) shows only when its leg exists. + +### The JSON state address + +`GET /state` returns everything the case screen shows, as JSON, after the same polls the screen runs: stage, sub-stage, next actions, each leg's status and ids, the inbox items, the payments. Stage 10's drivers read this. + +### Polling on the request path + +Where there is no worker, the case screen and the state address run 7.3's poll fallback for any leg that is `submitting` or `checking` before rendering. Bound it: one poll per leg per request, a short timeout, and never a send. + +### Standalone mode + +Also the capture screens from 7.13, in the same style. + +## Rules + +- No screen shows a decision the exchange has not sent. +- Nothing the exchange already knows is typed. Rates, payer names, `preAuthRef`, the approved amount, the UTR and the payer's wording are rendered, never fields. +- An unknown case is a 404, never an invented page. +- Screens answer within two seconds; the poll is bounded. +- Forms post and the page re-renders; no client-side rendering is needed. + +## Validate + +- [ ] The case page's tabs are the eight of `flow.json`, in order, with those labels (string test on the HTML). +- [ ] Every step of `flow.json` with a `routes` entry answers on that route (or the plan's equivalent recorded in `screens.json`). +- [ ] Every route in `screens.json` answers 200 for a seeded case and 404 for an unknown one. +- [ ] A case with a pre-auth `submitting` and no answer renders "waiting" (or the plan's word) and neither "approved" nor "rejected" appears on the page. +- [ ] After a 21 is applied (`nhcx-package/fhir/C5/C5-approved-wf21.json`), the page shows its `preAuthRef` and approved amount verbatim. +- [ ] After a payment notice is applied (`nhcx-package/fhir/C9/C9-notice-wf30.json`), the payments screen shows its UTR verbatim. +- [ ] After a query is applied, the inbox shows the request's `contentString` text verbatim. +- [ ] No `` or `, unless spec.typed +``` + +### Which actions to offer + +``` +function actions(case): + out = [] + q = open_queries(case) + if q: out.append(action("Answer the payer (n)", tab = inbox if payer.query_mode == communication else leg_tab)) + leg = current_leg(case) + if leg.status == "rejected" and leg.kind == "preauth": out.append(action("Send a fresh pre-authorisation", sends = 12)) + if leg.status == "approved" and no_request_in_flight(case) and leg.kind == "preauth": + out.append(action("Enhance", sends = 13)); out.append(action("Cancel", sends = PC01)); out.append(action("Discharge and claim", tab = claim)) + if leg.kind == "claim" and leg.status == "rejected": out.append(action("Ask for a reprocess", sends = 36)) + if payer.status_enquiry: out.append(action("Ask status", sends = task status)) + for notice in unacknowledged_notices(case): out.append(action("Acknowledge payment", sends = 17 or echo)) + return out +``` + +## Component vocabulary (suggested, for a standalone build) + +A suggested set of helpers. Server-rendered HTML from Python functions returning strings, styled by the 0build kit 0.5.4 from jsDelivr. Components: `z-card`, `z-button`, `z-input`, `z-select`, `z-table`, `z-nav`, `z-tab` with `data-z-switcher`, `z-alert`, `z-badge`, `z-breadcrumb`. Utilities take values through custom properties (`class="display-grid gap" style="--gap: 4"`). Helpers a screen needs: `page`, `card`, `stack`, `table`, `grid`, `field`, `text_input`, `select`, `button`, `post_button`, `confirm_form`, `badge`, `when`, `muted`, `dl`, `tabs`, `stat`, `empty_state`. Tables cap at about eight columns; merge facts into a main line with a muted sub-line. Every state-changing action that is not a full form is a `post_button`; destructive ones confirm. + +In `integrate` mode use the HMIS's own components and conventions; the layouts above are the content, not the markup. diff --git a/plugins/nhcx/skills/nhcx-preauth/SKILL.md b/plugins/nhcx/skills/nhcx-preauth/SKILL.md new file mode 100644 index 000000000..223dbc1aa --- /dev/null +++ b/plugins/nhcx/skills/nhcx-preauth/SKILL.md @@ -0,0 +1,106 @@ +--- +name: nhcx-preauth +description: Add NHCX pre-authorisation to a hospital information system or a standalone claims desk. Link the admission, capture the dossier, ask the auth-requirements ruling, send the pre-auth (12), answer a PMJAY query (19, 131), raise an enhancement (13), cancel (PC01) and ask for a predetermination, reading every answer (20, 21, 22, 23, 24, PC02), held to the pinned bundles. Starts by checking whether the app already sends pre-auths or any of these legs, and whether the coverage and plan it depends on exist, then builds, extends or reuses only what is missing. Self-contained; needs no other skill installed. Use for pre-authorisation, enhancement, pre-auth query answers, cancelling a pre-auth, auth requirements, predetermination, NHCX use cases B3, B8 cancel, B9, D2 and D4 to D8, flow steps F5 to F9e. +--- + +# NHCX pre-authorisation: from the admission to the payer's decision + +This skill carries the episode from an eligible, quoted case to an approved pre-authorisation. It links the admission, captures the dossier, asks the payer to rule on the quoted set, sends the pre-auth, reads the acknowledgement and the decision, answers a PMJAY query in-band, raises an enhancement, withdraws a pre-auth, and asks for a quote. It is the heaviest skill and the one PMJAY refuses most. + +Read `core/LADDER.md` first. It holds the ladder every NHCX skill walks: the definition of compliant, the stages, the workspace, how to run a stage, and the rules. This folder carries everything it needs and runs on its own; the other six NHCX skills are separate folders, and none of them has to be installed. Paths starting `core/`, `stages/`, `references/`, `fhir/`, `flow/`, `ui/`, `templates/` or `scripts/` are relative to this folder. Paths starting `nhcx-package/` are in the NHCX package, which `scripts/fetch-package.sh` fetches into the target project beside `nhcx-build/`; `references/material.md` names the package file of every pin by its label. + +## What this skill covers + +| | | +| --- | --- | +| Flow steps | F5 Link or capture the admission, F6 The dossier, F8 Validate the set, F9 Send the pre-authorisation, F9a The payer answers, F9b Answer a query (a `resubmit` payer only), F9c Enhancement, F9d Cancel, F9e Predetermination | +| Tabs | Validate (tab 4); Pre-authorisation (tab 5, opens once `eligible`) | +| Wire | Auth requirements: `v1/coverageeligibility/check`, purpose `auth-requirements` with items, workflow id = the case number, asked and never awaited. `v1/preauth/submit` with workflow 12 (pre-auth), 19 (query answer, PMJAY), 13 (enhancement), 131 (enhancement query answer), and 12 with `use predetermination`. `v1/task/submit` with workflow PC01 (cancel). Answers: 20, then 21, 22, 23, 24, 231 or 241; PC02 | +| Next actions | "Send the pre-authorisation", "Send a fresh pre-authorisation", "Answer the query" (a `resubmit` payer), "Send the enhancement (n added)", "With the payer; ask where it stands" (the label; the enquiry behind it is the reprocess use case's) | +| Use cases | B3 and its enhancement row, B8 cancel, B9, D2, D4, D5, D6, D7, D8 | +| Modules | 7.6, whole; 7.7, the pre-auth legs (12, 13, 19, 131, predetermination); 7.8, the pre-auth, enhancement and predetermination answers; 7.9, cancel and PC02 | +| Pins | `coverage/authrequirements`, `preauth/request`, `preauth/enhancement`, `preauth/queryupdate`, `preauth/cancel`: `nhcx-package/fhir/B1/auth-requirements.json`, `nhcx-package/fhir/B3/preauth-{request,enhancement,queryupdate,cancel}.json` | +| Payer fixtures | `nhcx-package/fhir/C5/*` (20, 21, 22, 23, 24, generic and PMJAY), `nhcx-package/fhir/C10/C10-cancelled-*` (PC02), `nhcx-package/fhir/C11/*` (predetermination); the auth-requirements rulings `nhcx-package/fhir/C3/C3-response-generic.json` and `C3-response-pmjay.json`; the live PMJAY shapes in `nhcx-package/fhir/D4`, `D6`, `D7`, `D8` | +| Tables | `claim_auth`, `claim_auth_item`, `claim_auth_requirement`, `claim_preauth`, `claim_predetermination`, `claim_form_answer`, `claim_document`, `claim_diagnosis`, `claim_care_team`, `claim_item`; `claim.patient_id`, `claim.encounter_id` | +| FHIR | `fhir/FHIR.md` sections 2 (auth requirements), 4, 5 and 6 (cancel); `references/fhir-knowledge.md` sections 3, 5, 6, 7 and 8 | + +Not here: the query of a `communication` payer (a generic payer), which arrives as a CommunicationRequest and belongs to the communication use case (`nhcx-communication`); status enquiries, which belong to the reprocess use case (`nhcx-reprocess`, F13). + +## Needs and hands on + +Needs: an eligible episode and the coverage builder (the coverage use case); a plan ready, lines quoted, forms and requirements known (the insurance use case). Stage 0 checks for them below, whichever way the app got them. + +Hands on: a pre-auth `approved` or `partial` with `preauth_ref` (the payer's number), `claim_ref` (the number the claim goes under), the approved amount and the item verdicts; the dossier (admission, diagnoses, a care team with HPINs, documents under their codes, answered forms) that the claim builds on; the pre-auth bundle as sent (`request_json`), which a communication reply lifts entries from. After a PC02, a fresh claim number on the episode. + +## Capability check + +Stage 0 (`stages/0-capability-check.md`) gives every capability below a verdict: search for the markers, run the check, record what was observed. + +### Own + +| Id | What | Look for | Present when (observed) | +| --- | --- | --- | --- | +| `preauth.admission-link` | F5: link the eligible case to a current inpatient stay (integrate), or capture it (standalone) | `encounter_id` on the episode; a match on the ABHA the payer returned | Linking an `eligible` case to a current IPD stay whose ABHA matches, digits only, stores `patient_id` and `encounter_id`; linking before `eligible`, or to a stay that is not a current IPD admission, is refused | +| `preauth.dossier` | F6: admission and provisional discharge dates, ICD-10 diagnoses, the treating doctor with an HPIN, package or non-package, documents under the plan's codes (else `ODN`), forms answered | `save_preauth`, a diagnosis table, a care team table, documents with `code` and `stage`, form answers | Saving refuses a missing admission date, a discharge before the admission, no diagnosis, a doctor without an HPIN, and a package case with no line; an upload other than pdf, jpg, jpeg or png is refused; a file attached against a requirement carries its code | +| `preauth.auth-requirements` | F8: the ruling on the quoted set, fingerprinted, asked and never awaited | `auth-requirements`, `authorizationSupporting`, a fingerprint of the quoted set | 7.6's Validate section whole: the builder fed the pin's data produces `coverage/authrequirements` with an integer quantity; an unchanged set sends once and a changed quantity sends again; the reader, fed `nhcx-package/fhir/C3/C3-response-generic.json` and `C3-response-pmjay.json`, yields items and requirements with `stage` and `at_preauth`; a submit proceeds with the ruling still `checking` | +| `preauth.claim-bundle` | 7.7's builder, for the pre-auth legs: one pure function | `preauthorization`, `supportingInfo`, `Item/`, `SupportingInformation/`, `https://hpr.abdm.gov.in`, `programCode`, `ADDD` | The `preauth/request`, `preauth/enhancement` and `preauth/queryupdate` pins pass (single-item pins compared without `factor`); every reference resolves; every item, procedure and supportingInfo entry has an id, and the sequences run from 1 without a gap; every Practitioner has an HPIN; tiers appear only as modifiers; no literal `MAND\d+`, `MG\d+` or `/questionnaire/` in the code | +| `preauth.send` | F9, F9c: `submit_preauth` and the choice of send kind | `v1/preauth/submit`, workflow ids `12`, `13`, `19`, `131`, `121` | With the 7.1 stub: a fresh case gives 12; after a rejection 12, never 121; lines added after approval give 13 with every line old and new; every F9 guard refuses before any HTTP call; the three ids, `submission_kind` and `workflow_id` are stored, and `thread_correlation_id` is untouched until the payer answers | +| `preauth.response-reader` | F9a: 7.8 on the pre-auth thread | `ClaimResponse`, `preAuthRef`, `verdict_status`, `outcome` | `verdict_status` gives `submitting` on the 20, `approved` on the 21, `rejected` on the 23 and `queried` on the 24; a 20 then a 21 leaves `approved` with `preauth_ref` never empty; an enhancement 20 without `preAuthRef` keeps the parent's; `total[]` is read by category; a PMJAY query fills `query_note` verbatim | +| `preauth.query-answer` | F9b for a `resubmit` payer: 19, or 131 after an enhancement query | `queryupdate`, `CQD`, `NMI` | The `preauth/queryupdate` pin passes; the reply rides on `NMI/CQD` on a new correlation id; an empty reply is refused before sending; a `communication` payer's query is sent to the inbox instead | +| `preauth.cancel` | F9d: Task `cancel`, workflow PC01; PC02 read | `PC01`, `PC02`, `"cancel"`, `intimationNumber`, `claimNumber` | The `preauth/cancel` pin passes as it is; a PC02 sets the pre-auth `cancelled` and gives the episode a fresh claim number while the old one stays on the leg; a ProtocolResponse on the cancel thread leaves the pre-auth as it was; a cancel of a `rejected` pre-auth, a second cancel, and a cancel after a claim was raised are refused (7.9 Validate, rows 1 for the cancel pin, 2, 4 and 5) | +| `preauth.predetermination` | F9e: the F9 bundle with `use predetermination`, on its own row | `predetermination` | A quote creates its own row (`asking`, then `answered`) with the eligible amount, and the pre-auth row is untouched | +| `preauth.screens` | The Validate and Pre-authorisation tabs | the link card, the dossier form, the submit card, the decision card | The decision card renders the decision, `preAuthRef`, approved amount, eligible amount and item verdicts verbatim from the stored answer; a pre-auth sent and not answered reads as waiting, never approved or rejected; the reply box shows only for a `resubmit` payer | + +### Foundation + +All six capabilities in `core/FOUNDATION.md`. `foundation.storage` is partial until this skill's tables exist; `foundation.state` is partial until `case_stage` has the `preauth` and `enhancement` branches and `next_actions` the labels above. + +### Prerequisites + +The coverage use case (`nhcx-coverage`) and the insurance use case (`nhcx-insurance`) own these. The checks are here, so neither skill need be installed. + +| Capability | Why | Look for | Present when (observed) | +| --- | --- | --- | --- | +| `coverage.episode`, `coverage.check-leg`, `coverage.response-reader` | F5 and F9 hold `eligible` | an episode table with `claim_no`, `member_id`, `policy_code`, `payer_code`; a send on `v1/coverageeligibility/check`; `inforce` read | An episode opened from a policy row, checked with a stubbed client (workflow id = the claim number), and fed the answers in `nhcx-package/fhir/C3`, settles `eligible` | +| `coverage.request-builder` | The auth-requirements check is the coverage builder with items. Extend it; do not write a second | `CoverageEligibilityRequest`, `"purpose"` | Fed each pin's own data, it produces `coverage/{discovery,validation,benefits}` byte for byte; if it cannot take `items`, it is partial for this skill and 7.6 extends it | +| `insurance.plan-leg`, `insurance.plan-parser`, `insurance.lines` | Items, prices, tiers, documents and forms come from the plan; F9 needs at least one line | a plan table with benefits and forms; a line table with `parent_code` | `nhcx-package/fhir/C4/C4-response-pmjay.json` applied to an episode leaves a plan `ready` with rated benefits, requirements and forms; a line added from it takes the plan's rate, and a tier carries `parent_code` | + +### Host facts + +The encounter (admission time, ward, bed, admitting doctor, status); diagnoses (ICD-10 with a display, or a mapping to it); the practitioner table with HPR id, licence and qualification; the document store, a code and stage tag on a file, the accepted content types. + +## The ladder, for this skill + +| Stage | What is specific here | +| --- | --- | +| 0 | The tables above. | +| 1 | Confirm the shared page, or write it if this skill runs first on the app. Own rows: B3, B8 cancel, B9, D2, D4 to D8. Predetermination is commonly `later`. | +| 2 | Risks: one live pre-auth per beneficiary per hospital (PAYR-1238); one request at a time per case (PAYR-1322); a fresh 12 after a rejection (121 is PAYR-1214); a PMJAY query answer on a new correlation id; a missing HPIN (PAYR-1083); an enhancement adding a second conservative package (PAYR-1245). | +| 3 | The host facts above. | +| 4 | Source maps for the auth-requirements bundle, the Claim bundle's pre-auth legs and the cancel Task; the ClaimResponse and PC02 destinations; the HPIN's source; `preAuthRef` from the ClaimResponse. If this skill maps first, every table's home too. | +| 5 | The Validate and Pre-authorisation tabs; actions F5, F6, F8, F9, F9b (resubmit payer), F9c, F9d, F9e. | +| 6 | 7.6; the parts of 7.7, 7.8 and 7.9 above; the foundation modules stage 0 found absent or partial. | +| 7 | In that order. The builder stays one function with `leg` and `flow` arguments: the claim legs extend it later. | +| 8 | 7.6 whole; the rows of 7.7, 7.8 and 7.9 that name the pre-auth legs. | +| 9 | Five pin comparisons; reader tests on 20, 21, 22, 23, 24, PC02 and the ruling; matrix rows B3, B3 enhancement, B8 cancel, B9, D2, D4 to D8; send-kind selection after every prior state; the cross-cutting rows on the pre-auth thread (a door refusal of an enhancement leaves the pre-auth approved). | +| 10 | Rung 1. Rung 3 walks B3 and B8 cancel against a generic payer. Rung 4 walks D4, D6, D7 and D8; sweep live pre-auths first. | +| 11 | This skill's section. | + +## Rules for these legs + +- Never hard-code a document code, a package code, a questionnaire url or a summary code. Take them from the ruling, else the plan. +- Element ids on every indexed list (`Item/n`, `Procedure/n`, `SupportingInformation/n`) and a `sequence` on every supportingInfo entry, numbered once after the list is assembled (PAYR-1019, PAYR-1027). +- The consent form rides every pre-auth (PAYR-1256), and each guideline form rides its package (PAYR-1254). +- One item per procedure or implant; tiers ride as modifiers; `factor` 1, 0.5, 0.25 by cost rank on PMJAY; `total` is the sum of the nets. +- `LM100` never rides a pre-auth (PAYR-1270). +- The auth-requirements check is asked, never awaited, and never asked twice for one set. +- Never close a thread on the first reply: the 20 (`queued`) comes first and the decision after, on one correlation id. Never read `outcome` alone. +- Keep `preauth_ref`; never overwrite it with an empty value. +- A cancel retires the claim number. The cancel action is hidden once a claim has been raised. +- Read the payer's refusal before touching the code: half of them are scheme rules (`references/flow-knowledge.md` section 5). + +## Done when + +- Every gate in this skill's block of `nhcx-build/STATE.md` is closed with evidence. +- The five pins pass their comparisons. +- The compliance points in `core/LADDER.md` hold for F5 to F9e. diff --git a/plugins/nhcx/skills/nhcx-preauth/core/FOUNDATION.md b/plugins/nhcx/skills/nhcx-preauth/core/FOUNDATION.md new file mode 100644 index 000000000..2037811b9 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-preauth/core/FOUNDATION.md @@ -0,0 +1,65 @@ +# The foundation: what every skill stands on + +Six modules carry every leg, and no one skill owns them. Every skill's stage 0 checks them. The first skill that finds one absent or partial builds or extends it in its own stage 7, and records itself as `Built by` in the Foundation block of `nhcx-build/STATE.md`. Later skills find it present and reuse it. An HMIS that already has one (an NHCX integration, a webhook door, a claims table) has it `existing`. + +| Id | Module | What | Every skill adds | +| --- | --- | --- | --- | +| `foundation.transport` | 7.1 | Settings; the one transport behind `send` (the app's existing NHCX integration, the build's own, or nhcx-adapter when the user asked for it); the policy lookup; the outbound archive | Nothing; it sends through it | +| `foundation.storage` | 7.2 | The episode table with its claim number, payer and recipient codes, stage and sub-stage; the leg tables | The leg tables its `SKILL.md` lists, in its own migration | +| `foundation.callback` | 7.3 | The transport's receiving end and the door: dedupe, archive before apply, match by correlation id then claim number, the door refusal, the poll fallback where there is a ledger | Its readers, wired into the door's dispatch | +| `foundation.state` | 7.11 | The payer adapter table; `case_stage`, `stamp_case`, `next_actions` | The stage branches and next-action rows for its legs, labels verbatim from `flow/flow.json` | +| `foundation.screens` | 7.12 | The case screen shell: the eight tabs in the flow's order, the status line and actions, the JSON state address, the page-load polls, the cases list | Its own tabs and screens | +| `foundation.shell` | 7.13 | Standalone only: patients, admissions, practitioners, diagnoses, documents, settings, the run script | Nothing; `not applicable` in integrate mode | + +## Recognising each one + +For each capability: what to search for, what must be observed for it to be present, and what makes it partial. Search code, dependencies, migrations, configuration and tests. Run every check offline, with the network stubbed. + +### `foundation.transport` (7.1) + +- Look for an NHCX integration of the app's own: `x-hcx-`, `JWEPayload`, `RSA-OAEP-256`, `A256GCM`, a JOSE library among the dependencies, `bearer_auth`, a sessions URL on the ABDM gateway, `participanthcxservice`, `fetch/certs`, `participant/get/policies`, routes ending in `on_submit`, `on_check` or `on_request`, a vendor's NHCX or HCX client, a gateway service the app calls. Look also for nhcx-adapter already in use: `/fhir/out/`, `/out/v1/`, `jwe_headers`, an adapter URL setting, `/ledger/thread/`, `/internal/txn/related`. +- Present when: what was found meets the contract in `references/transport-knowledge.md` section 2, observed through 7.1's Validate rows 1 to 6 (and row 7 for an app that seals its own messages), with the network stubbed and a test key pair for the seal; and `send` is one function a test can replace. +- Partial when: it sends but misses a contract item (no `x-hcx-ben-abha-id`, the `payerid` as the recipient, no ids back to the caller, no archive) or cannot be stubbed. Extend it in place (`references/transport-knowledge.md` section 4). Never add a second transport beside it. +- Absent when: the app has no NHCX integration. The transport is then `own`, built from `references/transport-knowledge.md` section 3, unless the user has asked for nhcx-adapter. +- nhcx-adapter is never the answer to a partial or absent transport unless the user asked for it. Do not suggest it. + +### `foundation.storage` (7.2) + +- Look for: tables or models with `claim_no`, `correlation_id`, `txn_id`, `sub_stage`; migrations that mention claim, preauth or nhcx. +- Present when: observed on a migrated scratch database, or read from the schema file and confirmed by a migration run: the episode table has a unique claim number, member id, policy code, payer code, recipient code, patient and encounter keys, `stage` and `sub_stage`; every leg table this skill needs exists with `txn_id`, `correlation_id`, `api_call_id` and `thread_correlation_id`; the migration runs twice without error; deleting an episode removes its children (7.2 Validate, rows 2, 3, 5 and 6). For `nhcx-communication` and `nhcx-payment`, also row 4: the correlation id on their tables is unique by constraint. +- Partial when: the episode exists but a leg table this skill needs does not, a leg table lacks `thread_correlation_id` or `api_call_id`, or the episode keeps no `recipient_code`. The skill adds its tables and columns in a new migration. + +### `foundation.callback` (7.3) + +- Look for: routes under `/v1/` ending in `on_submit`, `on_check`, `on_request`, `/v1/error`, or a route with `callback` in it; `JWEPayload`, `ProtocolResponse`, `x-hcx-correlation_id`, `x-hcx-api_call_id`, a receipt with `protocol_status`. +- Present when: 7.3 Validate rows 1 to 5, 7 and 8 are observed by calling the receiving end with deliveries of the transport's kind (every inbound path reaches it; an unreadable body is archived and changes nothing; one api call id delivered twice changes state once and is `ignored`; an unknown correlation id is answered and archived under `unmatched`; a delivery is archived even when the apply raises; no outbound call during a delivery; the inbound authentication of the kind). Row 6, the door refusal, is checked by each skill on its own thread. +- Partial when: it receives but routes by path instead of by correlation id, lacks the dedupe, archives after applying, answers the exchange with anything but the 202 receipt (`own`, `existing`), hosts no `/v1/error`, or, with `adapter`, has no poll fallback. Extend it; there is one door. +- A skill whose reader is not wired into the door is partial for its own capability, not for the door. + +### `foundation.state` (7.11) + +- Look for: `query_mode`, `resubmit`, `1518`, a workflow id table (`"12"`, `"PC01"`, `"161"`), `sub_stage`, `next_actions`, a stamp after each write. +- Present when: 7.11 Validate rows 1 to 3 are observed (`adapter_for` with `1518@hcx` and `1518` gives PMJAY and an unknown code gives generic; the PMJAY workflow table equals `references/flow-knowledge.md` section 2; an override changes one kind only), and rows 4 to 7 hold on the seeded states the legs built so far can reach. +- Partial when: the payer table exists and the stage machine does not, or the stage machine lacks this skill's stage branches or labels. Each skill adds its own. + +### `foundation.screens` (7.12) + +- Look for: routes like `/claims`, `/claims/`, `/claims//state`; the tab keys `eligibility`, `plan`, `lines`, `validate`, `preauth`, `communication`, `claim`, `payments`. +- Present when: 7.12 Validate rows 1, 3, 8 and 9 are observed on the shell (the eight tabs in the flow's order with the flow's labels; routes answer 200 for a seeded case and 404 for an unknown one; no input or select named for a rate, a payer name, a `preAuthRef`, a UTR or a status; the state address returns `stage`, `sub_stage`, `next_actions` and `legs`). Rows 4 to 7 belong to the skills whose tabs they test. +- Partial when: the case screen exists without some tabs, without the status line, or without the state address. +- An HMIS with its own screens: the shell may live inside them, for example a panel on the admission screen that opens the case. Present is judged on the eight tabs and the state address, not on the look. + +### `foundation.shell` (7.13, standalone only) + +- Present when: every row of 7.13's Validate section is observed. +- In integrate mode: `not applicable`. The HMIS is the shell; stage 3 finds its patients, admissions, practitioners and documents. + +## Who builds what + +| Verdict at stage 0 | What the running skill does | +| --- | --- | +| `absent` | Builds it in stage 7, before its own modules. 7.1 and 7.3 whole, for the transport chosen at stage 1. 7.2: the episode table and this skill's leg tables. 7.11: the payer adapter table whole, and this skill's stage branches and labels. 7.12: the shell with all eight tabs present in order, its own tabs filled, the others showing their empty state. 7.13 whole, in standalone mode. | +| `partial` | Extends it in the existing code, for the difference stage 0 named, and runs the module's whole Validate section after. | +| `present` | Reuses it. Stage 8 still runs the rows this skill depends on. | + +Record: the Foundation row in `STATE.md` with `Built by` (the skill, or `existing`), and the module record `nhcx-build/7-modules/7.N.md` with a part for each skill that touched it. diff --git a/plugins/nhcx/skills/nhcx-preauth/core/LADDER.md b/plugins/nhcx/skills/nhcx-preauth/core/LADDER.md new file mode 100644 index 000000000..7a6f3f12b --- /dev/null +++ b/plugins/nhcx/skills/nhcx-preauth/core/LADDER.md @@ -0,0 +1,185 @@ +# The NHCX build ladder + +This skill is one of seven NHCX skills, one per use case: `nhcx-coverage`, `nhcx-insurance`, `nhcx-preauth`, `nhcx-claim`, `nhcx-communication`, `nhcx-payment` and `nhcx-reprocess`. Each is a folder of its own and runs on its own: it carries this ladder, the stages, the module files, the references, the flow, the templates and the fetch script. The seven copies of these are the same; only `SKILL.md` differs. This file holds what they share. `SKILL.md` says which flow steps, legs, capabilities, modules, pins and test rows are this skill's own, and what it needs from the use cases before it. + +## Paths + +Paths that start with `core/`, `stages/`, `references/`, `fhir/`, `flow/`, `ui/`, `templates/` or `scripts/` are relative to this skill's folder, the one that holds `SKILL.md`. Paths that start with `nhcx-package/` are in the NHCX package, fetched into the target project beside `nhcx-build/` (below). Paths that start with `nhcx-build/` are the workspace in the target project. + +## Getting the material + +Pins, payer fixtures and docs come from the NHCX package, published at https://github.com/nha-in/nhcx-package. `scripts/fetch-package.sh` downloads the latest release, unpacks it to `nhcx-package/` beside `nhcx-build/` and verifies its MANIFEST (pass a link or a local path to use a different build). `references/material.md` says what the package holds, gives the file of every pin by its label (`preauth/request` is `nhcx-package/fhir/B3/preauth-request.json`), and lists what it does not hold. Read it once, at stage 0. + +## What the skills produce + +Software that raises cashless claims on the National Health Claims Exchange (NHCX) with a private insurer and with PMJAY, in one of two shapes: + +| Mode | You start with | You end with | +| --- | --- | --- | +| `integrate` | A working hospital information system (HMIS, EMR, HIS, billing system) in any language | The same system, with a claims module that speaks NHCX through its transport, kept in sidecar tables and removable | +| `standalone` | Nothing | A self-contained claims desk: its own patients, admissions, documents and screens, speaking NHCX through a transport of its own | + +Every message goes through one transport, chosen at stage 1 from three (`references/transport-knowledge.md` section 1): + +| Transport | When | What the build does | +| --- | --- | --- | +| `existing` | Stage 0 found the app already speaks NHCX: its own client, a vendor gateway, an SDK | Wraps it behind 7.1's `send` and 7.3's door, and closes its gaps; never replaces it | +| `own` | The app has no NHCX integration, and the user has not asked for nhcx-adapter | Builds the protocol into the app from NHA's published chapters: the ABDM session token, the key and certificate, the participant record, the recipient's certificate, the JWE, the callback and its receipt | +| `adapter` | Only when the user asks for nhcx-adapter | Downloads it from https://github.com/nha-in/nhcx-adapter/releases and talks plain FHIR to it (`references/api-knowledge.md`) | + +Never propose nhcx-adapter; use it only when the user asks for it. Whichever the transport, the rest of the build sees the same two things: `send`, and a door that receives `{meta, jwe_headers, fhir}`. + +## The seven skills + +One skill per use case. Together they walk the whole flow in `flow/FLOW.md`; each one alone builds its slice. This folder builds only its own row. The others are named so that a verdict can say which skill owns a missing piece. + +| Skill | Flow steps | Legs | Use cases | Pins | +| --- | --- | --- | --- | --- | +| `nhcx-coverage` | F1, F2, F3 | policy search; `v1/coverageeligibility/check` purpose `discovery`, `validation`, `benefits` | A2, B1, D3 | `coverage/{discovery,validation,benefits}` | +| `nhcx-insurance` | F4, F7 | `v1/insuranceplan/request`; lines quoted from the plan | B2, D1 | `insurance` | +| `nhcx-preauth` | F5, F6, F8, F9, F9a, F9b for a `resubmit` payer, F9c, F9d, F9e | auth requirements; `v1/preauth/submit` 12, 19, 13, 131 and predetermination; cancel PC01 | B3, B8 cancel, B9, D2, D4 to D8 | `coverage/authrequirements`, `preauth/{request,enhancement,queryupdate,cancel}` | +| `nhcx-claim` | F10, F11 | `v1/claim/submit` 15; 161 (PMJAY) or 151 (generic); 16 (generic) | B5, D9, D10 | `claim/{request,queryupdate}` | +| `nhcx-communication` | F9b and the claim query for a `communication` payer, F12b | `v1/communication/request` in; `v1/communication/on_request` out | B4 | `communication/response`, and the `communication/request` reader | +| `nhcx-payment` | F12 | `v1/paymentnotice/request` in; `v1/paymentnotice/on_request` out on 17 or the notice's own id | B7, D13 | `payment/notice-ack` | +| `nhcx-reprocess` | F13 | `v1/task/submit`: reprocess and release on 36, status; 37 and the status Task read | A5, B8 reprocess, D11, D12 | `claim/{reprocess,release}` | + +`flow/flow.json` names the skills of every step in `skills`. Fifteen pins, each owned by exactly one skill, plus the communication request read as the sixteenth comparison. + +### The order they depend on + +The use cases depend on one another in the order the episode happens. A full build runs the seven skills top to bottom. Any one can run alone on an app that already has what it needs; stage 0 establishes whether it does, with the checks in this skill's `SKILL.md` under "Prerequisites". The other skills do not have to be installed for that check. + +| Skill | Needs | Because | +| --- | --- | --- | +| `nhcx-coverage` | nothing | It opens the episode | +| `nhcx-insurance` | coverage: an episode with an `eligible` verdict | The plan is fetched for an eligible episode's policy | +| `nhcx-preauth` | coverage (eligible, and its builder for auth requirements); insurance (plan ready, lines quoted) | Items, prices, documents and forms come from the plan; F9 holds `eligible` | +| `nhcx-claim` | preauth: an approved or partial pre-auth with its `preAuthRef`, the dossier, the Claim builder | The claim goes under the pre-auth's number, built by the same builder | +| `nhcx-communication` | preauth or claim: a leg the payer can ask about, with its bundle as sent | A query names a Claim; the reply lifts entries from the bundle sent | +| `nhcx-payment` | claim: a filed claim | A notice is matched by the claim number | +| `nhcx-reprocess` | claim: a decided claim; payment for a release; preauth for status on a pre-auth | A reprocess reopens a decided claim; a release follows a short payment | + +## The foundation + +Six modules carry every leg and belong to no one skill: 7.1 (the transport), 7.2 (storage), 7.3 (the callback door), 7.11 (state and payer adapters), 7.12 (the case screen shell) and 7.13 (the standalone shell). Every skill's stage 0 checks them. The first skill that finds one absent builds it; a skill that runs later on the same app finds it present and reuses it. `core/FOUNDATION.md` says how to recognise each and what makes it present. + +## What compliant means + +Every skill is held to the same points, for its own legs: + +1. Every hospital-side leg the skill owns (`references/flow-knowledge.md` section 1) is sent with its workflow id, and every payer answer on it is read. +2. Every bundle the skill sends matches its pin in `nhcx-package/fhir` byte for byte, `created` excepted. +3. The callback door answers 2xx fast, dedupes on `x-hcx-api_call_id`, archives before it applies, and matches by correlation id first. +4. No screen shows a decision the exchange has not sent, and nothing the exchange already said is retyped. +5. The offline tests pass, and the report says honestly which rungs of the test pyramid were climbed. +6. The software walks the flow in `flow/FLOW.md`, step for step: the same steps in the same order, the same tabs with the same names, the same guards, the same action labels. The flow is copied, never redesigned. +7. Nothing the app already did is built a second time. Every capability stage 0 found present is reused, and validated and tested like new code. + +## The flow + +An NHCX provider desk walks one path from policy search to settlement, and a build from these skills walks it. `flow/FLOW.md` is that path: thirteen steps with their branches, the case screen's eight tabs in order, the status line, the action labels the desk sees, the guards before every send, and what runs on every page load. `flow/flow.json` is the same, machine-readable, with step ids `F1` to `F13`. Read FLOW.md whole at stage 1; stage 4 copies the steps, stage 5 puts the screens on them, stage 7 implements them by id, stage 8 checks every step has a route. An agent that reorders, merges or renames these steps has left the skill. + +## The ladder + +Twelve stages, 0 to 11. Each has one file under `stages/`, reads the artefacts of the stages before it, writes into `nhcx-build/` in the target project, and ends at a gate. A gate is a list of conditions a reader can check without trusting you. Do not start a stage until the gate before it is closed, and never close a gate by asserting it; close it by pointing at the evidence. + +This skill runs every stage over its own slice. Stage 1 is shared with any other NHCX skill that runs on the same app: the first writes it and later ones confirm it. Parts of stages 3 to 6 are the episode's, not the skill's: the first skill to reach them writes those parts whole, and later skills build on them. + +| Stage | File | Scope | Writes | Gate closes when | +| --- | --- | --- | --- | --- | +| 0 | `stages/0-capability-check.md` | this skill | `nhcx-build/0-capability.md` section, `nhcx-build/capabilities.json` entries | Every own, foundation and prerequisite capability has a verdict with observed evidence | +| 1 | `stages/1-idea.md` | shared | `nhcx-build/1-idea.md` | The mode, the payers, the scope of every step with its skill, and the constraints are written and the user has agreed | +| 2 | `stages/2-planning.md` | this skill | `nhcx-build/2-planning.md` section, this skill's block in `nhcx-build/STATE.md` | Every later stage has a size and a proof; every module has its action from stage 0 | +| 3 | `stages/3-discovery.md` | shared rows; this skill's host facts | `nhcx-build/3-discovery.md` | Every host fact this skill needs is answered with proof, or marked as a gap | +| 4 | `stages/4-flow-and-data-mapping.md` | the flow and table homes episode-wide; this skill's bundles | `nhcx-build/4-flow-data-mapping.md`, `nhcx-build/mapping.json` | Every table has a home, every leg the four ids, every bundle of this skill a source map | +| 5 | `stages/5-screen-plan.md` | the case screen shell episode-wide; this skill's tabs | `nhcx-build/5-screen-plan.md`, `nhcx-build/screens.json` | Every value on this skill's screens names its message; the honesty rules hold | +| 6 | `stages/6-code-plan.md` | this skill's modules; the client and configuration episode-wide | `nhcx-build/6-code-plan.md`, `nhcx-build/modules.json` | Every module this skill touches has files, dependencies, a pin and an action | +| 7 | `stages/7-write-code/README.md` and `7.N-*.md` | what stage 0 found absent or partial | Code, plus `nhcx-build/7-modules/7.N.md` | Each module's "Done when" list is met, in order | +| 8 | `stages/8-validate-modules.md` | every module part this skill owns, reused ones included | `nhcx-build/8-validation.md`, `nhcx-build/8-validation/7.N.json` | Every row passes, or carries a named, accepted exception | +| 9 | `stages/9-write-tests.md` | this skill's pins, readers and matrix rows | Test code, plus `nhcx-build/9-tests.md` | Every row this skill owns has a test, or a written reason it cannot | +| 10 | `stages/10-run-tests.md` | this skill's tests | `nhcx-build/10-test-run.md` and the raw outputs | The offline rung passes; the higher rungs are run only when the user starts the services | +| 11 | `stages/11-build-report.md` | this skill | `nhcx-build/11-report.md` section | The report is written from the artefacts, names every gap, and a stranger could resume from it | + +Stage 7 is a module ladder of its own, 7.1 to 7.13. Each module file carries its own Build, Pseudo code, Validate and Tests sections, and names the skills that build it; stage 8 runs the Validate sections and stage 9 writes the Tests sections, so a module is never validated against a checklist written somewhere else. + +## The workspace + +Everything this skill writes lives in one folder in the target project, so the work can be resumed, reviewed and deleted as a unit. When several NHCX skills work on one app they share that folder, whichever skill folder each runs from: each adds its own section or entries and leaves the others alone. + +``` +nhcx-build/ + STATE.md the gate ledger: the shared rows, the foundation, one block per skill + capabilities.json every capability checked, its verdict and its evidence; read and written by every skill + 0-capability.md one section per skill; scratch checks under 0-capability/ + 1-idea.md shared + 2-planning.md one section per skill + 3-discovery.md shared; each row says which skill answered it + 4-flow-data-mapping.md the flow and table homes, then one section per skill; plus mapping.json + 5-screen-plan.md the case screen shell, then one section per skill; plus screens.json + 6-code-plan.md the client and configuration, then one section per skill; plus modules.json + 7-modules/7.1.md .. 7.13.md one record per module; a shared module has a part per skill + 8-validation.md one section per skill; plus 8-validation/7.N.json, each row tagged with its skill + 9-tests.md one section per skill + 10-test-run.md one section per skill; plus 10-test-run/-*.log + 11-report.md a summary across skills, then one section per skill + NOTES.md every place a skill was silent, ambiguous or wrong +``` + +`templates/` holds the skeleton of each artefact. Copy the skeleton, fill it, keep its headings: later stages find things by heading. + +## How to run a stage + +1. Read `nhcx-build/STATE.md`. If stage 1 in the Shared block is open, and this skill's stage 0 is closed, run stage 1. Otherwise find the first open gate in this skill's block. That is the stage to run; do not skip ahead and do not redo a closed stage unless the user asks. +2. Read the stage file. Read the artefacts it lists under Inputs, and this skill's `SKILL.md` row for the stage. Read the references it names, in the sections it names. +3. Do the work. Write the artefact from its template, in this skill's section. +4. Walk the gate. For each condition, write the evidence into STATE.md: a file path, a line, a command and its output. A condition with no evidence stays open. Every artefact that names a step, a tab or an action uses the ids and words from `flow/flow.json`. +5. If a gate needs the user (stage 0 when a prerequisite is missing; stage 1 always when it is first written; stage 10 rungs 3 and 4 always), stop and ask. Otherwise continue to the next stage. + +Resuming later is step 1 again. Nothing lives in your memory; everything lives in `nhcx-build/`. + +You may be asked to run one stage alone with the earlier artefacts already written. Treat those as closed; do not rewrite them. + +## Rules that hold throughout + +- Reading and offline commands only until stage 10 says otherwise. Never start a service or send live traffic unless the user asks. +- Never edit the files in `nhcx-package/`. They are the truth you are held to. +- Build only what stage 0 found absent or partial. A capability found present is reused through its existing code, never built a second time: two transports or two callback doors break the rule that one module sends and one receives. +- Present means a check was observed passing. Code that looks right is partial until its check has run. +- Never build another skill's capability inside this one. When a prerequisite is missing, stop and say which skill owns it. +- When this skill extends a module another skill built, it re-runs that skill's Validate rows for the module. The rows are in the module file, which every skill folder carries. +- This skill writes its own section of a shared artefact and leaves the other skills' sections alone. +- Never hard-code a document code, a package code or a questionnaire url. Take them from the payer's plan or auth-requirements answer. +- Every outbound leg stores three things from the transport's answer: `txn_id`, `correlation_id` and `api_call_id`. Every message is addressed to the policy's processor (`recipient_code`) and carries the beneficiary's ABHA. Every inbound message is matched by `x-hcx-correlation_id` first and by the claim number inside the bundle second. +- Take the decisions from the module files (Build, Rules, Pseudo code) and `fhir/FHIR.md`, and write them in the target's language and conventions. Never invent a shape the pins do not show. +- Write `nhcx-build/NOTES.md` as you go. A fact the skill does not give you is a gap to record, never a guess to bury in code. +- No em dashes anywhere you write. Short sentences. Tables for anything with more than three columns of fact. +- Do not claim a rung of the test pyramid was climbed when it was not. The report's value is its honesty. + +## Reference map + +| File | Holds | Read at | +| --- | --- | --- | +| `core/FOUNDATION.md` | The six foundation capabilities: how to recognise each, what makes it present, who builds it | Stage 0, stage 7 when building one | +| `references/flow-knowledge.md` | The episode and its legs, every workflow id, the two payer kinds, the classification rule, stage vocabulary, the use-case catalogue, rules no document states | Stages 1, 2, 4, 7.4 to 7.11 | +| `references/transport-knowledge.md` | The three transports and when each applies; the contract `send` and the door rely on; building the protocol yourself from NHA's chapters (token, key and certificate, participant record, policy lookup, recipient certificate, JWE, callback and receipt, status and `/v1/error`); wrapping an existing integration; getting nhcx-adapter when asked | Stages 0, 1, 4, 6, 7.1, 7.3 | +| `references/api-knowledge.md` | The nhcx-adapter contract, read only when the user chose the adapter: config, routes, envelope and answer, delivery, ledger, kit endpoints, curl | 7.1 and 7.3, adapter only | +| `references/fhir-knowledge.md` | Every bundle sent and received, element ids, HPIN, consent questionnaires, supportingInfo, LM100, ONS and DTM, the TaskBundle reply, where the pins live, the validator | Stages 4, 6, 7.4 to 7.10, 8 | +| `references/errors-and-debugging.md` | PAYR and ERR codes with meaning and fix, gateway errors, reading a ledger thread, correlation mistakes, redelivery, sandbox pace | Stages 8, 10, 11 | +| `references/testing-knowledge.md` | The test pyramid, the test-case matrix per use case, a skeleton offline test | Stages 2, 9, 10 | +| `fhir/FHIR.md` | The FHIR guide: every bundle sent and read, entries in pinned order, the code systems, pseudo code for each builder and reader, the refusal each rule guards against | Stages 0, 4, 6, 7.4 to 7.10, 8 | +| `ui/UI-GUIDE.md` | The screens: the two honesty rules, where every value comes from, a layout per screen, the state words, pseudo code for the status line, the timeline and the actions | Stages 5, 7.12, 7.13 | +| `flow/FLOW.md`, `flow/flow.json` | The one path an episode walks: steps F1 to F13 and their skills, the tab order, the action labels, the guards, the page-load polls | Stage 1 whole; stages 4, 5, 7, 8 by step id | +| `references/material.md` | Where the pins, fixtures and docs live: the NHCX package, the pin map, what the package lacks | Stage 0, and whenever a cited file is needed | + +## Keeping the seven copies in step + +Everything in this folder except `SKILL.md` is the same in all seven skill folders. A change to one of these files is made in all seven. `diff -r --exclude=SKILL.md` between any two skill folders prints nothing when they agree. + +## Deliverables + +- This skill's sections of `nhcx-build/`, every gate in its STATE.md block closed with evidence or open with a reason. +- Its verdicts in `capabilities.json`, each with the check that decided it. +- Schema additions for its legs (integrate) or its tables in the whole schema (standalone), under the target's conventions. +- Builders and readers for every leg it owns, each compared with its pin in the offline test. +- Its tabs and screens, deriving every state from received messages. +- Tests covering its rows of the matrix, a run record, and a report section a stranger could act on. diff --git a/plugins/nhcx/skills/nhcx-preauth/fhir/FHIR.md b/plugins/nhcx/skills/nhcx-preauth/fhir/FHIR.md new file mode 100644 index 000000000..90b85cbae --- /dev/null +++ b/plugins/nhcx/skills/nhcx-preauth/fhir/FHIR.md @@ -0,0 +1,658 @@ +# NHCX FHIR: the bundles a hospital sends and reads + +Every bundle here is held to a pin in the NHCX package, under `nhcx-package/fhir/B*`. Read `../references/fhir-knowledge.md` for the why; this file is the how. The pseudo code is language-neutral: a `dict` is a JSON object, a `list` is a JSON array, and `ref(url)` is `{"reference": url}`. + +## 1. Conventions every bundle follows + +"Validator" below is the HL7 FHIR validator with the NRCeS `ndhm.in` IG, run as `../references/fhir-knowledge.md` section 11 describes. + +| Rule | Detail | Refusal if broken | +| --- | --- | --- | +| Bundle | `resourceType Bundle`, `type collection`, `id` fixed per shape, `meta.profile` = the NRCES bundle profile | validator error | +| Entries | Every entry has an absolute `fullUrl` under `https://nhcx.abdm.gov.in/...`; every `reference` resolves to a `fullUrl` in the same bundle | validator error, PAYR-10xx | +| Profiles | Every resource carries `meta.profile` = `https://nrces.in/ndhm/fhir/r4/StructureDefinition/` | validator warning | +| No timestamps on requests | No `meta.versionId`, `meta.lastUpdated`, bundle `timestamp` (the communication reply is the exception) | none, but the pin differs | +| Money | `{"value": n, "currency": "INR"}`; whole numbers as integers, never `3300.0` | pin differs | +| Instants | IST with `+05:30`, seconds precision | PAYR on dates | +| Identifiers | Typed with a `type.coding` from the NDHM identifier-type system or HL7 v2-0203, `system` where the pin has one | PAYR-1083 and kin | + +### Code systems, named once + +``` +NDHM = "https://nrces.in/ndhm/fhir/r4/CodeSystem/" +PROFILE = "https://nrces.in/ndhm/fhir/r4/StructureDefinition/" +BASE = "https://nhcx.abdm.gov.in" +HL7 = "http://terminology.hl7.org/CodeSystem/" +SNOMED = "http://snomed.info/sct" +ICD10 = "http://hl7.org/fhir/sid/icd-10" +HPR = "https://hpr.abdm.gov.in" + +ID_TYPE = NDHM + "ndhm-identifier-type-code" # PMJAY, ABHA, HPID, HPIN, CLN +V2_0203 = HL7 + "v2-0203" # MB, MD, NH, NPI, NIIP +V2_0360 = HL7 + "v2-0360" # qualification degrees +ORG_TYPE = HL7 + "organization-type" # prov, pay +ACT_CODE = HL7 + "v3-ActCode" # HIP +REL = HL7 + "subscriber-relationship" # self +PRIORITY = HL7 + "processpriority" # normal +CARE_ROLE = HL7 + "claimcareteamrole" # primary, assist +DX_TYPE = HL7 + "ex-diagnosistype" # admitting +DX_ONADM = HL7 + "ex-diagnosis-on-admission" # yes +FIN_TASK = HL7 + "financialtaskcode" # poll, cancel, reprocess, release, status +FIN_INPUT = HL7 + "financialtaskinputtype" # include +COMM_CAT = HL7 + "communication-category" # notification + +BENEFIT_CAT = NDHM + "ndhm-benefit-category" # Claim.item.category (specialty) +PROC_CODE = NDHM + "ndhm-procedure-code" # Claim.item.productOrService (package) +PROGRAM = NDHM + "ndhm-program-code" # AB-PMJAY +SI_CATEGORY = NDHM + "ndhm-supportinginfo-category" # INV, ONS, OTH, HDS, DIS, NMI, INF, STG +SI_CODE = NDHM + "ndhm-supportinginfo-code" # ADDD, EDT, PSP, DSDE, DTM, DTH, LAMA, DAMA, CQD, ODN +DOC_CODE = BASE + "/document-code" # the plan's MANDxxxx codes, else ODN +TASK_INPUT = NDHM + "ndhm-task-input-type-code" # policyNumber, providerId, claimNumber, intimationNumber, document +TASK_INPUT_X = BASE + "/task-input-type" # amount +TASK_OUTPUT = NDHM + "ndhm-task-output-type" # status +TASK_OUTVAL = NDHM + "ndhm-task-output-value" # paymentack +TASK_CODES = NDHM + "ndhm-task-codes" # deliver +REASON = NDHM + "ndhm-reason-code" # treatmentplanchanged, claimrejected, partialpayment, rejectiondisputed +CAT_CODE = BASE + "/category-code" # CoverageEligibilityRequest.item.category +PRODUCT_CODE = BASE + "/product-code" # CoverageEligibilityRequest.item.productOrService +PROC_TYPE = BASE + "/procedure-type" # conservative, medical, surgical +DOC_TYPE_EXT = settings.document_type_extension_url # on a Communication attachment; participant-defined (nhcx-package/docs/05-FHIR Reference/17-Communication.md). + # The communication/response pin carries its author's own url: the pin comparison sets this from the pin. +``` + +### Shared helpers + +``` +function cc(system, code, display=null): # CodeableConcept + coding = {"code": code}; if system: coding.system = system; if display: coding.display = display + return {"coding": [coding]} + +function typed_id(type_system, type_code, type_display, value, system=null): + out = {"type": cc(type_system, type_code, type_display), "value": value} + if system: out.system = system # put "system" before "value" as the pins do; canonical JSON sorts anyway + return out + +function entry(url, resource): return {"fullUrl": url, "resource": resource} + +function profile(name): return {"profile": [PROFILE + name]} + +function bundle(id, profile_name, entries): # profile_name: "ClaimBundle", "TaskBundle", "CoverageEligibilityRequestBundle" + return {"resourceType": "Bundle", "id": id, "meta": profile(profile_name), "type": "collection", "entry": entries} + +function organization(role, identifier_code, identifier_display, id_value, name, res_id=null): + o = {"resourceType": "Organization", "meta": profile("Organization"), + "identifier": [typed_id(V2_0203, identifier_code, identifier_display, id_value, BASE)], + "type": [cc(ORG_TYPE, role, "Healthcare Provider" if role == "prov" else "Payer")], "name": name} + if res_id: o.id = res_id + return o + +function provider_org(facility, res_id=null): return organization("prov", "NPI", "National provider identifier", facility.hfr_id, facility.name, res_id) +function payer_org(payer, res_id=null): return organization("pay", "NIIP", "National Insurance Payor Identifier (Payor)", strip_hcx(payer.participant_code), payer.name, res_id) +function strip_hcx(code): return code.split("@")[0] + +function money(v): return {"value": int(v) if v == int(v) else round(v, 2), "currency": "INR"} +``` + +## 2. Coverage eligibility request + +Pins: `coverage/{discovery,validation,benefits,authrequirements}`. Sent on `v1/coverageeligibility/check`, workflow id = the case number. Purposes: `discovery` (who covers this person), `validation` (is the policy in force), `benefits` (balances), `auth-requirements` (rule on the quoted items). + +Entries, in order: CoverageEligibilityRequest, Patient, provider Organization, payer Organization, Location, Coverage, PractitionerRole. + +``` +function build_coverage_request(d): + # d: purpose, member_id, policy_code (null on discovery), facility{hfr_id,name}, payer{participant_code,name}, created, items[] (benefits, auth-requirements only) + U = BASE + cer = {"resourceType": "CoverageEligibilityRequest", "meta": profile("CoverageEligibilityRequest"), + "identifier": [{"system": BASE}], "status": "active", + "priority": cc(PRIORITY, "normal", "Normal"), "purpose": [d.purpose], + "patient": ref(U + "/patient"), "created": d.created, + "enterer": ref(U + "/practitioner-role"), "provider": ref(U + "/provider"), + "insurer": ref(U + "/payer"), "facility": ref(U + "/location"), + "insurance": [{"focal": true, "coverage": ref(U + "/coverage")}]} + if d.purpose in ("benefits", "auth-requirements"): + cer.item = [eligibility_item(i) for i in d.items] + patient = {"resourceType": "Patient", "meta": profile("Patient"), + "identifier": [typed_id(ID_TYPE, "PMJAY", "Pradhan Mantri Jan Aarogya Yojana (PMJAY) ID", d.member_id), + typed_id(V2_0203, "MB", "Member Number", d.member_id)]} # no name, no demographics + coverage = {"resourceType": "Coverage", "meta": profile("Coverage"), + "identifier": [typed_id(V2_0203, "NH", "National Health Plan Identifier", d.policy_code or "NONE")], + "status": "active", "type": cc(ACT_CODE, "HIP", "health insurance plan policy"), + "subscriber": ref(U + "/patient"), "subscriberId": d.member_id, "beneficiary": ref(U + "/patient"), + "relationship": cc(REL, "self"), "payor": [ref(U + "/payer")]} + location = {"resourceType": "Location", "name": d.facility.name, "managingOrganization": ref(U + "/provider")} + role = {"resourceType": "PractitionerRole", "meta": profile("PractitionerRole"), + "code": [cc(SNOMED, "307988006", "Medical technician")]} + return bundle("coverage-" + d.purpose.replace("-", "") + "-request-generic", "CoverageEligibilityRequestBundle", [ + entry(U + "/coverage-eligibility/request", cer), entry(U + "/patient", patient), + entry(U + "/provider", provider_org(d.facility)), entry(U + "/payer", payer_org(d.payer)), + entry(U + "/location", location), entry(U + "/coverage", coverage), entry(U + "/practitioner-role", role)]) + +function eligibility_item(i): + # i: category{code,display}, code, display, quantity (integer), tiers[] {code, display} + out = {"category": cc(CAT_CODE, i.category.code, i.category.display), + "productOrService": cc(PRODUCT_CODE, i.code, i.display), + "quantity": {"value": int(i.quantity)}} + if i.tiers: out.modifier = [cc(null, t.code, t.display) for t in i.tiers] # no system on a tier + return out +``` + +Bundle ids: `coverage-discovery-request-generic`, `coverage-validation-request-generic`, `coverage-benefits-request-generic`, `coverage-authrequirements-request-generic`. + +### Reader: CoverageEligibilityResponse + +The payer echoes the request's entries and appends its own; take the last of each type. + +``` +function parse_validation_bundle(b): + resp = last(b, "CoverageEligibilityResponse"); pat = last(b, "Patient"); cov = last(b, "Coverage") + out = {"outcome": resp.outcome, "disposition": resp.disposition, "inforce": resp.insurance[0].inforce, + "auth_required": any(item.authorizationRequired for item in resp.insurance[0].item or []), + "allowed": null, "used": null} + for item in resp.insurance[0].item or []: + for ben in item.benefit or []: + if ben.allowedMoney and (out.allowed is null or ben.allowedMoney.value > out.allowed): + out.allowed = ben.allowedMoney.value; out.used = (ben.usedMoney or {}).value or 0 + out.patient = {"name": pat.name[0].text, "gender": pat.gender, "birthDate": pat.birthDate, + "abha": first_identifier(pat, "ABHA"), "photo": pat.photo[0].data if pat.photo else null} + out.coverage = {"class": cov.class[0].name if cov.class else null, "period": cov.period} + return out +# status: eligible if inforce else not-eligible; balance shown = allowed - used +``` + +### Reader: the auth-requirements ruling + +``` +function parse_auth_bundle(b): + resp = last(b, "CoverageEligibilityResponse"); items = []; requirements = [] + for item in resp.insurance[0].item or []: + items.append({"code": item.productOrService.coding[0].code, "authorised": item.authorizationRequired, + "excluded": item.excluded, "benefit": item.benefit[0] if item.benefit else null}) + for sup in item.authorizationSupporting or []: + text = sup.text or "" # the scheme overloads free text + r = {"line": item.productOrService.coding[0].code, "code": sup.coding[0].code if sup.coding else null, + "display": sup.coding[0].display if sup.coding else text} + if "fullUrl:" in text: r.kind = "form"; r.url = after("fullUrl:", text).strip(); r.stage = "pre" + else: r.kind = "document"; r.stage = "post" if "Type: post" in text else "pre" + r.at_preauth = (r.kind == "form") or (r.stage == "pre") + requirements.append(r) + return {"items": items, "requirements": requirements} +``` + +## 3. Insurance plan request + +Pin: `insurance`. Sent on `v1/insuranceplan/request`, workflow id = the case number. One entry. + +``` +function build_plan_request(policy_code, provider_id): + task = {"resourceType": "Task", "meta": profile("Task"), "status": "requested", "intent": "order", + "code": cc(FIN_TASK, "poll"), + "input": [{"type": cc(TASK_INPUT, "policyNumber"), "valueString": policy_code}, + {"type": cc(TASK_INPUT, "providerId"), "valueString": provider_id}]} + return bundle("insurance-request-generic", "TaskBundle", [entry(BASE + "/insurance/request", task)]) +# no id, no authoredOn, no requester; at least one input is mandatory +``` + +### Reader: the plan + +``` +function parse_plan_bundle(b): + plan = first(b, "InsurancePlan"); forms = {q.url: q for q in all(b, "Questionnaire")} + benefits = {} # keyed by package code + for p in plan.plan or []: # shape 1: package-based + for sc in p.specificCost or []: + specialty = sc.category.coding[0] + for ben in sc.benefit or []: + code = ben.type.coding[0].code; row = benefits.setdefault(code, new_benefit(code, ben.type.coding[0].display, specialty)) + for cost in ben.cost or []: + kind = cost.type.coding[0].code # Procedure | Implant | Stratification + if kind == "Procedure": row.rate = cost.value.value; row.kind = "Procedure" + else: row.extras.append({"kind": kind, "code": cost.qualifiers[0].coding[0].code, "display": cost.qualifiers[0].coding[0].display, "amount": cost.value.value}) + row.conditions.update(read_conditions(ben.extension)); row.requirements += read_requirements(ben.extension) + for cov in plan.coverage or []: # shape 2: coverage-based + for ben in cov.benefit or []: + code = ben.type.coding[0].code; row = benefits.setdefault(code, new_benefit(code, ben.type.coding[0].display, cov.type.coding[0])) + for lim in ben.limit or []: + if lim.code.coding[0].code == code: row.rate = lim.value.value + else: row.extras.append({"kind": "Stratification", "code": lim.code.coding[0].code, "display": lim.code.coding[0].display, "amount": lim.value.value}) + row.conditions.update(read_conditions(ben.extension)); row.requirements += read_requirements(ben.extension) + policy_requirements = read_requirements(plan.extension) # policy-wide: identity proof, consent forms + return {"plan": {"id": plan.id, "name": plan.name}, "benefits": list(benefits.values()), + "policy_requirements": policy_requirements, + "forms": [{"url": u, "title": q.title, "kind": "stg" if "/stgquestionnaire/" in u else "policy", + "questions": [{"linkId": it.linkId, "text": it.prefix or it.text, "type": it.type, + "options": [o.valueString or o.valueCoding.display for o in it.answerOption or []], + "default": first_selected(it)} for it in q.item]} for u, q in forms.items()]} + +function read_conditions(exts): # extension url family "...Claim-Condition": children named by their url tail + out = {} + for e in exts or []: + if "Claim-Condition" in e.url: + for child in e.extension or []: out[tail(child.url)] = child.valueString or child.valueBoolean or child.valueCodeableConcept.coding[0].code + return out + +function read_requirements(exts): # "...Claim-SupportingInfoRequirement": one nested requirement per document + out = [] + for e in exts or []: + if "Claim-SupportingInfoRequirement" in e.url: + for req in e.extension or []: + r = {} + for f in req.extension or []: + if tail(f.url) == "category": r.category = f.valueCodeableConcept.coding[0].code + if tail(f.url) == "code": r.code = f.valueCodeableConcept.coding[0].code; r.display = f.valueCodeableConcept.coding[0].display + if tail(f.url) == "documentationUrl": r.url = f.valueUri or f.valueString + out.append(r) + return out +``` + +## 4. The Claim bundle + +Pins: `preauth/request`, `preauth/enhancement`, `preauth/queryupdate`, `claim/request`, `claim/queryupdate`. One builder, three switches: `leg` (`preauth`, `claim`, `predetermination`), `flow` (`request`, `enhancement`, `queryupdate`), `use` (`preauthorization`, `claim`, `predetermination`). + +Entries, in order: Claim, Patient, provider Organization (id 1), payer Organization (id 2), Coverage (id 1), Practitioner (one per care team member), Procedure (one per package line), QuestionnaireResponse (one per answered form). + +``` +function claim_bundle(leg, use, d): + # d: flow, claim_no, created, admission{admitted_at, discharged_at, surgery_at, death_at, mode, stage}, + # patient{member_id, abha, name, phone, gender, birthDate}, facility, payer, policy_code, + # care_team[] {hpid, licence, hpin, name, qualification_code, qualification_display, specialty_snomed, specialty_display}, + # diagnoses[] {code, display}, lines[] (procedures and implants, each with tiers[]), documents[] {code, category, content_type, bytes, title}, + # forms[] {url, answers[] {linkId, type, value}}, program_code (AB-PMJAY or null), factor_rule (pmjay or null), + # preauth_ref (claim leg), summary{code, content_type, bytes, title} (claim leg), query_reply (queryupdate) + U = BASE; anchor = U + "/" + leg + "/" + d.flow + practitioners = [practitioner_resource(m, n + 1) for n, m in enumerate(d.care_team)] + procedures = [procedure_resource(line, n + 1, completed = (leg == "claim"), when = d.admission.surgery_at or d.admission.admitted_at) for n, line in enumerate(package_lines(d.lines))] + (qrs, form_refs) = questionnaire_responses(d.forms, d.created) + (si, si_refs) = supporting_info(d, leg, form_refs) + claim = {"resourceType": "Claim", "id": d.claim_no, "meta": profile("Claim"), + "identifier": [typed_id(ID_TYPE, "CLN", "Claim number", d.claim_no, BASE)], + "status": "active", "type": cc(SNOMED, "737481003", "Inpatient care management (procedure)"), "use": use, + "patient": ref(U + "/patient"), + "billablePeriod": {"start": d.admission.admitted_at, "end": d.admission.discharged_at or planned_end(d)}, + "created": d.created, "insurer": ref(U + "/payer"), "provider": ref(U + "/provider"), + "priority": cc(PRIORITY, "normal", "Normal"), + "careTeam": [{"sequence": n + 1, "provider": ref(practitioner_url(n)), + "role": cc(CARE_ROLE, "primary" if n == 0 else "assist", "Primary provider" if n == 0 else "Assisting Provider"), + "qualification": cc(SNOMED, m.specialty_snomed, m.specialty_display)} for n, m in enumerate(d.care_team)], + "supportingInfo": si, + "diagnosis": [{"sequence": n + 1, "diagnosisCodeableConcept": cc(ICD10, dx.code, dx.display), + "type": [cc(DX_TYPE, "admitting", "Admitting Diagnosis")], "onAdmission": cc(DX_ONADM, "yes", "Yes")} for n, dx in enumerate(d.diagnoses)], + "procedure": [{"id": "Procedure/" + str(n + 1), "sequence": n + 1, + "type": [cc(PROC_TYPE, line.procedure_type.lower(), line.procedure_type)], # from the plan's ProcedureType condition + "date": d.admission.surgery_at or d.admission.admitted_at, + "procedureReference": {"reference": U + "/procedure/" + str(n + 1), "display": line.display}} for n, line in enumerate(package_lines(d.lines))], + "insurance": [{"sequence": 1, "focal": true, "coverage": ref(U + "/coverage")}], + "item": claim_items(d, si_refs), + "total": money(sum(item.net.value for item in items))} + if leg == "claim": claim.insurance[0].preAuthRef = [d.preauth_ref] # the payer's ClaimResponse.preAuthRef + entries = [entry(anchor, claim), entry(U + "/patient", patient_resource(d.patient)), + entry(U + "/provider", provider_org(d.facility, "1")), entry(U + "/payer", payer_org(d.payer, "2")), + entry(U + "/coverage", coverage_resource(d.policy_code, d.patient.member_id))] + entries += [entry(practitioner_url(n), p) for n, p in enumerate(practitioners)] + entries += [entry(U + "/procedure/" + str(n + 1), p) for n, p in enumerate(procedures)] + entries += [entry(U + "/questionnaireresponse/" + str(n + 1), q) for n, q in enumerate(qrs)] + return bundle(leg + "-" + d.flow + "-request-generic", "ClaimBundle", entries) + # preauth-request-generic, preauth-enhancement-request-generic, preauth-queryupdate-request-generic, claim-request-generic, claim-queryupdate-request-generic + +function practitioner_url(n): return BASE + "/practitioner" + ("" if n == 0 else "/" + str(n + 1)) + +function patient_resource(p): + ids = [typed_id(ID_TYPE, "PMJAY", "Pradhan Mantri Jan Aarogya Yojana (PMJAY) ID", p.member_id)] + if p.abha: ids.append(typed_id(ID_TYPE, "ABHA", "Ayushman Bharat Health Account (ABHA) ID", p.abha)) + ids.append(typed_id(V2_0203, "MB", "Member Number", p.member_id)) + return {"resourceType": "Patient", "id": "1", "meta": profile("Patient"), "identifier": ids, + "name": [{"text": p.name}], "telecom": [{"system": "phone", "value": p.phone}], "gender": p.gender, "birthDate": p.birthDate} + +function practitioner_resource(m, n): + ids = [typed_id(ID_TYPE, "HPID", "Healthcare Professional ID (HPID)", m.hpid or m.hpin, BASE)] + if m.licence: ids.append(typed_id(V2_0203, "MD", "Medical License number", m.licence, BASE)) + ids.append(typed_id(ID_TYPE, "HPIN", "Health Practitioner ID issued by NDHM", m.hpin, HPR)) # PAYR-1083 without it + return {"resourceType": "Practitioner", "id": str(n), "meta": profile("Practitioner"), "identifier": ids, + "name": [{"text": m.name}], "qualification": [{"code": cc(V2_0360, m.qualification_code, m.qualification_display)}]} + +function coverage_resource(policy_code, member_id): + return {"resourceType": "Coverage", "id": "1", "meta": profile("Coverage"), + "identifier": [typed_id(V2_0203, "NH", "National Health Plan Identifier", policy_code)], + "status": "active", "type": cc(ACT_CODE, "HIP", "health insurance plan policy"), + "subscriber": ref(BASE + "/patient"), "subscriberId": member_id, "beneficiary": ref(BASE + "/patient"), + "relationship": cc(REL, "self"), "payor": [ref(BASE + "/payer")]} + +function procedure_resource(line, n, completed, when): + return {"resourceType": "Procedure", "id": str(n), "meta": profile("Procedure"), + "status": "completed" if completed else "preparation", + "code": {"coding": [{"system": SNOMED, "code": "71388002", "display": "Procedure"}], "text": line.display}, + "subject": ref(BASE + "/patient"), "performedDateTime": when} +``` + +### Items: one per procedure or implant, never per tier + +``` +function package_lines(lines): return [l for l in lines if l.kind in ("procedure", "implant")] # tiers ride on their parent + +function claim_items(d, si_refs): + groups = package_lines(d.lines); factors = procedure_factors(groups, d.factor_rule) + items = [] + for n, line in enumerate(groups): + tiers = [t for t in d.lines if t.kind == "tier" and t.parent_code == line.code] + net = line.amount + sum(t.amount for t in tiers) + item = {"id": "Item/" + str(n + 1), "sequence": n + 1, "careTeamSequence": [1], "diagnosisSequence": [1], + "procedureSequence": [n + 1], "informationSequence": si_refs, # every supportingInfo sequence + "category": cc(BENEFIT_CAT, line.category.code, line.category.display), + "productOrService": cc(PROC_CODE, line.code, line.display)} + if tiers: item.modifier = [cc(null, t.code, t.display) for t in tiers] + if d.program_code: item.programCode = [cc(PROGRAM, d.program_code, "Ayushman Bharat Pradhan Mantri Jan Arogya Yojana (AB-PMJAY)")] + item.servicedPeriod = {"start": day(d.admission.admitted_at), "end": day(d.admission.discharged_at or planned_end(d))} + item.quantity = {"value": int(line.quantity)} + item.unitPrice = money(net / line.quantity) + if factors: item.factor = factors[n] + item.net = money(net) + items.append(item) + return items + +function procedure_factors(groups, rule): + # PMJAY multiple-procedure rule: by cost rank, 1, 0.5, 0.25; a generic payer sends no factor + if rule != "pmjay" or len(groups) < 2: return null # the single-item pins carry factor 0.5 (their own contradiction); compare without it + ranked = sorted(range(len(groups)), key = lambda i: -groups[i].amount) + return {i: [1, 0.5, 0.25][min(rank, 2)] for rank, i in enumerate(ranked)} +``` + +### supportingInfo: the table, then the numbering + +``` +function supporting_info(d, leg, form_refs): + si = [] + for doc in d.documents: # one per attached file; never drop one + si.append({"category": cc(SI_CATEGORY, doc.category or "INV", display_for(doc.category or "INV")), + "code": cc(DOC_CODE, doc.code or "ODN", doc.title), # the plan's code, else ODN + "valueAttachment": {"contentType": doc.content_type, "data": base64(doc.bytes), "title": doc.title}}) + if leg == "claim": + si.append({"category": cc(SI_CATEGORY, "HDS", "Discharge summary"), "code": cc(DOC_CODE, d.summary.code or "HDS", d.summary.title), + "valueAttachment": {"contentType": d.summary.content_type, "data": base64(d.summary.bytes), "title": d.summary.title}}) + si.append(scalar("ONS", "ADDD", "Admission date -Discharge date", d.admission.admitted_at)) + si.append(scalar("OTH", "EDT", "EncounterDateTime", d.admission.admitted_at)) + if leg == "claim": + if d.admission.surgery_at: si.append(scalar("ONS", "PSP", "Procedure start", d.admission.surgery_at)) + si.append(scalar("ONS", "DSDE", "Discharge date", d.admission.death_at or d.admission.discharged_at)) + if d.admission.mode == "death": si.append(scalar("ONS", "DTM", "Date and time of death", d.admission.death_at)) # PAYR-1096 without it + code = {"normal": "DTH", "lama": "LAMA", "dama": "DAMA", "death": "DTM"}[d.admission.mode] + si.append(scalar("DIS", code, display_for(code), stage_words(d.admission.stage))) # "Before Surgery" | "During Surgery" | "After Surgery" + if d.flow == "queryupdate": + si.append(scalar("NMI", "CQD", "Claim query detail", d.query_reply)) # the desk's words; PMJAY reads its answer from here + for (form, url) in form_refs: # one per answered form + cat = "STG" if form.kind == "stg" else "INF"; code = "STG" if form.kind == "stg" else "ODN" + si.append({"category": cc(SI_CATEGORY, cat, display_for(cat)), "code": cc(SI_CODE, code, display_for(code)), "valueReference": ref(url)}) + for n, s in enumerate(si): # number once, after assembly: PAYR-1019 without sequence + s.id = "SupportingInformation/" + str(n + 1); s.sequence = n + 1 + reorder(s, ["id", "sequence", "category", "code", "value*"]) + return (si, [s.sequence for s in si]) + +function scalar(cat, code, display, value): + return {"category": cc(SI_CATEGORY, cat, display_for(cat)), "code": cc(SI_CODE, code, display), "valueString": value} +``` + +### Questionnaire responses + +``` +function questionnaire_responses(forms, authored): + qrs = []; refs = [] + for n, form in enumerate(forms): + url = BASE + "/questionnaireresponse/" + str(n + 1) + qr = {"resourceType": "QuestionnaireResponse", "id": str(n + 1), "meta": profile("QuestionnaireResponse"), + "questionnaire": form.url, "status": "completed", "subject": ref(BASE + "/patient"), "authored": authored, + "item": [{"linkId": a.linkId, "answer": [typed_answer(a)]} for a in form.answers]} + qrs.append(qr); refs.append((form, url)) + return (qrs, refs) + +function typed_answer(a): + switch a.type: + "string", "text", "choice": return {"valueString": a.value} + "date", "dateTime": return {"valueDateTime": a.value} + "boolean": return {"valueBoolean": a.value} + "integer": return {"valueInteger": int(a.value)} + "decimal": return {"valueDecimal": a.value} + "attachment": return {"valueAttachment": {"contentType": a.content_type, "data": base64(a.bytes), "title": a.title}} +``` + +### Which forms and documents ride + +``` +function required_forms(case, stage): # stage: preauth | claim + if case.ruling: forms = [r for r in case.ruling.requirements if r.kind == "form" and (stage == "preauth" or r.stage != "pre")] + else: forms = plan_stg_forms(case.plan, case.lines) if stage == "preauth" else [] + return forms + policy_forms(case.plan) # consent every leg: PAYR-1256 / PAYR-1363; STG: PAYR-1254 / PAYR-1365 + +function required_documents(case, stage): + if case.ruling: return [r for r in case.ruling.requirements if r.kind == "document" and (r.stage == "pre") == (stage == "preauth")] + wanted = plan_documents(case.plan, case.lines) + return wanted if stage == "preauth" else [w for w in wanted if not attached_at_preauth(case, w.code)] +``` + +### The legs, and the LAMA collapse + +``` +function lines_for(case, leg): + if leg == "claim" and case.admission.mode in ("lama", "dama") and case.admission.stage in ("before", "during"): + return [{"kind": "procedure", "code": "LM100", "display": "Left against medical advice", "quantity": 1, + "amount": plan_rate(case.plan, "LM100") or 0, "category": lm100_category(case.plan)}] # PAYR-1362 if the package stays + return case.lines # LM100 never on a pre-auth: PAYR-1270 +``` + +| Leg | flow | use | Procedure status | Workflow | Extra | +| --- | --- | --- | --- | --- | --- | +| Pre-auth | `request` | `preauthorization` | `preparation` | 12 | fresh 12 after a rejection too (PAYR-1214 on 121) | +| Enhancement | `enhancement` | `preauthorization` | `preparation` | 13 | every line, old and new, same claim number; factors 1 and 0.5 | +| Query answer | `queryupdate` | `preauthorization` | `preparation` | 19 (131 after an enhancement query) | `NMI/CQD`; new correlation id | +| Claim | `request` | `claim` | `completed` | 15 | discharge scalars, `HDS`, `preAuthRef`, under the pre-auth's number (ERR-PYR-CLM-007) | +| Claim query answer | `queryupdate` | `claim` | `completed` | 161 (PMJAY), 151 (generic) | as the claim plus `NMI/CQD` | +| Predetermination | `request` | `predetermination` | `preparation` | 12 on `v1/preauth/submit` | no state effects | + +## 5. Reader: ClaimResponse + +Fed by every answer on a pre-auth, enhancement, claim or predetermination thread. Entries: ClaimResponse, Patient, two Organizations, Coverage. + +``` +function parse_claim_response(b): + r = first(b, "ClaimResponse") + status_adj = first(a for a in r.adjudication or [] if a.category.coding[0].code == "status") + out = {"use": r.use, "outcome": r.outcome, "disposition": r.disposition, + "status_reason": status_adj.reason.coding[0].code.lower() if status_adj else null, # submitted|approved|queried|rejected|cancelled + "preauth_ref": r.preAuthRef if is_string(r.preAuthRef) else (r.preAuthRef[0] if r.preAuthRef else null), + "claim_no": r.identifier[0].value if r.identifier else null, + "totals": {t.category.coding[0].code: t.amount.value for t in r.total or []}, # by category, never by position + "items": [], "notes": [n.text for n in r.processNote or []]} + for it in r.item or []: + adj = {a.category.coding[0].code: a for a in it.adjudication or []} + out.items.append({"sequence": it.itemSequence, + "status": adj.status.reason.coding[0].code.lower() if adj.status else null, + "eligible": adj.eligible.amount.value if adj.eligible else null, + "submitted": adj.submitted.amount.value if adj.submitted else null, + "reason": adj.reason.reason.coding[0].display if adj.reason else "", # verbatim, pipe-delimited USER~datetime~type~comment~trust + "eligpercent": adj.eligpercent.value if adj.eligpercent else null, + "deductible": adj.deductible.amount.value if adj.deductible else null}) + return out + +function verdict_status(p): # copy exactly; never read outcome alone + if p.outcome == "queued" or p.status_reason == "submitted": return "submitting" + if p.status_reason == "cancelled": return "rejected" + if p.status_reason == "queried": return "queried" + if p.outcome == "error": return "rejected" + if p.outcome == "partial": return "partial" if p.status_reason == "approved" else "queried" + if p.outcome == "complete": return "approved" if p.status_reason in ("approved", null) else "queried" + return "queried" + +function apply_claim_response(leg, p, envelope): + leg.status = verdict_status(p) + if p.preauth_ref: leg.preauth_ref = p.preauth_ref # never overwrite a value with an empty one + leg.eligible_amount = p.totals.get("eligible") or p.totals.get("benefit") + leg.submitted_amount = p.totals.get("submitted") + leg.approved_amount = p.totals.get("benefit") # what the screen shows as the decision + leg.items_json = p.items; leg.query_note = join(p.notes + [i.reason for i in p.items if i.reason]) + leg.thread_correlation_id = envelope.jwe_headers["x-hcx-correlation_id"] + leg.answered_at = now() if leg.status != "submitting" else leg.answered_at +``` + +Payer workflow ids are labels for the timeline only: 20 received, 21 approved, 22 enhancement approved, 23 rejected, 24 queried, 25 claim received, 26 approved, 27 queried, 291 rejected. The bundle decides the state. + +## 6. Task bundles the hospital sends + +Pins: `preauth/cancel`, `claim/reprocess`, `claim/release`, `payment/notice-ack`. Sent on `v1/task/submit` (the payment acknowledgement on `v1/paymentnotice/on_request`). Entries: Task, provider Organization, payer Organization. + +``` +function task_bundle(id, anchor, task, facility, payer): + return bundle(id, "TaskBundle", [entry(BASE + anchor, task), entry(BASE + "/provider", provider_org(facility)), entry(BASE + "/payer", payer_org(payer))]) + +function base_task(code, status, authored_on, description): + return {"resourceType": "Task", "meta": profile("Task"), "status": status, "intent": "order", + "code": cc(FIN_TASK, code), "description": description, "authoredOn": authored_on, + "requester": ref(BASE + "/provider"), "owner": ref(BASE + "/payer")} + +function task_input(code, display, value): return {"type": cc(TASK_INPUT, code, display), "valueString": value} +function based_on(claim_no): return [{"identifier": typed_id(ID_TYPE, "CLN", "Claim number", claim_no, BASE), "display": "Claim " + claim_no}] + +function cancel_task(claim_no, reason, authored_on, facility, payer): # workflow PC01 + t = base_task("cancel", "requested", authored_on, "Cancel the preauthorization " + claim_no) + t.reasonCode = cc(REASON, reason.code, reason.display) # treatmentplanchanged, ... + t.input = [task_input("claimNumber", "ClaimNumber", claim_no), task_input("intimationNumber", "IntimationNumber", claim_no)] + return task_bundle("preauth-cancel-request-generic", "/preauth/cancel", t, facility, payer) + +function reprocess_task(claim_no, member_id, reason, description, documents, authored_on, facility, payer): # workflow 36 + t = base_task("reprocess", "requested", authored_on, description) + t.reasonCode = cc(REASON, reason.code, reason.display) # claimrejected | partialpayment | rejectiondisputed + t.basedOn = based_on(claim_no) + t.input = [task_input("claimNumber", "ClaimNumber", claim_no), task_input("intimationNumber", "IntimationNumber", claim_no)] + t.input += [{"type": cc(TASK_INPUT, "document", "Document"), "valueAttachment": {"contentType": d.content_type, "data": base64(d.bytes), "title": d.title}} for d in documents] + t.for = {"identifier": typed_id(ID_TYPE, "PMJAY", "Pradhan Mantri Jan Aarogya Yojana (PMJAY) ID", member_id)} # MB on a generic payer + return task_bundle("claim-reprocess-request-generic", "/claim/reprocess", t, facility, payer) + +function release_task(claim_no, amount, authored_on, facility, payer): # workflow 36 + t = base_task("release", "requested", authored_on, "Release the balance amount for claim " + claim_no) + t.reasonCode = cc(REASON, "partialpayment", "Reprocess request due to partial payment by payer") + t.basedOn = based_on(claim_no) + t.input = [task_input("claimNumber", "ClaimNumber", claim_no), {"type": cc(TASK_INPUT_X, "amount", "Amount"), "valueMoney": money(amount)}] + return task_bundle("claim-release-request-generic", "/claim/release", t, facility, payer) + +function status_task(claim_no, authored_on, facility, payer): # workflow = the leg's correlation id; PMJAY refuses (PAYR-1018) + t = base_task("status", "requested", authored_on, "Status of " + claim_no) + t.input = [task_input("claimNumber", "ClaimNumber", claim_no)] + return task_bundle("claim-status-request-generic", "/claim/status", t, facility, payer) + +function payment_ack(claim_no, authored_on, facility, payer): # workflow 17 (PMJAY) or the notice's own id; x-hcx-correlation_id = the notice's + t = base_task("status", "completed", authored_on, "Received the payment for claim " + claim_no) + t.output = [{"type": cc(TASK_OUTPUT, "status", "Status"), "valueCodeableConcept": cc(TASK_OUTVAL, "paymentack", "Payment is acknowledged")}, + {"type": cc(TASK_INPUT, "claimNumber", "ClaimNumber"), "valueString": claim_no}] + return task_bundle("payment-notice-ack-generic", "/payment/notice-ack", t, facility, payer) +``` + +The pins and the build both carry `intimationNumber`, so the offline comparison diffs the pins unchanged. + +### Readers: PC02, 37, status + +``` +function parse_task_answer(b): + t = first(b, "Task"); cr = first(b, "ClaimResponse") # a 37 may carry a ClaimResponse queued + outputs = {o.type.coding[0].code: o for o in t.output or []} + return {"status": t.status, "code": t.code.coding[0].code, + "claim_status": (outputs.get("claimStatus") or outputs.get("status") or {}).valueCodeableConcept.coding[0].code if outputs else null, + "description": t.description, "queued": cr is not null and cr.outcome == "queued"} +# PC02: pre-auth -> cancelled, episode gets a fresh claim number, the withdrawn one stays on the leg +# 37: enquiry row -> answered; a fresh verdict follows on the claim's own thread +``` + +## 7. Communication + +Pins: `communication/request` (the payer's TaskBundle, the reader's input) and `communication/response` (the hospital's reply). On `v1/communication/request` in, `v1/communication/on_request` out, with the request's correlation id and workflow id echoed. + +``` +function parse_communication_request(b): + t = first(b, "Task"); cr = first(b, "CommunicationRequest") + return {"task_status": t.status, "intent": t.intent, "reason": t.reasonCode.coding[0].code.lower() if t.reasonCode else null, + "request_id": cr.id, "request_url": fullurl_of(b, cr), + "questions": [p.contentString for p in cr.payload or [] if p.contentString], + "about_claim": (cr.basedOn or [{}])[0].display, "claim_no": claim_no_in(b)} + +function classify_communication(adapter, reason, intent): + if adapter.query_mode == "resubmit": return "notification" + if intent == "proposal": return "notification" + if intent == "order": return "query" + if reason in (null, "additionalinfo", "questionnaire", "query"): return "query" + return "notification" # tatquery, grievance, walletupdate, policychange, claimarbitration + +function build_acknowledgement_bundle(request_bundle, facility): # a notification, sent back at once + b = deepcopy(request_bundle); t = first(b, "Task"); t.status = "completed" + move_first(b, "Organization", where = provider) # provider Organization first + return b + +function build_communication_bundle(q, text, documents, sent_leg_bundle, facility, payer, now): + # q: the parsed request; sent_leg_bundle: the pre-auth or claim bundle as sent (its Claim, Patient, Organizations, Practitioner, Coverage are lifted) + task_id = uuid(); comm_id = uuid() + comm = {"resourceType": "Communication", "id": comm_id, "meta": profile("Communication"), + "identifier": [{"value": q.request_identifier}], "basedOn": [{"reference": q.request_url, "display": "CommunicationRequest"}], # never inResponseTo + "status": "completed", "category": [cc(COMM_CAT, "notification")], "priority": "routine", + "about": [{"reference": claim_anchor(sent_leg_bundle), "display": "Claim " + claim_no}], + "sender": {"reference": BASE + "/provider", "display": "Organization"}, "recipient": [{"reference": BASE + "/payer", "display": "Organization"}], + "payload": [{"contentString": text}] + [{"contentAttachment": {"contentType": d.content_type, "data": base64(d.bytes), "title": d.title}, + "extension": [{"url": DOC_TYPE_EXT, "valueString": d.code}]} for d in documents]} + task = {"resourceType": "Task", "id": task_id, "meta": profile("Task"), "status": "completed", "intent": "order", + "code": cc(TASK_CODES, "deliver"), "reasonCode": cc(null, q.reason or "additionalinfo", "Additional information requested"), + "authoredOn": now, "requester": {"reference": BASE + "/provider", "display": "Organization"}, "owner": {"reference": BASE + "/payer", "display": "Organization"}, + "input": [{"type": cc(FIN_INPUT, "include"), "valueReference": {"reference": "urn:uuid:" + comm_id, "display": "Communication"}}]} + entries = [entry("urn:uuid:" + task_id, task), entry("urn:uuid:" + comm_id, comm), entry(q.request_url, q.request_resource)] + entries += [entry(e.fullUrl, e.resource) for e in sent_leg_bundle.entry if e.resource.resourceType in ("Claim", "Patient", "Organization", "Practitioner", "Coverage")] + b = bundle("communication-response-generic", "TaskBundle", entries) + b.meta.lastUpdated = now; b.timestamp = now # the IG example carries both; the only request that does + return b +``` + +Excluded from the byte comparison of the reply: `meta.lastUpdated`, `timestamp`, `authoredOn`, the two generated uuids. + +## 8. Payment notice + +Read on `v1/paymentnotice/request`. Entries: Task, PaymentNotice, PaymentReconciliation, two Organizations. + +``` +function parse_payment_notice(b): + pn = first(b, "PaymentNotice"); pr = first(b, "PaymentReconciliation"); t = first(b, "Task") + out = {"claim_no": pn.identifier[0].value if pn.identifier else claim_no_in(b), + "amount": pn.amount.value, "payment_status": pn.paymentStatus.coding[0].code, # paid | cleared | ... + "payment_date": pn.paymentDate, "utr": null, "details": []} + if pr: + out.utr = pr.paymentIdentifier.value if pr.paymentIdentifier else null + out.gross = pr.paymentAmount.value if pr.paymentAmount else null + out.details = [{"type": d.type.coding[0].code, "amount": d.amount.value if d.amount else null} for d in pr.detail or []] # deductions, TDS + if not out.utr and pn.payment and pn.payment.identifier: out.utr = pn.payment.identifier.value + return out +# record: one claim_payment row keyed on the message's correlation id (unique), matched by claim_no; then acknowledge with payment_ack() +``` + +## 9. Validate before you send + +``` +function validate_bundle(b, pin): # the offline gate, module 7.7 Validate + assert canonical(strip(b, ["created"])) == canonical(strip(pin, ["created"])) # plus the per-shape exclusions above + urls = {e.fullUrl for e in b.entry} + for r in all_references(b): assert r in urls or r.startswith("urn:uuid:") + c = first(b, "Claim") + if c: + for it in c.item: assert it.id and it.sequence + for p in c.procedure: assert p.id and p.sequence + for n, s in enumerate(c.supportingInfo): assert s.id and s.sequence == n + 1 + for pr in all(b, "Practitioner"): assert any(i.type.coding[0].code == "HPIN" and i.system == HPR for i in pr.identifier) + assert c.total.value == sum(it.net.value for it in c.item) + assert not any(it.productOrService.coding[0].code == "LM100" for it in c.item) or c.use == "claim" + assert no literal in the builder matches r"MAND\d+|MG\d+|/questionnaire/" +``` + +| Symptom | Refusal | +| --- | --- | +| an item without `id` | PAYR-1027 | +| a supportingInfo without `sequence` | PAYR-1019 | +| a Practitioner without `HPIN` | PAYR-1083 | +| a death claim without `ONS/DTM` | PAYR-1096, PAYR-1503 | +| a LAMA claim before surgery still carrying the package | PAYR-1362 | +| `LM100` on a pre-auth | PAYR-1270 | +| the consent form unanswered | PAYR-1256 (pre-auth), PAYR-1363 (claim) | +| a package's STG form unanswered | PAYR-1254, PAYR-1365 | +| a claim under its own number | ERR-PYR-CLM-007 | +| 121 after a rejection | PAYR-1214 | +| 151, 19 or 16 on `v1/claim/submit` to PMJAY | PAYR-1321 | +| a document outside pdf, jpg, jpeg, png; a Task the sandbox does not take; a misspelt intimation input on a reprocess | PAYR-1008 | diff --git a/plugins/nhcx/skills/nhcx-preauth/flow/FLOW.md b/plugins/nhcx/skills/nhcx-preauth/flow/FLOW.md new file mode 100644 index 000000000..312668e67 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-preauth/flow/FLOW.md @@ -0,0 +1,228 @@ +# The flow: the one path a claim episode walks + +This is the reference flow for an NHCX provider desk: these steps, in this order, with these guards and these words. A build from this skill walks the same path. It does not redesign it, reorder it, merge steps, or invent screens the path does not have. Stage 4 copies it, stage 5 puts screens on it, stage 7 implements it step by step, stage 8 checks every step exists, and test drivers check the same through `flow.json`. + +## The shape + +One episode is one case (`claim` row). It has one list screen, one "new case" screen and one case screen. The case screen has tabs in the order the episode happens, and above the tabs one status line and the actions the case is waiting for. Everything else (inbox, payments across cases) is a view over the same rows. + +Tabs on the case screen, in this order and with these names: + +| # | Tab key | Tab label | Opens when | +| --- | --- | --- | --- | +| 1 | `eligibility` | Eligibility | always | +| 2 | `plan` | Insurance plan | always (empty until the plan is fetched) | +| 3 | `lines` | Line items | always (quoting refused until the plan is `ready`) | +| 4 | `validate` | Validate | always (the ruling on the quoted set) | +| 5 | `preauth` | Pre-authorisation | once the coverage verdict is `eligible` | +| 6 | `communication` | Communication | always (the payer's questions on both legs) | +| 7 | `claim` | Claim | always; its submit opens once a pre-auth is approved or partial | +| 8 | `payments` | Payments | always | + +The episode may also render on one page, with the same sections in the same order. Either shape is fine; the order and the gating are not negotiable. + +## Which skill builds which step + +Seven skills build this flow, one slice each (`core/LADDER.md`). `flow.json` names them per step in `skills`, the first named being the one that owns the step. + +| Steps | Skill | +| --- | --- | +| F1, F2, F3 | `nhcx-coverage` | +| F4, F7 | `nhcx-insurance` | +| F5, F6, F8, F9, F9a, F9c, F9d, F9e; F9b for a `resubmit` payer (19, 131) | `nhcx-preauth` | +| F10, F11; the claim query answer for a `resubmit` payer (161) | `nhcx-claim` | +| F9b and the claim query for a `communication` payer; F12b | `nhcx-communication` | +| F12 | `nhcx-payment` | +| F13 | `nhcx-reprocess` | + +The case screen, its tabs, the status line and actions, and the page-load polls are the foundation's (`core/FOUNDATION.md`): the first skill lays them out whole, and each skill fills its own tabs. + +## The status line and the actions + +Above the tabs: `stage / sub-stage` from `case_stage` (module 7.11) and the list from `next_actions`, first item highlighted. The labels are these, verbatim: + +| Stage | Sub-stage | Action offered (label, tab) | +| --- | --- | --- | +| any | an open query exists | "Answer the payer (n)", `communication` (leads every list) | +| `eligibility` | `draft`, `error`, `not-eligible` | "Check the cover", `eligibility` | +| `eligibility` | `eligible`, no plan `ready` | "Fetch the package master", `plan` | +| `eligibility` | plan ready, no lines | "Quote the treatment", `lines` | +| `eligibility` | lines quoted | "Send the pre-authorisation", `preauth` | +| `preauth` or `enhancement` | `queried` | "Answer the query", `preauth` (resubmit payer) or "Answer the payer's query", `communication` (communication payer) | +| `preauth` | `draft`, `refused` | "Send the pre-authorisation", `preauth` | +| `preauth` | `rejected` | "Send a fresh pre-authorisation", `preauth` | +| `preauth` | `approved`, `partial`, lines added since | "Send the enhancement (n added)", `preauth` | +| `preauth` | `approved`, `partial`, not discharged | "Record the discharge", `claim` | +| `preauth` | `approved`, `partial`, discharged | "File the claim", `claim` | +| `preauth` | `requested`, `answered`, `resubmitted` | "With the payer; ask where it stands", `preauth` | +| `claim` | `queried` | "Answer the claim query", `claim` or "Answer the payer's query", `communication` | +| `claim` | `rejected`, `partial` | "Ask for a reprocess", `claim` | +| `claim` | `requested`, `answered`, `resubmitted` | "With the payer; ask where it stands", `claim` | +| `claim` | `refused` | "Send the claim again", `claim` (while a send kind remains) else "Ask for a reprocess" | +| `claim` | `approved` | "Await the payment notice", `payments` | +| `payment` | a notice unacknowledged | "Acknowledge the payment notice", `payments` | +| `payment` | all acknowledged | "Settled", `payments` | + +## The steps + +Each step: where it happens, what must hold, what the user does, what the system does (module in brackets), what goes on the wire, what is stored, where the case stands afterwards, and what the screen shows next. Ids are `F1` to `F13` with letters for branches; `flow.json` carries the same ids. + +### F1. Policy search + +- Screen: Cases list, "New case", `GET /claims/new`. +- Holds: nothing. +- User: picks an identifier type (`MemberId`, `AbhaNumber`, `MobileNo`) and a value, presses "Search policies". +- System [7.4]: `search_policies` through the transport: the participant service's `participant/get/policies`; normalises each row (`member_id`, `policy_code` from `productid`, `payer_code` from `payerid`, `recipient_code` from `processingid`, `product_name`). NHCX-1016 (nothing linked) is an empty list, not an error. +- Screen: a table, one row per policy: beneficiary, product and policy, payer, ABHA, mobile, a "Select" button. No name and no photo yet; the payer returns those at F3. + +### F2. Open the case + +- Screen: the same, "Select" on a row; `POST /claims`. +- System [7.4, 7.2]: `create_claim` snapshots the policy (`member_id`, `policy_code`, `payer_code`, `recipient_code`, `policy_json`), mints the claim number, stamps `eligibility / draft`. +- Redirect: the case screen, Eligibility tab, "Claim opened." +- Next action: "Check the cover". + +### F3. Check the cover (coverage eligibility) + +- Screen: Eligibility tab, card "Coverage eligibility check": purpose select (`validation` default, `benefits`, `discovery`), policy code and member id shown from the snapshot, "Send to payer". +- Holds: member id; policy code for `validation` and `benefits`. +- System [7.4]: `run_check(purpose)`, workflow id = the claim number, status `checking`; the page shows "Awaiting payer" and refreshes; the answer arrives by callback [7.3] or poll. +- Wire: `v1/coverageeligibility/check`; `on_check` back. +- Stored: `txn_id`, `correlation_id`, `api_call_id`; on the answer `inforce`, `outcome`, `disposition`, allowed and used amounts, the payer's `Patient` (name, gender, DOB, address, ABHA, photo), `Coverage` class and period. +- After: `eligibility / eligible` or `not-eligible` (or `error` with the payer's words). A `ProtocolResponse` or a 404 on `txn/related` settles as `error`, never spins. +- Screen: card "Payer verdict": Sum insured, Utilised, Wallet balance (allowed less used), Disposition verbatim, In force, Pre-authorisation required, Checked at, Correlation. Beneficiary card fills with the payer's demographics. "Check again" allowed from any settled state. +- Next action: "Fetch the package master". + +### F4. Fetch the package master (insurance plan) + +- Screen: Insurance plan tab, "Fetch the plan" (or "Refresh"). +- Holds: `eligible`. +- System [7.5]: `reuse_plan` first (same policy, provider, payer, status `ready`: zero sends); else `request_plan`, status `fetching`, workflow id = the claim number. +- Wire: `v1/insuranceplan/request`; `on_request` back with the InsurancePlan and Questionnaires. +- Stored: `claim_plan` (`ready`, `empty` or `error`), `claim_plan_benefit` per package, `claim_plan_form` per url. Both published shapes merged on package code. +- Screen: a search over the master (name or code, specialty filter, procedure or implant), one row per package with rate, kind, "View"; a package view with rate, implants approved, tiers, conditions, documents wanted, the forms those point at as questions; an "All forms" page. Policy-wide requirements shown above the table. +- Next action: "Quote the treatment". + +### F5. Link the admission (integrate) or capture it (standalone) + +- Screen: Pre-authorisation tab, card "Link the admission" (opens once `eligible`). +- Holds: `eligible`. +- Integrate: list every current inpatient stay of the patient whose ABHA matches the payer's (digits only); "Link" stores `patient_id` and `encounter_id`, defaults the admission date from the encounter. Linking before `eligible` and to a stay that is not a current IPD admission is refused. "Unlink" keeps the draft. +- Standalone [7.13]: register the patient (from the payer's demographics) and admit them here; the same two keys are stored. +- Screen after: card "Linked admission" with ward, bed, admitted at, consultant. + +### F6. The dossier (pre-auth capture) + +- Screen: Pre-authorisation tab, once linked: the form, saved in one transaction by `save_preauth` [7.7 inputs]. +- Captured: admission date (required) and provisional discharge date (not before admission); ICD-10 diagnoses (at least one; read off the admission when it recorded them, else a picker); the treating doctor (the admission's consultant, else a picker; must have an HPIN); package case or non-package case toggle; documents (pdf, jpg, jpeg, png, each recorded against the payer requirement code it answers, else `ODN`). +- Estimated amount: always recomputed server-side from the lines (F7), never from the form. +- Guards: saving a package case with no line quoted is refused. + +### F7. Quote the treatment (lines from the plan) + +- Screen: Line items tab, "Choose line items", `GET /claims//lines`. Three parts: what is quoted (editable quantities, running total, "remove"); what the payer says goes with it (implants approved for the quoted procedures, the tiers each offers; anything already quoted drops out); the whole master to search. +- Holds: plan `ready`. Quoting anything before that is refused. +- System [7.5]: `add_line(kind, code, parent_code)`; price read from the plan at add time; `amount = rate x quantity` server-side; a tier is added through the procedure that offers it and carries `parent_code`. Refused: a code the plan lacks, a tier the procedure does not offer, a duplicate, a zero quantity. +- Forms: the chosen lines pull in the questionnaires the plan attaches (STG per package, policy forms always); they render on the Pre-authorisation tab and are answered there (`save_answers`, one row per question, file answers upload a document). +- Next action: "Send the pre-authorisation". + +### F8. Validate the set (auth requirements) + +- Screen: Validate tab, "Ask the payer" (also run silently before F9). +- Holds: at least one line. +- System [7.6]: `ensure_auth_requirements`: fingerprint the quoted set; send only when the fingerprint is new; never wait for the answer. +- Wire: `v1/coverageeligibility/check` with purpose `auth-requirements` and the items; `on_check` back (the PMJAY sandbox rarely answers). +- Stored: `claim_auth` (`checking` then `ready`), items authorised or excluded, requirements (document or form, code, url, stage `pre` or `post`, `at_preauth`). +- Screen: the ruling per line, the documents and forms it wants for each leg; the pre-auth and claim tabs read it to build their document and form cards. Without a ruling they fall back to the plan's list. + +### F9. Send the pre-authorisation + +- Screen: Pre-authorisation tab, card "Submit": what will be sent (lines, forms answered, documents attached, the total), "Send to payer". +- Holds (all before any HTTP call): `eligible`; an admission linked; an admission date; at least one diagnosis; at least one care team member with an HPIN; at least one line; every required form answered; every document the ruling or plan asks for at pre-auth attached. +- System [7.7]: `submit_preauth`: `preauth_send_kind` picks `preauth` (12); builds the Claim bundle (`preauth`, `request`); status `submitting`, `submission_kind`, `workflow_id`; stores the three ids; `thread_correlation_id` untouched until the payer answers. +- Wire: `v1/preauth/submit`, workflow 12. +- After: `preauth / requested`. +- Screen: "Awaiting payer", the timeline row for the send, Refresh. Next action: "With the payer; ask where it stands". + +#### F9a. The payer answers + +- Callback [7.3] or poll: first the acknowledgement (workflow 20, `outcome queued`, reason `submitted`): recorded, `preauth_ref` kept, the leg stays `submitting`. Then the decision on the same correlation id: `verdict_status` [7.8]. +- After: `approved` (21), `partial` (approved for less), `queried` (24), `rejected` (23). Never read `outcome` alone. +- Screen: Decision, Payer reference (`preAuthRef`), Approved amount (`total[benefit]`), Eligible amount, the item verdicts table (eligible, status, reason verbatim, eligible %, quantity), process notes verbatim. A door refusal shows as a flag with the payer's code and text, the thread restored. +- Next action per the table above. + +#### F9b. Answer a query + +- Resubmit payer (PMJAY): the query is inside the ClaimResponse (`query_note`). Screen: Pre-authorisation tab, the payer's words, a reply box, "Submit again". System: `submit_preauth(reply)` with kind `preauth_query_response` (19; 131 after an enhancement query), flow `queryupdate`, `NMI/CQD` = the reply, a new correlation id. After: `answered`, then the decision. +- Communication payer (generic): the query is a CommunicationRequest on a new thread, filed in `claim_query` (F12 inbox). Screen: Communication tab, the questions verbatim, a reply box, documents to attach (existing or new, each under the payer's code else `ODN`), "Send the reply". System [7.10]: `answer_query`: the TaskBundle reply on `v1/communication/on_request` with the request's correlation id and workflow id. The leg stays `queried` until the decision arrives on its own thread. An empty reply is refused before any HTTP call. + +#### F9c. Enhancement + +- Screen: Line items tab, add a line after a decision; the Pre-authorisation card shows "enhancement pending (n added)"; "Submit enhancement". +- Holds: `approved` or `partial`; no request in flight. +- System: `submit_preauth` with kind `enhancement` (13; `enhancement_resubmit` 131 on a query): the whole bundle again, every line old and new, same claim number, factors 1 and 0.5. After: `enhancement / requested`, then 22 (or 21 from the SHA), 231, 241. + +#### F9d. Cancel + +- Screen: Pre-authorisation tab, "Withdraw": a reason picker (the seven documented reasons) and a note, required for Other. Hidden once a claim has been raised; refused on a `rejected` pre-auth and twice. +- System [7.9]: `cancel_preauth`: Task `cancel`, workflow PC01, on its own thread (`cancel_correlation_id`), `cancelling`. +- After PC02: `cancelled`; the episode gets a fresh claim number, the withdrawn one stays on the leg. + +#### F9e. Predetermination (a quote) + +- Screen: Pre-authorisation tab, "Ask for a quote". +- System [7.7]: the very bundle F9 would send with `use predetermination`, on `v1/preauth/submit`, workflow 12, its own row (`asking` then `answered`). Nothing on the pre-auth changes. + +### F10. Record the discharge + +- Screen: Claim tab, card "Discharge": mode (Normal, LAMA, DAMA, Death), stage (Before, During, After surgery), discharge date and time, surgery date and time, death date and time (death only). +- Holds: a pre-auth `approved` or `partial`. +- Stored: on `claim_submission` (`draft`) or the encounter. +- Screen after: the claim card opens; for LAMA or DAMA before or during surgery it says the approved packages are voided and the claim will carry `LM100` only. +- Next action: "File the claim". + +### F11. File the claim + +- Screen: Claim tab, cards "Documents for the claim" (what the ruling deferred to this stage, plus the discharge summary, always), "Forms for the claim" (the consent again, and what the ruling deferred), "Everything attached for the claim" (any further pdf or image), "Submit the claim". +- Holds: discharge recorded; the discharge summary attached; every claim-stage form answered; amount not above the approved amount. +- System [7.7]: `submit_claim`: `claim_send_kind` (`claim` 15; `claim_query_response` 161 PMJAY or 151 generic; `claim_resubmit` 16 generic only); the Claim bundle (`claim`, `request`) under the pre-auth's claim number with `preAuthRef`, procedures `completed`, discharge scalars, `HDS`, `DIS`; `LM100` collapse when it applies. +- Wire: `v1/claim/submit`. +- After: `claim / requested`; then 25 (ack), 26 `approved`, 27 `queried`, 291 `rejected`, read as F9a. +- Screen: as the pre-auth card: decision, amounts, item verdicts with `deductible`, notes verbatim. + +#### F11, continued: claim query and reprocess + +- Query: as F9b, on the claim (161 or the Communication reply). +- Rejected or partial: "Ask for a reprocess" (F13). There is no claim resubmit on PMJAY. + +### F12. Payments + +- The payer starts it: `v1/paymentnotice/request` arrives on a new thread, matched by the claim number inside (a `CLN` identifier, then any untyped identifier on the notice, the reconciliation, the Task; never the bundle id), looked up against `claim_no` and every leg's `claim_ref`. +- System [7.10]: `record_payment`: one `claim_payment` row per notice, deduped on the notice's correlation id; details from the PaymentReconciliation; a payer that reuses the notice id updates the row. Then, at once and automatically, `acknowledge_payment`: Task `status` `completed`, output `paymentack`, to the notice's own sender, its correlation id echoed, workflow 17 (PMJAY) or the notice's own (generic). A failed acknowledgement is kept on the row; the notice is still recorded and the callback still answered 2xx. +- After: `payment / noticed` or `paid`. Paid is counted once per UTR, newest notice winning; an initiated notice without a UTR shows "Initiated, UTR awaited" and is not money received. +- Screen: Payments tab, one card per notice: status, amount, UTR as text, the breakdown, "Acknowledged at" or "Send the acknowledgement again". Across cases: the payments view. +- Next action: "Acknowledge the payment notice" while one is pending, else "Settled". + +### F12b. The inbox + +- Every CommunicationRequest is classified [7.10]: query, notification or note. Notifications are acknowledged at once (the payer's bundle back, Task `completed`) and the case left alone. Queries are filed `open` and lead every action list until answered (F9b). Notes are shown, never acted on. +- Screen: Communication tab on the case; the inbox view across cases, by kind and reason. + +### F13. The small exchanges + +- Status: "Ask where it stands" on the pre-auth and claim cards, while awaiting and after a decision; Task `status`, workflow = the leg's correlation id (fallback 13); not offered to a payer whose adapter refuses it (PMJAY, PAYR-1018). The answer fills the enquiry row; the leg is unchanged. +- Reprocess: on a decided claim not paid in full, "Send reprocess request" with a coded reason (`claimrejected`, `partialpayment`, `rejectiondisputed`), words, and documents; Task `reprocess`, workflow 36. The payer's `completed` Task (37) reopens the claim: the submission goes back to `requested` and the new verdict lands on the claim's own thread. +- Release: once part of an approved claim is paid, "Ask for the balance" with the amount owed; Task `release`, reason `partialpayment`, `valueMoney`, workflow 36. +- Each ask is its own `claim_enquiry` row on its own thread, shown on the card it belongs to, newest first. + +## What runs on every page load of the case + +In this order, before rendering, each bounded to one poll and a short timeout, never a send: coverage (`checking`), plan (`fetching`), ruling (`checking`), claim (`submitting`), predeterminations (`asking`), pre-auth (`submitting` or `cancelling`), enquiries (`asking`). Then the beneficiary card, the policy card, the verdict card, the status line and actions, the tabs. A "Refresh" button reloads the same tab. + +## What is not in the flow + +- No status control anywhere. Stage and sub-stage are derived. +- No manual acknowledgement of a payment notice as the only path; it goes automatically and the screen shows that it went. +- No "chase" button without the status exchange behind it. +- No separate discharge submission on PMJAY; the discharge rides on the claim. +- No claim resubmit on PMJAY; a decided claim is reprocessed. diff --git a/plugins/nhcx/skills/nhcx-preauth/flow/flow.json b/plugins/nhcx/skills/nhcx-preauth/flow/flow.json new file mode 100644 index 000000000..315d1a4b8 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-preauth/flow/flow.json @@ -0,0 +1,818 @@ +{ + "source": "flow/FLOW.md", + "tabs": [ + { + "key": "eligibility", + "label": "Eligibility", + "opens": "always" + }, + { + "key": "plan", + "label": "Insurance plan", + "opens": "always" + }, + { + "key": "lines", + "label": "Line items", + "opens": "always; quoting refused until the plan is ready" + }, + { + "key": "validate", + "label": "Validate", + "opens": "always" + }, + { + "key": "preauth", + "label": "Pre-authorisation", + "opens": "coverage verdict eligible" + }, + { + "key": "communication", + "label": "Communication", + "opens": "always" + }, + { + "key": "claim", + "label": "Claim", + "opens": "always; submit once the pre-auth is approved or partial" + }, + { + "key": "payments", + "label": "Payments", + "opens": "always" + } + ], + "stages": [ + "eligibility", + "preauth", + "enhancement", + "claim", + "payment" + ], + "sub_stages": [ + "draft", + "checking", + "eligible", + "not-eligible", + "requested", + "resubmitted", + "answered", + "queried", + "approved", + "partial", + "rejected", + "cancelling", + "cancelled", + "refused", + "noticed", + "paid" + ], + "next_actions": [ + { + "when": "an open query exists", + "label": "Answer the payer (n)", + "tab": "communication", + "leads": true + }, + { + "stage": "eligibility", + "sub_stage": [ + "draft", + "error", + "not-eligible" + ], + "label": "Check the cover", + "tab": "eligibility" + }, + { + "stage": "eligibility", + "when": "no plan ready", + "label": "Fetch the package master", + "tab": "plan" + }, + { + "stage": "eligibility", + "when": "no lines", + "label": "Quote the treatment", + "tab": "lines" + }, + { + "stage": "eligibility", + "when": "lines quoted", + "label": "Send the pre-authorisation", + "tab": "preauth" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "queried" + ], + "label": "Answer the query", + "tab": "preauth", + "payer": "resubmit" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "queried" + ], + "label": "Answer the payer's query", + "tab": "communication", + "payer": "communication" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "draft", + "refused" + ], + "label": "Send the pre-authorisation", + "tab": "preauth" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "rejected" + ], + "label": "Send a fresh pre-authorisation", + "tab": "preauth" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "approved", + "partial" + ], + "when": "lines added since", + "label": "Send the enhancement (n added)", + "tab": "preauth" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "approved", + "partial" + ], + "when": "not discharged", + "label": "Record the discharge", + "tab": "claim" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "approved", + "partial" + ], + "when": "discharged", + "label": "File the claim", + "tab": "claim" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "requested", + "answered", + "resubmitted" + ], + "label": "With the payer; ask where it stands", + "tab": "preauth" + }, + { + "stage": "claim", + "sub_stage": [ + "queried" + ], + "label": "Answer the claim query", + "tab": "claim", + "payer": "resubmit" + }, + { + "stage": "claim", + "sub_stage": [ + "queried" + ], + "label": "Answer the payer's query", + "tab": "communication", + "payer": "communication" + }, + { + "stage": "claim", + "sub_stage": [ + "rejected", + "partial" + ], + "label": "Ask for a reprocess", + "tab": "claim" + }, + { + "stage": "claim", + "sub_stage": [ + "requested", + "answered", + "resubmitted" + ], + "label": "With the payer; ask where it stands", + "tab": "claim" + }, + { + "stage": "claim", + "sub_stage": [ + "refused" + ], + "label": "Send the claim again", + "tab": "claim", + "when": "a send kind remains, else Ask for a reprocess" + }, + { + "stage": "claim", + "sub_stage": [ + "approved" + ], + "label": "Await the payment notice", + "tab": "payments" + }, + { + "stage": "payment", + "when": "a notice unacknowledged", + "label": "Acknowledge the payment notice", + "tab": "payments" + }, + { + "stage": "payment", + "when": "all acknowledged", + "label": "Settled", + "tab": "payments" + } + ], + "steps": [ + { + "id": "F1", + "name": "Policy search", + "screen": "new case", + "tab": null, + "routes": [ + "GET /claims/new" + ], + "module": "7.4", + "skills": ["nhcx-coverage"], + "holds": [], + "user": "Search policies", + "sends": { + "path": "participant/get/policies", + "kind": "registry REST" + }, + "stores": [], + "after": null, + "shows": "one row per policy with Select" + }, + { + "id": "F2", + "name": "Open the case", + "screen": "new case", + "tab": null, + "routes": [ + "POST /claims" + ], + "module": "7.4", + "skills": ["nhcx-coverage"], + "holds": [], + "user": "Select", + "sends": null, + "stores": [ + "claim: member_id, policy_code, payer_code, recipient_code, policy_json, claim_no" + ], + "after": { + "stage": "eligibility", + "sub_stage": "draft" + }, + "next_action": "Check the cover" + }, + { + "id": "F3", + "name": "Check the cover", + "screen": "case", + "tab": "eligibility", + "routes": [ + "POST /claims//check" + ], + "module": "7.4", + "skills": ["nhcx-coverage"], + "holds": [ + "member id", + "policy code for validation and benefits" + ], + "user": "purpose, Send to payer", + "sends": { + "path": "v1/coverageeligibility/check", + "workflow": "", + "reply": "on_check" + }, + "stores": [ + "txn_id", + "correlation_id", + "api_call_id", + "inforce", + "outcome", + "disposition", + "allowed_amount", + "used_amount", + "patient demographics", + "coverage class and period" + ], + "after": { + "stage": "eligibility", + "sub_stage": "eligible|not-eligible|error" + }, + "shows": "Payer verdict: sum insured, utilised, wallet balance, disposition verbatim", + "next_action": "Fetch the package master" + }, + { + "id": "F4", + "name": "Fetch the package master", + "screen": "case", + "tab": "plan", + "routes": [ + "POST /claims//plan", + "GET /claims//plan/", + "GET /claims//plan/forms" + ], + "module": "7.5", + "skills": ["nhcx-insurance"], + "holds": [ + "eligible" + ], + "user": "Fetch the plan (reuse first)", + "sends": { + "path": "v1/insuranceplan/request", + "workflow": "", + "reply": "on_request" + }, + "stores": [ + "claim_plan", + "claim_plan_benefit", + "claim_plan_form" + ], + "after": { + "plan": "ready|empty|error" + }, + "shows": "searchable master, package view, all forms", + "next_action": "Quote the treatment" + }, + { + "id": "F5", + "name": "Link or capture the admission", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//link", + "POST /claims//unlink" + ], + "module": "7.13 or the HMIS", + "skills": ["nhcx-preauth"], + "holds": [ + "eligible" + ], + "user": "Link the admission", + "sends": null, + "stores": [ + "claim.patient_id", + "claim.encounter_id", + "admission date default" + ], + "after": null + }, + { + "id": "F6", + "name": "The dossier", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//preauth", + "POST /claims//documents", + "POST /claims//documents/required" + ], + "module": "7.7 inputs", + "skills": ["nhcx-preauth"], + "holds": [ + "linked" + ], + "user": "Save the dossier", + "sends": null, + "stores": [ + "claim_diagnosis", + "claim_care_team", + "claim_document (code, stage)", + "claim_item" + ], + "guards": [ + "admission date required", + "at least one diagnosis", + "doctor with HPIN", + "package case needs a line" + ] + }, + { + "id": "F7", + "name": "Quote the treatment", + "screen": "lines", + "tab": "lines", + "routes": [ + "GET /claims//lines", + "POST /claims//lines", + "POST /claims//lines/quantities", + "POST /claims//lines//delete", + "POST /claims//forms" + ], + "module": "7.5", + "skills": ["nhcx-insurance"], + "holds": [ + "plan ready" + ], + "user": "add procedure, implant or tier; quantities; answer the forms the lines pull in", + "sends": null, + "stores": [ + "claim_line (rate from the plan, parent_code on a tier)", + "claim_form_answer" + ], + "guards": [ + "code not in plan", + "tier not offered by the procedure", + "duplicate", + "zero quantity" + ], + "next_action": "Send the pre-authorisation" + }, + { + "id": "F8", + "name": "Validate the set", + "screen": "case", + "tab": "validate", + "routes": [ + "POST /claims//auth" + ], + "module": "7.6", + "skills": ["nhcx-preauth"], + "holds": [ + "at least one line" + ], + "user": "Ask the payer (validate)", + "sends": { + "path": "v1/coverageeligibility/check", + "purpose": "auth-requirements", + "workflow": "", + "reply": "on_check", + "awaited": false + }, + "stores": [ + "claim_auth (fingerprint)", + "claim_auth_item", + "claim_auth_requirement" + ], + "after": { + "auth": "checking|ready" + } + }, + { + "id": "F9", + "name": "Send the pre-authorisation", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//submit" + ], + "module": "7.7", + "skills": ["nhcx-preauth"], + "holds": [ + "eligible", + "linked", + "admission date", + "diagnosis", + "care team with HPIN", + "a line", + "required forms answered", + "required documents attached" + ], + "user": "Send to payer", + "sends": { + "path": "v1/preauth/submit", + "workflow": "12", + "kind": "preauth", + "reply": "on_submit 20 then 21|23|24" + }, + "stores": [ + "claim_preauth: submitting, submission_kind, workflow_id, txn_id, correlation_id, api_call_id, request_json" + ], + "after": { + "stage": "preauth", + "sub_stage": "requested" + }, + "next_action": "With the payer; ask where it stands" + }, + { + "id": "F9a", + "name": "The payer answers", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /nhcx/callback/v1/preauth/on_submit" + ], + "module": "7.8", + "skills": ["nhcx-preauth"], + "holds": [], + "user": null, + "reads": "20 queued (stay submitting, keep preauth_ref) then the decision via verdict_status", + "stores": [ + "status", + "preauth_ref", + "approved_amount", + "eligible_amount", + "items_json", + "query_note", + "thread_correlation_id" + ], + "after": { + "stage": "preauth", + "sub_stage": "approved|partial|queried|rejected" + }, + "shows": "decision, payer reference, approved amount, item verdicts, notes verbatim; door refusal as a flag" + }, + { + "id": "F9b", + "name": "Answer a query", + "screen": "case", + "tab": "preauth or communication", + "routes": [ + "POST /claims//submit (reply)", + "POST /claims//queries//reply" + ], + "module": "7.7 or 7.10", + "skills": ["nhcx-preauth", "nhcx-communication"], + "holds": [ + "queried" + ], + "user": "reply text and documents", + "sends": { + "resubmit": { + "path": "v1/preauth/submit", + "workflow": "19 or 131", + "flow": "queryupdate", + "new_thread": true + }, + "communication": { + "path": "v1/communication/on_request", + "workflow": "", + "correlation_id": "" + } + }, + "after": { + "stage": "preauth", + "sub_stage": "answered (resubmit) or queried until the decision (communication)" + } + }, + { + "id": "F9c", + "name": "Enhancement", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//submit" + ], + "module": "7.7", + "skills": ["nhcx-preauth"], + "holds": [ + "approved or partial", + "lines added", + "no request in flight" + ], + "user": "Submit enhancement", + "sends": { + "path": "v1/preauth/submit", + "workflow": "13 or 131", + "flow": "enhancement", + "whole_bundle": true + }, + "after": { + "stage": "enhancement", + "sub_stage": "requested" + } + }, + { + "id": "F9d", + "name": "Cancel", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//cancel" + ], + "module": "7.9", + "skills": ["nhcx-preauth"], + "holds": [ + "not rejected", + "not cancelled", + "no claim raised" + ], + "user": "Withdraw the pre-authorisation", + "sends": { + "path": "v1/task/submit", + "workflow": "PC01", + "task": "cancel", + "own_thread": true + }, + "after": { + "stage": "preauth", + "sub_stage": "cancelling then cancelled; fresh claim number" + } + }, + { + "id": "F9e", + "name": "Predetermination", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//predetermination" + ], + "module": "7.7", + "skills": ["nhcx-preauth"], + "holds": [ + "as F9" + ], + "user": "Ask for a quote", + "sends": { + "path": "v1/preauth/submit", + "workflow": "12", + "use": "predetermination" + }, + "after": { + "predetermination": "asking then answered; the pre-auth unchanged" + } + }, + { + "id": "F10", + "name": "Record the discharge", + "screen": "case", + "tab": "claim", + "routes": [ + "POST /claims//discharge" + ], + "module": "7.7 inputs", + "skills": ["nhcx-claim"], + "holds": [ + "approved or partial" + ], + "user": "mode (normal, lama, dama, death), stage, discharge, surgery and death times", + "sends": null, + "stores": [ + "claim_submission draft: discharge_mode, discharge_stage, dates" + ], + "next_action": "File the claim" + }, + { + "id": "F11", + "name": "File the claim", + "screen": "case", + "tab": "claim", + "routes": [ + "POST /claims//claim", + "POST /claims//claim/documents" + ], + "module": "7.7", + "skills": ["nhcx-claim", "nhcx-communication"], + "holds": [ + "discharge recorded", + "discharge summary attached", + "claim-stage forms answered", + "amount not above approved" + ], + "user": "Submit the claim", + "sends": { + "path": "v1/claim/submit", + "workflow": "15 (161 or 151 query answer; 16 generic resubmit)", + "kind": "claim", + "under": "the pre-auth's claim number", + "reply": "on_submit 25 then 26|27|291" + }, + "after": { + "stage": "claim", + "sub_stage": "requested then approved|queried|rejected|partial" + } + }, + { + "id": "F12", + "name": "Payments", + "screen": "case", + "tab": "payments", + "routes": [ + "POST /nhcx/callback/v1/paymentnotice/request", + "POST /claims//payments//ack", + "GET /claims/payments" + ], + "module": "7.10", + "skills": ["nhcx-payment"], + "holds": [], + "user": null, + "reads": "PaymentNotice matched by claim number; deduped on its correlation id", + "sends": { + "path": "v1/paymentnotice/on_request", + "workflow": "17 (PMJAY) or the notice's own", + "correlation_id": "", + "to": "the notice's sender", + "automatic": true + }, + "after": { + "stage": "payment", + "sub_stage": "noticed|paid" + }, + "next_action": "Acknowledge the payment notice, then Settled" + }, + { + "id": "F12b", + "name": "The inbox", + "screen": "inbox", + "tab": "communication", + "routes": [ + "POST /nhcx/callback/v1/communication/request", + "GET /claims/inbox", + "POST /claims//queries//acknowledge" + ], + "module": "7.10", + "skills": ["nhcx-communication"], + "holds": [], + "reads": "classify: query | notification | note", + "sends": { + "notification": { + "path": "v1/communication/on_request", + "automatic": true + } + }, + "after": { + "query": "open, leads every action list" + } + }, + { + "id": "F13", + "name": "Status, reprocess, release", + "screen": "case", + "tab": "preauth or claim", + "routes": [ + "POST /claims//status", + "POST /claims//reprocess", + "POST /claims//release" + ], + "module": "7.9", + "skills": ["nhcx-reprocess"], + "holds": [ + "status: payer allows it", + "reprocess: claim decided and not paid in full", + "release: part paid" + ], + "sends": { + "path": "v1/task/submit", + "workflow": "leg correlation id (status) or 36", + "own_thread": true + }, + "after": { + "enquiry": "asking then answered|error; a reprocess reopens the claim to requested" + } + } + ], + "page_load_polls": [ + "coverage checking", + "plan fetching", + "ruling checking", + "claim submitting", + "predeterminations asking", + "preauth submitting or cancelling", + "enquiries asking" + ], + "not_in_the_flow": [ + "a status control", + "a manual-only payment acknowledgement", + "a chase button without the status exchange", + "a separate discharge submission on PMJAY", + "a claim resubmit on PMJAY" + ] +} \ No newline at end of file diff --git a/plugins/nhcx/skills/nhcx-preauth/references/api-knowledge.md b/plugins/nhcx/skills/nhcx-preauth/references/api-knowledge.md new file mode 100644 index 000000000..3b07e901d --- /dev/null +++ b/plugins/nhcx/skills/nhcx-preauth/references/api-knowledge.md @@ -0,0 +1,400 @@ +# API knowledge: the nhcx-adapter contract (optional transport) and the HMIS endpoints that face it + +Read this file only when the transport is nhcx-adapter, and use nhcx-adapter only when the user has asked for it (`references/transport-knowledge.md` section 1). Otherwise the build reaches NHCX through the app's existing integration or its own transport, and `references/transport-knowledge.md` sections 3 and 4 replace everything here. + +This file describes nhcx-adapter (https://github.com/nha-in/nhcx-adapter) as its release ships it, and the HMIS side a build needs to face it. A release carries the binary, `config.sample.json`, `serve.sh`, `stop.sh`, `update.sh` and `README.md`. `nhcx-package/docs/02-Getting Started/10-NHCX Adapter.md` covers the same adapter. When a detail matters, check the release README and `config.sample.json` for the version you run. + +## 1. What the adapter is + +One binary, one `config.json`, no database. You POST plain FHIR to it. It mints the protocol ids, fetches the recipient's certificate, encrypts a compact JWE, posts to the NHCX gateway, and records the exchange in a file ledger. NHCX callbacks reach it encrypted; it decrypts them and POSTs plain FHIR to your HMIS. Both directions are synchronous; there is no queue (release README, "How it works"). + +The same binary can front several participants at once. Inbound, `x-hcx-recipient_code` picks the profile whose key decrypts and whose callback receives. Outbound, `x-hcx-sender_code` picks who sends (release README, "Hosting several participants"). Encrypting for a code the same adapter holds is allowed. So one adapter can host a hospital and a test payer together, and a test between them needs no second gateway. + +## 2. Configuration + +File: `config.sample.json` in the release. `${NAME}` reads an environment variable; `@file` reads a file next to the config. Unknown keys are rejected. + +| Key | Default | What it does | +| --- | --- | --- | +| `env` | `sandbox` | `sandbox` or `production`. Picks the gateway (`https://apisbx.abdm.gov.in/hcx/v1` or `https://apis.abdm.gov.in/hcx/v1`), registry, session endpoint and `X-CM-ID` (`sbx` or `abdm`). | +| `listen` | `127.0.0.1:8090` | The HTTP listener. | +| `publicUrl` | empty | How NHCX reaches the adapter. Register `/in` as the participant's `endpoint_url`. | +| `apiKey` | `${NHCX_ADAPTER_API_KEY}` | The key your HMIS presents on `/out`, `/fhir/out`, `/ledger*`, `/token`. Demanded in production, honoured but not demanded in sandbox. `requireApiKey: true` closes a sandbox adapter. | +| `participant.participantId` | none; the sample carries an example code | Your registry code. `@hcx` is added if missing. | +| `participant.clientId`, `clientSecret` | `${NHCX_CLIENT_ID}`, `${NHCX_CLIENT_SECRET}` | ABDM credentials that mint the session token. | +| `participant.privateKey` | `@private_key.pem` | The RSA key of your registered certificate. | +| `participants[]` | `[]` | Further hosted identities. Each needs only `participantId` and `callback`; the rest is inherited. | +| `callback.url` | `http://127.0.0.1:8765/nhcx/callback` in the sample | Where decrypted messages are POSTed. | +| `callback.appendPath` | `true` | Appends the NHCX path: `.../callback` receives `v1/preauth/on_submit` at `.../callback/v1/preauth/on_submit`. | +| `callback.timeoutSeconds` | `20` | One delivery. NHCX wants its 202 within 30 seconds. | +| `callback.apiKey` | empty | Sent to your HMIS as `Authorization: Bearer `. | +| `callback.routes` | `{}` | Per-path overrides, used exactly as written: `{"v1/preauth/on_submit": "http://preauth-svc/hook"}`. | +| `callback.also` | absent | Extra targets for the same delivery (two systems behind one participant code). Every target must accept or NHCX redelivers to all. | +| `ledger.enabled`, `ledger.dir`, `ledger.retentionDays`, `ledger.storeBodies` | `true`, `data/ledger`, `30`, `true` | The traffic ledger. A hand-written config that leaves out `retentionDays` keeps every day. | +| `maxBodyBytes` | 8 MiB in the v1.0.1 README | Caps request bodies on both surfaces. A PMJAY package master is far larger: set 100 MiB (`104857600`) explicitly. | +| `panel.password`, `panel.path` | empty, `/panel` | The browser console; off until a password is set. | +| `auth.mode`, `auth.tokenTtlSeconds` | `sessions`, `1200` | How the ABDM token is obtained. | + +Minimal working config for one hospital: + +```json +{ + "env": "sandbox", + "listen": "127.0.0.1:8090", + "publicUrl": "https:///in", + "apiKey": "${NHCX_ADAPTER_API_KEY}", + "participant": { + "participantId": "@hcx", + "clientId": "${NHCX_CLIENT_ID}", + "clientSecret": "${NHCX_CLIENT_SECRET}", + "privateKey": "@private_key.pem" + }, + "callback": { "url": "http://127.0.0.1:/nhcx/callback", "appendPath": true, "apiKey": "" } +} +``` + +Start it with `./nhcx-adapter serve`, or `./serve.sh` from the release archive; `./stop.sh` stops a background server. It checks token, participant record, certificate and registered endpoint first and offers to fix each in a terminal (release README, "Startup checks"). `./nhcx-adapter check --no-tui` is the same as a health gate. `serve --no-tui --skip-checks` starts it with no prompts and no checks, for a script that has already checked. + +## 3. Routes + +| Route | Auth | Does | +| --- | --- | --- | +| `POST /out/{path...}` | API key | Send. `path` is the NHCX API path, `v1/preauth/submit`. | +| `POST /fhir/out/{path...}` | API key | Same handler, hcxkit's prefix. The client in section 11 sends here. | +| `POST /in/{path...}` | none | NHCX delivers here. Register `/in`. | +| `POST /v1/{path...}` | none | Alias of `/in` for a registry `endpoint_url` of `/`. | +| `GET /ledger` | API key | Newest first. Filters: `direction, entity, kind, status, sender, recipient, participant, correlation_id, workflow_id, since, until, before, limit` (1 to 500). `since` and `until` take RFC 3339, a date, or a duration such as `24h`. | +| `GET /ledger/stats` | API key | Counts by direction, status, entity. | +| `GET /ledger/thread/{cid}` | API key | Every message on one correlation id plus the derived state. | +| `GET /ledger/{id}` | API key | One message in full, bundle included. | +| `GET /token`, `POST /token/refresh` | API key | The ABDM session token, for calls the adapter does not make (registry, PMJAY payer service). `?participant=` for a hosted identity. | +| `GET /healthz`, `GET /readyz` | none | Liveness; readiness is 503 until a token is held. | +| `GET /panel` | its own password | Operator console: Live, Ledger, Send, Lookup, Setup. | +| `/internal/*` | none | hcxkit-compatible console API, section 8. | + +API key check: `Authorization: Bearer ` first, then `X-Api-Key: `. Constant-time compare. A miss answers `401 {"ok":false,"error":{"code":"UNAUTHORIZED","message":"missing or invalid API key"}}`. + +## 4. The outbound envelope + +The body must be a JSON object. Header precedence, lowest to highest: + +1. HTTP request headers named `x-hcx-*`. +2. The `jwe_headers` object (hcxkit spelling). +3. Top-level `x-hcx-*` keys. +4. Top-level short aliases: `sender`, `recipient`, `correlation_id`, `request_id`, `api_call_id`, `workflow_id`, `status`. + +The payload is `fhir`, else `payload`, else the body itself when it carries `resourceType`. Otherwise `400 INVALID_ENVELOPE`. + +The protected header names: + +``` +x-hcx-api_call_id x-hcx-request_id x-hcx-correlation_id x-hcx-timestamp +x-hcx-status x-hcx-sender_code x-hcx-recipient_code x-hcx-workflow_id +``` + +Completion rules: + +- Sender and recipient codes get `@hcx` appended if missing. +- `api_call_id`, `request_id`, `correlation_id` are kept only when they are plain 8-4-4-4-12 UUIDs; anything else is replaced with a fresh UUID. So a response must carry the request's `correlation_id` as a UUID or the thread is lost. +- `x-hcx-status` defaults to `request.initiated`, or `response.complete` when the last path segment starts with `on_`. +- `x-hcx-timestamp` defaults to now as `YYYY-MM-DDThh:mm:ss±hhmm`. The zone has no colon: `+0530`, not `+05:30`. +- An empty `x-hcx-workflow_id` is dropped, not sent. +- On an `on_` path with no usable correlation id, the adapter threads the message to the newest inbound request of that entity from that recipient. Do not rely on it; send the id. + +What a hospital sends on a normal leg: + +```json +{ + "jwe_headers": { + "x-hcx-sender_code": "@hcx", + "x-hcx-recipient_code": "@hcx", + "x-hcx-workflow_id": "12" + }, + "fhir": { "resourceType": "Bundle", "type": "collection", "...": "..." } +} +``` + +Add `"x-hcx-correlation_id": ""` only on the two reply legs: the communication reply on `v1/communication/on_request` and the payment acknowledgement on `v1/paymentnotice/on_request`. + +## 5. The outbound answer + +The HTTP status is the NHCX gateway's own. Body: + +```json +{ + "ok": true, + "path": "v1/preauth/submit", + "url": "https://apisbx.abdm.gov.in/hcx/v1/preauth/submit", + "headers": { "x-hcx-correlation_id": "...", "x-hcx-api_call_id": "...", "x-hcx-request_id": "...", "x-hcx-workflow_id": "12", "x-hcx-status": "request.initiated", "x-hcx-timestamp": "...", "x-hcx-sender_code": "...", "x-hcx-recipient_code": "..." }, + "gateway_status": 202, + "response": { "...": "the NHCX 202 body" }, + "duration_ms": 412, + "ledger_id": "7UMV0007", + "txn_id": "7UMV0007", + "correlation_id": "...", + "request_id": "..." +} +``` + +Store three things on the leg: `txn_id` (the ledger id), `correlation_id` (the thread), and `headers["x-hcx-api_call_id"]`. Store them on every send. + +Local failures come back as `{"ok": false, "error": {"code", "message", "retryable"}, "request_id", "upstream_status", "upstream_body"}` with these statuses: `400` for `INVALID_ENVELOPE`, `INVALID_PAYLOAD`, `INVALID_BODY`, `INVALID_JWE`, `NO_PATH`, `NO_RECIPIENT`, `WRONG_RECIPIENT`, `BODY_READ`; `401` for the API key; `413` `BODY_TOO_LARGE`; `422` for `DECRYPT_FAILED`, `CERT_NOT_FOUND`, `SELF_ENCRYPTION_KEY`; `502` for any code starting `CALLBACK_`, `GATEWAY_`, `CERT_FETCH_`, `TOKEN_`; `501` `LEDGER_DISABLED`. A gateway refusal is recorded in the ledger as `rejected` with `GATEWAY_HTTP_`. + +## 6. The inbound callback your HMIS receives + +The adapter POSTs to `callback.url` plus the NHCX path. Body: + +```json +{ + "meta": { + "type": "in", + "payloadType": "fhir", + "path": "v1/preauth/on_submit", + "ip": "1.2.3.4", + "time": "", + "redelivery": false, + "participant": "@hcx" + }, + "jwe_headers": { + "alg": "RSA-OAEP-256", "enc": "A256GCM", + "x-hcx-api_call_id": "...", "x-hcx-correlation_id": "...", "x-hcx-request_id": "...", + "x-hcx-sender_code": "@hcx", "x-hcx-recipient_code": "@hcx", + "x-hcx-status": "response.partial", "x-hcx-timestamp": "...", "x-hcx-workflow_id": "20" + }, + "fhir": { "resourceType": "Bundle", "...": "..." } +} +``` + +`payloadType` is `fhir` for a bundle and `protocol` for a ProtocolResponse. A ProtocolResponse is a refusal. Then `fhir` is the plain JSON body with `type: "ProtocolResponse"`, `x-hcx-status: response.error` and `x-hcx-error_details` at its top level. + +HTTP headers on the delivery: + +| Header | Value | +| --- | --- | +| `X-Nhcx-Path` | `v1/preauth/on_submit` | +| `X-Nhcx-Payload-Kind` | `fhir` or `protocol` | +| `X-Nhcx-Correlation-Id` | the thread | +| `X-Nhcx-Api-Call-Id` | this delivery's id, stable across redeliveries | +| `X-Nhcx-Redelivery` | `true` when the ledger already holds this api_call_id (absent otherwise) | +| `X-Nhcx-Participant` | the hosted identity it was addressed to | +| `X-Hcxkit-Txn-Id` | equals `x-hcx-api_call_id` (what a kit-style backend dedupes on) | +| `X-Hcxkit-Type` | entity: `coverage`, `insurance`, `preauth`, `claim`, `task`, `payment`, `communication`, `status` | +| `X-Hcxkit-Flow` | `request` for an arriving response, `on_request` for an arriving request (inverted on purpose) | +| `X-Hcxkit-Payload-Kind` | same as `X-Nhcx-Payload-Kind` | +| `Authorization` | `Bearer ` when configured | + +Contract: answer any 2xx quickly. The adapter then answers NHCX with the 202 acceptance body and an `X-Nhcx-Ledger-Id` header: + +```json +{ + "timestamp": "11/09/2026 10:00:00:123", + "api_call_id": "...", "correlation_id": "...", + "result": { "sender_code": "...", "recipient_code": "...", "entity_type": "preauth", "protocol_status": "request.queued" }, + "error": { "code": "", "message": "" } +} +``` + +A non-2xx from your HMIS becomes `CALLBACK_HTTP_` and NHCX redelivers. NHCX makes five attempts, then drops the correlation id. Your handler must therefore be idempotent on `x-hcx-api_call_id`. Do not do slow work inside the callback: store the envelope, answer 200, apply it after. Apply a delivery on a context detached from the incoming request, so a gateway that hangs up cannot roll the write back. + +The HMIS callback handler: + +- Routes `POST /callback`, `POST /callback/` and `POST /nhcx/callback`. +- Takes an optional shared secret on the query string (`?token=`). +- Reads `X-Hcxkit-Type`, `X-Hcxkit-Flow` and `X-Hcxkit-Payload-Kind`. +- Archives the envelope before applying it. +- Answers `400` for an unreadable body, because redelivery cannot help. Anything unexpected becomes a 500, so the adapter retries. +- Returns `{"status": "settled" | "unmatched" | "ignored"}`. +- Routes by correlation id, never by path. + +## 7. The ledger + +Layout: `ledger.dir//.json`, one file per message, plus `/index.jsonl` with one summary line per message. Ids are eight base32 characters (alphabet `0-9A-V`), a day prefix and a counter that restarts each day: `7UMV0001` is the first message of its day. Pruned hourly by `retentionDays`. + +Entry fields: `id, direction (out|in), created_at, path, entity, action, kind (request|response), format (fhir|protocol|json), sender, recipient, correlation_id, api_call_id, request_id, workflow_id, hcx_status, status, error{code,message}, redelivery, duration_ms, peer{url,status_code,response}, also[], headers{}, fhir{}, fhir_summary{resource_type,bundle_type,entries,resource_types,focus,identifier,patient,outcome}`. + +`status` values: outbound `accepted`, `rejected`, `failed`; inbound `delivered`, `delivery_failed`, `rejected`. + +Thread: `{correlation_id, entity, workflow_id, counterparty, role (initiator|responder), state, started, updated, messages[]}`. `state` is derived by walking the messages in order: + +- `awaiting_response`: you sent a request. +- `awaiting_our_response`: a request reached you. +- `partial`: a `response.partial` arrived. +- `completed`: a response closed it. +- `error`: a rejection, a failed send or delivery, a protocol message, or an `error` status. +- `unknown`. + +Two ledger behaviours you rely on. An outbound `on_` response with no `correlation_id` is threaded to the newest matching inbound request. An inbound whose `api_call_id` was seen before is flagged `redelivery: true`. + +CLI, same data, no server needed for `follow`: + +```sh +nhcx-adapter ledger list --since 24h --entity preauth --status rejected +nhcx-adapter ledger follow --direction in +nhcx-adapter ledger show 7UMV0007 +nhcx-adapter ledger thread +nhcx-adapter ledger stats +nhcx-adapter decrypt --file body.json +nhcx-adapter cert +nhcx-adapter send --path v1/preauth/submit --recipient --file bundle.json +``` + +## 8. hcxkit-compatible endpoints + +A client written against hcxkit polls the adapter for the other side's answer instead of only waiting for its callback. The adapter serves the sliver of hcxkit's `/internal` API that such a client needs. None of these need the API key. Keep the adapter's port off any network you do not control (`nhcx-package/docs/02-Getting Started/10-NHCX Adapter.md`, "Before you expose it"). + +| Route | Body | Answers | +| --- | --- | --- | +| `GET /internal/config/get` | none | `{participant{participantId,name,callbackUrl}, participants[], CMID, env, urls{nhcx,participant,sessions}}` | +| `POST /internal/participants/search` | `{"participant_code": ""}` | `{participants:[registry record + participant_code, participant_name, endpoint_url, status, roles]}`; an unknown code is `{participants: []}` | +| `POST /internal/txn/related` | `{"txnId": ""}` | every ledger row on the same correlation id, both directions, as `{id, direction, status, sender, recipient, correlation_id, api_call_id, type, flow, created_at}`; `404 TXN_NOT_FOUND` when the ledger no longer holds it | +| `POST /internal/txn/fhir` | `{"txnId": ""}` | `{meta{type,payloadType,path,time}, jwe_headers, fhir}`, the same envelope shape a delivery carries | +| `POST /internal/txn/dispatch` | `{"txnId": ""}` | `{txnId, status}` with `dispatch_failed` for a failed or rejected send, `dispatched` for accepted or delivered, plus `errorCode`, `errorMessage` | +| `GET /internal/txn/list?limit=200` | none | the recent ledger, newest first, same row shape | +| `POST /internal/policies/search` | `{"identifiertype": "MemberId", "MobileNo" or "AbhaNumber", "identifiervalue": "..."}` (also `mobile`, `abhaNo`) | the ABDM registry's `participant/get/policies` answer, status passed through; "No policies found" is an error the caller reads as empty | +| `POST /internal/policies/abha/link`, `.../delink` | forwarded verbatim | registry answer | +| `POST /internal/participants/list` | forwarded verbatim | registry roster | +| `POST /internal/participants/certs` | `{"participantid": ""}` | `{participant_code, encryption_cert}` | +| `GET /internal/participants/saved` | none | the configured profiles | + +The polling pattern: + +1. After a send, call `/internal/txn/related` with the stored `txn_id`. +2. Take the inbound rows on the thread that were not sent by you. Keep only rows addressed to the participant the send came from. +3. Fetch each with `/internal/txn/fhir`, newest first. +4. Take the first whose bundle carries the resource the reply is made of (ClaimResponse, CoverageEligibilityResponse, InsurancePlan, Task). +5. Apply it through the same code path the callback uses. Dedupe on `x-hcx-api_call_id`. + +A `404` from `txn/related` means the ledger was reset. Settle the leg as an error instead of spinning. + +## 9. curl examples + +Set these once. The address is the adapter's default `listen`: + +```sh +export ADAPTER=http://127.0.0.1:8090 +export KEY= +export ME=@hcx +export PAYER=@hcx +``` + +Liveness and readiness: + +```sh +curl -s $ADAPTER/healthz +curl -s $ADAPTER/readyz +``` + +Send a coverage eligibility check. Write the envelope to a file first. The bundle is the package's validation request, `nhcx-package/fhir/B1/validation.json`, with your own identifiers substituted. Run this from the project root that holds `nhcx-package/`: + +```sh +python3 - <<'EOF' +import json, os +bundle = json.load(open("nhcx-package/fhir/B1/validation.json")) +env = {"jwe_headers": {"x-hcx-sender_code": os.environ["ME"], + "x-hcx-recipient_code": os.environ["PAYER"], + "x-hcx-workflow_id": ""}, + "fhir": bundle} +json.dump(env, open("/tmp/coverage-out.json", "w")) +EOF +curl -s $ADAPTER/fhir/out/v1/coverageeligibility/check \ + -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \ + --data-binary @/tmp/coverage-out.json +``` + +Read the answer back from the ledger with the `correlation_id` from that response: + +```sh +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger/thread/" +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger?direction=in&entity=coverageeligibility&since=1h" +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger/" +``` + +Same thread through the kit endpoints (no key): + +```sh +curl -s $ADAPTER/internal/txn/related -H 'Content-Type: application/json' -d '{"txnId":""}' +curl -s $ADAPTER/internal/txn/fhir -H 'Content-Type: application/json' -d '{"txnId":""}' +``` + +A session token for the PMJAY payer service or a registry call: + +```sh +curl -s -H "Authorization: Bearer $KEY" $ADAPTER/token +``` + +Simulate a delivery to your own callback while the adapter is not involved (useful for the callback handler's unit test). This is the exact shape the adapter posts. Wrap the package's bare payer bundle, here the pre-auth approval `nhcx-package/fhir/C5/C5-approved-wf21.json`, as `{"meta":{...},"jwe_headers":{...},"fhir":}` first: + +```sh +python3 - <<'EOF' +import json +bundle = json.load(open("nhcx-package/fhir/C5/C5-approved-wf21.json")) +env = {"meta": {"type": "in", "payloadType": "fhir", "path": "v1/preauth/on_submit"}, + "jwe_headers": {"x-hcx-correlation_id": "", "x-hcx-api_call_id": "", + "x-hcx-sender_code": "@hcx", + "x-hcx-recipient_code": "@hcx", + "x-hcx-status": "response.complete", "x-hcx-workflow_id": "21"}, + "fhir": bundle} +json.dump(env, open("/tmp/delivery.json", "w")) +EOF +curl -s -X POST "http://127.0.0.1:/nhcx/callback/v1/preauth/on_submit" \ + -H 'Content-Type: application/json' -H 'X-Nhcx-Path: v1/preauth/on_submit' \ + -H 'X-Nhcx-Payload-Kind: fhir' -H 'X-Nhcx-Correlation-Id: ' -H 'X-Nhcx-Api-Call-Id: ' \ + -H 'X-Hcxkit-Txn-Id: ' -H 'X-Hcxkit-Type: preauth' -H 'X-Hcxkit-Flow: request' -H 'X-Hcxkit-Payload-Kind: fhir' \ + -H 'Authorization: Bearer ' \ + --data-binary @/tmp/delivery.json +``` + +## 10. The HMIS-side endpoints a build exposes + +Use these as the model for what your HMIS needs. `` is the claim episode id. + +| Method | Path | Purpose | Leg | +| --- | --- | --- | --- | +| GET | `/claims`, `/claims/new`, `/claims/` | list, policy search, detail | none | +| POST | `/claims` | open an episode from a chosen policy | none | +| GET | `/claims//state` | the whole episode as JSON after the page-load polls | none | +| POST | `/claims//check` | coverage eligibility (validation, benefits, discovery) | `v1/coverageeligibility/check` | +| POST | `/claims//plan` | fetch or refresh the package master | `v1/insuranceplan/request` | +| GET | `/claims//plan/forms`, `.../forms/`, `.../plan/` | questionnaires and one package | none | +| POST | `/claims//link`, `/unlink` | attach or detach the admission | none | +| POST | `/claims//preauth` | save the dossier draft | none | +| GET, POST | `/claims//lines`, `.../lines/quantities`, `.../lines//delete` | procedure, implant and tier lines | none | +| POST | `/claims//forms` | save questionnaire answers | none | +| POST | `/claims//auth` | auth-requirements ruling | `v1/coverageeligibility/check` | +| POST | `/claims//submit` | pre-auth 12, query answer 19, enhancement 13, enhancement answer 131 | `v1/preauth/submit` | +| POST | `/claims//predetermination` | a quote | `v1/preauth/submit` | +| POST | `/claims//cancel` | cancel Task PC01 | `v1/task/submit` | +| POST | `/claims//status` | status enquiry Task | `v1/task/submit` | +| POST | `/claims//reprocess`, `/release` | reprocess or balance release, 36 | `v1/task/submit` | +| POST | `/claims//queries//reply`, `.../acknowledge` | communication reply or notification acknowledgement | `v1/communication/on_request` | +| POST | `/claims//discharge` | record how the stay ended | none | +| POST | `/claims//claim` | claim 15, query answer 161 or 151, resubmit 16 | `v1/claim/submit` | +| POST | `/claims//claim/documents`, `/documents`, `/documents/required`, `.../delete` | attachments | none | +| GET | `/claims//documents/` | view an attachment | none | +| POST | `/claims//payments//ack` | resend a payment acknowledgement | `v1/paymentnotice/on_request` | +| POST | `/v1/` under the registered `endpoint_url` (own transport), or `/callback`, `/callback/`, `/nhcx/callback` (nhcx-adapter) | a delivery | inbound | + +The HMIS configuration a build needs: + +- The transport's settings: for nhcx-adapter, its base URL (it listens on `127.0.0.1:8090` by default) and API key; for your own transport, the ABDM client id and secret, the private key, and the sessions, NHCX and registry addresses (`references/transport-knowledge.md` section 3). +- The payer's participant code (`1518@hcx` for the PMJAY SHA Himachal Pradesh sandbox) and the payer's name. +- The callback shared secret. +- A workflow-id override table, JSON, that overrides the per-payer table key by key, for example `cancel=122`. +- A map from payer code to payer adapter, for example `1518=pmjay,=generic`. +- The archive folder for cases, and a switch to turn the archive off. + +The sender code is not an environment variable. It is the facility's participant code, held in the HMIS's own settings. + +## 11. What the adapter client looks like in code + +The whole client is one function, `_api(path, payload, timeout, method, claim_id, use_case)`. It builds the URL from the base, adds `Authorization: Bearer` when a key is set, POSTs JSON, raises `GatewayError(message, status)` on any non-2xx or network failure, decodes JSON, and archives the envelope beside the case when `claim_id` is given. Every send in the module goes through it, which is what lets a test replace it with a stub: + +```python +posted = {} +def _ack(path, payload=None, **kw): + posted["path"], posted["payload"] = path, payload + return {"txn_id": "01PLAN", "correlation_id": "corr-plan-1"} +claims._api = _ack +``` + +Give your HMIS the same single door. diff --git a/plugins/nhcx/skills/nhcx-preauth/references/errors-and-debugging.md b/plugins/nhcx/skills/nhcx-preauth/references/errors-and-debugging.md new file mode 100644 index 000000000..9be844d82 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-preauth/references/errors-and-debugging.md @@ -0,0 +1,167 @@ +# Errors and debugging + +Sources: + +- `nhcx-package/nhcx-error.yaml`: every NHCX, PAYR and ERR-PYR code, with the standard and reference payer readings side by side. +- `nhcx-package/docs/06-Reference/01-Error Codes.md`: the same codes as tables. +- `nhcx-package/docs/01-Overview/04-JWE, Status and Errors.md`, "Codes met live". +- `nhcx-package/docs/03-Building a Provider/11-PMJAY Sandbox Run.md`: one full case run, refusal by refusal. +- `nhcx-package/docs/06-Reference/02-Troubleshooting.md`. +- The nhcx-adapter release README, "Troubleshooting". + +The live readings are from runs against the PMJAY SHA Himachal Pradesh sandbox payer (`1518@hcx`). + +## 1. Where an error comes from + +Three places refuse a message, and the family of the code says which (`nhcx-error.yaml`, `spaces`): + +| Family | Who refused | How you hear it | +| --- | --- | --- | +| Gateway answers to your own send (`400`, `401`) | the exchange, before the message goes further | the HTTP answer to your POST on `/v1/...`; a `401` is an expired token or a missing `Bearer` | +| A delivery your key cannot open (own transport) | your receiving end | the JWE will not decrypt: the certificate on your participant record is not the key you hold | +| Adapter codes (`INVALID_ENVELOPE`, `CERT_NOT_FOUND`, `CALLBACK_HTTP_500`), nhcx-adapter only | nhcx-adapter, before or after the wire | the HTTP answer to your `/fhir/out` call, `{"ok": false, "error": {...}}` | +| `NHCX-*` | the exchange; the message never reached the payer | the HTTP answer to your call (`gateway_status` 4xx with `upstream_body`), or a `ProtocolResponse` delivered to your callback later | +| `PAYR-*`, `ERR-PYR-*` | the payer; the message reached it | a `ProtocolResponse` on your callback with `x-hcx-status: response.error` and `x-hcx-error_details {code, message}`, on the request's correlation id | + +A `ProtocolResponse` is plain JSON, not a bundle. The exchange delivers it with `type: ProtocolResponse` and the `x-hcx-` fields in the clear; nhcx-adapter passes it on with `X-Nhcx-Payload-Kind: protocol` and `fhir` set to the body. Read `fhir.type == "ProtocolResponse"` and `fhir["x-hcx-error_details"]`. Settle the leg as refused at the door with the payer's words, and keep the thread the payer last answered on. + +PAYR numbers are not globally unique. The same number means different things on different sheets (`nhcx-error.yaml` lists them under `collisions`), and the live sandbox reuses several with a meaning the published sheet does not give. Match on the message text and log both. + +## 2. PAYR and ERR codes met live + +The published text is from `nhcx-package/nhcx-error.yaml`. Where the standard and reference payer sheets collide, both readings are given. The live text and the fix are from the sandbox runs. + +| Code | Published text | Live text | What it means | Fix | +| --- | --- | --- | --- | --- | +| PAYR-1008 | Invalid FHIR bundle received (reference payer); Eligible coverage amount is insufficient (standard) | "Invalid content type" or "Invalid input, code and reason code" or "Invalid Base64" | Three faults on one code: a document outside pdf, jpg, jpeg, png and fhir+json; a Task code paired with a reason the scheme does not accept (every `status`, `reprocess`, `release` Task on the sandbox, and a reprocess with the intimation input misspelt); an attachment it will not decode | Check the content type. For a Task, the sandbox takes only one financial task code, `cancel` (`11-PMJAY Sandbox Run.md`, "What the sandbox will not take"). Spell the reprocess input `intimationNumber` | +| PAYR-1018 | Time limit for submission expired (standard); No task reason code received (reference payer) | asks for a `Task.reasonCode` on a status enquiry | The status Task is refused as incomplete; with a reason it is refused with PAYR-1008 | Do not offer a status enquiry on PMJAY; switch it off in the PMJAY payer adapter | +| PAYR-1019 | Requested additional information was not received in time (standard); Invalid sequence received in supporting info element (reference payer) | "Invalid sequence received in supporting info element" | A `supportingInfo` entry with no `sequence` | Number the whole list once it is assembled | +| PAYR-1027 | (item error family) | "Invalid item id found for item in claim component" | `Claim.item` has no element `id` (`Item/1`). Nothing to do with the package code | Put `id` on every item, procedure and supportingInfo | +| PAYR-1083 | (practitioner family) | "No HPR details found for the practitioner ... category code as HPIN" | The Practitioner carries no identifier typed `HPIN` | Add the `HPIN` identifier under `https://hpr.abdm.gov.in` | +| PAYR-1096, PAYR-1503 | (supporting-info value-type family) | the death date is missing | A death claim without the `ONS`/`DTM` entry | Add `ONS`/`DTM` with the death instant and answer the plan's death forms | +| PAYR-1214 | No previous preauthorization approved record found for the resubmission request | same | A 121 after a rejection | Send a fresh 12 | +| PAYR-1238 | Beneficiary is having an active preauthorization request at this hospital with reference number ... | same; the reference ends in the SHA's case id | Scheme rule, not a bundle fault: one live pre-auth per beneficiary per hospital. Perversely the first sign the bundle is right, because validation runs first | Cancel the other case (PC01) or let it be rejected; sweep before a run | +| PAYR-1245 | Rule failure | "Only one conservative procedure can be booked for a case" | The master's `ProcedureType`; an enhancement on a conservative case must add a medical package | Pick a package whose `ProcedureType` is medical | +| PAYR-1254, PAYR-1365 | Response for STG Questionnaire id ... is mandatory for procedure code ... | same | A package's treatment-guideline questionnaire unanswered | Answer every `/stgquestionnaire/` form the plan attaches to the quoted packages | +| PAYR-1256, PAYR-1363 | Response for Authentication Consent Questionnaire is missing | same | The plan's consent questionnaire unanswered where no biometric token was taken; 1256 on the pre-auth, 1363 on the claim | Answer the policy-level consent form on both legs | +| PAYR-1270 | Item LM100 is not applicable for preauthorization request | same | `LM100` on a pre-auth | Only a LAMA or DAMA claim before or during surgery carries it | +| PAYR-1321 | Error occurred while processing the request due to invalid workflow id | same | 151, 19 or 16 on `v1/claim/submit` | Answer a claim query on 161; never resubmit a decided claim, reprocess it | +| PAYR-1322 | No active case found for the given case number | "Active instance found for case number" | A request is already open on that case; the scheme takes one at a time | Wait about 30 seconds after a decision, then send again; up to three tries | +| PAYR-1362 | No procedure with code LM100 received with 'Requested' status | same | A LAMA or DAMA claim before or during surgery that still carries the package | Collapse the claim to one `LM100` line | +| PAYR-1367, PAYR-1368 | No biometric records found ... / units of cycle information received | same | A cyclic package (dialysis) claimed without a biometric record per cycle and cycle information | Do not claim a cyclic package unless the HMIS can produce both | +| PAYR-1401 | policy not allowed for the hospital | same | The plan was asked for under a policy the hospital is not empanelled under | Ask under the beneficiary's own policy code from the policy search | +| PAYR-1406 | Existing request with correlation id ... is in progress | same | A second plan request while one is still being served | Wait 15 to 60 minutes; reuse the master you hold | +| ERR-PYR-CLM-007 | on none of the published sheets; `nhcx-error.yaml` lists it as observed live | "No prior preauthorization or claim record found for case number" | The claim was sent under a number of its own instead of the pre-auth's | Send the claim under the pre-auth's claim number | + +Refusals arrive in order: the SHA validates the bundle first and applies the scheme's rules only to a bundle that passed. A refusal in the `PAYR-102x` block is structural, so check ids and sequences before values. + +## 3. Gateway protocol errors + +From `nhcx-package/nhcx-error.yaml` (the gateway space) and the live notes: + +| Code | Message | When you meet it | Fix | +| --- | --- | --- | --- | +| NHCX-1006 | Duplicate request. Request with same correlation id already exist | A request sent again on a correlation id the exchange already holds | Mint a fresh correlation id for every request; only a response echoes one | +| NHCX-1010 | No Data with given Correlation id for call back request | A response sent on a thread the exchange has retired: the request was redelivered five times without a 2xx, or the id was never a request | Acknowledge inbound requests at once; a payer that decides minutes later sends `outcome queued` first | +| NHCX-1012 | No records found with the requested api caller id | The sandbox's own `v1/status` route, whatever id you pass | Ask status as a Task on `v1/task/submit` | +| NHCX-1015 | Invalid response received from receiver (published); the registry answers "You are not authorized to update/modify details" | Updating a participant's endpoint or certificate with a client id that did not create it | Use the creator's credentials or the NHCX participant portal (nhcx-adapter release README, "Troubleshooting") | +| NHCX-1016 | Invalid Api Action / no policies found (the registry, on a policy search) | A policy search that finds nothing | Read it as an empty result | +| NHCX-1018 | Invalid ABHA number received | An ABHA not in `XX-XXXX-XXXX-XXXX` form on the envelope | Format it, or omit the header | + +With nhcx-adapter as the transport, its local codes and their HTTP statuses are in `api-knowledge.md` section 5. The ones you will meet first: + +- `CERT_NOT_FOUND`: the recipient has no certificate on the registry; nothing to fix locally. +- `SELF_ENCRYPTION_KEY`: the registry handed out your own certificate for another code; run `nhcx-adapter cert --refresh`. +- `DECRYPT_FAILED` on `/in`: your registered certificate is not the key you hold; run `nhcx-adapter check`. +- `WRONG_RECIPIENT` on `/in`: a message for a participant this adapter does not hold. +- `CALLBACK_HTTP_` and `CALLBACK_UNREACHABLE`: your HMIS refused or was down; NHCX will redeliver up to five times. +- `TOKEN_HTTP_401`: wrong `clientId` or `clientSecret`, or sandbox credentials against production. + +## 4. Reading a ledger thread + +The per-case archive is the first place to look, with any transport: every message sent and received, by correlation id, in `//transactions.txt` (step 4). With nhcx-adapter as the transport, its ledger also holds what reached it but not your HMIS; the commands below read it. + +Step 1. Find the thread. From the leg row's `correlation_id`, or from the case number in a summary: + +```sh +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger/thread/" | python3 -m json.tool +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger?since=2h&direction=in&limit=100" | python3 -c 'import json,sys; [print(r["id"], r["created_at"][11:19], r["direction"], r["path"], r["workflow_id"], r["hcx_status"], r["status"], r.get("fhir_summary",{}).get("outcome")) for r in json.load(sys.stdin)["items"]]' +nhcx-adapter ledger thread # no server needed +``` + +Step 2. Read the derived `state`: + +| state | Meaning | What to do | +| --- | --- | --- | +| `awaiting_response` | You sent a request and nothing came back | Wait; on the SHA a decision needs the desk. Check `peer.status_code` on the outbound row is 202 | +| `partial` | A `response.partial` arrived (20, 25, or the SHA's 37) | The payer has it. The decision comes on the same thread | +| `completed` | A `response.complete` arrived | The leg should be settled in the HMIS. If it is not, the callback failed or the reader misread it | +| `awaiting_our_response` | A request reached you (a CommunicationRequest, a payment notice) | Your reply is due on this correlation id | +| `error` | A rejection, a failed send or delivery, or a protocol message | Open the message with `error` or `format: protocol` | + +Step 3. Read one message in full, bundle included: + +```sh +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger/" | python3 -m json.tool | less +``` + +On an inbound row, `peer.status_code` is what your callback answered and `peer.response` is its body. A `delivery_failed` row with a 500 is your handler raising. On an outbound row, `peer.status_code` is the gateway's answer and `peer.response` its body. A `rejected` row carries `GATEWAY_HTTP_` and the NHCX error in `peer.response`. + +Step 4. Compare with the HMIS's own archive for the case, `//transactions.txt`. Each line names the workflow id, correlation id, api call id, ledger id and file. + +- A message in the ledger and not in the archive is a callback that failed. +- A message in the archive marked `outcome=unmatched` is one the HMIS could not tie to a case: the correlation id is on no leg row, and the bundle names no claim number the HMIS knows. +- A message in neither is a send that never left; look at the HMIS's error on the leg row. + +Files, when the server is down: `//.json`, and `index.jsonl` in the same folder for the summaries. `ledger.dir` is `data/ledger` by default. + +## 5. Correlation mistakes + +Each of these was made once in a real build. + +- Answering on the wrong thread. A communication reply or a payment acknowledgement must carry the request's `x-hcx-correlation_id`; every other leg must not carry one. A PMJAY query answer (19, 131, 161) goes on a new correlation id; a same-thread answer is swallowed without a refusal. +- Sending a non-UUID correlation id. nhcx-adapter replaces anything that is not an 8-4-4-4-12 UUID with a fresh one, so the thread is silently lost; store what the transport returned, not what you sent. With your own transport, a request's correlation id is its own `api_call_id` and an answer echoes the request's. +- Matching by path or by header type. Route an inbound message by its correlation id first, then by the claim number inside the bundle. With nhcx-adapter, the `X-Hcxkit-Flow` header is inverted on purpose and must not be a filter. +- Closing a thread on the first reply. The acknowledgement and the decision share one correlation id; a settled-status guard throws the approval away. +- Losing the thread after a refusal at the door. A send refused with a ProtocolResponse went out under a correlation id the payer never took in. The case still lives on the thread the payer last answered; keep it as `thread_correlation_id`. +- Reusing a correlation id after an error. The exchange retires it; the next attempt needs a fresh one. +- Forgetting the workflow id on a reply. Some payers match the payment acknowledgement on the notice's own workflow id; PMJAY wants 17. + +## 6. Redelivery and deduplication + +NHCX redelivers an unacknowledged message up to five times and then drops the correlation id. The SHA redelivers a large plan answer on its own, two or three times about a minute apart, under the same `x-hcx-api_call_id`. A case archive showed it as three lines on one api call id. With `callback.also` configured, one delivery reaches every target, and a refusal by any one of them makes NHCX redeliver to all. + +So: + +- Dedupe on `x-hcx-api_call_id` (with nhcx-adapter, `X-Hcxkit-Txn-Id` carries the same value). Either store the last applied `api_call_id` on the leg row and ignore a repeat, or keep an inbound ledger keyed on it and answer `duplicate`. A payer that omits the id is deduped on identical outcome and adjudication. +- Dedupe payment notices and communication requests on their correlation id, with a unique index on each table. +- Answer 2xx before doing slow work. The exchange allows 30 seconds for the 202 receipt (nhcx-adapter gives your HMIS 20 of them, `callback.timeoutSeconds`); anything slower is a failed delivery. +- Un-record a delivery whose application failed for a passing reason (database away), so the redelivery is not waved off as a duplicate. +- With nhcx-adapter, treat `X-Nhcx-Redelivery: true` as a hint, not a rule: the ledger flag is per adapter process and is lost on a ledger reset. + +## 7. A send reported as failed can still have landed + +Seen live on the sandbox three times in one night. A pre-authorisation went out through nhcx-adapter, the connection dropped after the request had been written, and it answered the hospital `GATEWAY_UNREACHABLE` with HTTP 502. NHCX had taken the message: the SHA acknowledged it four seconds later on the correlation the adapter had minted. A hospital that treats that 502 as "not sent" sends again. The scheme refuses the duplicate (ERR-PYR-PRE-030 "Active instance found for case number", PAYR-1238 for a fresh pre-auth), and a live case stands at the payer that the hospital has no record of. + +So: + +- nhcx-adapter's failure body names the ids the message went out under: `ledger_id`, `txn_id`, `correlation_id`, `api_call_id`, `request_id` and the `headers` map. Keep them. With your own transport the ids are the ones you minted before sealing: store them before the POST, so a failed POST still has a thread to look for. +- Record the failed leg under that correlation, not as nothing. Carry the ids on the client's error and write them onto the leg row. +- When an answer arrives on a failed leg's correlation, revive it: the leg becomes a sent leg, the record moves from draft to with-the-payer, and the desk is not offered a second send. A protocol error answer revives nothing. +- Anything that creates a record before it sends must name that record in the refusal, or the record is orphaned where nobody can see it. An enhancement handler returns the child it raised alongside the gateway's words. + +## 8. Sandbox pace rules + +What the SHA Himachal Pradesh sandbox (`1518@hcx`) did across the runs. `nhcx-package/docs/03-Building a Provider/11-PMJAY Sandbox Run.md` records one such run in order. + +- One live pre-authorisation per beneficiary per hospital (PAYR-1238). Every HMIS that shares the facility's participant code shares the limit, so sweep before a run: withdraw every approved case without a claim, then wait ten seconds. +- One request at a time per case (PAYR-1322). About 30 seconds between a decision and the next leg; an enhancement refused with "Active instance" is resent up to three times. +- Decisions are taken on the NHCX Payer Service desk, not on the exchange (`nhcx-package/docs/03-Building a Provider/12-PMJAY Adjudication APIs.md`). A case has to be driven through roles: PPD-Trust decides a pre-auth; a claim walks CEX-Trust, CPD-Trust, the Medical Audit Committee, ACO-Trust, SHA-Trust and the Claim Review Committee. The desk answers "Event Meta Log not found" or "Case not found" until the exchange has delivered the request; retry every six seconds, up to 150 seconds. A decision the desk accepts is sometimes never sent; taken again a minute later it is answered in seconds, so decide up to four rounds of 90 seconds. +- An enhancement's query has to be taken a minute after the acknowledgement. +- A claim episode with a query answered and the roles walked takes about ten minutes. Run cases one at a time and allow 20 minutes per case. +- The plan answer arrives in pieces over a minute and is redelivered; expect the same api call id three times. +- The beneficiary registry behind the ABDM session refuses a search now and then while a token refreshes. Retry the search up to four times, 30 seconds apart. +- The sandbox approves a claim query answer at zero with "No query response comments received" when the `CQD` reply is missing, and sometimes even when it is present. Report it; do not assert on the amount. +- The status Task is refused on this sandbox: without a `Task.reasonCode` it answers PAYR-1018, with any reason code PAYR-1008. PMJAY decides on its own desk and answers no status enquiry, so do not offer one for it. Record the refusal on the enquiry row and move on. +- The reprocess Task is taken only under the standard's spelling, `intimationNumber`. Use that spelling on every Task (cancel included); the package's bundles carry it too. The SHA answers workflow 37, "Arbitration claim submission process completed successfully". +- A test payer you run yourself has none of these limits; six use cases ran in under four minutes against one. diff --git a/plugins/nhcx/skills/nhcx-preauth/references/fhir-knowledge.md b/plugins/nhcx/skills/nhcx-preauth/references/fhir-knowledge.md new file mode 100644 index 000000000..08ffbb6c6 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-preauth/references/fhir-knowledge.md @@ -0,0 +1,206 @@ +# FHIR knowledge: every bundle sent and received + +Sources: the bundles under `nhcx-package/fhir` (the hospital pins in `B1` to `B9`, the payer answers in `C3` to `C11`, the live PMJAY hospital captures in `D1` to `D13`) and the chapters under `nhcx-package/docs/05-FHIR Reference`. Get the package as `references/material.md` says. + +## 1. Where the examples live + +| Set | Path | What it is | +| --- | --- | --- | +| Pinned hospital bundles | `nhcx-package/fhir/B1` to `B9`, the lower-case files (`B3/preauth-request.json`) | One bundle per message a hospital sends, written to the specification with placeholders. A build is held to these byte for byte. The pin map is in `references/material.md`. | +| Payer answers | `nhcx-package/fhir/C3` to `C11` | One file per message the payer sends: the generic answer and, where one exists, its `-pmjay` twin. Feed these into your readers. | +| Live hospital captures | `nhcx-package/fhir/D1` to `D13` (PMJAY) and the capitalised B files such as `B3/B3-request.json` (generic) | Bundles taken from the sandbox wire, with the beneficiary's identifiers replaced | +| The catalogue | `nhcx-package/fhir/index.yaml` | For each file: direction, side, scheme (`generic` or `pmjay`), workflow id, focal resource, origin. Origin `example` means placeholders, not a payload; `wire` means a capture. | +| The NRCeS IG's own example | `nhcx-package/fhir/B4/communication-request.json` | The communication TaskBundle for the payer's request comes from the IG | +| Your build's archive | `//NNN--.json` and `transactions.txt` (modules 7.1 and 7.3) | Every envelope one episode sent and received, in order | +| Chapters | `nhcx-package/docs/05-FHIR Reference/*.md` | Element by element: `08-Preauthorisation Request.md`, `12-Claim Request.md`, `13-Claim Response.md`, `17-Communication.md`, `15-Cancel, Reprocess and Shortfall.md`, `16-Payment Notice and Acknowledgement.md`, `06-Insurance Plan Response, Package-Based.md`, `19-Codes and Value Sets.md` | + +Pins, by leg. Paths are under `nhcx-package/fhir/`. + +| Leg | Provider pin | Payer answer or capture | +| --- | --- | --- | +| Coverage eligibility | `B1/discovery.json`, `B1/validation.json`, `B1/benefits.json`, `B1/auth-requirements.json` | `C3/validation-response.json`, `C3/discovery-response.json`, `C3/benefits-response.json`, `C3/C3-response-generic.json`; PMJAY `C3/coverage-eligibility.json`, `C3/C3-benefits-pmjay.json`, `C3/C3-response-pmjay.json` | +| Insurance plan | `B2/insurance-plan-request.json` | `C4/C4-response-pmjay.json` (package-based, abridged), `C4/C4-response-generic.json` (coverage-based) | +| Pre-auth 12, enhancement 13, query answer 19 or 131 | `B3/preauth-request.json`, `B3/preauth-enhancement.json`, `B3/preauth-queryupdate.json` | `C5/C5-received-wf20.json`, `C5/C5-approved-wf21.json`, `C5/preauth-queried.json`, `C5/C5-rejected-wf23.json`, `C5/C5-enhancement-approved-wf22.json`; PMJAY the `-pmjay` twins and `C5/C5-queried-wf24.json` | +| Cancel PC01 | `B3/preauth-cancel.json` | `C10/C10-cancelled-wfPC02.json`, `C10/C10-cancelled-wfPC02-pmjay.json` | +| Claim 15, query answer 161 | `B5/claim-request.json`, `B5/claim-queryupdate.json` | `C7/C7-received-wf25.json`, `C7/C7-approved-wf26.json`, `C7/claim-queried.json`, `C7/C7-rejected-wf291.json`; PMJAY the `-pmjay` twins, `C7/C7-approved-deduction-wf26-pmjay.json` and `C7/C7-queried-wf27.json` | +| Reprocess 36, release 36 | `B5/claim-reprocess.json`, `B5/claim-release.json` | `C10/C10-arbitration-wf37.json`, `C10/C10-arbitration-wf37-pmjay.json` | +| Payment acknowledgement | `B7/payment-notice-ack.json` | The notice you answer: `C9/C9-notice-wf30.json`; PMJAY `C9/payment-notice.json`, `C9/C9-notice-tds-wf30-pmjay.json` | +| Communication reply | `B4/communication-response.json` | `B4/communication-request.json` (the query you answer; the IG's example), `C6/C6-preauth-query-wf24.json` and `C6/C6-claim-query-wf27.json` (live, generic), `C6/C6-notification-wfN02.json` (PMJAY) | +| Status enquiry | None. The published call carries no bundle (`nhcx-package/docs/05-FHIR Reference/18-Predetermination, Status and Search.md`). | None captured | + +## 2. Conventions every hospital bundle follows + +From `nhcx-package/docs/05-FHIR Reference/01-Bundles and Conventions.md` and the pins: + +- `Bundle.type` is `collection`; `Bundle.meta.profile` names the NRCES bundle profile (`ClaimBundle`, `TaskBundle`, `CoverageEligibilityRequestBundle`); every resource names its own profile under `https://nrces.in/ndhm/fhir/r4/StructureDefinition/`. +- Every entry has an absolute `fullUrl` under one base, `https://nhcx.abdm.gov.in/...`, and every reference resolves to another entry. A thing that is genuinely not in the bundle is named by identifier, not by a URL. The chapter's rule 3 also accepts `urn:uuid:` references; parse both. +- `Bundle.id` is fixed per shape: `coverage-validation-request-generic`, `preauth-request-generic`, `preauth-enhancement-request-generic`, `claim-queryupdate-request-generic`, `preauth-cancel-request-generic`. +- No `meta.versionId`, no `meta.lastUpdated`, no bundle `timestamp` on a request. The communication reply and acknowledgement are the exception: the IG example carries `meta.lastUpdated` and `timestamp`, and the build writes them. +- Money carries `currency: INR`; the total equals the sum of the item nets; whole numbers are written as integers. +- Instants are IST with `+05:30`. The four coverage pins in `B1` stamp `created` at `+05:00`, so leave `created` out of the byte comparison. + +## 3. Coverage eligibility request + +Builder: `build_coverage_request`. Seven entries, in this order and at these urls: + +1. `CoverageEligibilityRequest` at `/coverage-eligibility/request`: `identifier: [{system: https://nhcx.abdm.gov.in}]`, `status active`, `priority normal`, `purpose: []`, `patient`, `created`, `enterer` (the PractitionerRole), `provider`, `insurer`, `facility` (the Location), `insurance: [{focal: true, coverage}]`, and `item[]` on `benefits` and `auth-requirements`. +2. `Patient` at `/patient`: identifiers typed `PMJAY` (NDHM identifier-type system) and `MB` (v2-0203), both the member id. Nothing else; demographics are the payer's to return. +3. `Organization` provider at `/provider`: identifier `NPI` under `https://nhcx.abdm.gov.in` = the facility's registry id (HFR id); `type prov`; `name`. +4. `Organization` payer at `/payer`: identifier `NIIP` = the participant code without `@hcx` (`1518`); `type pay`. +5. `Location` at `/location`: `name`, `managingOrganization` the provider. +6. `Coverage` at `/coverage`: identifier `NH` = the policy code, or `NONE` on a discovery; `status active`; `type HIP`; `subscriber`, `beneficiary`, `subscriberId` = member id; `relationship self`; `payor`. +7. `PractitionerRole` at `/practitioner-role`: `code` SNOMED `307988006` Medical technician. + +Items (`eligibility_item`): `category` under `https://nhcx.abdm.gov.in/category-code` (the specialty), `productOrService` under `https://nhcx.abdm.gov.in/product-code` (the package), `quantity.value` as an integer, and each ward tier quoted through the package as a `modifier` coding with code and display and no system. No money, no diagnosis, no sequence. + +The four purposes differ only in `purpose`, the Coverage identifier and whether `item` is present. + +Reader (`parse_validation_bundle`): the payer echoes the request's entries and appends its own, so take the last `CoverageEligibilityResponse`, `Patient` and `Coverage`. Read `insurance[0].inforce`, `outcome`, `disposition`, `item[].authorizationRequired`, the largest `benefit[].allowedMoney` with its `usedMoney`, the Patient's name, gender, birth date, address, `ABHA` identifier and photo, the Coverage's `class[0].name` and `period`. The SHA answers on workflow id `5` (`nhcx-package/fhir/C3/C3-response-pmjay.json`). + +Auth-requirements reader (`parse_auth_bundle`, with `supporting_entry`; examples `C3/C3-response-generic.json` and `C3/C3-response-pmjay.json`): one `insurance[0].item` per line quoted, each with `authorizationRequired`, `excluded`, `benefit[0]` and `authorizationSupporting[]`. Each supporting entry is a CodeableConcept whose `text` is free text the scheme overloads: `fullUrl: ` marks a form to answer; `Type: pre` or `Type: post` says which leg a document is due at; `Procedure Code: X` says for which line. The space after the colon is sometimes missing; match both. A form is always wanted at pre-auth; a document only when its stage is `pre`. + +## 4. Insurance plan request and the plan + +Request (`build_plan_request`): a `TaskBundle` with one entry, a `Task` at `https://nhcx.abdm.gov.in/insurance/request`: `status requested`, `intent order`, `code poll` on the HL7 financial task code system, inputs typed `policyNumber` and `providerId` under the NDHM task-input code system. No id, no timestamp, no requester. At least one input is mandatory. Bundle id `insurance-request-generic`. + +Answer: an `InsurancePlanBundle` with one `InsurancePlan`, an `Organization`, and one `Questionnaire` per form the plan names (the same form repeated once per benefit that needs it; collect by `url`). The parser (`parse_plan_bundle`) reads both published shapes and merges them on package code: + +- `plan[].specificCost[].category` (the specialty) then `benefit[].type` (the package) then `cost[]`: the cost typed `Procedure` is the package rate; `Stratification` and `Implant` costs are money paid over the rate, named by their `qualifiers[0]`. +- `coverage[].benefit[].limit[]`: the limit whose code is the package's own is the rate; the rest (STRAT codes, implants) are tiers. +- Extensions on the plan, the coverage and each benefit, matched by a squashed url family: `Claim-Condition` children name conditions (`ProcedureType`, `IsDayCare`, and so on); `Claim-SupportingInfoRequirement` children are one nested requirement per document, each with `category`, `code` (`MAND0409` and the like) and `documentationUrl` pointing at a Questionnaire. Requirements on the `InsurancePlan` resource itself are policy-wide (proof of identity, the consent forms). +- A `Questionnaire` under `/questionnaire/` is a policy form; under `/stgquestionnaire/` a treatment-guideline checklist. Questions live on `item.prefix` far more often than `item.text`; answer options are plain strings; `initialSelected` is the payer's default. + +Store it once per facility and policy and copy it onto later episodes (`reuse_plan`). The PMJAY master runs to tens of megabytes; the validator cannot check it whole. + +## 5. The Claim bundle: pre-authorisation, enhancement, query answer, claim, predetermination + +One document for every leg (`claim_bundle`). Entries, in order and at these urls: + +1. `Claim` at `https://nhcx.abdm.gov.in//`: leg `preauth`, `claim` or `predetermination`; flow `request`, `enhancement` or `queryupdate`. +2. `Patient` at `/patient`, `id 1`: identifiers `PMJAY` (member id), `ABHA` (when known), `MB` (member id); `name.text`, `telecom`, `gender`, `birthDate`. +3. `Organization` provider at `/provider`, `id 1`; `Organization` payer at `/payer`, `id 2` (as in section 3). +4. `Coverage` at `/coverage`, `id 1`: `NH` identifier = policy code, `subscriberId` = member id. +5. `Practitioner` at `/practitioner` (the second and later at `/practitioner/2` and so on), `id n`: identifiers `HPID` under `https://nhcx.abdm.gov.in`, `MD` (licence) when known, and `HPIN` under `https://hpr.abdm.gov.in`. PMJAY looks the practitioner up by the `HPIN` typed identifier and refuses a bundle without one with PAYR-1083. `qualification.code` under HL7 v2-0360 with the table's own display (`degree_coding`). +6. `Procedure` at `/procedure/n`, `id n`, one per package: `status preparation` before treatment, `completed` on the claim; `code` SNOMED `71388002` with `text` = the package display; `performedDateTime`. +7. `QuestionnaireResponse` at `/questionnaireresponse/n`, one per answered form: `questionnaire` = the plan's Questionnaire url, `status completed`, `subject` the Patient, `authored`, `item[].answer[]` typed by the question (`valueString`, `valueDateTime`, `valueBoolean`, `valueInteger`, `valueDecimal`, `valueAttachment`). + +The Claim itself: + +- `id` = the claim number; `identifier[0]` typed `CLN` under `https://nhcx.abdm.gov.in` = the claim number. Element ids on every list the payer indexes: `item[].id = Item/n`, `procedure[].id = Procedure/n`, `supportingInfo[].id = SupportingInformation/n`. PAYR-1027 is an item without one. +- `status active`, `type` SNOMED `737481003` inpatient care, `use` = `preauthorization`, `claim` or `predetermination`, `billablePeriod`, `created`, `insurer`, `provider`, `priority normal`. +- `careTeam[]`: sequence, provider reference, role `primary` for the first and `assist` after, `qualification` SNOMED specialty. +- `diagnosis[]`: ICD-10 under `http://hl7.org/fhir/sid/icd-10`, type `admitting`, `onAdmission yes`. +- `procedure[]`: sequence, `type` under `https://nhcx.abdm.gov.in/procedure-type` = the plan's `ProcedureType` condition lower-cased (`conservative`, `medical`, `surgical`), `date`, `procedureReference` with the package display. +- `insurance[0]`: `sequence 1`, `focal true`, `coverage`; on the claim `preAuthRef: [""]`. The pin carries the pre-auth's own claim number there (`B5/claim-request.json` quotes `B3/preauth-request.json`'s claim id). The build carries the payer's `ClaimResponse.preAuthRef`, which the live capture `nhcx-package/fhir/D9/D9-request.json` shows as `2026091110000810`. +- `item[]` (`claim_items`): one per procedure or implant, never per tier. `sequence`, `careTeamSequence`, `diagnosisSequence`, `procedureSequence` (its own Procedure), `informationSequence` (every supportingInfo), `category` under `ndhm-benefit-category` (the specialty), `productOrService` under `ndhm-procedure-code` (the package), `modifier[]` one coding per ward tier with code and display and no system, `programCode` `AB-PMJAY` under `ndhm-program-code` for PMJAY and none for a generic payer, `servicedPeriod` as dates, `quantity`, `unitPrice` = net divided by quantity, `factor` from the scheme's multiple-procedure rule (1, 0.5, 0.25 by cost rank; PMJAY only), `net` = the line plus its tiers. +- `total` = the sum of the nets. + +supportingInfo (`supporting_info`), every entry numbered once the list is assembled (PAYR-1019 is an entry without `sequence`): + +| When | category | code | value | +| --- | --- | --- | --- | +| every leg, one per attached document | `INV` (or the document's own category) under `ndhm-supportinginfo-category` | the plan's requirement code (`MAND0408`) under `https://nhcx.abdm.gov.in/document-code`, else `ODN` | `valueAttachment {contentType, data, title}` | +| every leg | `ONS` | `ADDD` | `valueString` admission instant | +| every leg | `OTH` | `EDT` | `valueString` admission instant | +| claim | `HDS` | the plan's summary code (`MAND0006` in the pin) else `HDS` | `valueAttachment` the discharge summary | +| claim, when a surgery time is known | `ONS` | `PSP` | `valueString` surgery instant | +| claim | `ONS` | `DSDE` | `valueString` discharge instant, or the death instant | +| claim, death only | `ONS` | `DTM` | `valueString` death instant (PAYR-1096 and PAYR-1503 without it) | +| claim | `DIS` | `DTH`, `LAMA`, `DAMA` or `DTM` | `valueString` the stage: `Before Surgery`, `During Surgery`, `After Surgery` | +| query answer (flow `queryupdate`) | `NMI` | `CQD` | `valueString` the desk's reply. The SHA reads its query response comments from here; an answer without one is decided as if none was given | +| every leg, one per answered form | `INF` (or `STG` for a treatment guideline) | `ODN` (or `STG`) | `valueReference` to the QuestionnaireResponse entry | + +Which forms ride (`required_forms`): with an auth-requirements ruling, the forms it named for the leg; without one, at pre-auth every guideline form the plan attaches to the quoted packages; and on both legs every policy-level form. The scheme refuses a pre-auth that answers neither biometrically nor with its Authentication Consent questionnaire (PAYR-1256, PAYR-1271), a claim without the consent answered again at discharge (PAYR-1363, PAYR-1364), and a package without its STG questionnaire (PAYR-1254, PAYR-1365). The live D4 capture carries two policy questionnaires; the live D9 claim carries four, including the Discharge Consent (`nhcx-package/fhir/D9/D9-request.json`). + +Which documents ride (`required_documents`, `preauth_documents`): the ruling's list for the leg, else the plan's list for the quoted packages at pre-auth and whatever was not attached there at the claim. A file attached against a requirement carries that requirement's code; a file nobody asked for carries `ODN`. Never drop one. Content types the scheme takes: pdf, jpg, jpeg, png (PAYR-1008 otherwise). + +The legs differ in these ways only: + +| Leg | flow | use | Procedure status | Extra | +| --- | --- | --- | --- | --- | +| Pre-auth 12 | `request` | `preauthorization` | `preparation` | | +| Enhancement 13 | `enhancement` | `preauthorization` | `preparation` | every line, old and new, under the same claim number; the costlier package at factor 1 and the other at 0.5 (the live capture `nhcx-package/fhir/D6/D6-enhancement.json` carries the two lines at 1 and 0.5) | +| Query answer 19 or 131 | `queryupdate` | `preauthorization` | `preparation` | the `NMI`/`CQD` reply | +| Claim 15 | `request` | `claim` | `completed` | discharge scalars, summary, `preAuthRef`, the claim under the pre-auth's number (ERR-PYR-CLM-007) | +| Claim query answer 161 | `queryupdate` | `claim` | `completed` | as the claim, plus `NMI`/`CQD` | +| Predetermination | `request` | `predetermination` | `preparation` | sent on `v1/preauth/submit` with workflow 12 | + +LAMA and DAMA before or during surgery (`claim_lines`): the claim carries one item, procedure `LM100` at the plan's rate (the sandbox prices it at zero), no tier, and the payer disqualifies every approved item (PAYR-1362 if the package is still there). After surgery the package stands and `LM100` is not used. PAYR-1270 is `LM100` on a pre-auth. + +## 6. The ClaimResponse you read + +Shape (`nhcx-package/docs/01-Overview/07-Payer Flexibility.md`, "Answer detail"): `ClaimResponse`, `Patient`, the two `Organization` entries, `Coverage`, in that order. Fields to read (`parse_claim_response`): + +- `use`: `preauthorization` or `claim`; a bundle with none is whatever you sent on that thread. +- `outcome`: `queued` (acknowledgement), `partial` (queried, or approved for less), `complete`, `error` (rejected). +- `adjudication[]` at claim level: the entry whose `category` is `status` carries `reason.coding.code`: `submitted`, `approved`, `queried`, `rejected`, `cancelled`. +- `preAuthRef`: the payer's case number; see `flow-knowledge.md` section 3 for which answers carry it. +- `identifier[0].value`: your claim number, echoed on every answer. +- `total[]`: a repeating list by `category`, never positional: `benefit` (granted this round), `eligible` (what the case stands at), `submitted`; PMJAY adds `tax` and `incentive`. +- `item[].adjudication[]` by category: `eligible` (amount), `status` (reason `Approved`, `Queried`, `Rejected`), `reason` (the desk's remark, pipe-delimited `USER~datetime~type~comment~trust`, kept verbatim), `eligpercent`, `eligquant`, `deductible` with its reason after a claim. +- `processNote[].text`. +- `type` is present only on the pre-auth acknowledgement (SNOMED `737481003`). + +The status rule (`verdict_status`): `queued` or reason `submitted` is still `submitting`; reason `cancelled` is `rejected`; reason `queried` is `queried`; outcome `error` is `rejected`; outcome `partial` is `partial` only with reason `approved`, else `queried`; outcome `complete` is `approved` with reason `approved` or none, else `queried`. Never read `outcome` alone. + +## 7. Task bundles the hospital sends + +A `TaskBundle` with the `Task` at `https://nhcx.abdm.gov.in//` followed by the provider and payer Organizations. The Task: `status requested` (`completed` on an acknowledgement), `intent order`, `code` on the HL7 financial task code system with no display, `description`, `authoredOn`, `requester` the provider, `owner` the payer. + +| Task | code | reasonCode (NDHM reason code system) | inputs | Other | +| --- | --- | --- | --- | --- | +| Cancel PC01 | `cancel` | one of `treatmentplanchanged`, `patientrequest`, `financialconstraints`, `alternativetreatment`, `duplicateclaim`, `administrativeerror`, `other` (with `other` the description is the only justification) | `claimNumber`, `intimationNumber` (both typed under `ndhm-task-input-type-code`) | anchor `/preauth/cancel` | +| Reprocess 36 | `reprocess` | `claimrejected`, `partialpayment` or `rejectiondisputed` with the reference's displays | `claimNumber`, `intimationNumber` (the standard's spelling), one `document` input per attachment as `valueAttachment` | `basedOn[0].identifier` typed `CLN`; `for.identifier` typed `PMJAY` on the scheme, `MB` elsewhere; anchor `/claim/reprocess` | +| Release 36 | `release` | `partialpayment` | `claimNumber`, `amount` as `valueMoney` under `https://nhcx.abdm.gov.in/task-input-type` | `basedOn` as above; anchor `/claim/release` | +| Status | `status` | none | `claimNumber` | anchor `//status`; not in the package, whose status call carries no bundle (`18-Predetermination, Status and Search.md`); refused by PMJAY | +| Payment acknowledgement 17 | `status`, `status completed` | none | none; `output[]`: `status` = `paymentack` under the NDHM task-output systems, and `claimNumber` | anchor `/payment/notice-ack` | + +The spelling rule: the input is `intimationNumber`, the standard's spelling, on every Task. A reprocess under any other spelling is refused with PAYR-1008 (proven live; `nhcx-package/docs/01-Overview/07-Payer Flexibility.md`, "One spelling on the Task"). The pinned cancel and reprocess Tasks carry the same spelling, so the offline comparison diffs them unchanged. + +## 8. Task answers you read + +`parse_task_response`: find the `Task`, then follow each `output[].valueReference` to the entry it names; when that is a `ClaimResponse`, read it with the same parser as a verdict. + +- PC02 (`nhcx-package/fhir/C10/C10-cancelled-wfPC02.json`): Task `completed`, code `approve`, `output[0]` an `include` reference to a `ClaimResponse` with adjudication reason `cancelled`, `use preauthorization`. Accept the cancel when the Task status is `completed` or `accepted` and the outcome is not `error`. Retire the claim number after an accepted cancel. +- 37 (`nhcx-package/fhir/C10/C10-arbitration-wf37.json`): Task `accepted`, code `approve`, a `ClaimResponse` with outcome `queued`, `use claim`. Put the claim leg back to `submitting`; the new verdict comes on the claim's own thread. +- A status answer: none captured in the package. A generic payer that answers a status Task sends a Task `completed`, code `status`, `output[]` with `claimNumber` and a `claimStatus` string; PMJAY refuses the enquiry instead. + +## 9. The communication loop + +The query, generic payer (`nhcx-package/fhir/C6/C6-preauth-query-wf24.json`; the IG's example at `nhcx-package/fhir/B4/communication-request.json`): a `TaskBundle` with a `Task` `poll`, `requested`, `intent order`, `reasonCode additionalinfo`, one `include` input pointing at the `CommunicationRequest`; the request with `identifier` (the claim number), `basedOn` the Claim, `payload[].contentString` one per ask, `reasonCode[].text` repeating them; then the Claim, Patient, the two Organizations, Practitioner and Coverage. It arrives on `v1/communication/request` on a new correlation id, with the queried leg's correlation id in `x-hcx-workflow_id` when the payer sends one. + +The notification, PMJAY (`nhcx-package/fhir/C6/C6-notification-wfN02.json`): a Task `poll`, `completed`, `intent proposal`, reason `information` under `http://terminology.hl7.org/CodeSystem/communication-category`, a `CommunicationRequest` with one `contentString`, and the two Organizations. + +Reader (`parse_communication_request`): the first `CommunicationRequest`; the claim numbers it names in `about[]`, `basedOn[]` and `identifier[]`; the asks from `payload[].contentString`, else `reasonCode[].text`, else the Task's `description`; the Task's `intent` and `reasonCode`. Match the claim by those numbers first, then by a request id already held, then by the correlation id of one of your sends, then by the workflow id as a thread. + +The reply (`build_communication_bundle`; pin `nhcx-package/fhir/B4/communication-response.json`): a `TaskBundle` with `meta.lastUpdated`, `identifier` under the payer system, `timestamp`, and entries in this order: + +1. `Task` at `urn:uuid:`: `status completed`, `intent order`, `code deliver` under `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-codes`, `authoredOn`, `requester` the provider, `owner` the payer, one `input` typed `include` (HL7 financialtaskinputtype) pointing at the Communication, `reasonCode` echoed from the request's Task when it carried one. +2. `Communication` at `urn:uuid:`: `identifier` echoed from the request, `basedOn: [{reference: }]`, `about: [{reference: }]`, `status completed`, `category notification`, `priority routine`, `recipient` the payer, `sender` the provider, `payload[]`: a `contentString` for the text, then one `contentAttachment {contentType, title, creation, data}` per document, each with an `extension` carrying the document code. The extension url is participant-defined (`17-Communication.md`): write it under your own system and keep one url. `inResponseTo` is never set: FHIR allows only a Communication there and the validator refuses a request. +3. The `CommunicationRequest` echoed as it arrived. +4. The case as the payer holds it, lifted from the queried leg's own bundle: `Claim`, `Patient`, provider `Organization`, payer `Organization`, `Practitioner`, `Coverage`. + +Envelope for the reply: `x-hcx-correlation_id` = the request's, `x-hcx-workflow_id` = the request's, else the queried leg's correlation id, else the claim number; sender and recipient swapped. + +The acknowledgement of a notification: the payer's own bundle sent back with `Task.status` set to `completed`, its intent and reason as sent, the provider Organization ahead of the payer's, a fresh `timestamp`. A request that came without a Task gets one built round it, coded `poll`, intent `proposal`, pointing at the request. The package's `B4/communication-acknowledgement.json` is a different shape: a `status` Task, `completed`, with a `status` output and the two Organizations, and no CommunicationRequest. + +## 10. The payment notice you read and the acknowledgement you send + +Notice (`nhcx-package/fhir/C9/C9-notice-wf30.json`; PMJAY `C9/payment-notice.json` and `C9/C9-notice-tds-wf30-pmjay.json`): a Task `deliver`, `requested`, with a `status` input; a `PaymentNotice` with a `CLN` identifier (the claim number), `amount`, `paymentStatus paid`; a `PaymentReconciliation` with the same identifier, `disposition`, `paymentDate`, `paymentAmount`, `paymentIdentifier` typed `UTR`, and `detail[]` lines (`RF` and `Payment` in `payment-notice.json`; `TDS` and `Payment` in the other two); the two Organizations. It arrives on `v1/paymentnotice/request` on a new thread, workflow 30, 31 or 33. + +Reader (`parse_payment_notice`): the claim number from the `CLN` identifier on the notice, the reconciliation, the Task, or the first entry's untyped identifier, never from the bundle identifier; the amount from the notice or `paymentAmount`; the UTR; the details. Dedupe on the notice's correlation id; a second notice with the same `PaymentNotice.id` updates the first (`record_payment`). Count money once per UTR (`paid_total`). + +Acknowledgement: the Task in section 7, sent on `v1/paymentnotice/on_request` to whoever sent the notice (not always the claim's payer), with `x-hcx-correlation_id` = the notice's and `x-hcx-workflow_id` = `17` for PMJAY or the notice's own id for a generic payer. + +## 11. Validating a bundle + +The package ships no validator. Use the HL7 FHIR validator (`validator_cli.jar`, from HL7) with the NRCeS IG package `ndhm.in`, version 6.5.0. A bundle refused with PAYR-1004 or PAYR-1008 goes through the validator before anything else (`nhcx-package/docs/06-Reference/02-Troubleshooting.md`). The rules it checks against are in `nhcx-package/docs/05-FHIR Reference/01-Bundles and Conventions.md`. + +```sh +java -Xmx4g -jar validator_cli.jar \ + -version 4.0.1 -ig -tx n/a -output result.json +``` + +Pass every file in one call; starting the JVM is the slow part. `-tx n/a` keeps the terminology checks offline; drop it to add them. A bundle passes when the output holds no issue of severity error or fatal. + +The provider pins carry 0 to 13 errors each and the SHA accepted every one as it stands. An error that says "a code the profile does not define" is the scheme's own vocabulary, not a fault to fix. A warning is advice. diff --git a/plugins/nhcx/skills/nhcx-preauth/references/flow-knowledge.md b/plugins/nhcx/skills/nhcx-preauth/references/flow-knowledge.md new file mode 100644 index 000000000..098cd9dbc --- /dev/null +++ b/plugins/nhcx/skills/nhcx-preauth/references/flow-knowledge.md @@ -0,0 +1,206 @@ +# Flow knowledge: the claim episode, its workflow ids, the two payer kinds, the use cases + +Sources: the NHCX package, fetched by `scripts/fetch-package.sh` into `nhcx-package/` beside `nhcx-build/`. That means the overview chapters under `nhcx-package/docs/01-Overview`, the workflow sheet `nhcx-package/workflow.yaml`, the use-case catalogue `nhcx-package/usecases.yaml`, and the payer bundles under `nhcx-package/fhir/C3` to `nhcx-package/fhir/C11`. The published chapters live under `nhcx-package/docs/01-Overview`, `nhcx-package/docs/05-FHIR Reference` and `nhcx-package/docs/03-Building a Provider`. Everything else here was learnt live on the NHCX sandbox. + +## 1. The episode + +One hospital admission that an insurer pays for is one claim episode. Store it as one record with a claim number. Any number works if it is unique per hospital, short, sortable, and fits the payer's `CLN` identifier. The episode has these legs, each a separate exchange with its own correlation id: + +| Order | Leg | You send | Payer answers | Thread | +| --- | --- | --- | --- | --- | +| 1 | Policy lookup | The participant service's `participant/get/policies`, through the transport; the recipient of every later leg is the policy's `processingid` | synchronous JSON | none, plain REST | +| 2 | Coverage eligibility | `v1/coverageeligibility/check`, purpose `discovery`, `validation` or `benefits` | `on_check` | new per check | +| 3 | Insurance plan (package master) | `v1/insuranceplan/request` | `on_request` | new; one plan per facility and policy | +| 4 | Auth requirements | `v1/coverageeligibility/check`, purpose `auth-requirements`, with items | `on_check` (the PMJAY sandbox rarely answers; `nhcx-package/fhir/C3/C3-response-pmjay.json` is an SHA ruling, `C3/C3-response-generic.json` a generic one) | new per procedure set | +| 5 | Pre-authorisation | `v1/preauth/submit` wf 12 | `on_submit` 20 first, then 21, 23 or 24 | new; the acknowledgement comes first on the same thread | +| 5a | Pre-auth query answer | `v1/preauth/submit` wf 19 (PMJAY) or `v1/communication/on_request` (generic) | 21 or 23 | new (PMJAY) or the request's (generic) | +| 5b | Enhancement | `v1/preauth/submit` wf 13, the whole pre-auth again with the added line | 20 then 22, 231 or 241 (the SHA sandbox has also answered with 21) | new | +| 5c | Enhancement query answer | `v1/preauth/submit` wf 131 | 22 or 231 | new | +| 5d | Cancel | `v1/task/submit` wf PC01 | `task/on_submit` PC02 | new | +| 5e | Predetermination | `v1/preauth/submit`, `Claim.use = predetermination`, wf 12 | `on_submit` | new | +| 6 | Claim | `v1/claim/submit` wf 15, `Claim.use = claim`, under the pre-auth's number | 25 then 26, 27 or 291 | new | +| 6a | Claim query answer | `v1/claim/submit` wf 161 (PMJAY) or `v1/communication/on_request` (generic) | 26 or 291 | new (PMJAY) or the request's (generic) | +| 6b | Reprocess or release | `v1/task/submit` wf 36 | `task/on_submit` 37, then a fresh verdict on the claim's thread | new | +| 7 | Payment notice | the payer sends `v1/paymentnotice/request` wf 30 (31, 33) | you answer `v1/paymentnotice/on_request` wf 17 (PMJAY) or the notice's own id (generic) | the notice's | +| any | Status enquiry | `v1/task/submit`, Task code `status` | `task/on_submit` (generic); PMJAY refuses it | new | +| any | Communication | the payer sends `v1/communication/request` | you answer `v1/communication/on_request` | the request's | + +The payer's acknowledgement is `x-hcx-status: response.partial` and the decision is `response.complete`, on the same correlation id (`nhcx-package/docs/01-Overview/07-Payer Flexibility.md`, "Answer detail"). Read the acknowledgement as "the payer has it", never as a decision. Map `ClaimResponse.outcome` `queued`, or an adjudication reason `submitted`, to leg status `submitting` (`verdict_status`). + +## 2. Every workflow id + +The hospital's table. PMJAY and a generic payer differ in three rows: `claim_query_response`, `claim_resubmit` and `payment_ack`. + +| Kind | PMJAY | Generic | Path | Note | +| --- | --- | --- | --- | --- | +| `preauth` | `12` | `12` | `v1/preauth/submit` | A new pre-auth. Also a fresh request after a rejection: PMJAY refuses 121 there with PAYR-1214. | +| `preauth_resubmit` | `121` | `121` | `v1/preauth/submit` | Kept in the table. `preauth_send_kind` never picks it after a rejection. | +| `preauth_query_response` | `19` | `19` | `v1/preauth/submit` | The answer to a 24. A generic payer asks by communication instead, so this is a PMJAY leg. | +| `enhancement` | `13` | `13` | `v1/preauth/submit` | The whole pre-auth again under the parent's number, plus the added line. | +| `enhancement_resubmit` | `131` | `131` | `v1/preauth/submit` | The answer to a 241. | +| `cancel` | `PC01` | `PC01` | `v1/task/submit` | Task code `cancel`. The handbook's section 8.6 says 122 (`nhcx-package/docs/01-Overview/06-Workflow Codes.md`, "Reconciled Discrepancies and Authority Rules", takes PC01). If a payer insists on 122, override it per payer in configuration. | +| `claim` | `15` | `15` | `v1/claim/submit` | The final bill. | +| `claim_query_response` | `161` | `151` | `v1/claim/submit` | PMJAY refuses 151, 19 and 16 with PAYR-1321; 161 is taken. | +| `claim_resubmit` | none | `16` | `v1/claim/submit` | PMJAY has no claim resubmit. A decided claim goes back only as a reprocess. | +| `payment_ack` | `17` | none (echo the notice's own id) | `v1/paymentnotice/on_request` | `None` in the table means "echo". | +| `reprocess` | `36` | `36` | `v1/task/submit` | Task code `reprocess`; acknowledged on 37. | +| `release` | `36` | `36` | `v1/task/submit` | Task code `release`, reason `partialpayment`, an `amount` input. | +| status enquiry | the leg's correlation id, fallback `13` | same | `v1/task/submit` | The fallback id is `13`. The NHCX sandbox refuses `v1/status` with NHCX-1012. | +| coverage, plan, auth requirements | your case number | your case number | see section 1 | The sheet lists no code. Send the episode's case number. | + +The payer's ids you must branch on (`nhcx-package/workflow.yaml`, `nhcx-package/docs/01-Overview/06-Workflow Codes.md`), with what the sandbox actually sent: + +| Id | Meaning | Status word | +| --- | --- | --- | +| `20` | Pre-auth or enhancement received | `response.partial` | +| `21` | Pre-auth approved | `response.complete` | +| `22` | Enhancement approved. A generic payer sends 22. The SHA sandbox has answered an enhancement with 21, and `nhcx-package/fhir/C5/C5-enhancement-approved-wf22-pmjay.json` is an SHA answer on 22. Accept both. | `response.complete` | +| `23` | Pre-auth rejected | `response.complete` | +| `231` | Enhancement denied | `response.complete` | +| `24` | Pre-auth queried | the sheet says `request.initiated`; the SHA sent `response.complete` | +| `241` | Enhancement queried | as 24 | +| `25` | Claim received | `response.partial` | +| `26` | Claim approved | `response.complete` | +| `27` | Claim queried | as 24 | +| `28`, `29` | Claim in process, forwarded | `response.partial` | +| `291` | Claim rejected | `response.complete` | +| `251`, `252`, `253`, `254` | Reprocess received, approved, rejected, queried | listed; both live payers answer a 36 with 37 instead | +| `37` | Arbitration acknowledged (the reprocess taken) | `response.complete` (the SHA sent `response.partial`) | +| `PC02` | Cancellation done | `response.complete` | +| `30`, `31`, `33` | Payment initiated, processed, settled with UTR | `request.initiated`, new thread | +| `5` | The SHA's coverage eligibility and plan answers | `response.complete` (`nhcx-package/fhir/index.yaml` gives 5 for `C3/C3-response-pmjay.json` and `C4/C4-response-pmjay.json`) | +| `N02` | Notification to a provider (a PMJAY CommunicationRequest) | `request.initiated` | + +Other codes exist (10, 11, 14, 141, 18, 45 to 47, 181, 491, 34, 35, 38, 39, G11 to G13, RP1 to RP3, DC01, DC02, N01, N03, N04, the R-series). A hospital build sends none of them. See `nhcx-package/docs/01-Overview/06-Workflow Codes.md` for the full sheet and the seven codes the handbook and the sheet publish differently. + +## 3. Two kinds of payer + +Read `nhcx-package/docs/01-Overview/07-Payer Flexibility.md` in full. A generic payer is any payer on the exchange, IRDAI-regulated insurers and TPAs included (`nhcx-package/fhir/README.md`). The rule, as coded: + +| | PMJAY (`query_mode: resubmit`) | Generic (`query_mode: communication`) | +| --- | --- | --- | +| The query arrives as | a `ClaimResponse` on the case's own thread, `outcome: partial`, item status `Queried`, wf 24, 241 or 27 | a `CommunicationRequest` TaskBundle on `v1/communication/request`, on a new thread, wf 24, 241 or 27 | +| The answer | the whole bundle again on `v1/preauth/submit` or `v1/claim/submit`, wf 19, 131 or 161, a new correlation id, the reply text on the `NMI`/`CQD` supportingInfo entry | a Communication TaskBundle on `v1/communication/on_request`, the request's correlation id and workflow id echoed | +| A `CommunicationRequest` from this payer | always a notification: acknowledge and leave the case alone | classified (below) | + +Where the payer's case number arrives. The package files are under `nhcx-package/fhir/`; the rule is in `07-Payer Flexibility.md`, "When the case number arrives". + +| Answer | PMJAY | Generic | +| --- | --- | --- | +| 20 on a fresh pre-auth | The package says none, and `C5/C5-received-wf20-pmjay.json` carries none. A live SHA 20 has also carried the path form, `PMJAY/HP/S/2024/R2/`. Handle both. | present (`C5/C5-received-wf20.json`) | +| 20 on an enhancement | none; keep the parent's | present | +| 21, 23, 24 | the bare number (`C5/C5-approved-wf21-pmjay.json`, `C5/C5-rejected-wf23-pmjay.json`, `C5/C5-queried-wf24.json`) | present (`C5/C5-approved-wf21.json`, `C5/C5-rejected-wf23.json`) | +| 25 | the path form (`C7/C7-received-wf25-pmjay.json`) | present (`C7/C7-received-wf25.json`) | +| 26, 27, 291, PC02, 37 | none | none | + +So the brief's rule holds with care. A generic payer's `response.partial` acknowledgement carries the payer's case number. PMJAY's 25 carries it; its 20 may not. Read `ClaimResponse.preAuthRef` on every answer. Keep a value and never overwrite it with an empty one (`apply_preauth`). The bare number is what the payer service desk wants; the path form ends in it. + +`query_mode` lives on the payer adapter. Choose the adapter by the payer's participant code through configuration: `1518@hcx` is PMJAY, and an unmapped code is generic. + +### The classification rule + +`classify_communication(adapter, reason, intent)` applies these, in order: + +1. If the payer's `query_mode` is `resubmit`: notification. +2. Else if `Task.intent` is `proposal`: notification. If `order`: query. +3. Else look at `Task.reasonCode`: absent, `additionalinfo`, `questionnaire` or `query` is a query; anything else (`tatquery`, `grievance`, `walletupdate`, `policychange`, `claimarbitration`) is a notification. Fold `claimArbitartion` into `claimarbitration`. +4. A bare `Communication` with no `CommunicationRequest` is a note: recorded, shown, never acted on. + +Acknowledge a notification at once. Send the payer's own bundle back with `Task.status` flipped to `completed`, the reason echoed and the provider Organization first. File a query open for the desk, and answer it later with the TaskBundle reply (see `fhir-knowledge.md`). The reply names the request in `Communication.basedOn`, never `inResponseTo`. + +The live shapes. A generic payer's query (`nhcx-package/fhir/C6/C6-preauth-query-wf24.json`) carries a Task `poll`, `requested`, `intent order`, reason `additionalinfo`, and a CommunicationRequest with one `contentString` per ask and `basedOn` the Claim. PMJAY's notification (`nhcx-package/fhir/C6/C6-notification-wfN02.json`) carries a Task `poll`, `completed`, `intent proposal`, reason `information` under the HL7 communication-category system. + +## 4. Stage, sub-stage, next actions + +Stamp two words onto the episode after every leg write (`stamp_case`), and compute a next-action list from them. Copy the vocabulary; it is what a desk needs to see. + +Stages: `eligibility`, `preauth`, `enhancement`, `claim`, `payment`. + +Sub-stages: `draft`, `checking`, `eligible`, `not-eligible`, `requested`, `resubmitted`, `answered`, `queried`, `approved`, `partial`, `rejected`, `cancelling`, `cancelled`, `refused`, `noticed`, `paid`. + +How a send kind maps to a sub-stage: `preauth`, `claim`, `enhancement` set `requested`; `*_resubmit` sets `resubmitted`; `*_query_response` and `enhancement_resubmit` set `answered`. `requested`, `answered` and `resubmitted` mean "with the payer". + +Derivation (`case_stage`): a payment notice wins, then the filed claim, then the pre-auth (stage `enhancement` if the last submission kind was an enhancement), then a saved draft, then the eligibility status. An open communication query on a leg that is with the payer flips the sub-stage to `queried`, because a generic payer's query never touches the leg row. + +Next actions (`next_actions`) are `{label, tab, tone}`; the first is what the case waits for. Rules worth copying: + +- An unanswered query always leads with "Answer the payer (n)". +- The leg's own reply box is offered only for a `resubmit` payer. A `communication` payer's desk is sent to the communication tab. +- A claim refused at the door offers "send again" while `claim_send_kind` still yields a kind, else "Ask for a reprocess". +- After a rejection the pre-auth offers a fresh 12, not 121. + +## 5. Rules the exchange enforces that no document states + +Each was found live on the sandbox. + +- Acknowledge or lose the thread. NHCX redelivers an unanswered submission, then drops it and retires the correlation id; a verdict sent later is refused with NHCX-1010. Both live payers answer twice on one correlation: `outcome: queued` first, the decision after. Your reader must not close a thread on the first reply. +- One message is taken once. The SHA redelivers the same `api_call_id` two or three times, about a minute apart, and a transport can fan one delivery out to several receivers (nhcx-adapter's `callback.also`). Dedupe on `x-hcx-api_call_id`. +- One live pre-auth per beneficiary per hospital (PAYR-1238). Clear it with PC01 or a rejection (`nhcx-package/docs/03-Building a Provider/11-PMJAY Sandbox Run.md`, "PAYR-1238 An active preauthorisation exists"). Sweep live pre-auths before a test run. +- One request at a time per case (PAYR-1322, "Active instance found"). Wait about 30 seconds after a decision before the next leg. When a refusal says "Active instance", wait and resend, up to three times. +- One plan per facility and policy. Key it on policy code, provider id and payer. Copy the held master onto a new episode instead of asking again (`reuse_plan`). A PMJAY master runs to tens of megabytes; one fetched live was 56 MB. +- Never drop a document. A file nobody asked for by name goes under `ODN`, "other document". A file attached against a requirement carries that requirement's code (`attach_required_document`). Take the code list from the plan, not from a constant. +- Ask the auth-requirements check, never await it (`ensure_auth_requirements`). Fingerprint the quoted set (`procedure_set`) so an unchanged set is not asked twice. Send the quantity as a whole number. +- Tiers are modifiers, not lines. A ward or ICU tier rides on `Claim.item.modifier` under its procedure, and that item's `net` carries both. +- The claim goes under the pre-auth's number (ERR-PYR-CLM-007), and PMJAY bills the package alone at the whole amount (`11-PMJAY Sandbox Run.md`, "ERR-PYR-CLM-007" and "What the package master decides"). +- Answers to a PMJAY query go on a new correlation id (`07-Payer Flexibility.md`, "On the claim thread"). A same-thread answer is swallowed: no acknowledgement, no refusal, and the desk dies on the old id. +- Cancel retires the number. Give the episode a fresh claim number after an accepted PC01, and keep the withdrawn one on the leg. +- A send refused at the door keeps the case on the thread the payer last answered. An enhancement refused at the door leaves the pre-auth approved. + +## 6. The use-case catalogue + +Codes and titles are quoted from `nhcx-package/usecases.yaml`, rendered as `nhcx-package/docs/01-Overview/05-NHCX Use Cases.md`. "Proves" is what a test run must show for each one. "Package file" is the provider bundle the package holds for it, under `nhcx-package/fhir/`. + +### A: shared + +| Code | Title | What it proves | +| --- | --- | --- | +| A1 | Get participant list | You can find the payer's code in the registry (the participant service's `fetch/participants/list`). | +| A2 | Get policy | You can find a beneficiary's policy and the processor code that becomes `x-hcx-recipient_code` (the participant service's `participant/get/policies`). | +| A3 | Get public key | The transport fetches the recipient's certificate (`fetch/certs`) and caches it. | +| A4 | Get auth token | The transport holds an ABDM session token (the gateway's sessions call) and refreshes it. | +| A5 | Get status | A status Task on `v1/task/submit` gets a Task back (generic), or a PAYR-1018 then PAYR-1008 refusal (PMJAY). The package holds no bundle for A5 (`nhcx-package/fhir/README.md`). | +| A6 | Receive errors | Your callback accepts a `ProtocolResponse` on any path and answers 2xx. | + +### B: hospital on the generic network + +| Code | Title | Workflow | Proves | Package file | +| --- | --- | --- | --- | --- | +| B1 | Check coverage eligibility | none | The check goes out; `inforce` and the wallet come back. | `B1/B1-check.json` | +| B2 | Request insurance plan | none | The package master lands and is stored once per policy. | `B2/B2-request.json` | +| B3 | Submit pre-authorisation | 12, 13 | Sent, acknowledged on 20, decided on 21 or 23; an enhancement on 13 decided on 22. | `B3/B3-request.json`, `B3/B3-enhancement.json` | +| B4 | Respond to a communication | 24, 27 echoed | A CommunicationRequest is classified and the TaskBundle reply goes on the request's thread. | `B4/B4-preauth-query-answer.json`, `B4/B4-claim-query-answer.json` | +| B5 | Submit claim | 15 | The claim under the pre-auth's number, acknowledged 25, decided 26 or 291. | `B5/B5-request.json` | +| B6 | Search claims | none | Not built by these skills. | `B6/claim-search.json` (example) | +| B7 | Acknowledge payment notice | 30 echoed | The notice is filed by claim number, deduped by correlation id, acknowledged on `on_request`. | `B7/B7-acknowledgement.json` | +| B8 | Reprocess or cancel | 36, PC01 | A decided claim is reopened (37 then a new verdict); a live pre-auth is withdrawn (PC02). | `B8/B8-reprocess.json`, `B8/B8-cancel.json` | +| B9 | Submit predetermination | 12 | A quote comes back as a ClaimResponse; nothing else changes. | `B9/predetermination-request.json` (example); the answer is `C11/predetermination-response.json` | + +### C: payer answering (for reference; you build the reader, not the sender) + +C3 coverage answer, C4 plan answer, C5 pre-auth answers (20, 21, 22, 23, 24, 231, 241), C6 communication (24, 241, 27, N02), C7 claim answers (25, 26, 27, 28, 29, 291), C9 payment notice (30, 31, 33), C10 Task answers (PC02, 37, 251 to 254), C11 predetermination. Reader inputs: `nhcx-package/fhir/C3` to `nhcx-package/fhir/C11`. The files ending `-pmjay` are the SHA's own; the rest are the generic payer's. `nhcx-package/fhir/index.yaml` gives each file's scheme, workflow id and origin. The PMJAY captures have the beneficiary's identifiers replaced. + +### D: hospital on PMJAY + +| Code | Title | Workflow | Proves | Package file | +| --- | --- | --- | --- | --- | +| D1 | Fetch the insurance plan | none | The scheme's master, both `coverage[]` and `specificCost[]`, nested document requirements, questionnaires. | `D1/D1-request.json` | +| D2 | Authenticate the beneficiary | not NHCX | Biometric token or the consent questionnaire fallback. | none | +| D3 | Check coverage eligibility | none | The wallet answer on wf 5. | `D3/D3-check.json` | +| D4 | Submit pre-authorisation | 12 | Element ids, HPIN, consent QuestionnaireResponse, documents from the master; acknowledged 20, decided 21 or 23 with `preAuthRef`. | `D4/D4-request.json` | +| D5 | Resubmit pre-authorisation | 121 | Not reachable on the sandbox after a rejection (PAYR-1214); send a fresh 12. | none | +| D6 | Raise an enhancement | 13, 131 | A second package (medical, not conservative: PAYR-1245) under the parent's number; a 241 answered on 131. | `D6/D6-enhancement.json`, `D6/D6-enhancement-query-answer.json` | +| D7 | Answer a pre-authorisation query | 19 | The 24 answered as a fresh submit with `CQD` reply text, new correlation id, then 21. | `D7/D7-query-answer.json` | +| D8 | Cancel pre-authorisation | PC01 | Task `cancel` with `claimNumber` and `intimationNumber`; PC02 back. | `D8/D8-cancel.json` | +| D9 | Submit claim | 15 | Under the pre-auth's number, the package alone, discharge scalars, Discharge Consent answered, PDF documents; 25 then 26. | `D9/D9-request.json` | +| D10 | Answer a claim query | 161 | The 27 answered on 161 with a written reply; the sandbox approves at zero. | `D10/D10-query-answer.json` | +| D11 | Reprocess a rejected claim | 36 | Task `reprocess`, reason `claimrejected`, second input spelled `intimationNumber` on every Task (a reprocess under any other spelling is refused PAYR-1008). The SHA answers 37, "Arbitration claim submission process completed successfully", and reopens the case; a generic payer answers 37 too. | `D11/D11-reprocess.json` | +| D12 | Claim a shortfall | 36 | Task `reprocess` with `partialpayment` after a settled payment. Out of reach on the sandbox: its finance side issues the notice on its own schedule, and the combination is refused before notice 33 is acknowledged (`11-PMJAY Sandbox Run.md`, "What the sandbox will not take"). | none | +| D13 | Acknowledge the payment notice | 17 | Notice 30 filed and acknowledged on `on_request` with 17. | `D13/D13-acknowledgement.json` | + +Discharge variants the D9 claim must cover, each proven on the sandbox: normal after surgery; LAMA and DAMA before, during and after surgery; death before, during and after surgery. Before or during surgery, LAMA and DAMA collapse the claim to one `LM100` line; a death carries `ONS`/`DTM`. `nhcx-package/docs/03-Building a Provider/08-PMJAY Provider.md` states the LAMA and DAMA rule. + +## 7. What each payer sends back, in order + +A pre-authorisation on the SHA sandbox: 20 (`queued`, `response.partial`, `ClaimResponse.type` present only here, as in `nhcx-package/fhir/C5/C5-received-wf20-pmjay.json`), then 24 (query) or 21 or 23. A claim: 25, then 27 or 26 or 291. A cancel: PC02 as a Task `completed`, code `approve`, `output[0]` an `include` reference to a ClaimResponse whose adjudication reason is `cancelled` (`C10/C10-cancelled-wfPC02-pmjay.json`). A reprocess: 37 as a Task `accepted` with a `queued` ClaimResponse (`C10/C10-arbitration-wf37-pmjay.json`), then 26 or 291 on the claim's thread. A payment: 30 on a new thread with a Task `deliver`, a `PaymentNotice` and a `PaymentReconciliation` (`C9/payment-notice.json`). + +A generic payer sends the same ids with the generic differences: 22 for an enhancement, `preAuthRef` on every acknowledgement and every pre-auth decision, queries as CommunicationRequests, `response.complete` on 37. Its files are the ones without `-pmjay` under `nhcx-package/fhir/C5`, `C6`, `C7`, `C9` and `C10`. diff --git a/plugins/nhcx/skills/nhcx-preauth/references/material.md b/plugins/nhcx/skills/nhcx-preauth/references/material.md new file mode 100644 index 000000000..d8882931d --- /dev/null +++ b/plugins/nhcx/skills/nhcx-preauth/references/material.md @@ -0,0 +1,120 @@ +# Material: where the pins, fixtures and docs live + +The stage and module files cite pins, payer fixtures and chapters. All of them come from one source, the NHCX package. This file says how to get it, what it holds, and which package file each citation means. + +## The package + +| Source | Has | Get it | +| --- | --- | --- | +| The NHCX package (`nhcx-package/`) | The docs, every API as a request, the FHIR bundles (the fifteen hospital pins, the payer answers, the live PMJAY captures with identifiers replaced), the field mappings per use case, `workflow.yaml`, `usecases.yaml`, `nhcx-error.yaml`, `baseurl.yaml`, a `MANIFEST` with a sha256 per file | `scripts/fetch-package.sh`, or by hand (below) | +| nhcx-adapter (optional: only when the user asks for it) | The binary, `config.sample.json`, `serve.sh`, `README.md` | The latest release of https://github.com/nha-in/nhcx-adapter, downloaded only when the user chose it (`references/transport-knowledge.md` section 5). Its contract is in `references/api-knowledge.md`. | + +By default `scripts/fetch-package.sh` takes the build attached to the latest GitHub release of `nha-in/nhcx-package`. It checks the download against the sha256 the release records. To use a different build, pass a link or a local path: `scripts/fetch-package.sh `. + +By hand: download the `nhcx-package-v.zip` asset from https://github.com/nha-in/nhcx-package/releases/latest. Unzip it beside `nhcx-build/`. It unpacks to `nhcx-package/`. + +Where the web is off, copy the package in. Do not try to fetch it. + +After unpacking, check it. `nhcx-package/MANIFEST` names the version and lists every file with its size and sha256. Verify at least the pins you will be held to. + +What the package holds: + +| Path | What it is | +| --- | --- | +| `nhcx-package/fhir/B1` to `B9` | Hospital bundles. Lower-case files (`preauth-request.json`) are the pins, written to the specification with placeholders. Capitalised files (`B3-request.json`) are live captures. | +| `nhcx-package/fhir/C3` to `C11` | Payer answers. A generic file and, where one exists, its `-pmjay` twin. | +| `nhcx-package/fhir/D1` to `D13` | Live PMJAY hospital captures, identifiers replaced | +| `nhcx-package/fhir/index.yaml` | The catalogue: for each file its direction, side, scheme (`generic` or `pmjay`), workflow id, focal resource, origin (`wire` or `example`) | +| `nhcx-package/docs/` | The chapters, `01-Overview` to `07-Go Live` | +| `nhcx-package/mappings/.yaml` | Field mappings per bundle; `A1.yaml` is the master dictionary | +| `nhcx-package/apis/` | Every API as a request (a Bruno collection) | +| `nhcx-package/workflow.yaml`, `usecases.yaml`, `nhcx-error.yaml`, `baseurl.yaml` | Workflow ids, use cases, error codes, base URLs | +| `nhcx-package/MANIFEST` | Version, and a size and sha256 per file | + +## The pin map + +Every hospital-side pin, and its file in the package. The fifteen hospital-built pins are the bytes a build is held to (canonical JSON). The last row is a payer's message, the reader's input. + +| Pin | Package | Module | +| --- | --- | --- | +| `coverage/discovery` | `nhcx-package/fhir/B1/discovery.json` | 7.4 | +| `coverage/validation` | `nhcx-package/fhir/B1/validation.json` | 7.4 | +| `coverage/benefits` | `nhcx-package/fhir/B1/benefits.json` | 7.4 | +| `coverage/authrequirements` | `nhcx-package/fhir/B1/auth-requirements.json` | 7.6 | +| `insurance` | `nhcx-package/fhir/B2/insurance-plan-request.json` | 7.5 | +| `preauth/request` | `nhcx-package/fhir/B3/preauth-request.json` | 7.7 | +| `preauth/enhancement` | `nhcx-package/fhir/B3/preauth-enhancement.json` | 7.7 | +| `preauth/queryupdate` | `nhcx-package/fhir/B3/preauth-queryupdate.json` | 7.7 | +| `preauth/cancel` | `nhcx-package/fhir/B3/preauth-cancel.json` | 7.9 | +| `claim/request` | `nhcx-package/fhir/B5/claim-request.json` | 7.7 | +| `claim/queryupdate` | `nhcx-package/fhir/B5/claim-queryupdate.json` | 7.7 | +| `claim/reprocess` | `nhcx-package/fhir/B5/claim-reprocess.json` | 7.9 | +| `claim/release` | `nhcx-package/fhir/B5/claim-release.json` | 7.9 | +| `communication/response` | `nhcx-package/fhir/B4/communication-response.json` | 7.10 | +| `payment/notice-ack` | `nhcx-package/fhir/B7/payment-notice-ack.json` | 7.10 | +| `communication/request` (a payer's message, the reader's input) | `nhcx-package/fhir/B4/communication-request.json`. It is the NRCeS IG's own example, with the Patient's name, identifier, birth date and phone replaced. | 7.10 | + +## The payer fixtures + +What the readers are fed. `generic` is what any payer on the exchange sends, IRDAI-regulated insurers and TPAs included. `pmjay` is the SHA's own message, a live capture with the beneficiary's identifiers replaced. Some identifiers are absent from the PMJAY files: `C5-received-wf20-pmjay.json` carries no `preAuthRef`. Read a value from the file before you assert it. Paths are under `nhcx-package/fhir/`. + +| Answer | Generic | PMJAY | Reader | +| --- | --- | --- | --- | +| Coverage, validation | `C3/validation-response.json` | `C3/coverage-eligibility.json` | 7.4 | +| Coverage, discovery | `C3/discovery-response.json` | none | 7.4 | +| Coverage, benefits | `C3/benefits-response.json` | `C3/C3-benefits-pmjay.json` | 7.4 | +| Coverage, auth-requirements | `C3/C3-response-generic.json` | `C3/C3-response-pmjay.json` (workflow 5) | 7.6 | +| Insurance plan | `C4/C4-response-generic.json` (coverage-based) | `C4/C4-response-pmjay.json` (package-based) | 7.5 | +| Pre-auth received 20 | `C5/C5-received-wf20.json` | `C5/C5-received-wf20-pmjay.json` | 7.8 | +| Pre-auth approved 21 | `C5/C5-approved-wf21.json` | `C5/C5-approved-wf21-pmjay.json` | 7.8 | +| Enhancement approved 22 | `C5/C5-enhancement-approved-wf22.json` | `C5/C5-enhancement-approved-wf22-pmjay.json` | 7.8 | +| Pre-auth rejected 23 | `C5/C5-rejected-wf23.json` | `C5/C5-rejected-wf23-pmjay.json` | 7.8 | +| Pre-auth queried 24 | `C5/preauth-queried.json` | `C5/C5-queried-wf24.json` | 7.8 | +| Claim received 25 | `C7/C7-received-wf25.json` | `C7/C7-received-wf25-pmjay.json` | 7.8 | +| Claim approved 26 | `C7/C7-approved-wf26.json` | `C7/C7-approved-wf26-pmjay.json`, `C7/C7-approved-deduction-wf26-pmjay.json` | 7.8 | +| Claim queried 27 | `C7/claim-queried.json` | `C7/C7-queried-wf27.json` | 7.8 | +| Claim rejected 291 | `C7/C7-rejected-wf291.json` | `C7/C7-rejected-wf291-pmjay.json` | 7.8 | +| Cancellation done PC02 | `C10/C10-cancelled-wfPC02.json` | `C10/C10-cancelled-wfPC02-pmjay.json` | 7.9 | +| Arbitration acknowledged 37 | `C10/C10-arbitration-wf37.json` | `C10/C10-arbitration-wf37-pmjay.json` | 7.9 | +| Query on the communication API, 24 and 27 | `C6/C6-preauth-query-wf24.json`, `C6/C6-claim-query-wf27.json` | none | 7.10 | +| Notification N02 | none | `C6/C6-notification-wfN02.json` | 7.10 | +| The query the reply answers | `B4/communication-request.json` (the IG's example) | none | 7.10 | +| Payment notice 30 | `C9/C9-notice-wf30.json` | `C9/payment-notice.json`, `C9/C9-notice-tds-wf30-pmjay.json` | 7.10 | +| Predetermination | `B9/predetermination-request.json` (the request), `C11/predetermination-response.json` | none | 7.7, 7.8 | + +`nhcx-package/fhir/index.yaml` catalogues every file: direction, side, scheme, workflow id, focal resource, origin (`wire` or `example`). An `example` file is placeholders written to the specification, not a payload. + +## The live hospital captures + +What a hospital actually sent, as the payer accepted it. The module files quote these shapes. Paths are under `nhcx-package/fhir/`. + +| Scheme | Files | +| --- | --- | +| PMJAY | `D1/D1-request.json` (plan), `D3/D3-check.json` (auth-requirements), `D4/D4-request.json` (pre-auth 12), `D6/D6-enhancement.json` (13), `D6/D6-enhancement-query-answer.json` (131), `D7/D7-query-answer.json` (19), `D8/D8-cancel.json` (PC01), `D9/D9-request.json` (claim 15), `D10/D10-query-answer.json` (161), `D11/D11-reprocess.json` (36), `D13/D13-acknowledgement.json` (17) | +| Generic | `B1/B1-check.json`, `B2/B2-request.json`, `B3/B3-request.json`, `B3/B3-enhancement.json`, `B4/B4-preauth-query-answer.json`, `B4/B4-claim-query-answer.json`, `B5/B5-request.json`, `B7/B7-acknowledgement.json`, `B8/B8-cancel.json`, `B8/B8-reprocess.json` | + +## The docs and the data files + +| Cited | Package | +| --- | --- | +| a chapter | `nhcx-package/docs/`, from `01-Overview` to `07-Go Live` | +| workflow ids (`references/flow-knowledge.md` section 2) | `nhcx-package/workflow.yaml`, the maintained source; rendered as `nhcx-package/docs/01-Overview/06-Workflow Codes.md` | +| use cases (`flow-knowledge.md` section 6) | `nhcx-package/usecases.yaml`; rendered as `nhcx-package/docs/01-Overview/05-NHCX Use Cases.md` | +| PAYR and ERR codes (`references/errors-and-debugging.md`) | `nhcx-package/nhcx-error.yaml` | +| field mappings per bundle (stage 4) | `nhcx-package/mappings/.yaml`; `A1.yaml` is the master dictionary | +| base URLs, sandbox and production | `nhcx-package/baseurl.yaml` | +| every API as a request | `nhcx-package/apis/` (a Bruno collection) | +| the bundle catalogue | `nhcx-package/fhir/index.yaml` | + +## What the package does not hold + +| Missing | Without it | +| --- | --- | +| A status-enquiry answer | None captured. The published status call carries no bundle either way (`nhcx-package/docs/05-FHIR Reference/18-Predetermination, Status and Search.md`). | +| A validator wrapper | Run the HL7 FHIR validator directly, as `references/fhir-knowledge.md` section 11 describes | +| Reference application source | The decisions are written into the module files and the references. Build from them. Record in `NOTES.md` where you would have wanted more. | +| End-to-end drivers and checkers | Write the stage 10 driver against your own build's state address | + +## Which is newer + +Where the references and the package disagree, the package is newer for the published facts (workflow ids, error text, base URLs). The references are newer for what was seen live (which ids a payer actually sent, which refusals mean what). Say which you followed in `NOTES.md`. diff --git a/plugins/nhcx/skills/nhcx-preauth/references/testing-knowledge.md b/plugins/nhcx/skills/nhcx-preauth/references/testing-knowledge.md new file mode 100644 index 000000000..4a24d7946 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-preauth/references/testing-knowledge.md @@ -0,0 +1,405 @@ +# Testing knowledge + +Sources: the NHCX package, fetched by `scripts/fetch-package.sh` into `nhcx-package/` beside `nhcx-build/`. That means the pins and payer fixtures under `nhcx-package/fhir` (catalogued in `nhcx-package/fhir/index.yaml`), the use-case catalogue `nhcx-package/usecases.yaml`, and the chapters named below. Also what live runs on the NHCX sandbox taught. + +## 1. The pyramid + +| Rung | What it proves | Needs | How | +| --- | --- | --- | --- | +| 1. Offline | Every builder equals its pin (`created` excepted); every reader settles the right state from a payer fixture; the state machine refuses what it should | nothing running; a throwaway database; the transport's send stubbed; `nhcx-package/` | one suite in one process (sections 2 to 4) | +| 2. Validator | Every built bundle validates against the NRCeS profiles with no error you cannot explain | Java, the HL7 FHIR validator, the bundles your tests wrote | section 5 | +| 3. A generic payer on the sandbox | Every leg over the real exchange with a payer whose desk you can drive; queries as CommunicationRequests; payment released | the transport on the sandbox (your app's own, or nhcx-adapter when the user chose it), a generic payer you can drive, the sandbox reaching your callback | section 6 | +| 4. Live PMJAY sandbox | `1518@hcx`: the scheme's own refusals and rules, decisions taken on the payer service desk | the sandbox, a real beneficiary, patience | section 6 | + +Climb in order. Rungs 1 and 2 need no service and no consent. Rungs 3 and 4 put traffic on the live NHCX sandbox, and only the user starts them. + +## 2. Writing rung 1 for a new HMIS + +Build one suite with this shape, whatever the language: + +- One process, one seeded database under a temporary path, sections in the order the episode runs. `section(name)` starts a group; `check(label, condition, detail)` records one assertion and never raises. The run exits non-zero at the end if anything failed. +- The transport's `send` is one function, and the test replaces it. Every send goes through it; the test assigns a stub that records the path, recipient, workflow id, correlation id and bundle, and returns `{"txn_id": ..., "correlation_id": ..., "api_call_id": ...}`. Restore the real one in `finally`. The receiving end is tested apart from the door: for your own transport, seal a payer bundle with a test key pair, POST it, and check the 202 receipt and the envelope the door receives. +- Call the callback handler directly with an envelope, not over HTTP: `receive({"jwe_headers": {...}, "fhir": bundle}, "", "", "fhir")`. The return value is one of `settled`, `unmatched`, `ignored`. Feed it the payer bundles under `nhcx-package/fhir/C3` to `nhcx-package/fhir/C11`, both the generic files and the `-pmjay` ones. The auth-requirements rulings are `C3/C3-response-generic.json` (one line, 10 supporting entries) and `C3/C3-response-pmjay.json` (two lines, 22 entries). +- The pin comparison builds each bundle from the pin's own data and compares canonical JSON (`json.dumps(bundle, sort_keys=True)`) against the pin. The data is all in `nhcx-package/fhir/B3/preauth-request.json`: member `MD5SLS4X5`, policy `PMJAY/HP/S/G`, provider `IN1910000151`, payer `1518@hcx`, package `MG0111A` with tier `STRAT006b`, the four `MAND` documents. Drop from both sides only `created`. The bundle id and every entry's `fullUrl` are fixed strings in the pins (`preauth-request-generic`, `https://nhcx.abdm.gov.in/preauth/request`), and the build produces them as they are. +- The single-item pins carry `factor 0.5`. That contradicts the rule their own enhancement follows (`nhcx-package/fhir/B3/preauth-enhancement.json`: the costlier line 1, the next 0.5), so compare those with `factor` removed. Compare the cancel and reprocess pins as they are; they carry `intimationNumber`, the spelling the build sends. +- Read every expected value in a reader check from the fixture you feed: `preAuthRef`, amounts, claim numbers, the UTR. The PMJAY captures have the beneficiary's identifiers replaced, and some fields are absent (`C5/C5-received-wf20-pmjay.json` carries no `preAuthRef`). A typed literal tests your memory, not the reader. +- Negative checks are half the value. A code the plan does not carry is refused. A send while the leg is with the payer is refused. A redelivered api call id is ignored. A claim refused at the door goes back to `queried` with the question restored. A cancel while the payer holds the case is accepted, and a cancel of a rejected one is refused. +- Put the regression sections near the bottom. Each is a defect that reached working code, named after what went wrong. Add one each time the sandbox teaches you something. + +In a language whose JSON encoder does not sort keys, decode into a map and encode again before comparing, so key order cannot fail a check. Where a byte comparison is too strict, as with the wire captures, compare element by element. + +## 3. The test-case matrix + +One row per hospital-side use case. Preconditions are the state the HMIS must be in. The action is what the desk or the test does. The expected wire is what must go out and come back; the per-case archive shows it (and the adapter's ledger, when it is the transport). The expected state is what the HMIS must hold afterwards. Codes are those of `nhcx-package/usecases.yaml`. Workflow ids are the PMJAY table unless the row says generic. + +| Use case | Preconditions | Action | Expected wire | Expected state | +| --- | --- | --- | --- | --- | +| A5 Get status (generic) | A pre-auth or claim leg with the payer; a generic payer | Ask status for the leg | `v1/task/submit`, Task `status` with `claimNumber`, workflow = the leg's correlation id; a Task back with `claimStatus` | An enquiry row `answered` with the status word; the leg unchanged | +| A5 Get status (PMJAY) | as above; PMJAY | Ask status | the same Task; a ProtocolResponse PAYR-1018 (no reason) or PAYR-1008 (with one) | The enquiry row `error` with the payer's words; nothing else changes | +| B1 Check coverage eligibility | A patient with a member id and policy from the policy search; facility HFR id and participant code set | Validate, then discover | `v1/coverageeligibility/check` twice, new correlation each, workflow = the case number; `on_check` with the request echoed and a `CoverageEligibilityResponse` | `claim.status eligible`, `inforce 1`, allowed and used amounts, the payer's Patient demographics | +| B2 Request insurance plan | Eligible; no master held for this facility and policy | Fetch the plan | `v1/insuranceplan/request`, a Task `poll` with `policyNumber` and `providerId`; `on_request` with the InsurancePlan and Questionnaires | `claim_plan.status ready`, benefits with rates, tiers, requirements, forms by url; a second episode on the same policy copies it without a send | +| B3 Submit pre-authorisation | Plan ready; lines quoted from it; dossier saved; admission linked; documents and forms for the pre-auth stage attached | Submit | `v1/coverageeligibility/check` purpose `auth-requirements` first (sent, not awaited), then `v1/preauth/submit` workflow 12 equal to the pin but for identifiers; `on_submit` 20 (`queued`, `response.partial`) then 21 | `claim_preauth.status submitting` after the 20 with `preauth_ref` kept, `approved` after the 21 with `approved_amount`; stage `preauth`, sub-stage `approved` | +| B3 Auth-requirements ruling | The check sent with the pre-auth; the payer answers it | Nothing; read on arrival | inbound `on_check`, a CoverageEligibilityResponse with purpose `auth-requirements`, one `insurance[0].item` per quoted line with `authorizationRequired`, `excluded` and `authorizationSupporting[]` (`C3/C3-response-generic.json`, `C3/C3-response-pmjay.json`) | each quoted line holds its ruling and what is due at pre-auth (a form always, a document only when its `Type` is `pre`); the pre-auth leg unchanged | +| B3 Enhancement | Approved; a line added since (`enhancement_lines` non-empty) | Submit again | `v1/preauth/submit` workflow 13, every line old and new, factors 1 and 0.5; 20 then 22 (generic); the SHA has answered 21 or 22 | `submission_kind enhancement`, `enhancement_no 1`, `preauth_ref` kept, then `approved`; stage `enhancement` | +| B4 Respond to a communication (generic) | A pre-auth or claim with the payer; the payer sends a CommunicationRequest on a new thread | The desk replies with text and a document | inbound `v1/communication/request` with Task `poll`, reason `additionalinfo`; outbound `v1/communication/on_request` with the request's correlation id and workflow id, a TaskBundle: Task `deliver`, Communication `basedOn` the request, the request echoed, the case entries | `claim_query` row `kind query`, `status open` then `answered` with `reply_json`; the leg row untouched; sub-stage `queried` while open | +| B4 Notification | Any leg; the payer sends a CommunicationRequest with intent `proposal` or reason `tatquery` | Nothing; it is acknowledged on arrival | outbound `v1/communication/on_request` at once, the payer's bundle with `Task.status completed`, provider Organization first | `claim_query` row `kind notification`, `status acknowledged`; the case's stage unchanged | +| B5 Submit claim | Approved pre-auth; discharge recorded with mode and stage; claim-stage documents and forms attached | Submit the claim | `v1/claim/submit` workflow 15, `use claim`, `preAuthRef`, the discharge scalars, the summary; 25 (`queued`) then 26 | `claim_submission.status submitting` then `approved` with amounts and item verdicts; stage `claim` | +| B7 Acknowledge payment notice (generic) | An approved claim; the payer's desk releases payment | Nothing; acknowledged on arrival | inbound `v1/paymentnotice/request` workflow 30 on a new thread; outbound `v1/paymentnotice/on_request` with the notice's correlation id and its own workflow id echoed, Task `status completed` with `paymentack` | `claim_payment` row with amount, UTR, `ack_status sent`; stage `payment`, sub-stage `paid`; a redelivery of the notice is `ignored` | +| B8 Cancel | A pre-auth `submitting`, `approved`, `partial` or `queried` | Cancel with a reason | `v1/task/submit` workflow PC01, Task `cancel`, inputs `claimNumber` and `intimationNumber`; `task/on_submit` PC02 with a ClaimResponse adjudicated `cancelled` | `claim_preauth.status cancelling` then `cancelled`; the episode gets a fresh claim number, the old one stays on `claim_ref`; a cancel of a `rejected` pre-auth is refused before sending | +| B8 Reprocess (generic) | A claim `rejected` or `partial` | Reprocess with reason `claimrejected` and a document | `v1/task/submit` workflow 36, Task `reprocess`, `intimationNumber`, `basedOn` CLN, `document` inputs, `for` the member; 37 (Task `accepted`, ClaimResponse `queued`); then 26 on the claim's thread | The enquiry row `answered` with `reopened`; `claim_submission` back to `submitting`, then `approved` | +| B9 Submit predetermination | Eligible; dossier saved | Ask for a quote | `v1/preauth/submit` workflow 12 with `use predetermination`; a ClaimResponse back | A `claim_predetermination` row `answered` with `allowed_amount`; the pre-auth row untouched | +| D1 Fetch the insurance plan | Eligible on PMJAY | Fetch | as B2; the answer on workflow 5, both `specificCost[]` and `coverage[]`, nested document requirements, `/questionnaire/` and `/stgquestionnaire/` forms | as B2, with `ProcedureType` conditions and the consent forms among the policy documents | +| D2 Authenticate the beneficiary | A policy from the BIS | Not NHCX; take the consent questionnaire path | none | The consent form answered for the pre-auth stage | +| D3 Check coverage eligibility | as B1 with member `MD5SLS4X5` style ids | Validate | as B1; the answer on workflow 5 with the wallet | as B1 | +| D4 Submit pre-authorisation | as B3, plus: HPIN on the doctor, `Item/n` ids, consent and STG forms answered, documents under the plan's `MAND` codes | Submit | `v1/preauth/submit` workflow 12; 20 with the path-form `preAuthRef` or none (flow-knowledge.md section 3), then 21 with the bare number | as B3; `preauth_ref` = the bare case number after the 21 | +| D5 Resubmit pre-authorisation | A pre-auth `rejected` | Submit again | a fresh 12, never 121 | a new `submitting` round; 121 would be PAYR-1214 | +| D6 Raise an enhancement | Approved; a medical package added (not conservative) | Submit | workflow 13; 20 without `preAuthRef` (keep the parent's); 241 arrives as a ClaimResponse `partial` on the case thread; the desk answers on 131 with a `CQD` reply; then approved | `enhancement_no 1`; `queried` then `answered` then `approved`; a second conservative package would be PAYR-1245 | +| D7 Answer a pre-authorisation query | The 24 arrived as a ClaimResponse `partial`, item status `Queried` | The desk writes a reply and submits again | `v1/preauth/submit` workflow 19, flow `queryupdate`, `NMI`/`CQD` carrying the words, a new correlation id; 20 then 21 | `submission_kind preauth_query_response`, `query_note` holding the payer's question, then `approved`; an empty reply is refused before sending | +| D8 Cancel pre-authorisation | as B8 on PMJAY | Cancel | as B8 | as B8 | +| D9 Submit claim | as B5, plus: the claim under the pre-auth's claim number, the package alone at the whole amount, Discharge Consent answered, PDF documents | Submit | `v1/claim/submit` workflow 15; 25 with `preAuthRef` as a path; then 26 | as B5; item verdicts with `eligible`, `status Approved` | +| D9 LAMA or DAMA before or during surgery | Discharge mode `lama` or `dama`, stage `Before Surgery` or `During Surgery` | Submit the claim | one item `LM100`, no tier, `DIS` = `LAMA` or `DAMA` with the stage | approved; the package would be PAYR-1362 | +| D9 Death | Discharge mode `death` with a date and time | Submit the claim | `ONS`/`DTM` and `DSDE` with the death instant, `DIS`/`DTM`, the death forms | approved; without `DTM` PAYR-1096 | +| D10 Answer a claim query | The 27 arrived as a ClaimResponse `partial` | The desk writes a reply and submits again | `v1/claim/submit` workflow 161, `NMI`/`CQD`, a new correlation id; 25 then 26 | `submission_kind claim_query_response`, then `approved`, possibly at zero | +| D11 Reprocess a rejected claim | A claim `rejected` | Reprocess | as B8 reprocess; on the sandbox a ProtocolResponse PAYR-1008 | the enquiry row `error` with the refusal; on a generic payer as B8 | +| D12 Claim a shortfall | A settled payment short of the approved amount | Release with `partialpayment` and the amount | `v1/task/submit` workflow 36, Task `release`, `valueMoney` | an enquiry row; out of reach on the sandbox | +| D13 Acknowledge the payment notice | An approved claim; the SHA's finance side sends 30 | Nothing; acknowledged on arrival | outbound `v1/paymentnotice/on_request` with workflow 17, the notice's correlation id, to the notice's sender | as B7 | + +Cross-cutting rows every matrix needs: + +| Case | Action | Expected | +| --- | --- | --- | +| Redelivery | Deliver the same envelope twice | the second returns `ignored`; state unchanged | +| Unmatched | Deliver an answer on an unknown correlation id | `unmatched`; archived under `unmatched`; nothing changes | +| Refusal at the door | Deliver a ProtocolResponse on a leg's thread | the leg `error` (or `queried` restored for a query answer, `approved` restored for an enhancement) with the payer's words; `correlation_id` restored to `thread_correlation_id` | +| Ledger reset (nhcx-adapter only) | The adapter answers 404 on `txn/related` | the leg `error` with "send again"; no spinning | +| Stage after every write | Any of the above | `stage` and `sub_stage` on the episode agree with `case_stage` recomputed from the legs | + +## 4. A skeleton offline test + +Replace the placeholders marked `` with your HMIS's own. Every pin and payer answer is loaded from the package. + +```python +#!/usr/bin/env python3 +"""Offline NHCX checks for : builders against the package pins, readers against the payer fixtures. + + NHCX_PACKAGE=nhcx-package python3 nhcx_offline_test.py # exit 0 when every check passes +""" +from __future__ import annotations + +import copy +import json +import os +import tempfile + +PKG = os.environ.get("NHCX_PACKAGE", "nhcx-package") +GENERIC_PAYER = "" + +os.environ[""] = os.path.join(tempfile.mkdtemp(prefix="nhcx-test-"), "t.db") + +import as nhcx # noqa: E402 the module that owns transport, build_*, receive + +failures = 0 +current = "general" +tally: dict[str, list[int]] = {} + + +def section(name: str) -> None: + global current + current = name + tally.setdefault(name, [0, 0]) + print(f"\n-- {name} " + "-" * max(3, 60 - len(name))) + + +def check(label: str, condition: bool, detail: str = "") -> None: + global failures + tally.setdefault(current, [0, 0]) + tally[current][0 if condition else 1] += 1 + if not condition: + failures += 1 + print(f"[{' ok ' if condition else ' FAIL '}] {label}" + (f" ({detail})" if detail else "")) + + +def pin(rel: str) -> dict: + """A bundle from the package by its path under fhir/, e.g. pin("B3/preauth-request.json").""" + with open(os.path.join(PKG, "fhir", rel), encoding="utf-8") as fh: + return json.load(fh) + + +def resource(bundle: dict, kind: str) -> dict: + return next(e["resource"] for e in bundle["entry"] if e["resource"]["resourceType"] == kind) + + +def task_input(task: dict, code: str): + return next(i.get("valueString") for i in task.get("input", []) if i["type"]["coding"][0]["code"] == code) + + +def total(claim_response: dict, category: str): + return next((t["amount"].get("value") for t in claim_response.get("total", []) + if t["category"]["coding"][0]["code"] == category), None) + + +def normalised(bundle: dict, factor: bool = True) -> dict: + """Drop only `created`, which a builder stamps when it sends; with factor=False, the Claim items' factor too.""" + out = copy.deepcopy(bundle) + + def walk(node): + if isinstance(node, dict): + node.pop("created", None) + for value in node.values(): + walk(value) + elif isinstance(node, list): + for value in node: + walk(value) + + walk(out) + if not factor: + for entry in out["entry"]: + if entry["resource"]["resourceType"] == "Claim": + for item in entry["resource"].get("item", []): + item.pop("factor", None) + return out + + +def canonical(bundle: dict, factor: bool = True) -> str: + return json.dumps(normalised(bundle, factor), sort_keys=True, ensure_ascii=False) + + +def same(label: str, ours: dict, want: dict, factor: bool = True) -> None: + a, b = canonical(ours, factor), canonical(want, factor) + check(label, a == b, "" if a == b else a[:300]) + + +# The package pins' own data: nhcx-package/fhir/B3/preauth-request.json and B1/*.json. +# Every builder is fed this and must produce the pin. +REF = { + "claim_no": "VB26AA2600001", "member_id": "MD5SLS4X5", "policy": "PMJAY/HP/S/G", + "provider": {"id": "IN1910000151", "name": "Facility Name"}, + "payer": {"code": "1518@hcx", "id": "1518", "name": "Insurance Company"}, + "patient": {"name": "Patient Name", "gender": "male", "dob": "2004-09-18", + "phone": "9999999999", "abha": "91718280654077", "member_id": "MD5SLS4X5"}, + "practitioner": {"name": "Practitioner Name", "hpr_id": "982374978-2343", "license_no": "MCI-12345", + "qualification": "Doctor of Medicine", "qualification_code": "MD", + "specialty": "General medicine", "specialty_code": "394802001"}, + "diagnosis": {"code": "A97", "display": "Dengue"}, + "item": {"code": "MG0111A", "display": "Pleural Effusion", "category_code": "MG", + "category_display": "General Medicine", "quantity": 1, "unit_price": 3300, "net": 3300, + "kind": "Procedure", "procedure_type": "conservative"}, + "tier": {"code": "STRAT006b", "display": "HDU", "kind": "Stratification", "parent_code": "MG0111A"}, + # The benefits and auth-requirements pins quote a different package. + "coverage_item": {"code": "MG004C", "display": "Dengue shock syndrome (Dengue fever)", + "category_code": "MG", "category_display": "General Medicine", "quantity": 1, + "tier": {"code": "STRAT006c", "display": "ICU - Without Ventilator"}}, +} + + +def main() -> int: + section("coverage eligibility: ours is the pin") + for purpose, rel in (("discovery", "B1/discovery.json"), ("validation", "B1/validation.json"), + ("benefits", "B1/benefits.json"), ("auth-requirements", "B1/auth-requirements.json")): + want = pin(rel) + ours = nhcx.build_coverage_request((purpose, want)) + same(f"coverage {purpose}", ours, want) + + section("insurance plan request: ours is the pin") + same("plan request", nhcx.build_plan_request(REF["policy"], REF["provider"]["id"]), + pin("B2/insurance-plan-request.json")) + + section("claim bundles: ours is the pin") + ref_pa = pin("B3/preauth-request.json") + ref_pdf = next(si["valueAttachment"]["data"] for si in resource(ref_pa, "Claim")["supportingInfo"] + if "valueAttachment" in si) + dossier = (REF, ref_pdf, ref_pa) + same("preauth request", nhcx.build_preauth_bundle(dossier, flow="request"), ref_pa, factor=False) + ref_qu = pin("B3/preauth-queryupdate.json") + reply = next(si["valueString"] for si in resource(ref_qu, "Claim")["supportingInfo"] + if si["category"]["coding"][0]["code"] == "NMI") + same("preauth query update", + nhcx.build_preauth_bundle(dossier, flow="queryupdate", query_response=reply), + ref_qu, factor=False) + ref_cancel = pin("B3/preauth-cancel.json") + cancel = resource(ref_cancel, "Task") + reason = cancel["reasonCode"]["coding"][0] + same("preauth cancel", + nhcx.build_cancel_task(task_input(cancel, "claimNumber"), (reason["code"], reason["display"]), + cancel["authoredOn"], REF["provider"], REF["payer"]), + ref_cancel) + ref_ack = pin("B7/payment-notice-ack.json") + ack = resource(ref_ack, "Task") + acked_claim = next(o["valueString"] for o in ack["output"] if "valueString" in o) + same("payment acknowledgement", + nhcx.build_payment_ack(acked_claim, ack["authoredOn"], REF["provider"], REF["payer"]), + ref_ack) + + section("the transport is the one door, and it can be stubbed") + posted: list[dict] = [] + real_send = nhcx.transport.send + + def submitted(payer: str, corr: str): + def _send(path, bundle, recipient, workflow_id, correlation_id=None, **kw): + posted.append({"path": path, "recipient": recipient, "workflow_id": workflow_id, + "correlation_id": correlation_id, "bundle": bundle}) + return {"txn_id": "01TEST", "correlation_id": corr, "api_call_id": "acid-" + corr} + + seeded = (payer) # eligible, plan ready, lines quoted, dossier saved + nhcx.transport.send = _send + try: + nhcx.submit_preauth(seeded) + finally: + nhcx.transport.send = real_send + return seeded + + episode = submitted(REF["payer"]["code"], "corr-preauth-1") + sent = posted[-1] + leg = nhcx.preauth(episode) + check("the pre-auth goes out on the preauth route under workflow 12", + sent["path"] == "v1/preauth/submit" and str(sent["workflow_id"]) == "12") + check("no correlation id is passed on a request", sent["correlation_id"] is None) + check("the leg waits with the transport's ids", + leg["status"] == "submitting" and leg["txn_id"] == "01TEST" and leg["correlation_id"] == "corr-preauth-1") + + section("readers: the payer answers settle the right state") + + def deliver(bundle: dict, acid: str, workflow: str, status: str = "response.complete", + corr: str = "corr-preauth-1", sender: str = "1518@hcx") -> str: + return nhcx.receive({"jwe_headers": {"x-hcx-correlation_id": corr, + "x-hcx-api_call_id": acid, + "x-hcx-sender_code": sender, + "x-hcx-status": status, "x-hcx-workflow_id": workflow}, + "fhir": bundle}, "preauth", "request", "fhir") + + received = pin("C5/C5-received-wf20-pmjay.json") + before = nhcx.preauth(episode)["preauth_ref"] + check("the PMJAY acknowledgement leaves the leg waiting", + deliver(received, "acid-20", "20", "response.partial") == "settled" + and nhcx.preauth(episode)["status"] == "submitting") + check("an acknowledgement without preAuthRef overwrites nothing", + not resource(received, "ClaimResponse").get("preAuthRef") + and nhcx.preauth(episode)["preauth_ref"] == before) + check("the same api call id delivered again is ignored", + deliver(received, "acid-20", "20", "response.partial") == "ignored") + approval = pin("C5/C5-approved-wf21-pmjay.json") + approved = resource(approval, "ClaimResponse") + check("the approval settles the leg on the same thread with the payer's case number", + deliver(approval, "acid-21", "21") == "settled" + and nhcx.preauth(episode)["status"] == "approved" + and nhcx.preauth(episode)["approved_amount"] == total(approved, "benefit") + and nhcx.preauth(episode)["preauth_ref"] == approved["preAuthRef"]) + stage, sub_stage = nhcx.case_stage(episode) + check("the episode is stamped preauth / approved", (stage, sub_stage) == ("preauth", "approved")) + + other = submitted(GENERIC_PAYER, "corr-preauth-2") + generic = pin("C5/C5-received-wf20.json") + check("a generic payer's acknowledgement carries the case number, and it is kept", + deliver(generic, "acid-20g", "20", "response.partial", corr="corr-preauth-2", + sender=GENERIC_PAYER) == "settled" + and nhcx.preauth(other)["status"] == "submitting" + and nhcx.preauth(other)["preauth_ref"] == resource(generic, "ClaimResponse")["preAuthRef"]) + + section("auth requirements: the payer's ruling is read line by line") + for rel in ("C3/C3-response-generic.json", "C3/C3-response-pmjay.json"): + ruling = pin(rel) + answer = [e["resource"] for e in ruling["entry"] + if e["resource"]["resourceType"] == "CoverageEligibilityResponse"][-1] + want = {i["productOrService"]["coding"][0]["code"]: i.get("authorizationRequired") + for i in answer["insurance"][0]["item"]} + got = nhcx.parse_auth_bundle(ruling) # {procedure code: {"required": bool, "supporting": [...]}} + check(f"{rel}: one ruling per quoted line, required as the payer says", + {code: line["required"] for code, line in got.items()} == want) + + section("the query loop") + queried = pin("C5/C5-queried-wf24.json") + check("a PMJAY query is the leg queried, with the payer's words and case number kept", + deliver(queried, "acid-24", "24") == "settled" + and nhcx.preauth(episode)["status"] == "queried" + and bool(nhcx.preauth(episode)["query_note"]) + and nhcx.preauth(episode)["preauth_ref"] == resource(queried, "ClaimResponse")["preAuthRef"]) + try: + nhcx.submit_preauth(episode, reply="") + check("an empty reply is refused before sending", False) + except ValueError: + check("an empty reply is refused before sending", True) + check("a generic payer's CommunicationRequest is classified a query", + nhcx.classify_communication(nhcx.GENERIC_ADAPTER, "additionalinfo", "order") == "query" + and nhcx.classify_communication(nhcx.PMJAY_ADAPTER, "additionalinfo", "order") == "notification" + and nhcx.classify_communication(nhcx.GENERIC_ADAPTER, "tatquery", None) == "notification") + + section("refusal at the door") + refusal = {"type": "ProtocolResponse", "x-hcx-status": "response.error", + "x-hcx-correlation_id": "corr-preauth-1", + "x-hcx-error_details": {"code": "PAYR-1238", "message": "Beneficiary is having an active preauthorization request"}} + (episode) + check("a ProtocolResponse settles the leg as refused with the payer's words", + nhcx.receive({"jwe_headers": {"x-hcx-correlation_id": "corr-preauth-1"}, "fhir": refusal}, + "preauth", "request", "protocol") == "settled" + and nhcx.preauth(episode)["status"] == "error" + and "PAYR-1238" in (nhcx.preauth(episode)["error_message"] or "")) + + section("tasks and payment") + cancelled = pin("C10/C10-cancelled-wfPC02-pmjay.json") + verdict = resource(cancelled, "ClaimResponse")["adjudication"][0]["reason"]["coding"][0]["code"] + check("PC02 is read as an accepted cancellation", + nhcx.parse_task_response(cancelled)["adjudication"] == verdict == "cancelled") + arbitration = pin("C10/C10-arbitration-wf37-pmjay.json") + check("37 is read as the reprocess taken", + nhcx.parse_task_response(arbitration)["task_status"] == resource(arbitration, "Task")["status"]) + paid = pin("C9/payment-notice.json") + pn, pr = resource(paid, "PaymentNotice"), resource(paid, "PaymentReconciliation") + notice = nhcx.parse_payment_notice(paid) + check("the payment notice names the claim, the amount and the UTR", + notice["claim_ref"] == pn["identifier"][0]["value"] + and notice["amount"] == pn["amount"]["value"] + and notice["utr"] == pr["paymentIdentifier"]["value"]) + + print("\n" + "=" * 64) + total_checks = sum(ok + bad for ok, bad in tally.values()) + for name, (ok, bad) in tally.items(): + print(f" {name:44s} {ok:3d} passed {bad:2d} failed [{'FAIL' if bad else 'ok'}]") + print("=" * 64) + if failures: + print(f"{failures} of {total_checks} check(s) FAILED") + return 1 + print(f"all {total_checks} checks passed") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) +``` + +What each placeholder must do: + +- `` names the variable your HMIS reads its database path from, so the suite runs on a throwaway file. +- `` is the module that owns `transport`, the builders and `receive`. +- `` is the participant code of a generic payer (``) that your configuration maps to `query_mode: communication`. +- `` returns the dict your coverage builder takes, filled from `REF`. The discovery pin carries policy `NONE`. The benefits and auth-requirements pins quote `REF["coverage_item"]`. Copy the Location and PractitionerRole from the pin it is given. +- `` returns whatever your claim builder takes. That is the claim number, the item, the tier, the program `AB-PMJAY` and factors `(1, 0.5, 0.25)`. Add the four `MAND` documents (`MAND0408`, `MAND0455`, `MAND0409`, `MAND0570`, each with the pin's PDF), and copy the stay and procedure dates from the pin it is given. +- `` takes a payer code and inserts an eligible episode for that payer, with the plan and lines seeded straight into the database. +- `` puts the pre-auth row back to `submitting` on `corr-preauth-1`. + +Run the suite from the folder that holds `nhcx-package/`, or set `NHCX_PACKAGE` to its path. + +## 5. Running rung 2 + +Have your tests and live runs write every bundle they build into one archive folder. The package ships no validator. Run the HL7 FHIR validator with the NRCeS IG `ndhm.in` on the whole folder in one call, with the command and flags in `references/fhir-knowledge.md` section 11. + +Read the results in three piles. "A code the profile does not define" is the scheme's vocabulary, and it is expected. "A required element is missing" and "an id or value the base rules refuse" are yours to fix. Warnings are advice; the sandbox accepted every pin as it stands. Skip the package master; it exhausts the validator's memory. A live PAYR-1004 or PAYR-1008 is the first reason to run this rung again (`nhcx-package/docs/06-Reference/02-Troubleshooting.md`). + +## 6. Running rungs 3 and 4 + +Only the user runs these. Prepare what they start and the driver, then stop and ask. + +What the user starts: + +1. The transport. Your own or the app's existing one needs a participant record carrying its certificate and a public HTTPS `endpoint_url` the exchange can reach (`references/transport-knowledge.md` section 3). nhcx-adapter, only when the user chose it, comes from its release: `config.sample.json` filled in, started with `serve.sh`. +2. Your HMIS, reachable by the exchange through that transport. +3. For rung 3, a generic payer on the sandbox whose desk you can drive (``), mapped to `query_mode: communication`. For rung 4, nothing more: the PMJAY payer is `1518@hcx`, and its decisions are taken on the payer service desk. + +The driver is a script or a browser spec. It walks the matrix rows through the app's JSON state address or its own screens, one episode per test, in series, with a 20 minute timeout per episode. + +- Before a PMJAY run, sweep every live pre-auth for the beneficiaries the tests use. Cancel it on PC01, or have the desk reject it. Otherwise the first pre-auth is refused with PAYR-1238. +- One request at a time per case. Wait about 30 seconds after a decision before the next leg. On "Active instance found" (PAYR-1322), wait and resend, up to three times. +- Wait on the case's own state, never on a fixed sleep or a checklist. +- Log every verdict the sandbox gives, with its workflow id and words, so a refusal is a finding, not a mystery. +- Expect about four minutes for the rung 3 matrix and about ten minutes per episode on PMJAY. + +After the run, package its bundles by correlation id from the per-case archive: every message sent and received, filed under its case. With nhcx-adapter as the transport, `nhcx-adapter ledger thread ` gives the same conversation, with bodies only while `ledger.storeBodies` is true (`nhcx-package/docs/02-Getting Started/10-NHCX Adapter.md`). File each thread under its use case. diff --git a/plugins/nhcx/skills/nhcx-preauth/references/transport-knowledge.md b/plugins/nhcx/skills/nhcx-preauth/references/transport-knowledge.md new file mode 100644 index 000000000..a0838b9cd --- /dev/null +++ b/plugins/nhcx/skills/nhcx-preauth/references/transport-knowledge.md @@ -0,0 +1,283 @@ +# Transport knowledge: how the build reaches NHCX + +Every NHCX message is a FHIR bundle sealed in a JWE, sent with an ABDM session token, and answered later on the sender's own callback. Something has to do that work. This file says which of three things does it for a build, what the rest of the build expects from it, and how to build it yourself. + +Section 3 is drawn from NHA's published chapters: `nhcx-package/docs/02-Getting Started` (01 to 09, and 11), `nhcx-package/docs/01-Overview/04-JWE, Status and Errors.md` and `nhcx-package/docs/06-Reference/03-Envelope Fields.md`. Open them when a detail matters. Where they and this summary differ, they win. + +## 1. Three transports + +| Transport | Choose it when | The build | +| --- | --- | --- | +| `existing` | Stage 0 found the app already speaks NHCX: its own client that seals and posts JWEs, a vendor gateway or middleware, an HCX SDK, callbacks under `/v1/...` | Keeps it. Wraps it behind the contract in section 2 and closes the gaps section 4 lists. Never replaces a working one. | +| `own` | The app has no NHCX integration, and the user has not asked for nhcx-adapter. This is the default. | Builds the protocol into the app (section 3): the session token, the key and certificate, the participant record, the recipient's certificate, sealing and sending, the callback and its receipt. | +| `adapter` | Only when the user asks for nhcx-adapter, by name or by asking for "the adapter" | Downloads it (section 5) and talks plain FHIR to it. `references/api-knowledge.md` is its contract. | + +The rules: + +- Never propose nhcx-adapter, and never choose it because it is easier. Use it only when the user has asked for it, and write their words into `nhcx-build/1-idea.md`. +- An app with an NHCX integration of its own keeps it, even when it is partial. Extend it; never put a second transport beside it. +- The choice is made once per app, at stage 1, from stage 0's verdict on `foundation.transport`. Every skill after the first reads it from `1-idea.md`. + +## 2. The contract every transport meets + +The rest of the build (modules 7.2 to 7.13) never sees the transport, only these functions: + +| Function | Takes | Gives | Notes | +| --- | --- | --- | --- | +| `send(path, bundle, recipient, workflow_id, correlation_id = null, ben_abha_id = null, claim_no, usecase)` | The NHCX path (`v1/preauth/submit`), the bundle, the recipient's participant code, the workflow id; a correlation id only when answering (the communication reply, the payment acknowledgement); the beneficiary's ABHA, else the episode's by `claim_no` | `{txn_id, correlation_id, api_call_id, raw}` | Raises `TransportError(code, message, protocol_response, retryable)` on a refusal. Archives the outbound message. Every leg stores the three ids. | +| The receiving end | A delivery from the exchange (`own`, `existing`) or from nhcx-adapter | Calls 7.3's `receive(envelope)` with `{meta: {path, payloadType, redelivery}, jwe_headers: {every x-hcx- field}, fhir: }`; `payloadType` is `fhir`, `protocol` or `error` | Answers the sender as its transport requires (section 3.9 for `own`). The door does the rest. | +| `policies(id_type, value)` | `AbhaNumber`, `MemberId` or `MobileNo`, and the value | The participant service's answer, raw | Module 7.4 normalises it (section 3.6). | +| `participants(role)` | `PAYER`, `PROVIDER` or `TPA` | The registry's list | Cached for the day. | +| `token()` | nothing | The ABDM session token | For calls the transport does not make itself, such as the PMJAY payer service. | +| `thread(correlation_id)`, `fetch_missed(txn_id)` | | The messages on one thread; a missed answer | Only nhcx-adapter keeps a ledger to answer these. With `own` and `existing`, `thread` reads the per-case archive and `fetch_missed` answers `unavailable`; a lost answer surfaces through `/v1/error` and the status exchange instead (section 3.10). | + +Two values every transport needs from the build, both from the policy lookup (section 3.6). The recipient is the policy's `processingid`, kept on the episode as `recipient_code`. The insurer is its `payerid`, kept as `payer_code`: it goes inside the bundle and chooses the payer adapter (module 7.11). And every message carries the beneficiary's ABHA number in `x-hcx-ben-abha-id`. + +A test replaces `send` with a stub of the same signature (stage 9). Nothing else in the build changes for a test. + +## 3. Building it yourself (`own`) + +Seven things, in this order (`01-The Base Framework.md`): a token, a key and certificate, a participant record, the payer and policy lookups, the recipient's certificate, sealing and sending, and the callback. The last two are the ones every message uses. + +### 3.1 Before you start + +| Need | Why | +| --- | --- | +| The facility's HFR id | The registry that vouches for a hospital | +| ABDM sandbox client id and secret, Milestone 1 completed | NHCX uses the same credentials; there is no separate login | +| A public HTTPS server in India with a domain name | The exchange calls your callback; it will not call an IP address or a port number | +| `openssl` where the private key will live | The key pair | +| A JOSE library | RSA-OAEP-256 with A256GCM: `jose` on Node, `jwcrypto` on Python, Nimbus on Java, `jose-jwt` on .NET | + +Ask the user for the credentials. Never write them, the token or the private key into code, a log or `nhcx-build/`. + +### 3.2 Addresses and headers + +From `nhcx-package/baseurl.yaml`: + +| Service | Sandbox | Production | +| --- | --- | --- | +| ABDM session token | `https://dev.abdm.gov.in/api/hiecm/gateway/v3/sessions` | `https://apis.abdm.gov.in` plus the same path; confirm it in the onboarding letter | +| NHCX exchange, every use-case call under `/v1` | `https://apisbx.abdm.gov.in/hcx` | Shared by NHA after sandbox exit | +| Participant service | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice` | `https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice` | + +Keep every address in configuration. Every call to the participant service and the use-case endpoints carries `Accept: application/json`, `Content-Type: application/json` and `bearer_auth: Bearer `. The header is `bearer_auth`, not `Authorization`; some NHA pages write `Authorization`, so send both with the same value. + +### 3.3 The session token + +`POST` to the sessions address with three headers, none optional: `REQUEST-ID` (a fresh UUID on every call), `TIMESTAMP` (UTC with milliseconds and a trailing `Z`, from the system clock) and `X-CM-ID` (`sbx` on the sandbox, `abdm` in production). The body is `{"clientId", "clientSecret", "grantType": "client_credentials"}`. The answer carries `accessToken` and `expiresIn`. + +- NHA's documents give its life as 300, 1200 and 6000 seconds. Rely on none: keep the token and when you got it, and fetch a new one when it is a few minutes old. +- On any `401`, get a new token and retry that call once. Never retry with the same token. +- Put `Bearer` and a space before the token. Without it, `401`. + +`03-Session Token.md` also shows the two timestamp shapes in ten languages: the gateway's UTC `...975Z`, the exchange's `+05:30`. + +### 3.4 Your key and certificate + +```bash +openssl genpkey -algorithm RSA -out private.key -pkeyopt rsa_keygen_bits:2048 +openssl req -new -key private.key -out request.csr +openssl x509 -req -in request.csr -signkey private.key -out certificate.crt -days 365 +base64 -w 0 certificate.crt > certificate.b64 # macOS: base64 -i certificate.crt -o certificate.b64 +``` + +`private.key` never leaves the server that receives callbacks. `certificate.b64` goes on the participant record as `encryption_cert`. Note the expiry: a lapsed certificate stops every sender. Replace it yearly (`04-Your Certificate.md`). + +### 3.5 The participant record + +On the sandbox, `POST /participant/create` with: + +| Field | Value | +| --- | --- | +| `linked_registry_codes` | `["10001"]` (HFR) | +| `registryid` | Your ABDM client id on the sandbox; the HFR id in production | +| `roles` | `["10001"]` (provider) | +| `participant_name`, `scheme_code`, `state`, `district`, `primaryEmail`, `phone`, `primaryMobile` | The facility's | +| `encryption_cert` | The base64 certificate | +| `endpoint_url` | The base of your callback server | + +The answer is your `participant_code`: the `x-hcx-sender_code` on everything you send. `participant/update` changes the certificate or the address. Production takes four steps with a passcode to the mobile on the HFR record (`v2/participant/create`, `validate`, `v2/participant/update`, `update/validate`), and `v2/update/cert` rotates only the certificate (`05-Creating and Updating a Participant.md`). + +The exchange appends the use-case path to `endpoint_url`: a pre-auth decision arrives at `/v1/preauth/on_submit`. Only the client id that created the record may change it; any other gets NHCX-1015. + +This is the user's onboarding, not the build's. The build writes the script or the settings screen; the user runs it with their credentials. Check it worked by fetching your own certificate back (section 3.7). + +### 3.6 The payer and the policy + +- Payers: `POST /fetch/participants/list` with `role` (`PAYER`, `PROVIDER`, `TPA`), `fromdate` and `todate` (`dd/MM/yyyy`), and optionally `entitytype` (`Gov`). There is no server-side search by name: fetch, filter locally, and cache for the day. +- Policies: `POST /participant/get/policies` with `identifiertype` and `identifiervalue`. Try `AbhaNumber` (no hyphens), then `MemberId`, then `MobileNo`, and stop at the first that returns a policy. Each policy carries `payerid`, `processingid`, `memberid`, `productid` and `productname`. The published answer is a sketch: read a real one before writing the parser, and keep it raw on the episode. +- Send to the processor. `processingid` is the envelope's recipient and whose certificate seals the message; `payerid` is the insurer named inside the bundle. They are the same when the insurer processes its own claims and differ when a TPA does. Addressing the `payerid` is the portal's seventh most common mistake. A policy with no `processingid` cannot be addressed: stop and say so (`06-Finding Participants and Policies.md`). + +### 3.7 The recipient's certificate + +`POST /fetch/certs` with `{"participantid": ""}`. The answer is PEM text: usually an X.509 certificate, sometimes a bare SPKI public key (anything under about 400 bytes). Load it as a certificate and take its key; if that fails, load it as a key. NHA does not publish the JSON envelope around it, so read one real answer first. Cache by participant code for 24 hours, and refresh early when the other side stops being able to open your messages (`07-Fetching a Recipient Certificate.md`). + +### 3.8 Sealing and sending + +The protected header (`08-Building and Sending a JWE.md`, `06-Reference/03-Envelope Fields.md`): + +| Field | Value | +| --- | --- | +| `alg`, `enc` | `RSA-OAEP-256`, `A256GCM`; not `RSA-OAEP` | +| `x-hcx-sender_code` | Your participant code | +| `x-hcx-recipient_code` | The policy's `processingid` on a request; the request's sender on an answer | +| `x-hcx-api_call_id` | A fresh UUID on every message, answers included | +| `x-hcx-request_id` | A UUID per request; optional, send it | +| `x-hcx-correlation_id` | On a request, this message's own `api_call_id`. On an answer, the request's `correlation_id`, so the two ids differ on an answer | +| `x-hcx-workflow_id` | The step code (`references/flow-knowledge.md` section 2). Optional in the specification, but payers key on it: send it wherever the sheet gives one | +| `x-hcx-timestamp` | ISO 8601 with `+05:30`, no milliseconds, from the system clock | +| `x-hcx-status` | `request.initiated` on a request; `response.complete` on an answer (an `on_` path) | +| `x-hcx-ben-abha-id` | The beneficiary's ABHA number without hyphens. Mandatory on every exchange | +| `x-hcx-use_case` | Optional: `New`, `Enhancement` or `Resubmit` on a pre-auth; `New` or `Resubmit` on a claim | + +Seal with the JOSE library: the bundle as plaintext, the recipient's public key, the header above as the protected header, compact serialisation (five parts, four dots). POST `{"payload": ""}` to `/v1/` with the headers of section 3.2. The sandbox collection also repeats the `x-hcx-` fields as HTTP headers; send them both ways. + +What comes back: + +| Answer | Means | The build | +| --- | --- | --- | +| `202` with a receipt (`protocol_status: request.queued`) | The envelope was valid and is queued. It is not the decision | Store `api_call_id` and `correlation_id`, and the archive id as `txn_id`; the leg waits | +| `400` | The envelope failed validation | Raise with the gateway's body; nothing went to the payer | +| `401` | The token expired, or `Bearer` is missing | New token, retry once | +| A connection dropped after the request was written | Unknown: it may have landed | Do not resend at once (`references/errors-and-debugging.md` section 7) | + +A correlation id that failed at the gateway is retired. The next attempt needs a fresh `api_call_id` and a fresh `correlation_id` (`01-Overview/04-JWE, Status and Errors.md`). + +### 3.9 Receiving + +Host these under `endpoint_url` (`09-Receiving a Callback.md`): `/v1/coverageeligibility/on_check`, `/v1/insuranceplan/on_request`, `/v1/preauth/on_submit`, `/v1/claim/on_submit`, `/v1/predetermination/on_submit`, `/v1/search/on_submit`, `/v1/communication/request`, `/v1/paymentnotice/request`, `/v1/task/on_submit`, `/v1/on_status` and `/v1/error`. Build one handler. The path gives the receipt's `entity_type`; the correlation id routes everything else (module 7.3). + +- The address: a domain over HTTPS with TLS 1.2 or newer, hosted in India, reachable from the exchange's outbound addresses `3.109.99.210`, `13.126.152.0` and `13.200.129.223`. +- The body: `{"type": "JWEPayload", "payload": ""}`; or, when the recipient refused your message, `{"type": "ProtocolResponse", "x-hcx-...": ..., "x-hcx-status": "response.error", "x-hcx-error_details": {code, message, trace}}` with the fields in the clear. `/v1/error` carries neither: it is a plain report of a request the exchange gave up on after five attempts. Store it whole and do not parse it against a fixed schema. +- Open a `JWEPayload` with your private key: the protected header comes out in the clear and the bundle is the plaintext. A failure to decrypt means the message was sealed for a certificate that is not the one on your participant record. +- Answer every delivery with `202` and the receipt within 30 seconds, `/v1/error` and unrecognised messages included. Not `200`, and not an empty body: + + ```json + {"timestamp": "dd/MM/yyyy HH:mm:ss:SSS", "api_call_id": "", "correlation_id": "", + "result": {"sender_code": "", "recipient_code": "", "entity_type": "preauth", "protocol_status": "request.queued"}, + "error": {"code": "", "message": ""}} + ``` + + `entity_type` is the path's second-to-last segment, or the last where that is `v1`, with `on_` stripped. +- Hand the door `{meta: {path, payloadType, redelivery}, jwe_headers, fhir}`: `payloadType` `fhir` with the bundle, `protocol` with the ProtocolResponse body as `fhir`, `error` with the `/v1/error` report. The door dedupes on `x-hcx-api_call_id`, archives, matches and applies, fast and with no outbound calls, so the receipt still goes inside the 30 seconds. +- The exchange signs its calls to you with a JWT (RS256; claims `jti`, `iss`, `sub`, `iat`, `exp`). No published source gives the NHCX public key or the header the token arrives in. Build the check with the key in configuration. While no key is configured, log that at every start, accept calls only from the three addresses above, and ask NHA for the key at onboarding. Never leave the check off silently. + +### 3.10 Status and the error endpoint + +- `/v1/status` asks the exchange what became of a message you sent. The payload is empty; `x-hcx-correlation_id` is that message's `api_call_id`. The answer arrives on `/v1/on_status` with `request.queued`, `request.dispatched` or `request.stopped` (redelivery exhausted; the correlation is retired). Call it when a case has been quiet longer than the payer's turnaround, never on a timer (`11-Status and Search.md`). `references/flow-knowledge.md` section 2 records what the sandbox did with it; keep the path configurable. This is not the claim's status Task of module 7.9. +- `/v1/error` is how you learn a request died. Without it a lost message is silent. + +With no ledger to poll, these two, the per-case archive and the receipts are what an `own` transport has. A leg with no answer stays waiting; it never turns into an error on a timer. + +### 3.11 Proving it + +The sandbox's dummy payer answers when you trigger it. Send it a bundle, then `POST https://apisbx.abdm.gov.in/pmjay/sbxhcx/dummyhcxpayer/process/request` with `{"action": "Approve" | "Reject" | "Query", "method": "Preauth" | "Claim", "correlationId": ""}`. Its answer reaching your `/v1/preauth/on_submit`, sealed or as a ProtocolResponse, proves the token, the participant record, the address, the sealing and the opening together (`09-Receiving a Callback.md`, "Closing the loop"). This is live traffic: stage 10, rung 3, started by the user. + +### 3.12 Pseudo code + +``` +settings.nhcx = {sessions, base, registry, cm_id, client_id, client_secret, # from configuration, never from code + private_key, signing_key} # signing_key empty until onboarding gives it + +function token(): + if cache.token and age(cache.at) < 240s: return cache.token + r = http_post(settings.nhcx.sessions, json = {clientId: settings.nhcx.client_id, clientSecret: settings.nhcx.client_secret, + grantType: "client_credentials"}, + headers = {"REQUEST-ID": uuid4(), "TIMESTAMP": utc_millis_z(), "X-CM-ID": settings.nhcx.cm_id}) + cache = {token: r.json().accessToken, at: now()} + return cache.token + +function authed_post(url, body, extra_headers = {}): + for attempt in (1, 2): + t = token() + r = http_post(url, json = body, timeout = 90, + headers = {"Accept": "application/json", "Content-Type": "application/json", + "bearer_auth": "Bearer " + t, "Authorization": "Bearer " + t} + extra_headers) + if r.status != 401: return r + cache.token = null # one retry, with a fresh token + return r + +function registry(path, body): return authed_post(settings.nhcx.registry + "/" + path, body) + +function recipient_key(code): # cached for 24 hours + if certs[code] and age(certs[code].at) < 24h: return certs[code].key + pem = pem_in(registry("fetch/certs", {participantid: code}).json()) # read one real answer first + key = try_certificate(pem).public_key() or load_public_key(pem) # X.509 first, bare SPKI second + certs[code] = {key, at: now()} + return key + +function send(path, bundle, recipient, workflow_id, correlation_id = null, ben_abha_id = null, claim_no = null, usecase = ""): + abha = digits(ben_abha_id or ben_abha(claim_no)) + if not recipient or not workflow_id or not abha: raise ValueError("recipient, workflow id and beneficiary ABHA are required") + answer = path.split("/")[-1].startswith("on_") + api_call_id = uuid4() + header = {"alg": "RSA-OAEP-256", "enc": "A256GCM", + "x-hcx-sender_code": with_hcx(settings.participant_code), "x-hcx-recipient_code": with_hcx(recipient), + "x-hcx-api_call_id": api_call_id, "x-hcx-request_id": uuid4(), + "x-hcx-correlation_id": correlation_id if answer else api_call_id, + "x-hcx-workflow_id": str(workflow_id), "x-hcx-timestamp": now_ist_seconds(), + "x-hcx-status": "response.complete" if answer else "request.initiated", + "x-hcx-ben-abha-id": abha} + jwe = jose_encrypt_compact(to_json(bundle), recipient_key(with_hcx(recipient)), protected = header) + r = authed_post(settings.nhcx.base + "/" + path, {"payload": jwe}, extra_headers = without(header, "alg", "enc")) + txn = archive.record(claim_no, usecase, "out", {path, header, bundle, status: r.status, response: r.text}) + if r.status >= 300: + raise TransportError(code = "GATEWAY_HTTP_" + r.status, message = r.text, retryable = r.status >= 500) + return {txn_id: txn, correlation_id: header["x-hcx-correlation_id"], api_call_id: api_call_id, raw: r.json()} + +route POST /v1/ # under endpoint_url; exempt from session auth and CSRF; the exchange's addresses only +function inbound(request, path): + verify_nhcx_jwt(request, settings.nhcx.signing_key) # when the key is configured; else logged at start, never silent + body = parse_json_or_null(request.body) + if path == "error": + env = {meta: {path: "v1/error", payloadType: "error"}, jwe_headers: {}, fhir: body} + elif body and body.type == "ProtocolResponse": + env = {meta: {path: "v1/" + path, payloadType: "protocol"}, jwe_headers: x_hcx_fields(body), fhir: body} + else: + try: header, plaintext = jose_decrypt_compact(body.payload, settings.nhcx.private_key) + except: archive.record(null, "undecryptable", "in", request.body); return 202, receipt({}, path, error = "DECRYPT_FAILED") + env = {meta: {path: "v1/" + path, payloadType: "fhir"}, jwe_headers: header, fhir: parse_json(plaintext)} + receive(env) # module 7.3: dedupe, archive, match, apply; fast, no sends + return 202, receipt(env.jwe_headers, path) # within 30 seconds + +function receipt(h, path, error = ""): + return {"timestamp": now_ist("dd/MM/yyyy HH:mm:ss:SSS"), + "api_call_id": h["x-hcx-api_call_id"], "correlation_id": h["x-hcx-correlation_id"], + "result": {"sender_code": h["x-hcx-sender_code"], "recipient_code": h["x-hcx-recipient_code"], + "entity_type": entity_type(path), "protocol_status": "request.queued"}, + "error": {"code": error, "message": ""}} + +function entity_type(path): # "v1/preauth/on_submit" -> "preauth"; "v1/on_status" -> "status" + parts = ("v1/" + path).split("/"); seg = parts[-2] if parts[-2] != "v1" else parts[-1] + return seg.removeprefix("on_") +``` + +## 4. Using an existing integration (`existing`) + +How stage 0 recognises one: `x-hcx-`, `JWEPayload`, `RSA-OAEP-256`, `A256GCM`, a JOSE library among the dependencies, `bearer_auth`, a sessions URL on the ABDM gateway, `participanthcxservice`, `fetch/certs`, `participant/get/policies`, routes ending in `on_submit`, `on_check` or `on_request`, a vendor's NHCX or HCX client library, a separate gateway service the app calls. + +What it must do, checked by running it offline with the network stubbed and a test key pair for the seal: + +| Contract item (section 2) | Look at | Common gap | +| --- | --- | --- | +| `send` emits the protected header of section 3.8 | What it seals or posts | No `x-hcx-ben-abha-id`; a request correlation id that is not its own `api_call_id`; UTC timestamps; `RSA-OAEP` | +| The recipient | Who it addresses | The `payerid` instead of the `processingid` | +| The three ids back to the caller | Its return value | Only a success flag; the ids stay inside it | +| Receiving: a `202` receipt within 30 seconds on every path, `/v1/error` included | Its callback handler | `200` or an empty body; no `/v1/error`; slow work before answering | +| Handing on the header and the bundle | What it gives the app | The bundle without the header; no ProtocolResponse path | +| Dedupe on `x-hcx-api_call_id` | Its store | None | +| A record of every message | Its logs | Bodies not kept | + +The build wraps it. 7.1's `send` calls the existing client and returns the three ids. The existing callback handler, after its receipt, calls 7.3's `receive` with the envelope of section 2. Each gap is closed in the existing code, in its style (stage 7, action `extend`). The existing transport is not rewritten, and no second one is added beside it. If it cannot be made to hand on the ids or the header, record `partial` and ask the user whether to extend it further or, with their agreement, build `own` in its place. + +## 5. nhcx-adapter, only when asked + +nhcx-adapter is NHA's optional single binary that does section 3 for you (`nhcx-package/docs/02-Getting Started/10-NHCX Adapter.md`, titled "Optional"). Use it only when the user has asked for it. Then: + +1. Get it, with the user's go-ahead, from https://github.com/nha-in/nhcx-adapter/releases (the latest). Each release carries one archive per platform, `nhcx-adapter___.tar.gz` (darwin, linux, windows, freebsd; amd64, arm64, 386), holding the binary, `config.sample.json`, `serve.sh`, `stop.sh`, `update.sh` and `README.md`. Put it in a folder of the user's, not in the skill. +2. Its contract is `references/api-knowledge.md`: configuration (section 2), routes (3), the outbound envelope and answer (4, 5), the delivery your HMIS receives (6), the ledger (7), the kit endpoints (8). +3. Onboarding is sections 3.1 to 3.5 again: credentials, a key, a participant record, a public address. The adapter can generate and register the key itself (`config init`, `cert generate`, its startup checks). +4. It does not queue or retry, does not build or validate bundles, and does not verify who sent an inbound message beyond decrypting it. Its `/internal/*` routes have no authentication: bind it to loopback. + +How it maps onto section 2: `send` POSTs `{jwe_headers, fhir}` to `/fhir/out/`; the receiving end is the HMIS route the adapter posts to (`api-knowledge.md` section 6); `policies` is `/internal/policies/search`; `thread` and `fetch_missed` are its ledger and `/internal/txn/*`. diff --git a/plugins/nhcx/skills/nhcx-preauth/scripts/fetch-package.sh b/plugins/nhcx/skills/nhcx-preauth/scripts/fetch-package.sh new file mode 100755 index 000000000..efbafa50b --- /dev/null +++ b/plugins/nhcx/skills/nhcx-preauth/scripts/fetch-package.sh @@ -0,0 +1,122 @@ +#!/usr/bin/env bash +# Fetch the NHCX package and unpack it beside nhcx-build/ as nhcx-package/. +# +# scripts/fetch-package.sh [url-or-path] [target-dir] +# +# With no [url-or-path] (or "latest"), the zip is the build attached to the latest +# release of https://github.com/nha-in/nhcx-package (the nhcx-package-v.zip +# asset); its sha256 is checked against the digest GitHub records for the asset. +# Otherwise [url-or-path] is a link to the zip or a local path to it. +# [target-dir] defaults to the current directory. The zip unpacks to /nhcx-package/. +# +# Afterwards MANIFEST is checked: every file it lists must exist with the sha256 +# it records. Nothing is deleted; an existing nhcx-package/ is replaced. +set -euo pipefail + +repo="nha-in/nhcx-package" +src="${1:-latest}" +target="${2:-.}" +if [[ "$src" == "-h" || "$src" == "--help" ]]; then + echo "usage: $0 [latest|url-or-path-to-package.zip] [target-dir]" >&2 + exit 2 +fi + +download() { # + if command -v curl >/dev/null 2>&1; then + curl -fsSL -o "$2" "$1" + elif command -v wget >/dev/null 2>&1; then + wget -qO "$2" "$1" + else + echo "neither curl nor wget is available" >&2 + exit 1 + fi +} + +mkdir -p "$target" +tmp="$(mktemp -d)" +zip="$tmp/package.zip" +want_sha="" + +if [[ "$src" == "latest" ]]; then + # Ask the releases API for the latest release's zip asset and its digest. + api="https://api.github.com/repos/$repo/releases/latest" + if download "$api" "$tmp/release.json" 2>/dev/null; then + read -r tag url want_sha < <(python3 - "$tmp/release.json" <<'PY' +import json, sys +rel = json.load(open(sys.argv[1], encoding="utf-8")) +assets = [a for a in rel.get("assets", []) + if a["name"].startswith("nhcx-package") and a["name"].endswith(".zip")] +if not assets: + sys.exit(f"release {rel.get('tag_name')} has no nhcx-package*.zip asset") +a = assets[0] +digest = a.get("digest") or "" +print(rel["tag_name"], a["browser_download_url"], + digest.split(":", 1)[1] if digest.startswith("sha256:") else "") +PY + ) + else + # API unreachable or rate limited: read the tag off the releases/latest redirect + # and build the asset name from it. No digest to check in this case. + tag="$(curl -fsSIL -o /dev/null -w '%{url_effective}' "https://github.com/$repo/releases/latest")" + tag="${tag##*/}" + if [[ -z "$tag" || "$tag" == "latest" ]]; then + echo "could not resolve the latest release of $repo" >&2 + exit 1 + fi + url="https://github.com/$repo/releases/download/$tag/nhcx-package-v$tag.zip" + fi + echo "fetching $repo release $tag: $url" + download "$url" "$zip" + if [[ -n "$want_sha" ]]; then + got_sha="$(python3 -c 'import hashlib,sys; print(hashlib.sha256(open(sys.argv[1],"rb").read()).hexdigest())' "$zip")" + if [[ "$got_sha" != "$want_sha" ]]; then + echo "sha256 mismatch for $url: got $got_sha, release says $want_sha" >&2 + exit 1 + fi + fi +elif [[ -f "$src" ]]; then + cp "$src" "$zip" +else + download "$src" "$zip" +fi + +rm -rf "$target/nhcx-package" +unzip -q "$zip" -d "$target" +if [[ ! -f "$target/nhcx-package/MANIFEST" ]]; then + echo "unpacked, but $target/nhcx-package/MANIFEST is missing; is this the NHCX package?" >&2 + exit 1 +fi + +# Verify every file the MANIFEST lists. The MANIFEST is YAML; its file entries +# carry path, bytes and sha256 on separate lines. +python3 - "$target/nhcx-package" <<'PY' +import hashlib, os, re, sys +root = sys.argv[1] +text = open(os.path.join(root, "MANIFEST"), encoding="utf-8").read() +# Only the `files:` section lists a sha256 per path; the `contents:` summary above it +# lists directories. Parse entry by entry so a directory entry never borrows the next +# file's hash. +files_section = text.split("\nfiles:\n", 1)[1] if "\nfiles:\n" in text else "" +entries = [] +for chunk in re.split(r"\n\s*-\s+path:\s*", "\n" + files_section)[1:]: + path = chunk.split("\n", 1)[0].strip() + m = re.search(r"^\s+sha256:\s*([0-9a-f]{64})", chunk, re.M) + if path and m: + entries.append((path, m.group(1))) +bad = [] +for path, want in entries: + p = os.path.join(root, path) + if not os.path.isfile(p): + bad.append(f"missing {path}") + continue + got = hashlib.sha256(open(p, "rb").read()).hexdigest() + if got != want: + bad.append(f"sha256 mismatch {path}") +print(f"nhcx-package: {len(entries)} file(s) listed, {len(bad)} problem(s)") +for b in bad[:20]: + print(" " + b) +sys.exit(1 if bad else 0) +PY + +rm -rf "$tmp" +echo "ready: $target/nhcx-package (see references/material.md for the path map)" diff --git a/plugins/nhcx/skills/nhcx-preauth/stages/0-capability-check.md b/plugins/nhcx/skills/nhcx-preauth/stages/0-capability-check.md new file mode 100644 index 000000000..8186c3288 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-preauth/stages/0-capability-check.md @@ -0,0 +1,92 @@ +# Stage 0: capability check + +Purpose: before anything is planned, find out what the app already does. For this skill's own capabilities, for the foundation it stands on, and for what it needs from the use cases before it, write one verdict each with the evidence that decides it. The verdicts decide what the later stages reuse, extend, build or wait for. Nothing is built twice, and nothing is reused on faith. + +## Inputs + +- This skill's `SKILL.md`, section "Capability check": its own capabilities (what to look for, what makes each present), and its prerequisites with the check that proves each present. The skills that own the prerequisites do not need to be installed; their checks are in this skill's `SKILL.md`. +- `core/FOUNDATION.md`: the six foundation capabilities. +- `nhcx-build/capabilities.json` and `nhcx-build/0-capability.md`, if another NHCX skill already ran on this app. +- The target: the codebase (integrate), or the folder where the standalone app lives or will live. +- The pins and payer fixtures each check names, in `nhcx-package/`. If it is not beside `nhcx-build/`, fetch it now (`scripts/fetch-package.sh`); `references/material.md` names each pin's file. + +## The verdicts + +| Verdict | Means | What happens next | +| --- | --- | --- | +| `present` | Located, and its check was run and observed passing | Reuse. Stage 7 builds nothing for it. Stage 8 still runs its Validate rows; stage 9 still tests it. | +| `partial` | Located, but its check fails; or it covers some legs or branches and not others; or it was located and could not be run | Extend. Stage 7 builds the difference, in the existing code. | +| `absent` | Searched for as the skill says and not found | Build. Stage 7 builds it. | +| `unknown` | Could not be searched: no code is reachable | Planned as absent; stage 0 runs again when the code is reachable. | +| `not applicable` | The mode or the scope excludes it: 7.13 in integrate mode, a leg the user marked out | Nothing. | + +For a prerequisite, a verdict of `absent` or `unknown` is a stop: see step 5. + +Present is a claim about behaviour. Code that looks right is `partial` until its check has run. + +## Do + +### 1. Find the target + +Integrate: the codebase root, its language and framework, enough to search and to run code offline (stage 3 does the full survey). Standalone: the app folder. If it is empty and no other NHCX skill has built anything there, every capability is `absent` and this stage is short. Write which in one line. + +If `nhcx-build/capabilities.json` exists, read it. A verdict another skill recorded is a lead, not a result. If the code changed since its date (the version control log says), run its check again; otherwise carry it forward with its evidence and date. + +### 2. Locate + +For each capability in the three lists (own, foundation, prerequisites), search for the markers: NHCX paths such as `v1/preauth/submit`, resource names such as `CoverageEligibilityRequest`, workflow ids as strings, table and column names. `SKILL.md` lists them for its own capabilities; for a prerequisite, the marker is what its check names. Record every hit as `path:line`. A hit in a comment, a dead branch or a test fixture is not the capability; say so. + +Look also for the same job done another way: a pre-auth sent to a TPA portal, an eligibility check recorded from a phone call, a payment keyed in from a bank statement. That is a host capability that stages 3 and 4 may link to. The NHCX capability is still `absent`. + +### 3. Check + +For every capability located, run the check `SKILL.md` names, offline: + +- a builder: feed it the pin's own data and compare its output with the pin (canonical JSON, `created` excluded, and only the exclusions the module names); +- a reader: feed it the payer fixture and read the state it settles; +- a sender: call it with the 7.1 stub, or a stub of the app's own client, and read what it posted; +- the door: call the handler with an envelope; +- a screen: render it on a seeded state and read the text. + +Use the app's own test runner where it can host the check, else a one-off script under `nhcx-build/0-capability/`. Nothing leaves the machine. + +Where the existing code cannot be called without the network or a running service, record `partial` with `not run: `. Never `present`. + +### 4. Decide + +One verdict per capability, with where (the paths), how (the command), observed (the output, or the first lines of the diff), and the action: reuse, extend, build or wait. For `partial`, name the difference: which pin fails and at which element, which branch is missing (a PMJAY query answer on 19 but none on 131), which column is missing. + +### 5. When a prerequisite is missing + +A prerequisite is a capability another skill owns that this skill's legs cannot run without. `SKILL.md` lists them with their checks. If one is `absent` or `unknown`: + +1. Stop and tell the user which capability is missing, which skill owns it, and what this skill cannot do without it. +2. Offer the two ways on: run the owning skill first (installing it if it is not beside this one; it is the default); or continue with this skill's offline work only (builders, readers and tests against seeded rows), with the live legs marked `later` in stage 1 and the dependency written in `NOTES.md`. +3. Never build another skill's capability inside this one. It would be built without that skill's checks. + +A `partial` prerequisite does not stop the skill. Its gap goes into stage 2's risk table. + +## Write + +- `nhcx-build/capabilities.json` from `templates/capabilities.json`: one entry per capability, keyed by id, with `skill`, `module`, `verdict`, `located`, `how`, `observed`, `action`, `checked_by` and `date`. Update the entries this skill checked; leave the others. +- `nhcx-build/0-capability.md` from `templates/0-capability.md`: a section headed with this skill's name, holding the three tables (own, foundation, prerequisites) and the summary line. +- The scratch checks under `nhcx-build/0-capability/`, kept: stage 8 runs them again. +- This skill's block in `nhcx-build/STATE.md` (create the file from `templates/STATE.md` if it does not exist), with stage 0's row closed and its evidence. + +## Gate + +- [ ] Every capability in this skill's list, every foundation capability, and every prerequisite has a verdict. +- [ ] Every `present` names the command run and its observed output. None rests on reading alone. +- [ ] Every `partial` names the difference. +- [ ] Every `absent` names what was searched for, so a reader can repeat the search. +- [ ] A missing prerequisite was put to the user, and the answer is recorded. +- [ ] `capabilities.json` parses and holds this skill's entries. + +## Common mistakes + +- Marking a capability present because its endpoint name appears in the code. The pin decides. +- Rebuilding a working NHCX transport or callback door because this skill did not write it. An app that already seals, sends and receives NHCX messages keeps its own; the verdict says reuse. +- Proposing nhcx-adapter for an app that lacks a transport. The transport is then `own`; the adapter is used only when the user asks for it. +- Treating a legacy TPA workflow as the NHCX capability. It is a host capability; the NHCX one is absent. +- Checking against the live sandbox. Stage 0 is offline; the live rungs are stage 10's, and the user's. +- Carrying another skill's verdict forward after the code changed. diff --git a/plugins/nhcx/skills/nhcx-preauth/stages/1-idea.md b/plugins/nhcx/skills/nhcx-preauth/stages/1-idea.md new file mode 100644 index 000000000..b9f391316 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-preauth/stages/1-idea.md @@ -0,0 +1,80 @@ +# Stage 1: the idea + +Purpose: agree with the user what is being built before anything is designed. One page, shared by the seven skills. Wrong answers here cost the most later, so this is the one stage that always ends with a question to the user when it is first written. + +The first skill to reach this stage writes `1-idea.md` whole: the mode, the payers, the constraints, and a scope row for every step of the flow, each naming the skill that owns it. A later skill reads the page, confirms that the mode and the payers still hold, and marks its own rows. It asks the user only when it would change a row or an answer. + +## Inputs + +- This skill's section of `nhcx-build/0-capability.md`: what the app already does. A leg found present is still in scope: it is validated and tested, not rebuilt. Say so in the scope table's reason column. A prerequisite the user chose to wait for makes this skill's live legs `later`. +- `flow/FLOW.md`, whole. The build walks this path; the scope table below marks its steps in, later or out, and nothing else. `flow/flow.json` names the skills of each step in `skills`. +- What the user said. If they pasted a brief, quote it in the artefact. +- `references/flow-knowledge.md` sections 1, 3 and 6: the legs, the two payer kinds, the use-case catalogue. Read them so the scope table below uses the catalogue's codes. + +## Do + +Decide five things, in this order. A later skill confirms the first two and the fourth, and does the third for its own rows. + +### 1. Mode + +| Signal | Mode | +| --- | --- | +| A codebase, a database, a running system is named | `integrate` | +| "from scratch", "standalone", "a claims app", no existing system | `standalone` | +| Unclear | Ask. Do not guess; the two modes diverge at stage 3. | + +### 2. Payers + +Which participant codes the software will talk to, and which kind each is: + +| Payer | Participant code | Kind | Query mode | +| --- | --- | --- | --- | +| PMJAY (SHA Himachal Pradesh, sandbox) | `1518@hcx` | scheme | `resubmit` | +| A generic sandbox payer you can drive, for testing | from the participant registry | generic | `communication` | +| Any other insurer | from the registry | generic unless told otherwise | `communication` | + +Both kinds are in scope by default. A build that targets only one still keeps the payer adapter switch (module 7.11), because the second is one config line away. + +### 3. Scope of legs + +Copy the steps of `flow/flow.json` (F1 to F13 with their branches) into a scope table, with the skill that owns each (`skills`), and mark each `in`, `later` or `out`, with a reason; add the catalogue code from `flow-knowledge.md` section 6 beside each. The default scope for a first release is every hospital-side leg in `flow-knowledge.md` section 1. Cutting a leg is the user's call; propose it, do not decide it. Legs that are commonly `later`: predetermination, status enquiry (PMJAY refuses it), release of a shortfall (out of reach on the sandbox). + +A later skill changes only its own rows. + +### 4. Constraints + +Ask the codebase, not the user, where you can: + +- Language and framework (integrate: whatever the HMIS uses; standalone: Python standard library unless the user names another, because the module files' pseudo code maps onto it directly). +- The transport (`references/transport-knowledge.md` section 1): `existing` when stage 0 found the app already speaks NHCX; else `own`, built into the app from NHA's protocol; `adapter` (nhcx-adapter) only when the user has asked for it, their words quoted. Never propose the adapter. +- The inbound path. For `own`: a public HTTPS domain in India, registered as the participant's `endpoint_url` and reachable from the exchange. For `existing`: the app's own callback. For `adapter`: whether the app can receive the adapter's POST; if not, polling the adapter's ledger is the only inbound path. Write it down now. +- What onboarding needs from the user: the ABDM sandbox client id and secret (Milestone 1), the facility's HFR id, and a participant record carrying the build's certificate and callback address. +- Document storage: blob, filesystem, object store. +- Whether a background worker exists. Without one, polls happen on the request path. +- Anything the user forbids: new dependencies, schema changes to existing tables, a build step. + +### 5. Definition of done + +Write the compliance points from `core/LADDER.md` as they apply to this build, and the highest rung of the test pyramid the user wants climbed before handover (`references/testing-knowledge.md` section 1). The offline rung is never optional. + +## Write + +`nhcx-build/1-idea.md` from `templates/1-idea.md`. Keep the headings. Under two pages. A later skill edits only its scope rows and adds a line under "Agreed". + +## Gate + +- [ ] Mode is `integrate` or `standalone`, and the reason is one sentence. +- [ ] Every payer has a participant code and a query mode. +- [ ] The scope table has every step of the flow and every catalogue row, each with its skill, marked in, later or out. +- [ ] Constraints name the language, the transport (existing, own, or nhcx-adapter because the user asked for it), the inbound path and the document store. +- [ ] Definition of done names the target rung. +- [ ] The user has read the page and agreed, or a written brief stands in for the user. A later skill that changed nothing records that it confirmed the page. + +Record the gate in the Shared block of `nhcx-build/STATE.md`. + +## Common mistakes + +- Choosing `standalone` because the HMIS is unfamiliar. Unfamiliar is what stage 3 is for. +- Leaving PMJAY out because the user only named an insurer. PMJAY is the payer that refuses most; a build that handles it handles the rest. +- Dropping a leg from scope because stage 0 found it present. It stays in: present capabilities are validated and tested. +- Writing design here. Tables, screens and modules belong to stages 4 to 6. diff --git a/plugins/nhcx/skills/nhcx-preauth/stages/10-run-tests.md b/plugins/nhcx/skills/nhcx-preauth/stages/10-run-tests.md new file mode 100644 index 000000000..e7e5d8d32 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-preauth/stages/10-run-tests.md @@ -0,0 +1,59 @@ +# Stage 10: run the tests + +Purpose: climb the pyramid as far as the user asked in stage 1, for this skill's rows, and record every rung honestly. Rung 1 you run yourself. Rungs 2 to 4 need services or live payers, and only the user starts those. + +## Inputs + +- `nhcx-build/1-idea.md` (the target rung), `nhcx-build/9-tests.md` (the run command, this skill's rows) +- This skill's `SKILL.md`: its stage 10 row (which matrix rows each rung walks) +- `references/testing-knowledge.md` sections 1, 5 and 6 +- `references/errors-and-debugging.md` sections 4 to 8 (reading the ledger, sandbox pace) + +## The rungs + +| Rung | What | Who starts it | Record | +| --- | --- | --- | --- | +| 1 Offline | The suite from stage 9, against the pins and fixtures, no network | you | the full output | +| 2 Validator | The HL7 FHIR validator on every bundle this skill builds, run as `references/fhir-knowledge.md` section 11 says | you, if Java and the validator are installed | one table: bundle, errors, warnings | +| 3 Generic payer | The transport on the sandbox (the app's own, or nhcx-adapter when the user chose it) and a generic sandbox payer whose desk you can drive; this skill's legs, every query as a CommunicationRequest, payment from its desk | the user | the ledger thread per leg, the state address after each | +| 4 PMJAY sandbox | SHA Himachal Pradesh, `1518@hcx`; sweep live pre-auths first; one request at a time per case, 30 seconds between; decisions on the payer service desk | the user | the ledger, the archive folder, every refusal verbatim | + +## Do + +### Rung 1 + +Run the command from `nhcx-build/9-tests.md`: the whole suite, not only this skill's tests, because a skill that extended a shared module can break another skill's test. Save the whole output to `nhcx-build/10-test-run/-rung1.log`. In `integrate` mode also run the HMIS's own suite and save it. A failure goes back to stage 7 (the module) or stage 9 (the test); record the fix and the re-run. Do not edit a test to make it pass unless the test was wrong, and say so. + +### Rung 2 + +If the validator runs, validate every bundle this skill's tests built (write them to a folder from the tests). Warnings are advice; the sandbox accepted every pin as it stands. Errors are findings. If it does not run, write `not run` and why. + +### Rungs 3 and 4 + +Prepare, do not run: + +1. The commands the user runs: the HMIS with its public callback (`own` or `existing`), nhcx-adapter with its filled config only when the user chose it, and the payer (rung 3). For `own`, the sandbox's dummy payer proves the loop first (`references/transport-knowledge.md` section 3.11). Write them into this skill's section of `nhcx-build/10-test-run.md` under "Runbook". +2. The driver: a script or a spec that walks this skill's matrix rows through the JSON state address, waiting on the case's own state and never on a fixed sleep, logging every verdict the payer gives. The earlier legs a row needs (an eligible case, an approved pre-auth) are reached by the earlier skills' drivers or through the app's own screens. +3. The sweep for rung 4: cancel or let expire every live pre-auth for the beneficiaries the tests use (PAYR-1238 otherwise). +4. Then stop and ask the user to start the services. When they have, run the driver, save its log, and package the run's bundles by correlation id from the per-case archive (or the adapter's ledger, when it is the transport). + +While a live run is going: one request at a time per case; wait about 30 seconds after a decision; on "Active instance found" wait and resend up to three times; on a refusal read the ledger thread before touching the code. + +## Write + +This skill's section of `nhcx-build/10-test-run.md` from `templates/10-test-run.md`: per rung, `passed`, `failed`, `not run` with the reason, the log path, and the findings (each a line: what, where, the PAYR or rule, the fix or the open question). The raw logs under `nhcx-build/10-test-run/`, named for the skill. + +## Gate + +- [ ] This skill's rung 1 log exists and shows every test in the suite passing, or the failures are listed as findings with a stage to return to. +- [ ] In `integrate` mode the HMIS's own suite log exists and passes. +- [ ] Rung 2 has a table or `not run` with a reason. +- [ ] Rungs 3 and 4 have a runbook and a driver for this skill's rows, and either a log or `not run: user has not started the services`. +- [ ] No rung is marked passed without a log. + +## Common mistakes + +- Starting a service yourself: the app's public callback, or nhcx-adapter. Only the user does. +- Running only this skill's tests at rung 1. A shared module may have broken another skill's. +- Sleeping a fixed time in a driver. Wait on the state address. +- Reading a refusal as a code bug before reading the ledger thread. Half of them are scheme rules (flow-knowledge section 5). diff --git a/plugins/nhcx/skills/nhcx-preauth/stages/11-build-report.md b/plugins/nhcx/skills/nhcx-preauth/stages/11-build-report.md new file mode 100644 index 000000000..4ea8a0806 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-preauth/stages/11-build-report.md @@ -0,0 +1,64 @@ +# Stage 11: the report + +Purpose: one document a stranger can pick up to know what was built, what was found already there, what was proven, what was not, and what to do next. Written from the artefacts in `nhcx-build/`, not from memory. Its value is its honesty. + +`11-report.md` has a summary across the skills at the top and one section per skill below it. This skill writes its section and updates its row of the summary. + +## Inputs + +- Everything in `nhcx-build/`, `STATE.md` first, `NOTES.md` last +- This skill's sections of `0-capability.md`, `8-validation.md` and `10-test-run.md` + +## Do + +### 1. Read STATE.md + +Every gate row in this skill's block, and the foundation rows it built, with their evidence. A gate without evidence is reported as open, whatever you remember. + +### 2. Write this skill's section + +From `templates/11-report.md`, in this order: + +| Section | Holds | +| --- | --- | +| Capabilities | Every capability in this skill's section of `0-capability.md`: its verdict at stage 0, what was done (reused, extended, built), and its evidence after stage 8 | +| What was built | Each module part this skill built or extended, with its files and its record (`7-modules/7.N.md`) | +| Compliance | The seven points from `core/LADDER.md` for this skill's legs, each with the evidence path (the pin comparisons, the door tests, the screen tests, the rung logs) | +| The test pyramid | Per rung: passed, failed, not run, the log | +| Findings | Every failure from stages 8 and 10 with its resolution or its open state | +| Gaps | This skill's entries in `NOTES.md` folded in: what the skills did not say, what the docs did not say, what the sandbox did that no document states | +| Exceptions | Every accepted exception from stage 8 and the user's agreement | +| Runbook | How to start it, how to run the suite, how to run rungs 3 and 4, what to sweep first, where the archive and the ledger are | +| Next | The `later` legs from stage 1, the open gates, the rungs not climbed, and the skill to run next in the order `core/LADDER.md` gives | + +Then update this skill's row in the summary table: stages closed, rung reached, what it reused, extended and built, what is open. Mode, payers and "today a user can" are for the whole build; bring them up to date. + +### 3. Check the report against the rules + +- Every claim of "passes" has a log or a record path beside it. +- Every rung not run says so. +- Every capability reported as reused has its stage 8 evidence, not only stage 0's. +- No em dashes, short sentences, tables for facts. +- A stranger with this report and the target project could resume at the first open gate. + +## Write + +This skill's section of `nhcx-build/11-report.md`, and its summary row. Update `STATE.md` with the final gate. + +## Gate + +- [ ] Every section in the template is present in this skill's section. +- [ ] Every capability in this skill's section of `0-capability.md` appears under Capabilities. +- [ ] Every module part this skill touched appears in "What was built" or, if reused, under Capabilities. +- [ ] Every compliance point names evidence. +- [ ] The pyramid table matches this skill's section of `10-test-run.md`. +- [ ] This skill's entries in `NOTES.md` are folded into "Gaps" in full. +- [ ] The runbook has the start commands, the test command and the sweep. +- [ ] The summary table has this skill's row. + +## Common mistakes + +- Reporting the rung the user asked for as reached because the offline rung passed. +- Reporting a reused capability as working on the strength of stage 0 alone. +- Dropping a finding that was fixed. Fixed findings are the most useful part of the report for the next build. +- Writing the report before stage 10's logs exist. diff --git a/plugins/nhcx/skills/nhcx-preauth/stages/2-planning.md b/plugins/nhcx/skills/nhcx-preauth/stages/2-planning.md new file mode 100644 index 000000000..06c405cdc --- /dev/null +++ b/plugins/nhcx/skills/nhcx-preauth/stages/2-planning.md @@ -0,0 +1,67 @@ +# Stage 2: planning + +Purpose: turn the idea and the capability check into this skill's schedule of gates, and add its block to the ledger every later stage writes to. This is bookkeeping, and it is short. + +## Inputs + +- `nhcx-build/1-idea.md` +- This skill's section of `nhcx-build/0-capability.md`: the verdict of every capability it owns or stands on +- `core/LADDER.md`, "The ladder"; this skill's `SKILL.md`, "The ladder, for this skill" +- `references/testing-knowledge.md` section 1 (the pyramid) and section 3 (the matrix), so the acceptance tests below are the matrix's rows and not invented ones + +## Do + +### 1. Size each stage + +For every stage 3 to 11, write one row for this skill: what it produces for this build, how big it is (small, medium, large), and what proves it done. "What proves it done" is the stage's gate, restated for this skill. + +For stage 7, list the modules this skill's `SKILL.md` names and the foundation modules, each with its verdict from stage 0 turned into an action: + +| Verdict | Action in stage 7 | +| --- | --- | +| `present` | reuse: nothing built; validated in stage 8, tested in stage 9 | +| `partial` | extend: the difference, in the existing code | +| `absent`, `unknown` | build | +| `not applicable` | nothing | + +Module 7.13 depends on the mode: + +| Module | integrate | standalone | +| --- | --- | --- | +| 7.1 to 7.12 | yes | yes | +| 7.13 standalone shell | no | yes | + +Module 7.12 (screens) is smaller in `integrate` mode when the HMIS already has patients, admissions and documents; the plan says which existing screens gain a panel and which are new. + +### 2. Order and dependencies + +The ladder is sequential by stage. Inside stage 7, foundation modules come first, then this skill's modules in the order of `stages/7-write-code/README.md`; the plan may not reorder them, because each module's validation assumes the ones before it exist. + +### 3. Risks + +Copy into a risk table the rules from `references/flow-knowledge.md` section 5 that touch this skill's legs; its `SKILL.md` names them in its stage 2 row. Each rule is a way the build fails live even when the offline tests pass. When this skill builds or extends a foundation module, add the foundation's rules too: acknowledge or lose the thread; one message is taken once (dedupe on `x-hcx-api_call_id`). Add every `partial` prerequisite from stage 0, and the build's own risks: a missing HPIN on the practitioner table, no inbound route to the HMIS, a plan master too large for the database column, a callback behind auth middleware. + +### 4. What the user must do + +List every point where the ladder stops for the user: agreeing stage 1, running an owning skill first when a prerequisite is missing, supplying participant credentials (the ABDM client id and secret), registering the participant's certificate and callback address, starting the services for stage 10 rungs 3 and 4 (the app's public callback, or nhcx-adapter when the user chose it), sweeping live pre-auths before a PMJAY run. + +## Write + +- This skill's section of `nhcx-build/2-planning.md`, from `templates/2-planning.md`. +- This skill's block in `nhcx-build/STATE.md` (created at stage 0 from `templates/STATE.md`), with a row per stage and a row per module part, each module row carrying its action. +- `nhcx-build/NOTES.md`, empty but for its heading, if it does not exist. + +## Gate + +- [ ] Every stage 3 to 11 has a row with a size and a proof, for this skill. +- [ ] Every module this skill touches, and every foundation module, has its verdict and its action; 7.13 is marked by mode. +- [ ] The risk table holds every rule this skill's `SKILL.md` names for stage 2, and the foundation's rules when this skill builds or extends a foundation module. +- [ ] The user-action list names the credentials and the service starts. +- [ ] STATE.md has this skill's block with a row per stage and per module part. + +## Common mistakes + +- Estimating in days. Estimate in size; the user turns size into time. +- Planning to skip stage 8 or 9 "for the first pass". They are what makes the report true. +- Planning to rebuild a capability stage 0 found present. +- Reordering modules so screens come first. Screens derive from messages; without readers there is nothing to derive from. diff --git a/plugins/nhcx/skills/nhcx-preauth/stages/3-discovery.md b/plugins/nhcx/skills/nhcx-preauth/stages/3-discovery.md new file mode 100644 index 000000000..9feb26eca --- /dev/null +++ b/plugins/nhcx/skills/nhcx-preauth/stages/3-discovery.md @@ -0,0 +1,97 @@ +# Stage 3: discovery + +Purpose: find the surface you will build on. In `integrate` mode that is the HMIS; in `standalone` mode it is the runtime, the storage and the deployment target the user has chosen. Every answer names the file, table or endpoint that proves it. An answer without proof is a gap. + +`3-discovery.md` is shared by the seven skills: one row per concern, each naming the skill that answered it. This skill answers the rows its `SKILL.md` lists under "Host facts", and the framework and runtime rows if no skill has. A row an earlier skill answered with proof is reused; check it again only if the code changed since. + +Stage 0 looked for NHCX capabilities. This stage looks at the host: where patients, admissions, doctors, documents and bills live. + +## Inputs + +- `nhcx-build/1-idea.md`, `nhcx-build/2-planning.md`, this skill's section of `nhcx-build/0-capability.md` +- This skill's `SKILL.md`, "Host facts" +- The target codebase (integrate) or the chosen runtime (standalone) +- `stages/7-write-code/7.2-storage.md` (the claim tables) and `stages/7-write-code/7.13-standalone-shell.md` (patient, encounter, practitioner, document), as the shape to compare against + +## Do + +Answer in writing every question below that this skill's host facts name, plus the framework and runtime questions when they are not yet answered. Reading only; change nothing. + +### Framework and runtime + +| Question | Why it matters | +| --- | --- | +| Language, web framework, ORM, database engine, migration tool | Where a new table goes and how it is created | +| How configuration is read (env, file, database) | Where the transport's settings live: the participant code, and the client id and secret and the private key (`own`), or the adapter URL and key (`adapter`) | +| How the app exposes an HTTP endpoint an outside process can POST to; which auth middleware must be exempted | The callback door, module 7.3 | +| Background worker or scheduler, or none | Whether polls run on the request path or in a worker | +| How the app serves a page and what the screen conventions are | Module 7.12 must match them | +| How tests are run and where they live | Stage 9 must match them | + +### Patients + +| Question | Why it matters | +| --- | --- | +| The patient table, its primary key, the unique identifier (MRN) | `claim.patient_id` | +| Where name, gender, date of birth, phone, ABHA number live | The Patient resource in every bundle | +| Where a scheme member id (PMJAY id) and a policy code can be stored, per patient or per visit | The Coverage resource; the policy search result | + +### Admissions and encounters + +| Question | Why it matters | +| --- | --- | +| The inpatient encounter table: admission time, discharge time, ward or bed, admitting doctor, status | `billablePeriod`, `ONS/ADDD`, the care team | +| How discharge is recorded, and whether it can carry a mode (normal, LAMA, DAMA, death) and a stage (before, during, after surgery) | `DIS` and `DSDE` on the claim; the LM100 collapse | +| Diagnoses: SNOMED, ICD-10 or free text | The payer needs ICD-10 with a display | +| Procedures or surgeries, and whether a surgery time is recorded | `ONS/PSP` | + +### Billing + +| Question | Why it matters | +| --- | --- | +| Billing lines: code, quantity, unit price, net; which charge master | Lines are quoted from the payer's plan, not the HMIS master, but the two must be reconcilable | +| Whether a line can be tagged with a payer package code and a category | `claim_line` | +| Invoices and receipts: where a settlement amount and a UTR go | Payment notices, module 7.10 | + +### Documents + +| Question | Why it matters | +| --- | --- | +| Where PDFs and images live (blob column, filesystem, object store) | `valueAttachment` needs the bytes and the content type | +| Whether a file can be tagged with a payer document code and a stage (pre-auth or claim) | The plan's requirement codes; never `ODN` for a file that was asked for by name | +| Accepted content types | The scheme takes pdf, jpg, jpeg, png only (PAYR-1008) | + +### Doctors + +| Question | Why it matters | +| --- | --- | +| The practitioner table; an HPR id (HPIN); a licence number; a qualification string | PMJAY refuses a pre-auth without an HPIN typed identifier (PAYR-1083) | + +### Facility + +| Question | Why it matters | +| --- | --- | +| The facility's HFR id, name, phone; its NHCX participant code | The provider Organization; the sender code | + +### Standalone mode + +The same questions, answered for the runtime the user chose. Where the answer is "nothing exists yet", write what module 7.13 will create: `patient`, `encounter`, `practitioner`, `document`, `settings`. A standalone app still has to hold every fact the questions ask for; it simply has to capture it itself. + +## Write + +`nhcx-build/3-discovery.md` from `templates/3-discovery.md`: one table, concern by concern, columns `Concern | Where it lives (proof) | Gap | Answered by`. A gap is what stage 4 fills. Add rows; do not rewrite another skill's rows. + +## Gate + +- [ ] Every host fact this skill's `SKILL.md` names has a row, and so does every framework and runtime question. +- [ ] Every row that is not a gap names a file path, a table, or an endpoint. +- [ ] When this skill builds or extends the callback door, the callback route is answered: which URL, which middleware to exempt, or "no inbound route, poll only". +- [ ] When this skill's bundles carry a Practitioner, the HPIN question is answered; if the practitioner table has no HPR id, the gap says so. +- [ ] When this skill attaches documents, the document store is answered with content-type handling. + +## Common mistakes + +- Answering from the framework's documentation instead of the codebase. The proof column is the codebase. +- Skipping the discharge-mode question. A death claim without `DTM` is refused (PAYR-1096); the HMIS must be able to say the patient died and when. +- Treating "no background worker" as a blocker. Without one, polls run on the request path; it is a design input, not a stop. +- Answering every concern for every skill. Answer the ones this skill needs; the next skill adds its own. diff --git a/plugins/nhcx/skills/nhcx-preauth/stages/4-flow-and-data-mapping.md b/plugins/nhcx/skills/nhcx-preauth/stages/4-flow-and-data-mapping.md new file mode 100644 index 000000000..bf51c7991 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-preauth/stages/4-flow-and-data-mapping.md @@ -0,0 +1,92 @@ +# Stage 4: flow and data mapping + +Purpose: decide where every fact the exchange needs comes from and where every fact the exchange returns goes, leg by leg. This is the design stage with the most rows; get it right and stages 6 and 7 are transcription. + +Two parts of this stage belong to the episode, not to one skill: the flow table (section 1) and the home of every table (section 2), with the matching order (section 4). The first skill to run this stage writes them whole, so every later skill builds on one design; a later skill checks them and adds only what its gaps need. The field mapping (section 3) is this skill's own bundles only. + +## Inputs + +- `nhcx-build/1-idea.md` (scope), `nhcx-build/3-discovery.md` (the surface and its gaps), this skill's section of `nhcx-build/0-capability.md` (what exists already) +- This skill's `SKILL.md`: its steps, legs, bundles and tables +- `flow/FLOW.md` and `flow/flow.json`: the steps this build implements. They are copied, not redesigned. +- `references/flow-knowledge.md` sections 1, 2, 4 and 5 +- `references/transport-knowledge.md` section 2 (what a send returns, what arrives at the door) +- `references/fhir-knowledge.md` sections 3 to 10 (what each bundle needs); `fhir/FHIR.md` for the exact elements, as the builders' data dictionaries name them +- `stages/7-write-code/7.2-storage.md`: the claim tables and the columns each must hold + +## Do + +### 1. The flow, for this build + +The first skill copies every step of `flow/flow.json` into the flow table, in order, with its id and its skills, and adds two columns for this build: the HMIS event it hangs off (admission, discharge, a desk action) and the mark from stage 1 (`in`, `later`, `out`). The steps, their order, their tabs, their guards and their action labels are the flow's; this build adds where each fact comes from, nothing else. Then note the payer branches as the flow has them (F9b, F11, F12: `19`/`131`/`161` resubmits against a Communication reply; `17` against an echoed id). The stage and sub-stage vocabulary is copied as is; do not rename it. + +Write the step ids into `mapping.json` under `flow.steps` and the eight tabs, in order and with their labels, under `flow.tabs`. + +A later skill checks its own steps' rows and fills their HMIS event where the first skill left it open. + +### 2. The episode tables + +The first skill gives every table below a home, not only its own. The home is one decision for the episode (sidecar tables, or columns on the HMIS's tables), and a skill that chose differently later would split the design. It writes the columns each table must hold, and the legs' columns under `legs`. Later skills read the homes and add only the columns their gaps need. + +For each table below, decide one of three homes and write it down: + +| Home | When | +| --- | --- | +| A new sidecar table keyed on the HMIS's own ids | Default. Keeps the HMIS schema untouched and the integration removable. | +| Columns added to an existing HMIS table | Only for a scalar the HMIS already half-holds (a member id on the visit, an HPIN on the doctor) | +| An existing table used as is (`existing`) | Only when it already holds every column named below. This is the home of a capability stage 0 found present: record its real name and its columns, and a gap for each column it lacks | + +| Table | Why it exists | Must hold | +| --- | --- | --- | +| `claim` | The episode: beneficiary, policy, payer, eligibility verdict, link to the admission, pre-auth draft, stage and sub-stage | claim number, member id, policy code, payer participant code, patient and encounter keys, `txn_id`, `correlation_id`, `stage`, `sub_stage` | +| `claim_plan`, `claim_plan_benefit`, `claim_plan_form` | The payer's package master, flattened; one per facility and policy, copied onto later episodes | packages with rate, kind, conditions, extras (tiers, implants), document requirements; questionnaires by url | +| `claim_auth`, `claim_auth_item`, `claim_auth_requirement` | The auth-requirements ruling on the quoted set | per line: authorised, excluded; per requirement: kind (document or form), code, url, stage | +| `claim_line` | What is quoted: procedures, implants, ward tiers with a parent procedure | code, kind, quantity, unit price, amount, parent code | +| `claim_form_answer` | Answers to the plan's questionnaires | url, linkId, answer, stage | +| `claim_preauth` | The pre-auth leg, one row rewritten each round (12, 19, 13, 131) | status, `txn_id`, `correlation_id`, `thread_correlation_id`, `api_call_id`, `preauth_ref`, `submission_kind`, `workflow_id`, request and response json, cancel fields | +| `claim_submission` | The claim leg plus the discharge | discharge mode, stage, dates; the same exchange columns as the pre-auth | +| `claim_query` | Every CommunicationRequest or Communication from the payer, classified | `correlation_id` (unique), request id, kind, reason code, status, reply fields | +| `claim_payment`, `claim_payment_detail` | Payment notices, matched by claim number, deduped by correlation id | amount, UTR, payment status, ack fields | +| `claim_enquiry` | Status, reprocess and release Tasks, one row per ask | kind, `correlation_id`, answer | +| `claim_predetermination` | A quote, one row per ask | as a pre-auth, without state effects | +| `claim_document` | Attachments with the payer's code, category and stage | bytes or a pointer, content type, code, stage | +| `claim_diagnosis`, `claim_care_team`, `claim_item` | ICD-10 codes, doctors, non-package items | as named | + +The rule that never bends: every leg row holds `txn_id`, `correlation_id` and `api_call_id` from the transport's answer, and `thread_correlation_id` separately, because a send refused at the door must not lose the thread the payer last answered on. + +### 3. Field mapping, per bundle + +For each bundle this skill sends (its `SKILL.md` lists them; `fhir-knowledge.md` sections 3, 4, 5, 7, 9, 10), one table: `FHIR element | Source (table.column or constant or payer answer) | Transform | Gap`. Do not fill values; name sources. The elements that are always mapped from a payer answer and never from the HMIS: package codes and rates (the plan), document codes and questionnaire urls (the plan or the ruling), `preAuthRef` (the ClaimResponse), the payer's own case number. + +For each bundle this skill reads (sections 6, 8, 9, 10 and the coverage answer in section 3), one table: `FHIR element | Destination | Rule`. The status rule for a ClaimResponse is `verdict_status`, copied verbatim; never read `outcome` alone. + +Where stage 0 found a builder or reader present, map what it does today, and name each element where it differs from the pin as a gap. + +### 4. Inbound matching + +Written once, by the first skill. Write the matching order as a numbered list: `x-hcx-correlation_id` against every leg table; then the claim number inside the bundle; then unmatched, archived, 2xx returned. Write the dedupe key: `x-hcx-api_call_id`. Write the archive path: `//NNN--.json` plus `transactions.txt`. A later skill adds its leg tables to the correlation order. + +## Write + +- `nhcx-build/4-flow-data-mapping.md` from `templates/4-flow-data-mapping.md`. The first skill writes the flow table, the table homes and the matching order at the top; each skill writes a section headed with its name holding its field mappings. +- `nhcx-build/mapping.json` in the shape of `templates/mapping.json`. The first skill writes `flow`, `episode`, `tables`, `legs` and `inbound` whole; every skill adds its bundles under `bundles`, each entry with `"skill"`. Stage 6 reads it. + +## Gate + +- [ ] The flow table has every step of `flow/flow.json`, in its order, with its id, its skills and an in/later/out mark; `mapping.json` `flow.steps` lists every id and `flow.tabs` the eight tabs verbatim. +- [ ] Every table above has a home in `mapping.json` under `tables`. +- [ ] Every leg table's columns in `mapping.json` include `txn_id`, `correlation_id`, `api_call_id` and `thread_correlation_id`. +- [ ] `mapping.json` `episode.columns` includes `stage` and `sub_stage`. +- [ ] Every bundle this skill sends has a source table; every element with no source is listed as a gap, not omitted. +- [ ] Where this skill's bundles carry a Practitioner, the HPIN element's source is named (or its gap is). +- [ ] Every capability stage 0 found present is mapped to what exists, with its differences from the pin as gaps. +- [ ] The matching order, the dedupe key and the archive path are written. + +## Common mistakes + +- Redesigning the flow: merging tabs, adding a "status" step, moving the discharge out of the claim tab. The flow is the reference flow; copy it. +- Giving homes only to this skill's tables when it is the first to run the stage. The next skill would choose differently. +- Mapping package rates to the HMIS charge master. Prices come from the plan; the master is for reconciliation. +- One `correlation_id` column on the episode instead of one per leg. Each leg is its own thread. +- Forgetting `thread_correlation_id`. It is the difference between a recoverable door refusal and a dead case. +- Mapping `Patient` demographics on the coverage request. Only the member id goes out; the payer returns the rest. diff --git a/plugins/nhcx/skills/nhcx-preauth/stages/5-screen-plan.md b/plugins/nhcx/skills/nhcx-preauth/stages/5-screen-plan.md new file mode 100644 index 000000000..9ec0d8bc2 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-preauth/stages/5-screen-plan.md @@ -0,0 +1,74 @@ +# Stage 5: screen plan + +Purpose: decide the screens, and for every value on every screen, the received message it is derived from. The two honesty rules are the whole point of this stage, and a reviewer tests them before anything else. + +The case screen is the episode's (`foundation.screens`): its eight tabs, the status line and actions, the JSON state address and the cases list. The first skill to run this stage lays them out whole, every tab present with its opening condition. Each skill then plans the values and actions of its own tabs and screens, which its `SKILL.md` lists. + +## Inputs + +- `nhcx-build/1-idea.md`, `nhcx-build/3-discovery.md` (screen conventions), `nhcx-build/4-flow-data-mapping.md` +- This skill's `SKILL.md`: its tabs, its screens, its next actions +- `flow/FLOW.md` ("The shape", "The status line and the actions", every step's Screen line) and `flow/flow.json`: the screens are put on these steps, not invented. +- `references/flow-knowledge.md` section 4 (stage, sub-stage, next actions) +- `ui/UI-GUIDE.md`: the screens, a layout per screen, where every value comes from, the state words. Read it whole before planning. +- `nhcx-package/docs/03-Building a Provider/09-UI Guide.md` (the published source of the guide) + +## The two rules + +1. No screen shows a decision the exchange has not sent. Every state on every screen is derived from a stored message. A case with a request sent and no answer back reads as waiting, never approved, never rejected. That case exists only because module 7.3 kept a record of what was sent, so the screen must be able to render a leg with a request and no response. +2. Nothing the exchange already knows is typed. Payer names, policies, balances, package rates, the payer's own wording, `preAuthRef`, the approved amount, the UTR are rendered from the message that carried them. A package rate is never an editable field. + +## Do + +### 1. The screen list + +The case screen carries the eight tabs of `flow.json` `tabs`, in that order, with those labels, opening under those conditions. The status line and the action list above the tabs use the labels of `flow.json` `next_actions` verbatim. Then, minimum, once every skill has run: + +| Screen | Who | Shows | Derived from | Planned by | +| --- | --- | --- | --- | --- | +| Cases list | billing clerk | every episode, its stage and sub-stage, what it waits for | `claim.stage`, `sub_stage`, `next_actions` | the first skill | +| Case | everyone | the timeline of legs, the payer's answer verbatim, the actions open now | every leg row and its archived messages | the first skill; each skill its tabs | +| Inbox | desk | payer messages routed by kind: query, notification, note | `claim_query` | `nhcx-communication` | +| Payments | accounts | notices, deductions, UTR, reconciliation | `claim_payment`, `claim_payment_detail` | `nhcx-payment` | +| Find and cover | registration clerk | policy search, eligibility verdict, register or link | the policy search answer and the `on_check` bundle | `nhcx-coverage` | +| Plan | doctor | specialty, package, add-ons, tiers, the documents and forms the plan wants | `claim_plan_*`, `claim_auth_*` | `nhcx-insurance`, with the ruling from `nhcx-preauth` | + +`integrate` mode adds a panel to the HMIS's own admission screen linking the admission to its episode. `standalone` mode adds the capture screens module 7.13 describes (patient, admission, discharge, documents, settings). + +Where stage 0 found a screen present, plan what it shows today against the rules, and list every value that breaks one as a gap. + +### 2. Per screen, per value + +For every value on this skill's screens, one row: `Value | Message and element | Empty state`. The empty state is what the screen shows before the message arrives (for a decision: "waiting"; for a rate: nothing, the field does not exist yet). A value whose source is "the user types it" is allowed only for things the exchange cannot know: the discharge mode and dates, the desk's reply to a query, the documents, the questionnaire answers, the chosen lines. + +### 3. Actions + +Every action is one step of `flow.json` and carries its id in `step`. For every action this skill's screens offer, the leg it sends, the sub-stage that must hold for it to be offered, and the sub-stage it moves to. Take the offered-when rules from `next_actions` in flow-knowledge section 4: an unanswered query always leads; the reply box is offered only to a `resubmit` payer; after a rejection the pre-auth offers a fresh 12, not 121. + +### 4. Addresses and conventions + +Write the route for each screen in the HMIS's own style (from stage 3). The state of a case must also be readable as JSON at one address, because stage 10 drives the screens through it (for example `GET /claims//state`). Each skill adds its legs to what the address returns. + +## Write + +- `nhcx-build/5-screen-plan.md` from `templates/5-screen-plan.md`: the shell at the top (first skill), then a section per skill. +- `nhcx-build/screens.json` in the shape of `templates/screens.json`: the first skill writes `rules`, `tabs`, `state_address`, the cases list and the case screen; each skill adds its screens and actions. + +## Gate + +- [ ] `screens.json` `tabs` lists the eight tabs of `flow.json` in order with the same keys and labels. +- [ ] Every user-driven step this skill owns (its steps among F1 to F13, except F9a, F12 and F12b, which the payer starts) appears as an action with its `step` id, and every action's `label` is one of `flow.json` `next_actions` or the step's own button. +- [ ] `screens.json` holds the cases list, the case screen, and every screen this skill plans, each with a route (plus 7.13's in standalone mode). +- [ ] Every screen this skill plans has a `values` list and every value names a message element or is marked `typed` with a reason from the allowed list. +- [ ] Every decision-bearing value has an empty state of waiting. +- [ ] No `values` entry marks a rate, a payer name, a `preAuthRef` or a UTR as typed. +- [ ] Every action names its leg, its offered-when sub-stage and its resulting sub-stage. +- [ ] A JSON state address exists for a case. + +## Common mistakes + +- A status dropdown on the case. Status is derived; there is no dropdown. +- Showing `preAuthRef` from the pre-auth's own claim number. It comes from the ClaimResponse. +- Designing the desk's reply box for a `communication` payer on the leg. It belongs on the inbox item. +- Laying out only this skill's tab when it is the first to run the stage. The shell has all eight. +- Screens that need JavaScript. Forms post and the page re-renders; that is enough. diff --git a/plugins/nhcx/skills/nhcx-preauth/stages/6-code-plan.md b/plugins/nhcx/skills/nhcx-preauth/stages/6-code-plan.md new file mode 100644 index 000000000..2167000f1 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-preauth/stages/6-code-plan.md @@ -0,0 +1,68 @@ +# Stage 6: code plan + +Purpose: turn the mapping, the screen plan and the capability verdicts into a list of modules with files, dependencies, the pin each is held to, and what this skill does to each. Stage 7 builds this list in order; stage 8 validates it in order. + +The transport's shape, the configuration, the archive and the test placement (sections 2 to 5) are the episode's: the first skill to run this stage writes them, and later skills use them. + +## Inputs + +- `nhcx-build/3-discovery.md`, `nhcx-build/4-flow-data-mapping.md`, `mapping.json`, `nhcx-build/5-screen-plan.md`, `screens.json` +- This skill's section of `nhcx-build/0-capability.md` and `nhcx-build/2-planning.md` (the action per module) +- `stages/7-write-code/README.md` and every `7.N-*.md` this skill touches: the module ladder is fixed; the plan decides the files +- `references/fhir-knowledge.md` section 1: where the pins live +- `fhir/FHIR.md`: the builders and readers the modules 7.4 to 7.10 implement, so the plan names them + +## Do + +### 1. Place each module + +For each module this skill touches (its `SKILL.md` lists them) and each foundation module it builds or extends, write: + +| Field | Meaning | +| --- | --- | +| `skills` | A map from skill to action: `build`, `extend` or `reuse`. A module another skill already placed keeps its entry; add this skill and its action | +| `files` | The files it creates or changes, in the target's layout and naming (from stage 3). For a reused or extended module, the files that exist | +| `depends_on` | The modules that must exist first; the ladder's order is the floor, the plan may add more | +| `held_to` | The pin in `nhcx-package/fhir` (its file, from `references/material.md`), the payer fixture, or the rule (for modules with no bundle) | +| `copy_from` | What the module follows: its own Pseudo code section and the `fhir/FHIR.md` section it names | +| `tables` | The tables from `mapping.json` it reads and writes | +| `screens` | The screens from `screens.json` it serves (7.12 and 7.13 only) | + +`modules.json` holds one entry per module, in ladder order (7.1 to 7.13), whichever skill adds it. + +### 2. The transport's shape + +Decide once, and every module uses it: the transport kind from stage 1, and the functions of the contract in `references/transport-knowledge.md` section 2: `send`, the receiving end that hands the door a normalised envelope, `policies`, `participants`, `token`, and `thread` and `fetch_missed` where the kind has them. Name them here so 7.4 to 7.10 call the same thing. A stub of `send`, recording the path, recipient, workflow id, correlation id and bundle and returning `{"txn_id", "correlation_id", "api_call_id"}`, is what stage 9 injects. When stage 0 found an existing transport, name its functions and what wraps them. + +### 3. Configuration + +List every setting and where it lives (from stage 3): the transport kind, participant code, facility HFR id and name, cases directory, per-payer overrides for workflow ids, and the transport's own. For `own`: the ABDM client id and secret, the private key, the sessions, NHCX and registry addresses, and the NHCX signing key once onboarding gives it. For `adapter`: its URL, API key and callback secret. For `existing`: whatever its client reads. Name the environment variables or config keys in the target's convention. + +### 4. The archive + +The per-case archive path from stage 4, and which module writes it (7.3 for inbound, 7.1 for outbound). + +### 5. Test placement + +Where the offline test lives (from stage 3's "how tests are run"), and how the pin comparison is wired: canonical JSON, `created` excluded, one comparison per pin. + +## Write + +- `nhcx-build/6-code-plan.md` from `templates/6-code-plan.md`: the episode sections once, the modules table, and this skill's section. +- `nhcx-build/modules.json` in the shape of `templates/modules.json`. + +## Gate + +- [ ] `modules.json` has an entry, in ladder order, for every module this skill touches and every foundation module (7.13 in standalone mode). +- [ ] Every entry this skill touches has non-empty `files`, `depends_on` (7.1 may be empty), `held_to` and `copy_from`, and this skill in `skills` with its action. +- [ ] Every pin this skill owns appears in some module's `held_to`. +- [ ] The transport kind and its functions are named. +- [ ] The configuration list includes the transport kind, the participant code, the cases directory, and every setting the chosen transport needs. +- [ ] The test file's location and the pin comparison rule are written. + +## Common mistakes + +- Splitting the claim bundle builder across modules by leg, or by skill. One builder, one `leg` and `flow` argument, is what the pins expect; `nhcx-claim` extends what `nhcx-preauth` built. +- Planning a second transport for the reply legs. Same function; the reply legs add `x-hcx-correlation_id` to the headers. +- Planning new files for a module stage 0 found present. +- Planning the screens before the readers exist in the dependency list. diff --git a/plugins/nhcx/skills/nhcx-preauth/stages/7-write-code/7.1-config-and-transport.md b/plugins/nhcx/skills/nhcx-preauth/stages/7-write-code/7.1-config-and-transport.md new file mode 100644 index 000000000..2ad046569 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-preauth/stages/7-write-code/7.1-config-and-transport.md @@ -0,0 +1,131 @@ +# Module 7.1: configuration and the NHCX transport + +Purpose: the one path every message leaves by, whichever transport carries it. The settings, the transport chosen at stage 1 behind one `send`, the policy lookup, and the outbound half of the per-case archive. + +Skills: the foundation (`core/FOUNDATION.md`). Built whole by the first skill whose stage 0 finds it absent; every skill sends through it. + +## Depends on + +Nothing. First module. + +## Inputs + +- `nhcx-build/1-idea.md`: the transport, `existing`, `own`, or `adapter` because the user asked for it +- `nhcx-build/6-code-plan.md` sections 2 to 4 (the transport's functions, the configuration keys, the archive path) +- `references/transport-knowledge.md` section 2 (the contract), and section 3 (`own`), 4 (`existing`) or 5 (`adapter`) for the kind chosen +- With `adapter` only: `references/api-knowledge.md` sections 2 to 5, 7, 8 and 11 + +## Build + +### Settings + +Read from the target's configuration mechanism (stage 3). + +| Setting | Transport | Meaning | +| --- | --- | --- | +| transport kind | all | `existing`, `own` or `adapter` | +| participant code | all | The hospital's, with `@hcx`: `x-hcx-sender_code` | +| facility HFR id, name, phone | all | The provider Organization | +| cases directory | all | The per-case archive root | +| per-payer workflow id overrides | all | Optional, for a payer that insists on a code the table does not carry (`cancel` as 122) | +| ABDM client id and secret | own | The session token (`transport-knowledge.md` section 3.3) | +| private key | own | The PEM behind the certificate on the participant record, read from a file or a secret store | +| sessions, NHCX and registry addresses, `X-CM-ID` | own | From `nhcx-package/baseurl.yaml`; the sandbox by default | +| NHCX signing key | own | For the exchange's JWT on inbound calls. Empty until onboarding gives it, and logged while empty | +| adapter URL, adapter API key, callback secret | adapter | `references/api-knowledge.md` section 2. Also fill the adapter's `config.sample.json` into `nhcx-build/adapter.config.json`, secrets as `${ENV}` placeholders | +| whatever the existing client reads | existing | Named here, not duplicated | + +Secrets are read from configuration: never in code, never in `nhcx-build/`. + +### The transport + +One `send` with the signature in `transport-knowledge.md` section 2, and beside it `policies`, `participants`, `token`, `thread` and `fetch_missed`. What sits under them depends on the kind: + +| Kind | `send` | `policies`, `participants`, `token` | `thread`, `fetch_missed` | +| --- | --- | --- | --- | +| `own` | Seal and post (`transport-knowledge.md` sections 3.3 to 3.8): the token, the recipient's certificate, the protected header, a compact JWE, `{"payload"}` to `/v1/`, a `401` retried once | The participant service directly (sections 3.6 and 3.7) | `thread` reads the per-case archive; `fetch_missed` answers `unavailable` | +| `existing` | Calls the app's own client and maps its answer onto `{txn_id, correlation_id, api_call_id}` (section 4) | The app's own calls, or the participant service directly | What the app keeps; else as `own` | +| `adapter` | POSTs `{jwe_headers, fhir}` to `/fhir/out/` with the bearer key (`api-knowledge.md` sections 4 and 5) | `/internal/policies/search`, `/internal/participants/list`, `/token` | The adapter's ledger and `/internal/txn/*` (`api-knowledge.md` sections 7 and 8) | + +Common to every kind: + +1. A send without a recipient, a workflow id or the beneficiary's ABHA is refused before anything goes on the wire. +2. The recipient is the policy's processor: `recipient_of(row)` is `claim.recipient_code`, else `claim.payer_code` for an episode opened before the processor was kept. +3. A correlation id is passed only on the two answer legs, the communication reply and the payment acknowledgement. On a request the transport mints it (`own`: the message's own `api_call_id`). +4. A refusal raises `TransportError(code, message, protocol_response, retryable)`: the gateway's status and body (`own`), the adapter's `error.code` and `upstream_body` (`adapter`), or the existing client's error. A ProtocolResponse inside it is a refusal at the door; the caller records the payer's words. +5. The outbound message is archived before `send` returns: `//NNN--out.json` with what was sent and what came back, and a `transactions.txt` line (sequence, time, direction, path, workflow id, correlation id, api call id, txn id, outcome). With `own`, the archive entry is the `txn_id`. +6. The caller stores `txn_id`, `correlation_id` and `api_call_id` on the leg. + +## Rules + +- Use nhcx-adapter only when the user asked for it; `1-idea.md` records their words. Never propose it. +- Keep an existing NHCX integration and wrap it. Never put a second transport beside it. +- Seal and open JWEs only for `own`, and only with a JOSE library: `RSA-OAEP-256`, `A256GCM`, compact serialisation. Never hand-roll the cryptography. +- The workflow id goes out on every leg that has one; `x-hcx-ben-abha-id` goes out on every message. +- The sandbox refuses sends faster than one per 30 seconds per case (PAYR-1322). The transport does not throttle; the caller does. Say so in the docstring. +- The private key never leaves the server that receives callbacks, and never enters a log. + +## Validate + +- [ ] A send with no recipient, no workflow id or no beneficiary ABHA is refused before anything goes on the wire. +- [ ] The protected header of a send carries every mandatory field under the protocol's rules: sender and recipient with `@hcx`, a fresh `api_call_id`, a `correlation_id` equal to the `api_call_id` on a request and to the request's on an answer, the workflow id, `x-hcx-timestamp` in ISO 8601 with `+05:30`, `x-hcx-status` `request.initiated` or `response.complete`, and `x-hcx-ben-abha-id`. Observed on what the transport emits: the JWE header opened with a test key pair (`own`), the posted `jwe_headers` with the adapter's completion rules (`adapter`), the existing client's output (`existing`). +- [ ] The recipient is the episode's `recipient_code`, the policy's `processingid`, whenever the episode has one. +- [ ] A refusal raises `TransportError` carrying the code and the words the exchange or the adapter gave. With `own`, a `401` is retried once with a fresh token, and a second `401` raises. +- [ ] The archive file and the `transactions.txt` line exist after a send, with the sequence number zero-padded to three digits. +- [ ] Secrets are read from configuration, not present in code or in `nhcx-build/`. +- [ ] With `own`: a bundle sealed for a test certificate opens with its private key to the same bytes and the same protected header; the token is reused while fresh and fetched again when stale; a recipient's certificate is fetched once and then read from the cache. + +## Tests + +- Stub the HTTP layer and assert the URL, the headers and the body of one send with and one without a correlation id: `bearer_auth` and `{"payload"}` for `own`; the bearer key and `{jwe_headers, fhir}` for `adapter`. +- `own`: seal with a test key pair and open it again; check the header fields above; a `401` then a `202` sends twice with two tokens; a certificate in SPKI form loads as well as an X.509 one. +- `adapter`: a `502` with a ProtocolResponse `upstream_body` raises an error whose text carries the payer's `x-hcx-error_details` message; a `404` from `txn/related` is terminal, not retried. +- The archive sequence increments across two sends on one case. + +## Pseudo code + +The `own` transport's token, certificate cache, sealing and receiving end: `references/transport-knowledge.md` section 3.12. The adapter client: `references/api-knowledge.md` section 11. What every kind shares: + +``` +settings = { + transport: env("NHCX_TRANSPORT", "own"), # own | existing | adapter; adapter only when the user asked for it + participant_code: env("NHCX_PARTICIPANT_CODE"), # "@hcx" + facility: {hfr_id: env("NHCX_HFR_ID"), name: env("NHCX_FACILITY_NAME"), phone: ...}, + cases_dir: env("NHCX_CASES_DIR", "data/cases"), + workflow_overrides: parse_json(env("NHCX_WORKFLOW_IDS", "{}")), # {"1518@hcx": {"cancel": "122"}} + nhcx: {sessions: env("NHCX_SESSIONS_URL", "https://dev.abdm.gov.in/api/hiecm/gateway/v3/sessions"), # own + base: env("NHCX_BASE_URL", "https://apisbx.abdm.gov.in/hcx"), + registry: env("NHCX_REGISTRY_URL", "https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice"), + cm_id: env("NHCX_CM_ID", "sbx"), + client_id: env("NHCX_CLIENT_ID"), client_secret: env("NHCX_CLIENT_SECRET"), + private_key: read_secret(env("NHCX_PRIVATE_KEY_FILE")), signing_key: env("NHCX_SIGNING_KEY", "")}, + adapter: {url: env("NHCX_ADAPTER_URL"), api_key: env("NHCX_ADAPTER_API_KEY"), # adapter only + callback_secret: env("NHCX_CALLBACK_SECRET")}, +} + +transport = {"own": OwnTransport, "existing": ExistingTransport, "adapter": AdapterTransport}[settings.transport]() +# each offers send, policies, participants, token, thread, fetch_missed (transport-knowledge.md section 2) + +function recipient_of(row): return row.recipient_code or row.payer_code + +function ben_abha(claim_no): # the payer's Patient from the coverage answer, else the HMIS patient + row = claim_by_no(claim_no) + return digits(abha_in(row.patient_json) or patient(row.patient_id).abha) + +function with_hcx(code): return code if code.endswith("@hcx") else code + "@hcx" + +# the archive, outbound half; 7.3 writes the inbound half through the same function +function archive.record(claim_no, usecase, direction, payload): + folder = settings.cases_dir + "/" + (claim_no or "unmatched"); mkdir(folder) + n = next_sequence(folder) # 001, 002, ... + write(folder + f"/{n:03d}-{usecase}-{direction}.json", pretty(payload)) + append(folder + "/transactions.txt", f"{n:03d} {now()} {direction} {payload.path} wf={payload.workflow_id} " + f"cid={payload.correlation_id} acid={payload.api_call_id} txn={payload.txn_id} {payload.outcome}") + return f"{claim_no or 'unmatched'}/{n:03d}" +``` + +## Done when + +- Validate passes for the transport chosen. +- `own`: the onboarding the user must do is written into `nhcx-build/7-modules/7.1.md`: the credentials, the key and certificate, the participant record, the `endpoint_url`, and the NHCX signing key to ask NHA for. `adapter`: `nhcx-build/adapter.config.json` exists with placeholders. `existing`: the wrapper and every gap it closed are listed. +- `nhcx-build/7-modules/7.1.md` is written. diff --git a/plugins/nhcx/skills/nhcx-preauth/stages/7-write-code/7.10-communication-and-payment.md b/plugins/nhcx/skills/nhcx-preauth/stages/7-write-code/7.10-communication-and-payment.md new file mode 100644 index 000000000..271d56732 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-preauth/stages/7-write-code/7.10-communication-and-payment.md @@ -0,0 +1,124 @@ +# Module 7.10: communication and payment + +Purpose: the two legs the payer starts. A CommunicationRequest is classified as a query, a notification or a note and answered accordingly; a PaymentNotice is recorded, matched to its claim, and acknowledged. + +Skills: `nhcx-communication` (classification, the notification acknowledgement, the reply) and `nhcx-payment` (the payment notice and its acknowledgement). Validate rows 1, 3, 4 and 5 are the communication half's; rows 2, 6 and 7 the payment half's; row 8 is both. + +## Depends on + +7.1 to 7.3, 7.7, 7.11 (for the payer's query mode; build 7.11's adapter table first if not yet). + +## Inputs + +- `references/flow-knowledge.md` section 3 (the two payer kinds, the classification rule) and section 1 rows "Payment notice" and "Communication" +- `references/fhir-knowledge.md` sections 9 and 10 +- Pins: `nhcx-package/fhir/B4/communication-request.json` (the payer's message), `B4/communication-response.json` (the reply), `nhcx-package/fhir/B7/payment-notice-ack.json` +- Payer messages: `nhcx-package/fhir/C6/C6-preauth-query-wf24.json` and `C6/C6-claim-query-wf27.json` (generic queries), `C6/C6-notification-wfN02.json` (PMJAY notification), `nhcx-package/fhir/C9/*.json` (payment notices) + +## Build + +### Classification + +`classify_communication(adapter, reason_code, intent) -> kind`, in order: a `resubmit` payer's request is a notification; `intent proposal` is a notification, `order` a query; then `reasonCode`: absent, `additionalinfo`, `questionnaire`, `query` is a query, anything else (`tatquery`, `grievance`, `walletupdate`, `policychange`, `claimarbitration`, with `claimArbitartion` folded in) a notification. A bare `Communication` with no request is a note: recorded, shown, never acted on. + +### Receiving + +`parse_communication_request(bundle)`: the Task's status, intent, reason; the CommunicationRequest's id, `basedOn` (the Claim), one question per `payload[].contentString`; the leg asked about (from the Claim's `use` or the `basedOn` identifier). Store a `claim_query` row keyed on the message's correlation id with `kind`, `stage`, `questions_json`, status `open`. + +### Acknowledging a notification + +`build_acknowledgement_bundle(query_id)`: the payer's own bundle sent back with `Task.status` flipped to `completed`, the reason echoed and the provider Organization first, on `v1/communication/on_request` with the request's correlation id and workflow id echoed in `jwe_headers`. Sent by `acknowledge_notification` from outside the callback (the desk's next request, or a worker). Status `acknowledged`. + +### Answering a query (communication payer) + +`build_communication_bundle(query_id, text, document_ids)`: a TaskBundle with a Task `deliver`, `completed`, including the Communication; the Communication `basedOn` the request (never `inResponseTo`) and `about` the Claim, its text a `contentString`, each document a `contentAttachment` under the document-type extension (its url is participant-defined: read it from configuration; the pin comparison takes the pin's own url); the CommunicationRequest echoed; then the Claim, Patient, provider Organization, payer Organization, Practitioner and Coverage lifted from the queried leg's bundle as sent. This bundle carries `meta.lastUpdated` and `timestamp` (the IG example does). Sent on `v1/communication/on_request` with the request's correlation id and workflow id. Status `answered`. + +For a `resubmit` payer the answer is not here: it is 7.7's query answer on a fresh thread. The inbox item for a PMJAY query is the leg's `query_note`, and its reply box calls `submit_preauth` or `submit_claim` with the reply. + +### Payment notice + +`parse_payment_notice(bundle)`: `PaymentNotice.amount`, `paymentStatus`, `paymentDate`, the `request` reference's identifier (the claim number), `payment` identifier (the UTR when settled), the `PaymentReconciliation` details when present. `record_payment` matches the claim number, dedupes on the correlation id, stores `claim_payment` and `claim_payment_detail`, and stamps the episode `payment`/`noticed` or `paid`. + +### Payment acknowledgement + +`build_payment_ack(payment_id)`: a TaskBundle in the shape of `B7/payment-notice-ack.json`, sent on `v1/paymentnotice/on_request` with the notice's correlation id and, for PMJAY, workflow `17`; for a generic payer the notice's own workflow id echoed (`None` in the adapter table means echo). Sent by `acknowledge_payment` from outside the callback. `ack_status` `sent` or `error`. + +## Rules + +- The reply names the request in `Communication.basedOn`, never `inResponseTo`. +- A `resubmit` payer's CommunicationRequest is always a notification, whatever it says. +- A notification is acknowledged at once and the case is left alone. +- The acknowledgement and the reply are the only two sends that carry `x-hcx-correlation_id` (with the payment acknowledgement). + +## Validate + +- [ ] `B4/communication-response.json` pin: the builder fed the request pin (`B4/communication-request.json`) and the pre-auth pin (`B3/preauth-request.json`) produces the response pin byte for byte (`meta.lastUpdated`, `timestamp` and `authoredOn` excluded). +- [ ] `B7/payment-notice-ack.json` pin comparison passes. +- [ ] Classification: the generic query (`C6/C6-preauth-query-wf24.json`: `intent order`, `additionalinfo`) is a query; the PMJAY notification (`C6/C6-notification-wfN02.json`: `intent proposal`, `information`) is a notification; the same PMJAY bundle under a `communication` adapter with `intent order` is a query; a bare Communication is a note. +- [ ] The reply's `Communication.basedOn` names the request and `inResponseTo` is absent. +- [ ] The acknowledgement and the reply carry `x-hcx-correlation_id` equal to the request's; the workflow id is echoed. +- [ ] Two deliveries of one notice create one `claim_payment` row. +- [ ] The PMJAY acknowledgement carries workflow `17`; the generic one echoes the notice's. +- [ ] No send happens inside the callback (7.1 stub sees zero sends during receipt). + +## Tests + +- The two pin comparisons. +- Classification table as a parametrised test. +- B6, B7, C6, D8, D13 and the notification rows from the matrix. + +## Pseudo code + +Classification, the acknowledgement, the reply and the payment reader: `fhir/FHIR.md` sections 7 and 8. Wiring: + +``` +APPLY["inbound_request"] = function (row, env): + kind = resource_types(env.fhir) + if "PaymentNotice" in kind: record_payment(row, env) + elif "CommunicationRequest" in kind: receive_communication(row, env) + elif "Communication" in kind: record_note(row, env) # a bare Communication: shown, never acted on + +function receive_communication(row, env): + p = fhir.parse_communication_request(env.fhir); adapter = payers.for_claim(row) + kind = fhir.classify_communication(adapter, p.reason, p.intent) + q = insert("claim_query", {claim_id: row.id, correlation_id: env.jwe_headers["x-hcx-correlation_id"], request_id: p.request_id, + workflow_id: env.jwe_headers["x-hcx-workflow_id"], sender_code: env.jwe_headers["x-hcx-sender_code"], + kind, stage: leg_asked_about(row, p), reason_code: p.reason, intent: p.intent, questions_json: p.questions, + request_json: env.fhir, status: "open", received_at: now()}) + if kind == "notification": enqueue(acknowledge_notification, q.id) # sent outside the callback + +function acknowledge_notification(query_id): + q = query(query_id); row = claim(q.claim_id) + bundle = fhir.build_acknowledgement_bundle(q.request_json, settings.facility) + r = transport.send("v1/communication/on_request", bundle, q.sender_code, workflow_id = q.workflow_id, correlation_id = q.correlation_id, claim_no = row.claim_no, usecase = "communication-ack") + update(q, {status: "acknowledged", reply_txn_id: r.txn_id, reply_api_call_id: r.api_call_id, replied_at: now()}) + +function answer_query(query_id, text, document_ids): # communication payer + q = query(query_id); row = claim(q.claim_id) + if payers.for_claim(row).query_mode == "resubmit": return submit_preauth(row.id, reply = text) if q.stage == "preauth" else submit_claim(row.id, reply = text) + sent = (preauth(row.id) if q.stage == "preauth" else submission(row.id)).request_json + bundle = fhir.build_communication_bundle(q, text, [doc_with_bytes(i) for i in document_ids], sent, settings.facility, payer_of(row), now_ist()) + r = transport.send("v1/communication/on_request", bundle, q.sender_code, workflow_id = q.workflow_id, correlation_id = q.correlation_id, claim_no = row.claim_no, usecase = "communication-reply") + update(q, {status: "answered", reply_text: text, reply_document_ids: document_ids, reply_txn_id: r.txn_id, replied_at: now()}); stamp_case(row.id) + +function record_payment(row, env): + p = fhir.parse_payment_notice(env.fhir) + pay = insert_or_ignore("claim_payment", {claim_id: row.id, correlation_id: env.jwe_headers["x-hcx-correlation_id"], workflow_id: env.jwe_headers["x-hcx-workflow_id"], + sender_code: env.jwe_headers["x-hcx-sender_code"], amount: p.amount, payment_status: p.payment_status, payment_date: p.payment_date, + utr: p.utr, notice_json: env.fhir, ack_status: "pending", received_at: now()}) + if not pay: return # the unique constraint caught a redelivery + for d in p.details: insert("claim_payment_detail", {payment_id: pay.id, type: d.type, amount: d.amount}) + enqueue(acknowledge_payment, pay.id) + +function acknowledge_payment(payment_id): + pay = payment(payment_id); row = claim(pay.claim_id); adapter = payers.for_claim(row) + bundle = fhir.payment_ack(submission(row.id).claim_ref or row.claim_no, now_ist(), settings.facility, payer_of(row)) + wf = adapter.workflow_ids.payment_ack or pay.workflow_id # 17 for PMJAY; echo for a generic payer + r = transport.send("v1/paymentnotice/on_request", bundle, pay.sender_code, workflow_id = wf, correlation_id = pay.correlation_id, claim_no = row.claim_no, usecase = "payment-ack") + update(pay, {ack_status: "sent", ack_txn_id: r.txn_id, ack_api_call_id: r.api_call_id, acked_at: now()}); stamp_case(row.id) +``` + +## Done when + +- Validate passes. +- `nhcx-build/7-modules/7.10.md` is written. diff --git a/plugins/nhcx/skills/nhcx-preauth/stages/7-write-code/7.11-state-and-payer-adapters.md b/plugins/nhcx/skills/nhcx-preauth/stages/7-write-code/7.11-state-and-payer-adapters.md new file mode 100644 index 000000000..94fbfc313 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-preauth/stages/7-write-code/7.11-state-and-payer-adapters.md @@ -0,0 +1,145 @@ +# Module 7.11: state and payer adapters + +Purpose: two small tables of truth the whole build reads. The payer adapter says how a payer behaves; the stage machine says where an episode stands and what it waits for. + +Skills: the foundation (`core/FOUNDATION.md`). The first skill builds the payer adapter table whole; each skill adds the `case_stage` branches and the `next_actions` rows for its own legs. + +## Depends on + +7.2. (7.7 to 7.10 call it; build the adapter table as early as 7.4 needs the participant codes.) + +## Inputs + +- `references/flow-knowledge.md` sections 2, 3 and 4, whole +- `nhcx-build/1-idea.md` (the payers in scope) + +## Build + +### The payer adapter + +A table keyed by participant code (normalised: `1518` and `1518@hcx` are one key), each entry holding: + +| Field | PMJAY | Generic | +| --- | --- | --- | +| `query_mode` | `resubmit` | `communication` | +| `workflow_ids` | the PMJAY column of flow-knowledge section 2 | the generic column; `payment_ack` is `None` (echo) | +| `program_code` | `AB-PMJAY` | none | +| `auth_requirements` | asked | asked | +| `status_enquiry` | refused; do not offer | offered | +| `claim_resubmit` | none; reprocess only | `16` | +| `payer_system` | the identifier system for the payer Organization | same | + +`adapter_for(participant_code)` returns the entry or the generic default. `for_claim(row)` reads the episode's payer code. Overrides from configuration (7.1) merge on top, per payer, so a payer that insists on `cancel` as 122 is one config line. + +### Stage and sub-stage + +Stages: `eligibility`, `preauth`, `enhancement`, `claim`, `payment`. Sub-stages: `draft`, `checking`, `eligible`, `not-eligible`, `requested`, `resubmitted`, `answered`, `queried`, `approved`, `partial`, `rejected`, `cancelling`, `cancelled`, `refused`, `noticed`, `paid`. Send kind to sub-stage: `preauth`, `claim`, `enhancement` set `requested`; `*_resubmit` sets `resubmitted`; `*_query_response` and `enhancement_resubmit` set `answered`. `requested`, `answered`, `resubmitted` mean "with the payer". + +`case_stage(row, ...) -> (stage, sub_stage)`: a payment notice wins, then the filed claim, then the pre-auth (stage `enhancement` if the last submission kind was one), then a saved draft, then the eligibility status. An open communication query on a leg that is with the payer flips the sub-stage to `queried`. + +`stamp_case(claim_id)`: recompute and write both onto the episode. Called after every leg write by 7.3, 7.4 to 7.10. + +### Next actions + +The table in `flow/FLOW.md` ("The status line and the actions") and `flow/flow.json` `next_actions` is the specification; the labels are used verbatim. + +`next_actions(claim_id) -> [{label, tab, tone}]`, first is what the case waits for: an unanswered query always leads with "Answer the payer (n)"; the leg's own reply box only for a `resubmit` payer, a `communication` payer is sent to the inbox; a claim refused at the door offers "send again" while `claim_send_kind` still yields a kind, else "Ask for a reprocess"; after a rejection the pre-auth offers a fresh 12; a payer whose adapter refuses status enquiry never gets a "Ask status" action. + +## Rules + +- An unmapped payer is generic. +- The two words are derived, never set by a screen. +- Stamp after every write. A test that checks state after every step is what makes stage 8 possible. + +## Validate + +- [ ] `adapter_for("1518@hcx")` and `adapter_for("1518")` return the PMJAY entry; an unknown code returns generic. +- [ ] The PMJAY `workflow_ids` table equals flow-knowledge section 2's PMJAY column for every kind listed; the generic table has `payment_ack` as echo and `claim_query_response` as `151`. +- [ ] A configuration override for one kind changes only that kind. +- [ ] `case_stage` on each seeded state (draft; checking; eligible; pre-auth submitting; approved; queried by communication; enhancement requested; claim submitting; payment noticed; paid) returns the expected pair (write the table in the test). +- [ ] `next_actions` leads with the query when one is open; offers no status enquiry for PMJAY; offers a fresh 12 after a rejection. +- [ ] For every row of `flow.json` `next_actions`, the seeded state yields that label, character for character. +- [ ] After every leg write in 7.4 to 7.10, `claim.stage` and `sub_stage` equal `case_stage` recomputed. + +## Tests + +- A parametrised table for `case_stage`. +- A parametrised table for `next_actions`. +- The adapter lookups and the override. + +## Pseudo code + +``` +QUERY_MODE_RESUBMIT = "resubmit"; QUERY_MODE_COMMUNICATION = "communication" + +PMJAY = {"name": "PMJAY", "query_mode": QUERY_MODE_RESUBMIT, "program_code": "AB-PMJAY", "auth_requirements": true, + "status_enquiry": false, "payer_system": "https://nhcx.abdm.gov.in", + "workflow_ids": {"preauth": "12", "preauth_resubmit": "121", "preauth_query_response": "19", "enhancement": "13", "enhancement_resubmit": "131", + "cancel": "PC01", "claim": "15", "claim_query_response": "161", "claim_resubmit": null, "payment_ack": "17", "reprocess": "36", "release": "36"}} +GENERIC = {"name": "generic", "query_mode": QUERY_MODE_COMMUNICATION, "program_code": null, "auth_requirements": true, "status_enquiry": true, + "payer_system": "https://nhcx.abdm.gov.in", + "workflow_ids": {... as PMJAY except "claim_query_response": "151", "claim_resubmit": "16", "payment_ack": null}} # null = echo the notice's id +ADAPTERS = {"1518": PMJAY} # keyed without @hcx + +function adapter_for(participant_code): + key = (participant_code or "").split("@")[0] + base = deepcopy(ADAPTERS.get(key, GENERIC)) + for (k, v) in settings.workflow_overrides.get(with_hcx(key), {}): base.workflow_ids[k] = v + return base + +function for_claim(row): return adapter_for(row.payer_code) + +STAGES = ["eligibility", "preauth", "enhancement", "claim", "payment"] +KIND_TO_SUB = {"preauth": "requested", "claim": "requested", "enhancement": "requested", "preauth_resubmit": "resubmitted", "claim_resubmit": "resubmitted", + "preauth_query_response": "answered", "claim_query_response": "answered", "enhancement_resubmit": "answered"} +WITH_PAYER = {"requested", "answered", "resubmitted"} + +function leg_sub_stage(leg): + if leg.status == "submitting": return KIND_TO_SUB.get(leg.submission_kind, "requested") + return {"approved": "approved", "partial": "partial", "queried": "queried", "rejected": "rejected", "error": "refused", + "cancelling": "cancelling", "cancelled": "cancelled", "draft": "draft"}.get(leg.status, leg.status) + +function case_stage(row): + paid = sum(p.amount for p in payments(row.id) if p.payment_status in ("paid", "cleared")) + if payments(row.id): return ("payment", "paid" if paid > 0 else "noticed") + cs = submission(row.id) + if cs and cs.status != "draft": + sub = leg_sub_stage(cs) + if sub in WITH_PAYER and "claim" in open_query_stages(row): sub = "queried" + return ("claim", sub) + pa = preauth(row.id) + if pa and pa.status != "draft": + stage = "enhancement" if pa.submission_kind in ("enhancement", "enhancement_resubmit") else "preauth" + sub = leg_sub_stage(pa) + if sub in WITH_PAYER and "preauth" in open_query_stages(row): sub = "queried" + return (stage, sub) + if pa: return ("preauth", "draft") + return ("eligibility", {"checking": "checking", "eligible": "eligible", "not-eligible": "not-eligible"}.get(row.status, "draft")) + +function stamp_case(claim_id): (s, sub) = case_stage(claim(claim_id)); update(claim(claim_id), {stage: s, sub_stage: sub}) + +function next_actions(claim_id): + row = claim(claim_id); adapter = for_claim(row); out = []; pa = preauth(claim_id); cs = submission(claim_id) + open_q = open_queries(claim_id) + if open_q: out.append({label: f"Answer the payer ({len(open_q)})", tab: "communication" if adapter.query_mode == "communication" else ("claim" if open_q[0].stage == "claim" else "preauth"), tone: "primary"}) + if row.status in ("draft", "not-eligible", "error"): out.append({label: "Check cover", tab: "cover", tone: "primary"}) + elif not row.plan_id: out.append({label: "Fetch the plan", tab: "plan", tone: "primary"}) + elif not pa or pa.status == "draft": out.append({label: "Submit the pre-authorisation", tab: "preauth", tone: "primary"}) + elif pa.status == "queried" and adapter.query_mode == "resubmit": out.append({label: "Answer the query", tab: "preauth", tone: "primary"}) + elif pa.status == "rejected": out.append({label: "Send a fresh pre-authorisation", tab: "preauth", tone: "primary"}) # 12, never 121 + elif pa.status == "error": out.append({label: "Send again", tab: "preauth", tone: "warn"}) + elif pa.status in ("approved", "partial") and (not cs or cs.status == "draft"): + out.append({label: "Discharge and claim", tab: "claim", tone: "primary"}) + if enhancement_lines(claim_id): out.append({label: "Send the enhancement", tab: "lines", tone: "default"}) + out.append({label: "Cancel the pre-authorisation", tab: "preauth", tone: "danger"}) + elif cs and cs.status == "error": out.append({label: "Send again" if claim_send_kind(claim_id) else "Ask for a reprocess", tab: "claim", tone: "warn"}) + elif cs and cs.status == "rejected": out.append({label: "Ask for a reprocess", tab: "claim", tone: "warn"}) + for p in payments(claim_id): if p.ack_status != "sent": out.append({label: "Acknowledge the payment", tab: "payments", tone: "default"}) + if adapter.status_enquiry and (pa or cs): out.append({label: "Ask status", tab: "enquiries", tone: "default"}) + return out +``` + +## Done when + +- Validate passes. +- `nhcx-build/7-modules/7.11.md` is written. diff --git a/plugins/nhcx/skills/nhcx-preauth/stages/7-write-code/7.12-screens.md b/plugins/nhcx/skills/nhcx-preauth/stages/7-write-code/7.12-screens.md new file mode 100644 index 000000000..130115d38 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-preauth/stages/7-write-code/7.12-screens.md @@ -0,0 +1,124 @@ +# Module 7.12: screens + +Purpose: the screens in `screens.json`, built the way the target builds screens, every value derived from a stored message, plus the JSON state address a driver reads. + +Skills: the foundation (`core/FOUNDATION.md`) builds the case screen shell: all eight tabs, the status line, the state address, the page-load polls, the cases list. Each skill fills its own tabs and screens, and adds its legs to the state address. + +## Depends on + +7.1 to 7.11. Screens come last because they render what the readers stored. + +## Inputs + +- `nhcx-build/5-screen-plan.md`, `nhcx-build/screens.json` +- `nhcx-build/3-discovery.md` (screen conventions, helpers, styling) +- `nhcx-package/docs/03-Building a Provider/09-UI Guide.md` +- `ui/UI-GUIDE.md` for the route shape, the state address and the helper vocabulary; two or three route modules of the target for its conventions + +## Build + +### The case screen walks the flow + +Tabs in the order and with the labels of `flow.json` `tabs`; the Pre-authorisation tab appears once the verdict is `eligible`. Above the tabs the status line and the actions from 7.11. Each step F1 to F13 has its control on the tab the flow names, offered only when the step's `holds` hold. The page-load polls run in the order `flow.json` `page_load_polls` gives, bounded, before rendering. + +### Every screen in `screens.json` + +For each screen: the route, the handler, the render. Each value in the screen's `values` list is rendered from the element it names; the empty state is what shows before the message arrived. A decision-bearing value with no message renders as waiting. There is no status control anywhere. + +### The case screen + +The timeline: one row per leg row and per archived message, in time order, with direction, path, workflow id label (7.8's labels), status word, and the payer's words verbatim (`disposition`, item remarks, process notes, `x-hcx-error_details` on a refusal). The actions open now are `next_actions` from 7.11, rendered as buttons that post to the senders; the first action is highlighted. Each pane (cover, plan, lines, forms, documents, pre-auth, communication, claim, payments) shows only when its leg exists. + +### The JSON state address + +`GET /state` returns everything the case screen shows, as JSON, after the same polls the screen runs: stage, sub-stage, next actions, each leg's status and ids, the inbox items, the payments. Stage 10's drivers read this. + +### Polling on the request path + +Where there is no worker, the case screen and the state address run 7.3's poll fallback for any leg that is `submitting` or `checking` before rendering. Bound it: one poll per leg per request, a short timeout, and never a send. + +### Standalone mode + +Also the capture screens from 7.13, in the same style. + +## Rules + +- No screen shows a decision the exchange has not sent. +- Nothing the exchange already knows is typed. Rates, payer names, `preAuthRef`, the approved amount, the UTR and the payer's wording are rendered, never fields. +- An unknown case is a 404, never an invented page. +- Screens answer within two seconds; the poll is bounded. +- Forms post and the page re-renders; no client-side rendering is needed. + +## Validate + +- [ ] The case page's tabs are the eight of `flow.json`, in order, with those labels (string test on the HTML). +- [ ] Every step of `flow.json` with a `routes` entry answers on that route (or the plan's equivalent recorded in `screens.json`). +- [ ] Every route in `screens.json` answers 200 for a seeded case and 404 for an unknown one. +- [ ] A case with a pre-auth `submitting` and no answer renders "waiting" (or the plan's word) and neither "approved" nor "rejected" appears on the page. +- [ ] After a 21 is applied (`nhcx-package/fhir/C5/C5-approved-wf21.json`), the page shows its `preAuthRef` and approved amount verbatim. +- [ ] After a payment notice is applied (`nhcx-package/fhir/C9/C9-notice-wf30.json`), the payments screen shows its UTR verbatim. +- [ ] After a query is applied, the inbox shows the request's `contentString` text verbatim. +- [ ] No `` or `, unless spec.typed +``` + +### Which actions to offer + +``` +function actions(case): + out = [] + q = open_queries(case) + if q: out.append(action("Answer the payer (n)", tab = inbox if payer.query_mode == communication else leg_tab)) + leg = current_leg(case) + if leg.status == "rejected" and leg.kind == "preauth": out.append(action("Send a fresh pre-authorisation", sends = 12)) + if leg.status == "approved" and no_request_in_flight(case) and leg.kind == "preauth": + out.append(action("Enhance", sends = 13)); out.append(action("Cancel", sends = PC01)); out.append(action("Discharge and claim", tab = claim)) + if leg.kind == "claim" and leg.status == "rejected": out.append(action("Ask for a reprocess", sends = 36)) + if payer.status_enquiry: out.append(action("Ask status", sends = task status)) + for notice in unacknowledged_notices(case): out.append(action("Acknowledge payment", sends = 17 or echo)) + return out +``` + +## Component vocabulary (suggested, for a standalone build) + +A suggested set of helpers. Server-rendered HTML from Python functions returning strings, styled by the 0build kit 0.5.4 from jsDelivr. Components: `z-card`, `z-button`, `z-input`, `z-select`, `z-table`, `z-nav`, `z-tab` with `data-z-switcher`, `z-alert`, `z-badge`, `z-breadcrumb`. Utilities take values through custom properties (`class="display-grid gap" style="--gap: 4"`). Helpers a screen needs: `page`, `card`, `stack`, `table`, `grid`, `field`, `text_input`, `select`, `button`, `post_button`, `confirm_form`, `badge`, `when`, `muted`, `dl`, `tabs`, `stat`, `empty_state`. Tables cap at about eight columns; merge facts into a main line with a muted sub-line. Every state-changing action that is not a full form is a `post_button`; destructive ones confirm. + +In `integrate` mode use the HMIS's own components and conventions; the layouts above are the content, not the markup. diff --git a/plugins/nhcx/skills/nhcx-reprocess/SKILL.md b/plugins/nhcx/skills/nhcx-reprocess/SKILL.md new file mode 100644 index 000000000..692450bcb --- /dev/null +++ b/plugins/nhcx/skills/nhcx-reprocess/SKILL.md @@ -0,0 +1,99 @@ +--- +name: nhcx-reprocess +description: Add the NHCX Task exchanges that follow a decision to a hospital information system or a standalone claims desk. Reprocess a rejected or partly paid claim (36), ask for the balance of a short payment (release, 36), and ask where a pre-auth or claim stands (status), reading the payer's answers (37 and the status Task), held to the pinned bundles. Starts by checking whether the app already sends these Tasks, and whether it holds the decided claim they act on, then builds, extends or reuses only what is missing. Self-contained; needs no other skill installed. Use for claim reprocess, arbitration, releasing a shortfall, status enquiries, NHCX use cases A5, B8 reprocess, D11 and D12, flow step F13. +--- + +# NHCX reprocess: reopening a decided claim, the balance, and where things stand + +This skill sends the small Task exchanges a desk needs once the payer has decided: a reprocess to reopen a rejected or partly paid claim, a release to ask for the balance of a short payment, and a status enquiry to ask where a pre-auth or claim stands. It reads the payer's answers and hands the reopened claim back to its thread. + +Read `core/LADDER.md` first. It holds the ladder every NHCX skill walks: the definition of compliant, the stages, the workspace, how to run a stage, and the rules. This folder carries everything it needs and runs on its own; the other six NHCX skills are separate folders, and none of them has to be installed. Paths starting `core/`, `stages/`, `references/`, `fhir/`, `flow/`, `ui/`, `templates/` or `scripts/` are relative to this folder. Paths starting `nhcx-package/` are in the NHCX package, which `scripts/fetch-package.sh` fetches into the target project beside `nhcx-build/`; `references/material.md` names the package file of every pin by its label. + +## What this skill covers + +| | | +| --- | --- | +| Flow step | F13 Status, reprocess, release | +| Tabs | Claim (tab 7): the reprocess and release cards; "Ask where it stands" on the pre-auth and claim cards | +| Wire | `v1/task/submit`: Task `reprocess`, workflow 36, reason `claimrejected`, `partialpayment` or `rejectiondisputed`, input `intimationNumber`, documents; Task `release`, workflow 36, reason `partialpayment`, `valueMoney`; Task `status`, workflow = the leg's correlation id, fallback 13. Answers: 37 (a Task `accepted` with a `queued` ClaimResponse), then a fresh verdict on the claim's own thread; the status Task with `claimStatus` | +| Next actions | "Ask for a reprocess", and the enquiry behind "With the payer; ask where it stands" | +| Use cases | A5 (the generic and PMJAY rows), B8 reprocess, D11, D12 | +| Module | 7.9, the reprocess, release and status parts | +| Pins | `claim/reprocess`, `claim/release`: `nhcx-package/fhir/B5/claim-{reprocess,release}.json` | +| Payer fixtures | `nhcx-package/fhir/C10/C10-arbitration-wf37.json` and its PMJAY twin (37); the live PMJAY reprocess in `nhcx-package/fhir/D11`. No status-enquiry answer is published; that reader is written from `nhcx-package/docs/05-FHIR Reference/18-Predetermination, Status and Search.md` | +| Tables | `claim_enquiry`: one row per ask, each on its own thread | +| FHIR | `fhir/FHIR.md` section 6; `references/fhir-knowledge.md` sections 7 and 8 | + +Not here: the cancel Task (PC01). It is a Task too, but it belongs to the pre-auth use case (`nhcx-preauth`). + +## Needs and hands on + +Needs: a decided claim (a reprocess needs one `rejected` or `partial`); a short payment (a release); a pre-auth or claim with the payer (a status enquiry). Stage 0 checks for them below, whichever way the app got them. + +Hands on: after a 37, the claim leg back to `submitting` (sub-stage `requested`), with the new verdict read by the claim's own reader; enquiry rows holding the payer's answers. + +## Capability check + +Stage 0 (`stages/0-capability-check.md`) gives every capability below a verdict: search for the markers, run the check, record what was observed. + +### Own + +| Id | What | Look for | Present when (observed) | +| --- | --- | --- | --- | +| `reprocess.reprocess` | Task `reprocess`, workflow 36 | `reprocess`, `"36"`, `intimationNumber`, `claimrejected` | The `claim/reprocess` pin passes as it is; the second input is spelled `intimationNumber` everywhere (a search for `initimation` finds nothing); it is offered only on a decided claim not paid in full | +| `reprocess.release` | Task `release`, workflow 36 | `release`, `valueMoney`, `partialpayment` | The `claim/release` pin passes; `valueMoney` carries `INR`; it is offered once part of an approved claim is paid | +| `reprocess.status` | Task `status` | `"status"`, `claimStatus`, the fallback `"13"` | The Task goes on `v1/task/submit` with workflow = the leg's correlation id; it is not offered at all for a payer whose adapter refuses it (PMJAY, PAYR-1018); the answer fills the enquiry row and leaves the leg unchanged | +| `reprocess.task-reader` | Read 37 and the status answer, and refusals | `parse_task_answer`, `accepted`, `37` | `C10-arbitration-wf37.json` (37) reads as the reprocess taken: the enquiry `answered`, the claim leg back to `submitting`; a ProtocolResponse on an enquiry thread sets the enquiry `error` with the payer's words and nothing else changes | +| `reprocess.screens` | The cards on the Claim tab; "Ask where it stands" | the reprocess form (reason, words, documents), the release form (amount) | Each ask is its own row, shown on its card, newest first, with the payer's answer verbatim | + +### Foundation + +All six capabilities in `core/FOUNDATION.md`. `foundation.storage` is partial until `claim_enquiry` exists; `foundation.state` until `next_actions` offers "Ask for a reprocess" and hides status for a payer that refuses it. + +### Prerequisites + +The claim use case (`nhcx-claim`), the payment use case (`nhcx-payment`) and the pre-auth use case (`nhcx-preauth`) own these. The checks are here, so none of those skills need be installed. + +| Capability | Why | Look for | Present when (observed) | +| --- | --- | --- | --- | +| `claim.send`, `claim.response-reader` | A reprocess reopens a decided claim, and the fresh verdict lands in the claim's reader | a claim leg with `claim_ref` and `correlation_id`; a ClaimResponse reader | A claim sent with a stubbed client on `v1/claim/submit` (workflow 15), then fed `nhcx-package/fhir/C7/C7-rejected-wf291.json` on its correlation id, ends `rejected`; the same reader settles `C7-approved-wf26.json` as `approved` | +| `payment.record` (only for `reprocess.release`) | A release needs a short payment | a payment table keyed on the notice's correlation id | `nhcx-package/fhir/C9/payment-notice.json` delivered for the claim makes one payment row with its amount | +| `preauth.send` (only for `reprocess.status` on a pre-auth) | A status enquiry needs a pre-auth with the payer | a pre-auth leg with `correlation_id` | A pre-auth sent with a stubbed client stores its correlation id | + +When only some prerequisites are present, the capabilities that depend on the missing ones are marked `later` in stage 1, and the rest go ahead. + +### Host facts + +The document store, since a reprocess can attach documents. + +## The ladder, for this skill + +| Stage | What is specific here | +| --- | --- | +| 0 | The tables above. | +| 1 | Confirm the shared page, or write it if this skill runs first on the app. Own rows: A5, B8 reprocess, D11, D12. D12 is commonly `later` (out of reach on the sandbox). Status for PMJAY is in scope as "not offered". | +| 2 | Risks: `intimationNumber` misspelled (PAYR-1008); status offered to PMJAY (PAYR-1018); a claim resubmit sent on PMJAY instead of a reprocess; the NHCX sandbox refuses `v1/status` (NHCX-1012), which is why status is a Task. | +| 3 | The host facts above. | +| 4 | The `claim_enquiry` home; the three Tasks' source maps; the destinations of the 37 and the status answer. If this skill maps first, every table's home too. | +| 5 | The cards on the Claim tab and the enquiry on the pre-auth card; action F13. | +| 6 | The parts of 7.9 above; the foundation modules stage 0 found absent or partial. If the app already has 7.9's Task builder for the cancel, extend it. | +| 7 | The parts of 7.9 above, as far as their verdicts say. | +| 8 | 7.9 Validate rows 1 (the reprocess and release pins), 2, 3 and 6; the cancel pin again if the Task builder changed. | +| 9 | Two pin comparisons; the 37 reader and the status reader; matrix rows A5 generic, A5 PMJAY, B8 reprocess, D11, D12; the cross-cutting rows on an enquiry thread. | +| 10 | Rung 1. Rung 3: B8 reprocess and A5 against a generic payer, which answers 37. Rung 4: D11 (see the rule below); A5 records the refusal. | +| 11 | This skill's section. | + +## Rules for these legs + +- Every Task input is spelled `intimationNumber`. +- A decided PMJAY claim goes back only as a reprocess; there is no 16. +- Each ask is its own `claim_enquiry` row, on its own thread, shown on the card it belongs to. +- The payer's 37 reopens the claim. The verdict that follows lands on the claim's own thread and is read by the claim's reader. +- A refusal changes nothing but the enquiry row, which keeps the payer's words. +- The sources disagree on D11 at the SHA: `references/flow-knowledge.md` section 6 records a 37 when the input is spelled `intimationNumber`, and the matrix in `references/testing-knowledge.md` section 3 records PAYR-1008. Build for the 37, record a refusal verbatim on the enquiry row, and write what the sandbox did in `NOTES.md`. + +## Done when + +- Every gate in this skill's block of `nhcx-build/STATE.md` is closed with evidence. +- The reprocess and release pins pass; status is not offered to a payer that refuses it. +- The compliance points in `core/LADDER.md` hold for F13. diff --git a/plugins/nhcx/skills/nhcx-reprocess/core/FOUNDATION.md b/plugins/nhcx/skills/nhcx-reprocess/core/FOUNDATION.md new file mode 100644 index 000000000..2037811b9 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-reprocess/core/FOUNDATION.md @@ -0,0 +1,65 @@ +# The foundation: what every skill stands on + +Six modules carry every leg, and no one skill owns them. Every skill's stage 0 checks them. The first skill that finds one absent or partial builds or extends it in its own stage 7, and records itself as `Built by` in the Foundation block of `nhcx-build/STATE.md`. Later skills find it present and reuse it. An HMIS that already has one (an NHCX integration, a webhook door, a claims table) has it `existing`. + +| Id | Module | What | Every skill adds | +| --- | --- | --- | --- | +| `foundation.transport` | 7.1 | Settings; the one transport behind `send` (the app's existing NHCX integration, the build's own, or nhcx-adapter when the user asked for it); the policy lookup; the outbound archive | Nothing; it sends through it | +| `foundation.storage` | 7.2 | The episode table with its claim number, payer and recipient codes, stage and sub-stage; the leg tables | The leg tables its `SKILL.md` lists, in its own migration | +| `foundation.callback` | 7.3 | The transport's receiving end and the door: dedupe, archive before apply, match by correlation id then claim number, the door refusal, the poll fallback where there is a ledger | Its readers, wired into the door's dispatch | +| `foundation.state` | 7.11 | The payer adapter table; `case_stage`, `stamp_case`, `next_actions` | The stage branches and next-action rows for its legs, labels verbatim from `flow/flow.json` | +| `foundation.screens` | 7.12 | The case screen shell: the eight tabs in the flow's order, the status line and actions, the JSON state address, the page-load polls, the cases list | Its own tabs and screens | +| `foundation.shell` | 7.13 | Standalone only: patients, admissions, practitioners, diagnoses, documents, settings, the run script | Nothing; `not applicable` in integrate mode | + +## Recognising each one + +For each capability: what to search for, what must be observed for it to be present, and what makes it partial. Search code, dependencies, migrations, configuration and tests. Run every check offline, with the network stubbed. + +### `foundation.transport` (7.1) + +- Look for an NHCX integration of the app's own: `x-hcx-`, `JWEPayload`, `RSA-OAEP-256`, `A256GCM`, a JOSE library among the dependencies, `bearer_auth`, a sessions URL on the ABDM gateway, `participanthcxservice`, `fetch/certs`, `participant/get/policies`, routes ending in `on_submit`, `on_check` or `on_request`, a vendor's NHCX or HCX client, a gateway service the app calls. Look also for nhcx-adapter already in use: `/fhir/out/`, `/out/v1/`, `jwe_headers`, an adapter URL setting, `/ledger/thread/`, `/internal/txn/related`. +- Present when: what was found meets the contract in `references/transport-knowledge.md` section 2, observed through 7.1's Validate rows 1 to 6 (and row 7 for an app that seals its own messages), with the network stubbed and a test key pair for the seal; and `send` is one function a test can replace. +- Partial when: it sends but misses a contract item (no `x-hcx-ben-abha-id`, the `payerid` as the recipient, no ids back to the caller, no archive) or cannot be stubbed. Extend it in place (`references/transport-knowledge.md` section 4). Never add a second transport beside it. +- Absent when: the app has no NHCX integration. The transport is then `own`, built from `references/transport-knowledge.md` section 3, unless the user has asked for nhcx-adapter. +- nhcx-adapter is never the answer to a partial or absent transport unless the user asked for it. Do not suggest it. + +### `foundation.storage` (7.2) + +- Look for: tables or models with `claim_no`, `correlation_id`, `txn_id`, `sub_stage`; migrations that mention claim, preauth or nhcx. +- Present when: observed on a migrated scratch database, or read from the schema file and confirmed by a migration run: the episode table has a unique claim number, member id, policy code, payer code, recipient code, patient and encounter keys, `stage` and `sub_stage`; every leg table this skill needs exists with `txn_id`, `correlation_id`, `api_call_id` and `thread_correlation_id`; the migration runs twice without error; deleting an episode removes its children (7.2 Validate, rows 2, 3, 5 and 6). For `nhcx-communication` and `nhcx-payment`, also row 4: the correlation id on their tables is unique by constraint. +- Partial when: the episode exists but a leg table this skill needs does not, a leg table lacks `thread_correlation_id` or `api_call_id`, or the episode keeps no `recipient_code`. The skill adds its tables and columns in a new migration. + +### `foundation.callback` (7.3) + +- Look for: routes under `/v1/` ending in `on_submit`, `on_check`, `on_request`, `/v1/error`, or a route with `callback` in it; `JWEPayload`, `ProtocolResponse`, `x-hcx-correlation_id`, `x-hcx-api_call_id`, a receipt with `protocol_status`. +- Present when: 7.3 Validate rows 1 to 5, 7 and 8 are observed by calling the receiving end with deliveries of the transport's kind (every inbound path reaches it; an unreadable body is archived and changes nothing; one api call id delivered twice changes state once and is `ignored`; an unknown correlation id is answered and archived under `unmatched`; a delivery is archived even when the apply raises; no outbound call during a delivery; the inbound authentication of the kind). Row 6, the door refusal, is checked by each skill on its own thread. +- Partial when: it receives but routes by path instead of by correlation id, lacks the dedupe, archives after applying, answers the exchange with anything but the 202 receipt (`own`, `existing`), hosts no `/v1/error`, or, with `adapter`, has no poll fallback. Extend it; there is one door. +- A skill whose reader is not wired into the door is partial for its own capability, not for the door. + +### `foundation.state` (7.11) + +- Look for: `query_mode`, `resubmit`, `1518`, a workflow id table (`"12"`, `"PC01"`, `"161"`), `sub_stage`, `next_actions`, a stamp after each write. +- Present when: 7.11 Validate rows 1 to 3 are observed (`adapter_for` with `1518@hcx` and `1518` gives PMJAY and an unknown code gives generic; the PMJAY workflow table equals `references/flow-knowledge.md` section 2; an override changes one kind only), and rows 4 to 7 hold on the seeded states the legs built so far can reach. +- Partial when: the payer table exists and the stage machine does not, or the stage machine lacks this skill's stage branches or labels. Each skill adds its own. + +### `foundation.screens` (7.12) + +- Look for: routes like `/claims`, `/claims/`, `/claims//state`; the tab keys `eligibility`, `plan`, `lines`, `validate`, `preauth`, `communication`, `claim`, `payments`. +- Present when: 7.12 Validate rows 1, 3, 8 and 9 are observed on the shell (the eight tabs in the flow's order with the flow's labels; routes answer 200 for a seeded case and 404 for an unknown one; no input or select named for a rate, a payer name, a `preAuthRef`, a UTR or a status; the state address returns `stage`, `sub_stage`, `next_actions` and `legs`). Rows 4 to 7 belong to the skills whose tabs they test. +- Partial when: the case screen exists without some tabs, without the status line, or without the state address. +- An HMIS with its own screens: the shell may live inside them, for example a panel on the admission screen that opens the case. Present is judged on the eight tabs and the state address, not on the look. + +### `foundation.shell` (7.13, standalone only) + +- Present when: every row of 7.13's Validate section is observed. +- In integrate mode: `not applicable`. The HMIS is the shell; stage 3 finds its patients, admissions, practitioners and documents. + +## Who builds what + +| Verdict at stage 0 | What the running skill does | +| --- | --- | +| `absent` | Builds it in stage 7, before its own modules. 7.1 and 7.3 whole, for the transport chosen at stage 1. 7.2: the episode table and this skill's leg tables. 7.11: the payer adapter table whole, and this skill's stage branches and labels. 7.12: the shell with all eight tabs present in order, its own tabs filled, the others showing their empty state. 7.13 whole, in standalone mode. | +| `partial` | Extends it in the existing code, for the difference stage 0 named, and runs the module's whole Validate section after. | +| `present` | Reuses it. Stage 8 still runs the rows this skill depends on. | + +Record: the Foundation row in `STATE.md` with `Built by` (the skill, or `existing`), and the module record `nhcx-build/7-modules/7.N.md` with a part for each skill that touched it. diff --git a/plugins/nhcx/skills/nhcx-reprocess/core/LADDER.md b/plugins/nhcx/skills/nhcx-reprocess/core/LADDER.md new file mode 100644 index 000000000..7a6f3f12b --- /dev/null +++ b/plugins/nhcx/skills/nhcx-reprocess/core/LADDER.md @@ -0,0 +1,185 @@ +# The NHCX build ladder + +This skill is one of seven NHCX skills, one per use case: `nhcx-coverage`, `nhcx-insurance`, `nhcx-preauth`, `nhcx-claim`, `nhcx-communication`, `nhcx-payment` and `nhcx-reprocess`. Each is a folder of its own and runs on its own: it carries this ladder, the stages, the module files, the references, the flow, the templates and the fetch script. The seven copies of these are the same; only `SKILL.md` differs. This file holds what they share. `SKILL.md` says which flow steps, legs, capabilities, modules, pins and test rows are this skill's own, and what it needs from the use cases before it. + +## Paths + +Paths that start with `core/`, `stages/`, `references/`, `fhir/`, `flow/`, `ui/`, `templates/` or `scripts/` are relative to this skill's folder, the one that holds `SKILL.md`. Paths that start with `nhcx-package/` are in the NHCX package, fetched into the target project beside `nhcx-build/` (below). Paths that start with `nhcx-build/` are the workspace in the target project. + +## Getting the material + +Pins, payer fixtures and docs come from the NHCX package, published at https://github.com/nha-in/nhcx-package. `scripts/fetch-package.sh` downloads the latest release, unpacks it to `nhcx-package/` beside `nhcx-build/` and verifies its MANIFEST (pass a link or a local path to use a different build). `references/material.md` says what the package holds, gives the file of every pin by its label (`preauth/request` is `nhcx-package/fhir/B3/preauth-request.json`), and lists what it does not hold. Read it once, at stage 0. + +## What the skills produce + +Software that raises cashless claims on the National Health Claims Exchange (NHCX) with a private insurer and with PMJAY, in one of two shapes: + +| Mode | You start with | You end with | +| --- | --- | --- | +| `integrate` | A working hospital information system (HMIS, EMR, HIS, billing system) in any language | The same system, with a claims module that speaks NHCX through its transport, kept in sidecar tables and removable | +| `standalone` | Nothing | A self-contained claims desk: its own patients, admissions, documents and screens, speaking NHCX through a transport of its own | + +Every message goes through one transport, chosen at stage 1 from three (`references/transport-knowledge.md` section 1): + +| Transport | When | What the build does | +| --- | --- | --- | +| `existing` | Stage 0 found the app already speaks NHCX: its own client, a vendor gateway, an SDK | Wraps it behind 7.1's `send` and 7.3's door, and closes its gaps; never replaces it | +| `own` | The app has no NHCX integration, and the user has not asked for nhcx-adapter | Builds the protocol into the app from NHA's published chapters: the ABDM session token, the key and certificate, the participant record, the recipient's certificate, the JWE, the callback and its receipt | +| `adapter` | Only when the user asks for nhcx-adapter | Downloads it from https://github.com/nha-in/nhcx-adapter/releases and talks plain FHIR to it (`references/api-knowledge.md`) | + +Never propose nhcx-adapter; use it only when the user asks for it. Whichever the transport, the rest of the build sees the same two things: `send`, and a door that receives `{meta, jwe_headers, fhir}`. + +## The seven skills + +One skill per use case. Together they walk the whole flow in `flow/FLOW.md`; each one alone builds its slice. This folder builds only its own row. The others are named so that a verdict can say which skill owns a missing piece. + +| Skill | Flow steps | Legs | Use cases | Pins | +| --- | --- | --- | --- | --- | +| `nhcx-coverage` | F1, F2, F3 | policy search; `v1/coverageeligibility/check` purpose `discovery`, `validation`, `benefits` | A2, B1, D3 | `coverage/{discovery,validation,benefits}` | +| `nhcx-insurance` | F4, F7 | `v1/insuranceplan/request`; lines quoted from the plan | B2, D1 | `insurance` | +| `nhcx-preauth` | F5, F6, F8, F9, F9a, F9b for a `resubmit` payer, F9c, F9d, F9e | auth requirements; `v1/preauth/submit` 12, 19, 13, 131 and predetermination; cancel PC01 | B3, B8 cancel, B9, D2, D4 to D8 | `coverage/authrequirements`, `preauth/{request,enhancement,queryupdate,cancel}` | +| `nhcx-claim` | F10, F11 | `v1/claim/submit` 15; 161 (PMJAY) or 151 (generic); 16 (generic) | B5, D9, D10 | `claim/{request,queryupdate}` | +| `nhcx-communication` | F9b and the claim query for a `communication` payer, F12b | `v1/communication/request` in; `v1/communication/on_request` out | B4 | `communication/response`, and the `communication/request` reader | +| `nhcx-payment` | F12 | `v1/paymentnotice/request` in; `v1/paymentnotice/on_request` out on 17 or the notice's own id | B7, D13 | `payment/notice-ack` | +| `nhcx-reprocess` | F13 | `v1/task/submit`: reprocess and release on 36, status; 37 and the status Task read | A5, B8 reprocess, D11, D12 | `claim/{reprocess,release}` | + +`flow/flow.json` names the skills of every step in `skills`. Fifteen pins, each owned by exactly one skill, plus the communication request read as the sixteenth comparison. + +### The order they depend on + +The use cases depend on one another in the order the episode happens. A full build runs the seven skills top to bottom. Any one can run alone on an app that already has what it needs; stage 0 establishes whether it does, with the checks in this skill's `SKILL.md` under "Prerequisites". The other skills do not have to be installed for that check. + +| Skill | Needs | Because | +| --- | --- | --- | +| `nhcx-coverage` | nothing | It opens the episode | +| `nhcx-insurance` | coverage: an episode with an `eligible` verdict | The plan is fetched for an eligible episode's policy | +| `nhcx-preauth` | coverage (eligible, and its builder for auth requirements); insurance (plan ready, lines quoted) | Items, prices, documents and forms come from the plan; F9 holds `eligible` | +| `nhcx-claim` | preauth: an approved or partial pre-auth with its `preAuthRef`, the dossier, the Claim builder | The claim goes under the pre-auth's number, built by the same builder | +| `nhcx-communication` | preauth or claim: a leg the payer can ask about, with its bundle as sent | A query names a Claim; the reply lifts entries from the bundle sent | +| `nhcx-payment` | claim: a filed claim | A notice is matched by the claim number | +| `nhcx-reprocess` | claim: a decided claim; payment for a release; preauth for status on a pre-auth | A reprocess reopens a decided claim; a release follows a short payment | + +## The foundation + +Six modules carry every leg and belong to no one skill: 7.1 (the transport), 7.2 (storage), 7.3 (the callback door), 7.11 (state and payer adapters), 7.12 (the case screen shell) and 7.13 (the standalone shell). Every skill's stage 0 checks them. The first skill that finds one absent builds it; a skill that runs later on the same app finds it present and reuses it. `core/FOUNDATION.md` says how to recognise each and what makes it present. + +## What compliant means + +Every skill is held to the same points, for its own legs: + +1. Every hospital-side leg the skill owns (`references/flow-knowledge.md` section 1) is sent with its workflow id, and every payer answer on it is read. +2. Every bundle the skill sends matches its pin in `nhcx-package/fhir` byte for byte, `created` excepted. +3. The callback door answers 2xx fast, dedupes on `x-hcx-api_call_id`, archives before it applies, and matches by correlation id first. +4. No screen shows a decision the exchange has not sent, and nothing the exchange already said is retyped. +5. The offline tests pass, and the report says honestly which rungs of the test pyramid were climbed. +6. The software walks the flow in `flow/FLOW.md`, step for step: the same steps in the same order, the same tabs with the same names, the same guards, the same action labels. The flow is copied, never redesigned. +7. Nothing the app already did is built a second time. Every capability stage 0 found present is reused, and validated and tested like new code. + +## The flow + +An NHCX provider desk walks one path from policy search to settlement, and a build from these skills walks it. `flow/FLOW.md` is that path: thirteen steps with their branches, the case screen's eight tabs in order, the status line, the action labels the desk sees, the guards before every send, and what runs on every page load. `flow/flow.json` is the same, machine-readable, with step ids `F1` to `F13`. Read FLOW.md whole at stage 1; stage 4 copies the steps, stage 5 puts the screens on them, stage 7 implements them by id, stage 8 checks every step has a route. An agent that reorders, merges or renames these steps has left the skill. + +## The ladder + +Twelve stages, 0 to 11. Each has one file under `stages/`, reads the artefacts of the stages before it, writes into `nhcx-build/` in the target project, and ends at a gate. A gate is a list of conditions a reader can check without trusting you. Do not start a stage until the gate before it is closed, and never close a gate by asserting it; close it by pointing at the evidence. + +This skill runs every stage over its own slice. Stage 1 is shared with any other NHCX skill that runs on the same app: the first writes it and later ones confirm it. Parts of stages 3 to 6 are the episode's, not the skill's: the first skill to reach them writes those parts whole, and later skills build on them. + +| Stage | File | Scope | Writes | Gate closes when | +| --- | --- | --- | --- | --- | +| 0 | `stages/0-capability-check.md` | this skill | `nhcx-build/0-capability.md` section, `nhcx-build/capabilities.json` entries | Every own, foundation and prerequisite capability has a verdict with observed evidence | +| 1 | `stages/1-idea.md` | shared | `nhcx-build/1-idea.md` | The mode, the payers, the scope of every step with its skill, and the constraints are written and the user has agreed | +| 2 | `stages/2-planning.md` | this skill | `nhcx-build/2-planning.md` section, this skill's block in `nhcx-build/STATE.md` | Every later stage has a size and a proof; every module has its action from stage 0 | +| 3 | `stages/3-discovery.md` | shared rows; this skill's host facts | `nhcx-build/3-discovery.md` | Every host fact this skill needs is answered with proof, or marked as a gap | +| 4 | `stages/4-flow-and-data-mapping.md` | the flow and table homes episode-wide; this skill's bundles | `nhcx-build/4-flow-data-mapping.md`, `nhcx-build/mapping.json` | Every table has a home, every leg the four ids, every bundle of this skill a source map | +| 5 | `stages/5-screen-plan.md` | the case screen shell episode-wide; this skill's tabs | `nhcx-build/5-screen-plan.md`, `nhcx-build/screens.json` | Every value on this skill's screens names its message; the honesty rules hold | +| 6 | `stages/6-code-plan.md` | this skill's modules; the client and configuration episode-wide | `nhcx-build/6-code-plan.md`, `nhcx-build/modules.json` | Every module this skill touches has files, dependencies, a pin and an action | +| 7 | `stages/7-write-code/README.md` and `7.N-*.md` | what stage 0 found absent or partial | Code, plus `nhcx-build/7-modules/7.N.md` | Each module's "Done when" list is met, in order | +| 8 | `stages/8-validate-modules.md` | every module part this skill owns, reused ones included | `nhcx-build/8-validation.md`, `nhcx-build/8-validation/7.N.json` | Every row passes, or carries a named, accepted exception | +| 9 | `stages/9-write-tests.md` | this skill's pins, readers and matrix rows | Test code, plus `nhcx-build/9-tests.md` | Every row this skill owns has a test, or a written reason it cannot | +| 10 | `stages/10-run-tests.md` | this skill's tests | `nhcx-build/10-test-run.md` and the raw outputs | The offline rung passes; the higher rungs are run only when the user starts the services | +| 11 | `stages/11-build-report.md` | this skill | `nhcx-build/11-report.md` section | The report is written from the artefacts, names every gap, and a stranger could resume from it | + +Stage 7 is a module ladder of its own, 7.1 to 7.13. Each module file carries its own Build, Pseudo code, Validate and Tests sections, and names the skills that build it; stage 8 runs the Validate sections and stage 9 writes the Tests sections, so a module is never validated against a checklist written somewhere else. + +## The workspace + +Everything this skill writes lives in one folder in the target project, so the work can be resumed, reviewed and deleted as a unit. When several NHCX skills work on one app they share that folder, whichever skill folder each runs from: each adds its own section or entries and leaves the others alone. + +``` +nhcx-build/ + STATE.md the gate ledger: the shared rows, the foundation, one block per skill + capabilities.json every capability checked, its verdict and its evidence; read and written by every skill + 0-capability.md one section per skill; scratch checks under 0-capability/ + 1-idea.md shared + 2-planning.md one section per skill + 3-discovery.md shared; each row says which skill answered it + 4-flow-data-mapping.md the flow and table homes, then one section per skill; plus mapping.json + 5-screen-plan.md the case screen shell, then one section per skill; plus screens.json + 6-code-plan.md the client and configuration, then one section per skill; plus modules.json + 7-modules/7.1.md .. 7.13.md one record per module; a shared module has a part per skill + 8-validation.md one section per skill; plus 8-validation/7.N.json, each row tagged with its skill + 9-tests.md one section per skill + 10-test-run.md one section per skill; plus 10-test-run/-*.log + 11-report.md a summary across skills, then one section per skill + NOTES.md every place a skill was silent, ambiguous or wrong +``` + +`templates/` holds the skeleton of each artefact. Copy the skeleton, fill it, keep its headings: later stages find things by heading. + +## How to run a stage + +1. Read `nhcx-build/STATE.md`. If stage 1 in the Shared block is open, and this skill's stage 0 is closed, run stage 1. Otherwise find the first open gate in this skill's block. That is the stage to run; do not skip ahead and do not redo a closed stage unless the user asks. +2. Read the stage file. Read the artefacts it lists under Inputs, and this skill's `SKILL.md` row for the stage. Read the references it names, in the sections it names. +3. Do the work. Write the artefact from its template, in this skill's section. +4. Walk the gate. For each condition, write the evidence into STATE.md: a file path, a line, a command and its output. A condition with no evidence stays open. Every artefact that names a step, a tab or an action uses the ids and words from `flow/flow.json`. +5. If a gate needs the user (stage 0 when a prerequisite is missing; stage 1 always when it is first written; stage 10 rungs 3 and 4 always), stop and ask. Otherwise continue to the next stage. + +Resuming later is step 1 again. Nothing lives in your memory; everything lives in `nhcx-build/`. + +You may be asked to run one stage alone with the earlier artefacts already written. Treat those as closed; do not rewrite them. + +## Rules that hold throughout + +- Reading and offline commands only until stage 10 says otherwise. Never start a service or send live traffic unless the user asks. +- Never edit the files in `nhcx-package/`. They are the truth you are held to. +- Build only what stage 0 found absent or partial. A capability found present is reused through its existing code, never built a second time: two transports or two callback doors break the rule that one module sends and one receives. +- Present means a check was observed passing. Code that looks right is partial until its check has run. +- Never build another skill's capability inside this one. When a prerequisite is missing, stop and say which skill owns it. +- When this skill extends a module another skill built, it re-runs that skill's Validate rows for the module. The rows are in the module file, which every skill folder carries. +- This skill writes its own section of a shared artefact and leaves the other skills' sections alone. +- Never hard-code a document code, a package code or a questionnaire url. Take them from the payer's plan or auth-requirements answer. +- Every outbound leg stores three things from the transport's answer: `txn_id`, `correlation_id` and `api_call_id`. Every message is addressed to the policy's processor (`recipient_code`) and carries the beneficiary's ABHA. Every inbound message is matched by `x-hcx-correlation_id` first and by the claim number inside the bundle second. +- Take the decisions from the module files (Build, Rules, Pseudo code) and `fhir/FHIR.md`, and write them in the target's language and conventions. Never invent a shape the pins do not show. +- Write `nhcx-build/NOTES.md` as you go. A fact the skill does not give you is a gap to record, never a guess to bury in code. +- No em dashes anywhere you write. Short sentences. Tables for anything with more than three columns of fact. +- Do not claim a rung of the test pyramid was climbed when it was not. The report's value is its honesty. + +## Reference map + +| File | Holds | Read at | +| --- | --- | --- | +| `core/FOUNDATION.md` | The six foundation capabilities: how to recognise each, what makes it present, who builds it | Stage 0, stage 7 when building one | +| `references/flow-knowledge.md` | The episode and its legs, every workflow id, the two payer kinds, the classification rule, stage vocabulary, the use-case catalogue, rules no document states | Stages 1, 2, 4, 7.4 to 7.11 | +| `references/transport-knowledge.md` | The three transports and when each applies; the contract `send` and the door rely on; building the protocol yourself from NHA's chapters (token, key and certificate, participant record, policy lookup, recipient certificate, JWE, callback and receipt, status and `/v1/error`); wrapping an existing integration; getting nhcx-adapter when asked | Stages 0, 1, 4, 6, 7.1, 7.3 | +| `references/api-knowledge.md` | The nhcx-adapter contract, read only when the user chose the adapter: config, routes, envelope and answer, delivery, ledger, kit endpoints, curl | 7.1 and 7.3, adapter only | +| `references/fhir-knowledge.md` | Every bundle sent and received, element ids, HPIN, consent questionnaires, supportingInfo, LM100, ONS and DTM, the TaskBundle reply, where the pins live, the validator | Stages 4, 6, 7.4 to 7.10, 8 | +| `references/errors-and-debugging.md` | PAYR and ERR codes with meaning and fix, gateway errors, reading a ledger thread, correlation mistakes, redelivery, sandbox pace | Stages 8, 10, 11 | +| `references/testing-knowledge.md` | The test pyramid, the test-case matrix per use case, a skeleton offline test | Stages 2, 9, 10 | +| `fhir/FHIR.md` | The FHIR guide: every bundle sent and read, entries in pinned order, the code systems, pseudo code for each builder and reader, the refusal each rule guards against | Stages 0, 4, 6, 7.4 to 7.10, 8 | +| `ui/UI-GUIDE.md` | The screens: the two honesty rules, where every value comes from, a layout per screen, the state words, pseudo code for the status line, the timeline and the actions | Stages 5, 7.12, 7.13 | +| `flow/FLOW.md`, `flow/flow.json` | The one path an episode walks: steps F1 to F13 and their skills, the tab order, the action labels, the guards, the page-load polls | Stage 1 whole; stages 4, 5, 7, 8 by step id | +| `references/material.md` | Where the pins, fixtures and docs live: the NHCX package, the pin map, what the package lacks | Stage 0, and whenever a cited file is needed | + +## Keeping the seven copies in step + +Everything in this folder except `SKILL.md` is the same in all seven skill folders. A change to one of these files is made in all seven. `diff -r --exclude=SKILL.md` between any two skill folders prints nothing when they agree. + +## Deliverables + +- This skill's sections of `nhcx-build/`, every gate in its STATE.md block closed with evidence or open with a reason. +- Its verdicts in `capabilities.json`, each with the check that decided it. +- Schema additions for its legs (integrate) or its tables in the whole schema (standalone), under the target's conventions. +- Builders and readers for every leg it owns, each compared with its pin in the offline test. +- Its tabs and screens, deriving every state from received messages. +- Tests covering its rows of the matrix, a run record, and a report section a stranger could act on. diff --git a/plugins/nhcx/skills/nhcx-reprocess/fhir/FHIR.md b/plugins/nhcx/skills/nhcx-reprocess/fhir/FHIR.md new file mode 100644 index 000000000..90b85cbae --- /dev/null +++ b/plugins/nhcx/skills/nhcx-reprocess/fhir/FHIR.md @@ -0,0 +1,658 @@ +# NHCX FHIR: the bundles a hospital sends and reads + +Every bundle here is held to a pin in the NHCX package, under `nhcx-package/fhir/B*`. Read `../references/fhir-knowledge.md` for the why; this file is the how. The pseudo code is language-neutral: a `dict` is a JSON object, a `list` is a JSON array, and `ref(url)` is `{"reference": url}`. + +## 1. Conventions every bundle follows + +"Validator" below is the HL7 FHIR validator with the NRCeS `ndhm.in` IG, run as `../references/fhir-knowledge.md` section 11 describes. + +| Rule | Detail | Refusal if broken | +| --- | --- | --- | +| Bundle | `resourceType Bundle`, `type collection`, `id` fixed per shape, `meta.profile` = the NRCES bundle profile | validator error | +| Entries | Every entry has an absolute `fullUrl` under `https://nhcx.abdm.gov.in/...`; every `reference` resolves to a `fullUrl` in the same bundle | validator error, PAYR-10xx | +| Profiles | Every resource carries `meta.profile` = `https://nrces.in/ndhm/fhir/r4/StructureDefinition/` | validator warning | +| No timestamps on requests | No `meta.versionId`, `meta.lastUpdated`, bundle `timestamp` (the communication reply is the exception) | none, but the pin differs | +| Money | `{"value": n, "currency": "INR"}`; whole numbers as integers, never `3300.0` | pin differs | +| Instants | IST with `+05:30`, seconds precision | PAYR on dates | +| Identifiers | Typed with a `type.coding` from the NDHM identifier-type system or HL7 v2-0203, `system` where the pin has one | PAYR-1083 and kin | + +### Code systems, named once + +``` +NDHM = "https://nrces.in/ndhm/fhir/r4/CodeSystem/" +PROFILE = "https://nrces.in/ndhm/fhir/r4/StructureDefinition/" +BASE = "https://nhcx.abdm.gov.in" +HL7 = "http://terminology.hl7.org/CodeSystem/" +SNOMED = "http://snomed.info/sct" +ICD10 = "http://hl7.org/fhir/sid/icd-10" +HPR = "https://hpr.abdm.gov.in" + +ID_TYPE = NDHM + "ndhm-identifier-type-code" # PMJAY, ABHA, HPID, HPIN, CLN +V2_0203 = HL7 + "v2-0203" # MB, MD, NH, NPI, NIIP +V2_0360 = HL7 + "v2-0360" # qualification degrees +ORG_TYPE = HL7 + "organization-type" # prov, pay +ACT_CODE = HL7 + "v3-ActCode" # HIP +REL = HL7 + "subscriber-relationship" # self +PRIORITY = HL7 + "processpriority" # normal +CARE_ROLE = HL7 + "claimcareteamrole" # primary, assist +DX_TYPE = HL7 + "ex-diagnosistype" # admitting +DX_ONADM = HL7 + "ex-diagnosis-on-admission" # yes +FIN_TASK = HL7 + "financialtaskcode" # poll, cancel, reprocess, release, status +FIN_INPUT = HL7 + "financialtaskinputtype" # include +COMM_CAT = HL7 + "communication-category" # notification + +BENEFIT_CAT = NDHM + "ndhm-benefit-category" # Claim.item.category (specialty) +PROC_CODE = NDHM + "ndhm-procedure-code" # Claim.item.productOrService (package) +PROGRAM = NDHM + "ndhm-program-code" # AB-PMJAY +SI_CATEGORY = NDHM + "ndhm-supportinginfo-category" # INV, ONS, OTH, HDS, DIS, NMI, INF, STG +SI_CODE = NDHM + "ndhm-supportinginfo-code" # ADDD, EDT, PSP, DSDE, DTM, DTH, LAMA, DAMA, CQD, ODN +DOC_CODE = BASE + "/document-code" # the plan's MANDxxxx codes, else ODN +TASK_INPUT = NDHM + "ndhm-task-input-type-code" # policyNumber, providerId, claimNumber, intimationNumber, document +TASK_INPUT_X = BASE + "/task-input-type" # amount +TASK_OUTPUT = NDHM + "ndhm-task-output-type" # status +TASK_OUTVAL = NDHM + "ndhm-task-output-value" # paymentack +TASK_CODES = NDHM + "ndhm-task-codes" # deliver +REASON = NDHM + "ndhm-reason-code" # treatmentplanchanged, claimrejected, partialpayment, rejectiondisputed +CAT_CODE = BASE + "/category-code" # CoverageEligibilityRequest.item.category +PRODUCT_CODE = BASE + "/product-code" # CoverageEligibilityRequest.item.productOrService +PROC_TYPE = BASE + "/procedure-type" # conservative, medical, surgical +DOC_TYPE_EXT = settings.document_type_extension_url # on a Communication attachment; participant-defined (nhcx-package/docs/05-FHIR Reference/17-Communication.md). + # The communication/response pin carries its author's own url: the pin comparison sets this from the pin. +``` + +### Shared helpers + +``` +function cc(system, code, display=null): # CodeableConcept + coding = {"code": code}; if system: coding.system = system; if display: coding.display = display + return {"coding": [coding]} + +function typed_id(type_system, type_code, type_display, value, system=null): + out = {"type": cc(type_system, type_code, type_display), "value": value} + if system: out.system = system # put "system" before "value" as the pins do; canonical JSON sorts anyway + return out + +function entry(url, resource): return {"fullUrl": url, "resource": resource} + +function profile(name): return {"profile": [PROFILE + name]} + +function bundle(id, profile_name, entries): # profile_name: "ClaimBundle", "TaskBundle", "CoverageEligibilityRequestBundle" + return {"resourceType": "Bundle", "id": id, "meta": profile(profile_name), "type": "collection", "entry": entries} + +function organization(role, identifier_code, identifier_display, id_value, name, res_id=null): + o = {"resourceType": "Organization", "meta": profile("Organization"), + "identifier": [typed_id(V2_0203, identifier_code, identifier_display, id_value, BASE)], + "type": [cc(ORG_TYPE, role, "Healthcare Provider" if role == "prov" else "Payer")], "name": name} + if res_id: o.id = res_id + return o + +function provider_org(facility, res_id=null): return organization("prov", "NPI", "National provider identifier", facility.hfr_id, facility.name, res_id) +function payer_org(payer, res_id=null): return organization("pay", "NIIP", "National Insurance Payor Identifier (Payor)", strip_hcx(payer.participant_code), payer.name, res_id) +function strip_hcx(code): return code.split("@")[0] + +function money(v): return {"value": int(v) if v == int(v) else round(v, 2), "currency": "INR"} +``` + +## 2. Coverage eligibility request + +Pins: `coverage/{discovery,validation,benefits,authrequirements}`. Sent on `v1/coverageeligibility/check`, workflow id = the case number. Purposes: `discovery` (who covers this person), `validation` (is the policy in force), `benefits` (balances), `auth-requirements` (rule on the quoted items). + +Entries, in order: CoverageEligibilityRequest, Patient, provider Organization, payer Organization, Location, Coverage, PractitionerRole. + +``` +function build_coverage_request(d): + # d: purpose, member_id, policy_code (null on discovery), facility{hfr_id,name}, payer{participant_code,name}, created, items[] (benefits, auth-requirements only) + U = BASE + cer = {"resourceType": "CoverageEligibilityRequest", "meta": profile("CoverageEligibilityRequest"), + "identifier": [{"system": BASE}], "status": "active", + "priority": cc(PRIORITY, "normal", "Normal"), "purpose": [d.purpose], + "patient": ref(U + "/patient"), "created": d.created, + "enterer": ref(U + "/practitioner-role"), "provider": ref(U + "/provider"), + "insurer": ref(U + "/payer"), "facility": ref(U + "/location"), + "insurance": [{"focal": true, "coverage": ref(U + "/coverage")}]} + if d.purpose in ("benefits", "auth-requirements"): + cer.item = [eligibility_item(i) for i in d.items] + patient = {"resourceType": "Patient", "meta": profile("Patient"), + "identifier": [typed_id(ID_TYPE, "PMJAY", "Pradhan Mantri Jan Aarogya Yojana (PMJAY) ID", d.member_id), + typed_id(V2_0203, "MB", "Member Number", d.member_id)]} # no name, no demographics + coverage = {"resourceType": "Coverage", "meta": profile("Coverage"), + "identifier": [typed_id(V2_0203, "NH", "National Health Plan Identifier", d.policy_code or "NONE")], + "status": "active", "type": cc(ACT_CODE, "HIP", "health insurance plan policy"), + "subscriber": ref(U + "/patient"), "subscriberId": d.member_id, "beneficiary": ref(U + "/patient"), + "relationship": cc(REL, "self"), "payor": [ref(U + "/payer")]} + location = {"resourceType": "Location", "name": d.facility.name, "managingOrganization": ref(U + "/provider")} + role = {"resourceType": "PractitionerRole", "meta": profile("PractitionerRole"), + "code": [cc(SNOMED, "307988006", "Medical technician")]} + return bundle("coverage-" + d.purpose.replace("-", "") + "-request-generic", "CoverageEligibilityRequestBundle", [ + entry(U + "/coverage-eligibility/request", cer), entry(U + "/patient", patient), + entry(U + "/provider", provider_org(d.facility)), entry(U + "/payer", payer_org(d.payer)), + entry(U + "/location", location), entry(U + "/coverage", coverage), entry(U + "/practitioner-role", role)]) + +function eligibility_item(i): + # i: category{code,display}, code, display, quantity (integer), tiers[] {code, display} + out = {"category": cc(CAT_CODE, i.category.code, i.category.display), + "productOrService": cc(PRODUCT_CODE, i.code, i.display), + "quantity": {"value": int(i.quantity)}} + if i.tiers: out.modifier = [cc(null, t.code, t.display) for t in i.tiers] # no system on a tier + return out +``` + +Bundle ids: `coverage-discovery-request-generic`, `coverage-validation-request-generic`, `coverage-benefits-request-generic`, `coverage-authrequirements-request-generic`. + +### Reader: CoverageEligibilityResponse + +The payer echoes the request's entries and appends its own; take the last of each type. + +``` +function parse_validation_bundle(b): + resp = last(b, "CoverageEligibilityResponse"); pat = last(b, "Patient"); cov = last(b, "Coverage") + out = {"outcome": resp.outcome, "disposition": resp.disposition, "inforce": resp.insurance[0].inforce, + "auth_required": any(item.authorizationRequired for item in resp.insurance[0].item or []), + "allowed": null, "used": null} + for item in resp.insurance[0].item or []: + for ben in item.benefit or []: + if ben.allowedMoney and (out.allowed is null or ben.allowedMoney.value > out.allowed): + out.allowed = ben.allowedMoney.value; out.used = (ben.usedMoney or {}).value or 0 + out.patient = {"name": pat.name[0].text, "gender": pat.gender, "birthDate": pat.birthDate, + "abha": first_identifier(pat, "ABHA"), "photo": pat.photo[0].data if pat.photo else null} + out.coverage = {"class": cov.class[0].name if cov.class else null, "period": cov.period} + return out +# status: eligible if inforce else not-eligible; balance shown = allowed - used +``` + +### Reader: the auth-requirements ruling + +``` +function parse_auth_bundle(b): + resp = last(b, "CoverageEligibilityResponse"); items = []; requirements = [] + for item in resp.insurance[0].item or []: + items.append({"code": item.productOrService.coding[0].code, "authorised": item.authorizationRequired, + "excluded": item.excluded, "benefit": item.benefit[0] if item.benefit else null}) + for sup in item.authorizationSupporting or []: + text = sup.text or "" # the scheme overloads free text + r = {"line": item.productOrService.coding[0].code, "code": sup.coding[0].code if sup.coding else null, + "display": sup.coding[0].display if sup.coding else text} + if "fullUrl:" in text: r.kind = "form"; r.url = after("fullUrl:", text).strip(); r.stage = "pre" + else: r.kind = "document"; r.stage = "post" if "Type: post" in text else "pre" + r.at_preauth = (r.kind == "form") or (r.stage == "pre") + requirements.append(r) + return {"items": items, "requirements": requirements} +``` + +## 3. Insurance plan request + +Pin: `insurance`. Sent on `v1/insuranceplan/request`, workflow id = the case number. One entry. + +``` +function build_plan_request(policy_code, provider_id): + task = {"resourceType": "Task", "meta": profile("Task"), "status": "requested", "intent": "order", + "code": cc(FIN_TASK, "poll"), + "input": [{"type": cc(TASK_INPUT, "policyNumber"), "valueString": policy_code}, + {"type": cc(TASK_INPUT, "providerId"), "valueString": provider_id}]} + return bundle("insurance-request-generic", "TaskBundle", [entry(BASE + "/insurance/request", task)]) +# no id, no authoredOn, no requester; at least one input is mandatory +``` + +### Reader: the plan + +``` +function parse_plan_bundle(b): + plan = first(b, "InsurancePlan"); forms = {q.url: q for q in all(b, "Questionnaire")} + benefits = {} # keyed by package code + for p in plan.plan or []: # shape 1: package-based + for sc in p.specificCost or []: + specialty = sc.category.coding[0] + for ben in sc.benefit or []: + code = ben.type.coding[0].code; row = benefits.setdefault(code, new_benefit(code, ben.type.coding[0].display, specialty)) + for cost in ben.cost or []: + kind = cost.type.coding[0].code # Procedure | Implant | Stratification + if kind == "Procedure": row.rate = cost.value.value; row.kind = "Procedure" + else: row.extras.append({"kind": kind, "code": cost.qualifiers[0].coding[0].code, "display": cost.qualifiers[0].coding[0].display, "amount": cost.value.value}) + row.conditions.update(read_conditions(ben.extension)); row.requirements += read_requirements(ben.extension) + for cov in plan.coverage or []: # shape 2: coverage-based + for ben in cov.benefit or []: + code = ben.type.coding[0].code; row = benefits.setdefault(code, new_benefit(code, ben.type.coding[0].display, cov.type.coding[0])) + for lim in ben.limit or []: + if lim.code.coding[0].code == code: row.rate = lim.value.value + else: row.extras.append({"kind": "Stratification", "code": lim.code.coding[0].code, "display": lim.code.coding[0].display, "amount": lim.value.value}) + row.conditions.update(read_conditions(ben.extension)); row.requirements += read_requirements(ben.extension) + policy_requirements = read_requirements(plan.extension) # policy-wide: identity proof, consent forms + return {"plan": {"id": plan.id, "name": plan.name}, "benefits": list(benefits.values()), + "policy_requirements": policy_requirements, + "forms": [{"url": u, "title": q.title, "kind": "stg" if "/stgquestionnaire/" in u else "policy", + "questions": [{"linkId": it.linkId, "text": it.prefix or it.text, "type": it.type, + "options": [o.valueString or o.valueCoding.display for o in it.answerOption or []], + "default": first_selected(it)} for it in q.item]} for u, q in forms.items()]} + +function read_conditions(exts): # extension url family "...Claim-Condition": children named by their url tail + out = {} + for e in exts or []: + if "Claim-Condition" in e.url: + for child in e.extension or []: out[tail(child.url)] = child.valueString or child.valueBoolean or child.valueCodeableConcept.coding[0].code + return out + +function read_requirements(exts): # "...Claim-SupportingInfoRequirement": one nested requirement per document + out = [] + for e in exts or []: + if "Claim-SupportingInfoRequirement" in e.url: + for req in e.extension or []: + r = {} + for f in req.extension or []: + if tail(f.url) == "category": r.category = f.valueCodeableConcept.coding[0].code + if tail(f.url) == "code": r.code = f.valueCodeableConcept.coding[0].code; r.display = f.valueCodeableConcept.coding[0].display + if tail(f.url) == "documentationUrl": r.url = f.valueUri or f.valueString + out.append(r) + return out +``` + +## 4. The Claim bundle + +Pins: `preauth/request`, `preauth/enhancement`, `preauth/queryupdate`, `claim/request`, `claim/queryupdate`. One builder, three switches: `leg` (`preauth`, `claim`, `predetermination`), `flow` (`request`, `enhancement`, `queryupdate`), `use` (`preauthorization`, `claim`, `predetermination`). + +Entries, in order: Claim, Patient, provider Organization (id 1), payer Organization (id 2), Coverage (id 1), Practitioner (one per care team member), Procedure (one per package line), QuestionnaireResponse (one per answered form). + +``` +function claim_bundle(leg, use, d): + # d: flow, claim_no, created, admission{admitted_at, discharged_at, surgery_at, death_at, mode, stage}, + # patient{member_id, abha, name, phone, gender, birthDate}, facility, payer, policy_code, + # care_team[] {hpid, licence, hpin, name, qualification_code, qualification_display, specialty_snomed, specialty_display}, + # diagnoses[] {code, display}, lines[] (procedures and implants, each with tiers[]), documents[] {code, category, content_type, bytes, title}, + # forms[] {url, answers[] {linkId, type, value}}, program_code (AB-PMJAY or null), factor_rule (pmjay or null), + # preauth_ref (claim leg), summary{code, content_type, bytes, title} (claim leg), query_reply (queryupdate) + U = BASE; anchor = U + "/" + leg + "/" + d.flow + practitioners = [practitioner_resource(m, n + 1) for n, m in enumerate(d.care_team)] + procedures = [procedure_resource(line, n + 1, completed = (leg == "claim"), when = d.admission.surgery_at or d.admission.admitted_at) for n, line in enumerate(package_lines(d.lines))] + (qrs, form_refs) = questionnaire_responses(d.forms, d.created) + (si, si_refs) = supporting_info(d, leg, form_refs) + claim = {"resourceType": "Claim", "id": d.claim_no, "meta": profile("Claim"), + "identifier": [typed_id(ID_TYPE, "CLN", "Claim number", d.claim_no, BASE)], + "status": "active", "type": cc(SNOMED, "737481003", "Inpatient care management (procedure)"), "use": use, + "patient": ref(U + "/patient"), + "billablePeriod": {"start": d.admission.admitted_at, "end": d.admission.discharged_at or planned_end(d)}, + "created": d.created, "insurer": ref(U + "/payer"), "provider": ref(U + "/provider"), + "priority": cc(PRIORITY, "normal", "Normal"), + "careTeam": [{"sequence": n + 1, "provider": ref(practitioner_url(n)), + "role": cc(CARE_ROLE, "primary" if n == 0 else "assist", "Primary provider" if n == 0 else "Assisting Provider"), + "qualification": cc(SNOMED, m.specialty_snomed, m.specialty_display)} for n, m in enumerate(d.care_team)], + "supportingInfo": si, + "diagnosis": [{"sequence": n + 1, "diagnosisCodeableConcept": cc(ICD10, dx.code, dx.display), + "type": [cc(DX_TYPE, "admitting", "Admitting Diagnosis")], "onAdmission": cc(DX_ONADM, "yes", "Yes")} for n, dx in enumerate(d.diagnoses)], + "procedure": [{"id": "Procedure/" + str(n + 1), "sequence": n + 1, + "type": [cc(PROC_TYPE, line.procedure_type.lower(), line.procedure_type)], # from the plan's ProcedureType condition + "date": d.admission.surgery_at or d.admission.admitted_at, + "procedureReference": {"reference": U + "/procedure/" + str(n + 1), "display": line.display}} for n, line in enumerate(package_lines(d.lines))], + "insurance": [{"sequence": 1, "focal": true, "coverage": ref(U + "/coverage")}], + "item": claim_items(d, si_refs), + "total": money(sum(item.net.value for item in items))} + if leg == "claim": claim.insurance[0].preAuthRef = [d.preauth_ref] # the payer's ClaimResponse.preAuthRef + entries = [entry(anchor, claim), entry(U + "/patient", patient_resource(d.patient)), + entry(U + "/provider", provider_org(d.facility, "1")), entry(U + "/payer", payer_org(d.payer, "2")), + entry(U + "/coverage", coverage_resource(d.policy_code, d.patient.member_id))] + entries += [entry(practitioner_url(n), p) for n, p in enumerate(practitioners)] + entries += [entry(U + "/procedure/" + str(n + 1), p) for n, p in enumerate(procedures)] + entries += [entry(U + "/questionnaireresponse/" + str(n + 1), q) for n, q in enumerate(qrs)] + return bundle(leg + "-" + d.flow + "-request-generic", "ClaimBundle", entries) + # preauth-request-generic, preauth-enhancement-request-generic, preauth-queryupdate-request-generic, claim-request-generic, claim-queryupdate-request-generic + +function practitioner_url(n): return BASE + "/practitioner" + ("" if n == 0 else "/" + str(n + 1)) + +function patient_resource(p): + ids = [typed_id(ID_TYPE, "PMJAY", "Pradhan Mantri Jan Aarogya Yojana (PMJAY) ID", p.member_id)] + if p.abha: ids.append(typed_id(ID_TYPE, "ABHA", "Ayushman Bharat Health Account (ABHA) ID", p.abha)) + ids.append(typed_id(V2_0203, "MB", "Member Number", p.member_id)) + return {"resourceType": "Patient", "id": "1", "meta": profile("Patient"), "identifier": ids, + "name": [{"text": p.name}], "telecom": [{"system": "phone", "value": p.phone}], "gender": p.gender, "birthDate": p.birthDate} + +function practitioner_resource(m, n): + ids = [typed_id(ID_TYPE, "HPID", "Healthcare Professional ID (HPID)", m.hpid or m.hpin, BASE)] + if m.licence: ids.append(typed_id(V2_0203, "MD", "Medical License number", m.licence, BASE)) + ids.append(typed_id(ID_TYPE, "HPIN", "Health Practitioner ID issued by NDHM", m.hpin, HPR)) # PAYR-1083 without it + return {"resourceType": "Practitioner", "id": str(n), "meta": profile("Practitioner"), "identifier": ids, + "name": [{"text": m.name}], "qualification": [{"code": cc(V2_0360, m.qualification_code, m.qualification_display)}]} + +function coverage_resource(policy_code, member_id): + return {"resourceType": "Coverage", "id": "1", "meta": profile("Coverage"), + "identifier": [typed_id(V2_0203, "NH", "National Health Plan Identifier", policy_code)], + "status": "active", "type": cc(ACT_CODE, "HIP", "health insurance plan policy"), + "subscriber": ref(BASE + "/patient"), "subscriberId": member_id, "beneficiary": ref(BASE + "/patient"), + "relationship": cc(REL, "self"), "payor": [ref(BASE + "/payer")]} + +function procedure_resource(line, n, completed, when): + return {"resourceType": "Procedure", "id": str(n), "meta": profile("Procedure"), + "status": "completed" if completed else "preparation", + "code": {"coding": [{"system": SNOMED, "code": "71388002", "display": "Procedure"}], "text": line.display}, + "subject": ref(BASE + "/patient"), "performedDateTime": when} +``` + +### Items: one per procedure or implant, never per tier + +``` +function package_lines(lines): return [l for l in lines if l.kind in ("procedure", "implant")] # tiers ride on their parent + +function claim_items(d, si_refs): + groups = package_lines(d.lines); factors = procedure_factors(groups, d.factor_rule) + items = [] + for n, line in enumerate(groups): + tiers = [t for t in d.lines if t.kind == "tier" and t.parent_code == line.code] + net = line.amount + sum(t.amount for t in tiers) + item = {"id": "Item/" + str(n + 1), "sequence": n + 1, "careTeamSequence": [1], "diagnosisSequence": [1], + "procedureSequence": [n + 1], "informationSequence": si_refs, # every supportingInfo sequence + "category": cc(BENEFIT_CAT, line.category.code, line.category.display), + "productOrService": cc(PROC_CODE, line.code, line.display)} + if tiers: item.modifier = [cc(null, t.code, t.display) for t in tiers] + if d.program_code: item.programCode = [cc(PROGRAM, d.program_code, "Ayushman Bharat Pradhan Mantri Jan Arogya Yojana (AB-PMJAY)")] + item.servicedPeriod = {"start": day(d.admission.admitted_at), "end": day(d.admission.discharged_at or planned_end(d))} + item.quantity = {"value": int(line.quantity)} + item.unitPrice = money(net / line.quantity) + if factors: item.factor = factors[n] + item.net = money(net) + items.append(item) + return items + +function procedure_factors(groups, rule): + # PMJAY multiple-procedure rule: by cost rank, 1, 0.5, 0.25; a generic payer sends no factor + if rule != "pmjay" or len(groups) < 2: return null # the single-item pins carry factor 0.5 (their own contradiction); compare without it + ranked = sorted(range(len(groups)), key = lambda i: -groups[i].amount) + return {i: [1, 0.5, 0.25][min(rank, 2)] for rank, i in enumerate(ranked)} +``` + +### supportingInfo: the table, then the numbering + +``` +function supporting_info(d, leg, form_refs): + si = [] + for doc in d.documents: # one per attached file; never drop one + si.append({"category": cc(SI_CATEGORY, doc.category or "INV", display_for(doc.category or "INV")), + "code": cc(DOC_CODE, doc.code or "ODN", doc.title), # the plan's code, else ODN + "valueAttachment": {"contentType": doc.content_type, "data": base64(doc.bytes), "title": doc.title}}) + if leg == "claim": + si.append({"category": cc(SI_CATEGORY, "HDS", "Discharge summary"), "code": cc(DOC_CODE, d.summary.code or "HDS", d.summary.title), + "valueAttachment": {"contentType": d.summary.content_type, "data": base64(d.summary.bytes), "title": d.summary.title}}) + si.append(scalar("ONS", "ADDD", "Admission date -Discharge date", d.admission.admitted_at)) + si.append(scalar("OTH", "EDT", "EncounterDateTime", d.admission.admitted_at)) + if leg == "claim": + if d.admission.surgery_at: si.append(scalar("ONS", "PSP", "Procedure start", d.admission.surgery_at)) + si.append(scalar("ONS", "DSDE", "Discharge date", d.admission.death_at or d.admission.discharged_at)) + if d.admission.mode == "death": si.append(scalar("ONS", "DTM", "Date and time of death", d.admission.death_at)) # PAYR-1096 without it + code = {"normal": "DTH", "lama": "LAMA", "dama": "DAMA", "death": "DTM"}[d.admission.mode] + si.append(scalar("DIS", code, display_for(code), stage_words(d.admission.stage))) # "Before Surgery" | "During Surgery" | "After Surgery" + if d.flow == "queryupdate": + si.append(scalar("NMI", "CQD", "Claim query detail", d.query_reply)) # the desk's words; PMJAY reads its answer from here + for (form, url) in form_refs: # one per answered form + cat = "STG" if form.kind == "stg" else "INF"; code = "STG" if form.kind == "stg" else "ODN" + si.append({"category": cc(SI_CATEGORY, cat, display_for(cat)), "code": cc(SI_CODE, code, display_for(code)), "valueReference": ref(url)}) + for n, s in enumerate(si): # number once, after assembly: PAYR-1019 without sequence + s.id = "SupportingInformation/" + str(n + 1); s.sequence = n + 1 + reorder(s, ["id", "sequence", "category", "code", "value*"]) + return (si, [s.sequence for s in si]) + +function scalar(cat, code, display, value): + return {"category": cc(SI_CATEGORY, cat, display_for(cat)), "code": cc(SI_CODE, code, display), "valueString": value} +``` + +### Questionnaire responses + +``` +function questionnaire_responses(forms, authored): + qrs = []; refs = [] + for n, form in enumerate(forms): + url = BASE + "/questionnaireresponse/" + str(n + 1) + qr = {"resourceType": "QuestionnaireResponse", "id": str(n + 1), "meta": profile("QuestionnaireResponse"), + "questionnaire": form.url, "status": "completed", "subject": ref(BASE + "/patient"), "authored": authored, + "item": [{"linkId": a.linkId, "answer": [typed_answer(a)]} for a in form.answers]} + qrs.append(qr); refs.append((form, url)) + return (qrs, refs) + +function typed_answer(a): + switch a.type: + "string", "text", "choice": return {"valueString": a.value} + "date", "dateTime": return {"valueDateTime": a.value} + "boolean": return {"valueBoolean": a.value} + "integer": return {"valueInteger": int(a.value)} + "decimal": return {"valueDecimal": a.value} + "attachment": return {"valueAttachment": {"contentType": a.content_type, "data": base64(a.bytes), "title": a.title}} +``` + +### Which forms and documents ride + +``` +function required_forms(case, stage): # stage: preauth | claim + if case.ruling: forms = [r for r in case.ruling.requirements if r.kind == "form" and (stage == "preauth" or r.stage != "pre")] + else: forms = plan_stg_forms(case.plan, case.lines) if stage == "preauth" else [] + return forms + policy_forms(case.plan) # consent every leg: PAYR-1256 / PAYR-1363; STG: PAYR-1254 / PAYR-1365 + +function required_documents(case, stage): + if case.ruling: return [r for r in case.ruling.requirements if r.kind == "document" and (r.stage == "pre") == (stage == "preauth")] + wanted = plan_documents(case.plan, case.lines) + return wanted if stage == "preauth" else [w for w in wanted if not attached_at_preauth(case, w.code)] +``` + +### The legs, and the LAMA collapse + +``` +function lines_for(case, leg): + if leg == "claim" and case.admission.mode in ("lama", "dama") and case.admission.stage in ("before", "during"): + return [{"kind": "procedure", "code": "LM100", "display": "Left against medical advice", "quantity": 1, + "amount": plan_rate(case.plan, "LM100") or 0, "category": lm100_category(case.plan)}] # PAYR-1362 if the package stays + return case.lines # LM100 never on a pre-auth: PAYR-1270 +``` + +| Leg | flow | use | Procedure status | Workflow | Extra | +| --- | --- | --- | --- | --- | --- | +| Pre-auth | `request` | `preauthorization` | `preparation` | 12 | fresh 12 after a rejection too (PAYR-1214 on 121) | +| Enhancement | `enhancement` | `preauthorization` | `preparation` | 13 | every line, old and new, same claim number; factors 1 and 0.5 | +| Query answer | `queryupdate` | `preauthorization` | `preparation` | 19 (131 after an enhancement query) | `NMI/CQD`; new correlation id | +| Claim | `request` | `claim` | `completed` | 15 | discharge scalars, `HDS`, `preAuthRef`, under the pre-auth's number (ERR-PYR-CLM-007) | +| Claim query answer | `queryupdate` | `claim` | `completed` | 161 (PMJAY), 151 (generic) | as the claim plus `NMI/CQD` | +| Predetermination | `request` | `predetermination` | `preparation` | 12 on `v1/preauth/submit` | no state effects | + +## 5. Reader: ClaimResponse + +Fed by every answer on a pre-auth, enhancement, claim or predetermination thread. Entries: ClaimResponse, Patient, two Organizations, Coverage. + +``` +function parse_claim_response(b): + r = first(b, "ClaimResponse") + status_adj = first(a for a in r.adjudication or [] if a.category.coding[0].code == "status") + out = {"use": r.use, "outcome": r.outcome, "disposition": r.disposition, + "status_reason": status_adj.reason.coding[0].code.lower() if status_adj else null, # submitted|approved|queried|rejected|cancelled + "preauth_ref": r.preAuthRef if is_string(r.preAuthRef) else (r.preAuthRef[0] if r.preAuthRef else null), + "claim_no": r.identifier[0].value if r.identifier else null, + "totals": {t.category.coding[0].code: t.amount.value for t in r.total or []}, # by category, never by position + "items": [], "notes": [n.text for n in r.processNote or []]} + for it in r.item or []: + adj = {a.category.coding[0].code: a for a in it.adjudication or []} + out.items.append({"sequence": it.itemSequence, + "status": adj.status.reason.coding[0].code.lower() if adj.status else null, + "eligible": adj.eligible.amount.value if adj.eligible else null, + "submitted": adj.submitted.amount.value if adj.submitted else null, + "reason": adj.reason.reason.coding[0].display if adj.reason else "", # verbatim, pipe-delimited USER~datetime~type~comment~trust + "eligpercent": adj.eligpercent.value if adj.eligpercent else null, + "deductible": adj.deductible.amount.value if adj.deductible else null}) + return out + +function verdict_status(p): # copy exactly; never read outcome alone + if p.outcome == "queued" or p.status_reason == "submitted": return "submitting" + if p.status_reason == "cancelled": return "rejected" + if p.status_reason == "queried": return "queried" + if p.outcome == "error": return "rejected" + if p.outcome == "partial": return "partial" if p.status_reason == "approved" else "queried" + if p.outcome == "complete": return "approved" if p.status_reason in ("approved", null) else "queried" + return "queried" + +function apply_claim_response(leg, p, envelope): + leg.status = verdict_status(p) + if p.preauth_ref: leg.preauth_ref = p.preauth_ref # never overwrite a value with an empty one + leg.eligible_amount = p.totals.get("eligible") or p.totals.get("benefit") + leg.submitted_amount = p.totals.get("submitted") + leg.approved_amount = p.totals.get("benefit") # what the screen shows as the decision + leg.items_json = p.items; leg.query_note = join(p.notes + [i.reason for i in p.items if i.reason]) + leg.thread_correlation_id = envelope.jwe_headers["x-hcx-correlation_id"] + leg.answered_at = now() if leg.status != "submitting" else leg.answered_at +``` + +Payer workflow ids are labels for the timeline only: 20 received, 21 approved, 22 enhancement approved, 23 rejected, 24 queried, 25 claim received, 26 approved, 27 queried, 291 rejected. The bundle decides the state. + +## 6. Task bundles the hospital sends + +Pins: `preauth/cancel`, `claim/reprocess`, `claim/release`, `payment/notice-ack`. Sent on `v1/task/submit` (the payment acknowledgement on `v1/paymentnotice/on_request`). Entries: Task, provider Organization, payer Organization. + +``` +function task_bundle(id, anchor, task, facility, payer): + return bundle(id, "TaskBundle", [entry(BASE + anchor, task), entry(BASE + "/provider", provider_org(facility)), entry(BASE + "/payer", payer_org(payer))]) + +function base_task(code, status, authored_on, description): + return {"resourceType": "Task", "meta": profile("Task"), "status": status, "intent": "order", + "code": cc(FIN_TASK, code), "description": description, "authoredOn": authored_on, + "requester": ref(BASE + "/provider"), "owner": ref(BASE + "/payer")} + +function task_input(code, display, value): return {"type": cc(TASK_INPUT, code, display), "valueString": value} +function based_on(claim_no): return [{"identifier": typed_id(ID_TYPE, "CLN", "Claim number", claim_no, BASE), "display": "Claim " + claim_no}] + +function cancel_task(claim_no, reason, authored_on, facility, payer): # workflow PC01 + t = base_task("cancel", "requested", authored_on, "Cancel the preauthorization " + claim_no) + t.reasonCode = cc(REASON, reason.code, reason.display) # treatmentplanchanged, ... + t.input = [task_input("claimNumber", "ClaimNumber", claim_no), task_input("intimationNumber", "IntimationNumber", claim_no)] + return task_bundle("preauth-cancel-request-generic", "/preauth/cancel", t, facility, payer) + +function reprocess_task(claim_no, member_id, reason, description, documents, authored_on, facility, payer): # workflow 36 + t = base_task("reprocess", "requested", authored_on, description) + t.reasonCode = cc(REASON, reason.code, reason.display) # claimrejected | partialpayment | rejectiondisputed + t.basedOn = based_on(claim_no) + t.input = [task_input("claimNumber", "ClaimNumber", claim_no), task_input("intimationNumber", "IntimationNumber", claim_no)] + t.input += [{"type": cc(TASK_INPUT, "document", "Document"), "valueAttachment": {"contentType": d.content_type, "data": base64(d.bytes), "title": d.title}} for d in documents] + t.for = {"identifier": typed_id(ID_TYPE, "PMJAY", "Pradhan Mantri Jan Aarogya Yojana (PMJAY) ID", member_id)} # MB on a generic payer + return task_bundle("claim-reprocess-request-generic", "/claim/reprocess", t, facility, payer) + +function release_task(claim_no, amount, authored_on, facility, payer): # workflow 36 + t = base_task("release", "requested", authored_on, "Release the balance amount for claim " + claim_no) + t.reasonCode = cc(REASON, "partialpayment", "Reprocess request due to partial payment by payer") + t.basedOn = based_on(claim_no) + t.input = [task_input("claimNumber", "ClaimNumber", claim_no), {"type": cc(TASK_INPUT_X, "amount", "Amount"), "valueMoney": money(amount)}] + return task_bundle("claim-release-request-generic", "/claim/release", t, facility, payer) + +function status_task(claim_no, authored_on, facility, payer): # workflow = the leg's correlation id; PMJAY refuses (PAYR-1018) + t = base_task("status", "requested", authored_on, "Status of " + claim_no) + t.input = [task_input("claimNumber", "ClaimNumber", claim_no)] + return task_bundle("claim-status-request-generic", "/claim/status", t, facility, payer) + +function payment_ack(claim_no, authored_on, facility, payer): # workflow 17 (PMJAY) or the notice's own id; x-hcx-correlation_id = the notice's + t = base_task("status", "completed", authored_on, "Received the payment for claim " + claim_no) + t.output = [{"type": cc(TASK_OUTPUT, "status", "Status"), "valueCodeableConcept": cc(TASK_OUTVAL, "paymentack", "Payment is acknowledged")}, + {"type": cc(TASK_INPUT, "claimNumber", "ClaimNumber"), "valueString": claim_no}] + return task_bundle("payment-notice-ack-generic", "/payment/notice-ack", t, facility, payer) +``` + +The pins and the build both carry `intimationNumber`, so the offline comparison diffs the pins unchanged. + +### Readers: PC02, 37, status + +``` +function parse_task_answer(b): + t = first(b, "Task"); cr = first(b, "ClaimResponse") # a 37 may carry a ClaimResponse queued + outputs = {o.type.coding[0].code: o for o in t.output or []} + return {"status": t.status, "code": t.code.coding[0].code, + "claim_status": (outputs.get("claimStatus") or outputs.get("status") or {}).valueCodeableConcept.coding[0].code if outputs else null, + "description": t.description, "queued": cr is not null and cr.outcome == "queued"} +# PC02: pre-auth -> cancelled, episode gets a fresh claim number, the withdrawn one stays on the leg +# 37: enquiry row -> answered; a fresh verdict follows on the claim's own thread +``` + +## 7. Communication + +Pins: `communication/request` (the payer's TaskBundle, the reader's input) and `communication/response` (the hospital's reply). On `v1/communication/request` in, `v1/communication/on_request` out, with the request's correlation id and workflow id echoed. + +``` +function parse_communication_request(b): + t = first(b, "Task"); cr = first(b, "CommunicationRequest") + return {"task_status": t.status, "intent": t.intent, "reason": t.reasonCode.coding[0].code.lower() if t.reasonCode else null, + "request_id": cr.id, "request_url": fullurl_of(b, cr), + "questions": [p.contentString for p in cr.payload or [] if p.contentString], + "about_claim": (cr.basedOn or [{}])[0].display, "claim_no": claim_no_in(b)} + +function classify_communication(adapter, reason, intent): + if adapter.query_mode == "resubmit": return "notification" + if intent == "proposal": return "notification" + if intent == "order": return "query" + if reason in (null, "additionalinfo", "questionnaire", "query"): return "query" + return "notification" # tatquery, grievance, walletupdate, policychange, claimarbitration + +function build_acknowledgement_bundle(request_bundle, facility): # a notification, sent back at once + b = deepcopy(request_bundle); t = first(b, "Task"); t.status = "completed" + move_first(b, "Organization", where = provider) # provider Organization first + return b + +function build_communication_bundle(q, text, documents, sent_leg_bundle, facility, payer, now): + # q: the parsed request; sent_leg_bundle: the pre-auth or claim bundle as sent (its Claim, Patient, Organizations, Practitioner, Coverage are lifted) + task_id = uuid(); comm_id = uuid() + comm = {"resourceType": "Communication", "id": comm_id, "meta": profile("Communication"), + "identifier": [{"value": q.request_identifier}], "basedOn": [{"reference": q.request_url, "display": "CommunicationRequest"}], # never inResponseTo + "status": "completed", "category": [cc(COMM_CAT, "notification")], "priority": "routine", + "about": [{"reference": claim_anchor(sent_leg_bundle), "display": "Claim " + claim_no}], + "sender": {"reference": BASE + "/provider", "display": "Organization"}, "recipient": [{"reference": BASE + "/payer", "display": "Organization"}], + "payload": [{"contentString": text}] + [{"contentAttachment": {"contentType": d.content_type, "data": base64(d.bytes), "title": d.title}, + "extension": [{"url": DOC_TYPE_EXT, "valueString": d.code}]} for d in documents]} + task = {"resourceType": "Task", "id": task_id, "meta": profile("Task"), "status": "completed", "intent": "order", + "code": cc(TASK_CODES, "deliver"), "reasonCode": cc(null, q.reason or "additionalinfo", "Additional information requested"), + "authoredOn": now, "requester": {"reference": BASE + "/provider", "display": "Organization"}, "owner": {"reference": BASE + "/payer", "display": "Organization"}, + "input": [{"type": cc(FIN_INPUT, "include"), "valueReference": {"reference": "urn:uuid:" + comm_id, "display": "Communication"}}]} + entries = [entry("urn:uuid:" + task_id, task), entry("urn:uuid:" + comm_id, comm), entry(q.request_url, q.request_resource)] + entries += [entry(e.fullUrl, e.resource) for e in sent_leg_bundle.entry if e.resource.resourceType in ("Claim", "Patient", "Organization", "Practitioner", "Coverage")] + b = bundle("communication-response-generic", "TaskBundle", entries) + b.meta.lastUpdated = now; b.timestamp = now # the IG example carries both; the only request that does + return b +``` + +Excluded from the byte comparison of the reply: `meta.lastUpdated`, `timestamp`, `authoredOn`, the two generated uuids. + +## 8. Payment notice + +Read on `v1/paymentnotice/request`. Entries: Task, PaymentNotice, PaymentReconciliation, two Organizations. + +``` +function parse_payment_notice(b): + pn = first(b, "PaymentNotice"); pr = first(b, "PaymentReconciliation"); t = first(b, "Task") + out = {"claim_no": pn.identifier[0].value if pn.identifier else claim_no_in(b), + "amount": pn.amount.value, "payment_status": pn.paymentStatus.coding[0].code, # paid | cleared | ... + "payment_date": pn.paymentDate, "utr": null, "details": []} + if pr: + out.utr = pr.paymentIdentifier.value if pr.paymentIdentifier else null + out.gross = pr.paymentAmount.value if pr.paymentAmount else null + out.details = [{"type": d.type.coding[0].code, "amount": d.amount.value if d.amount else null} for d in pr.detail or []] # deductions, TDS + if not out.utr and pn.payment and pn.payment.identifier: out.utr = pn.payment.identifier.value + return out +# record: one claim_payment row keyed on the message's correlation id (unique), matched by claim_no; then acknowledge with payment_ack() +``` + +## 9. Validate before you send + +``` +function validate_bundle(b, pin): # the offline gate, module 7.7 Validate + assert canonical(strip(b, ["created"])) == canonical(strip(pin, ["created"])) # plus the per-shape exclusions above + urls = {e.fullUrl for e in b.entry} + for r in all_references(b): assert r in urls or r.startswith("urn:uuid:") + c = first(b, "Claim") + if c: + for it in c.item: assert it.id and it.sequence + for p in c.procedure: assert p.id and p.sequence + for n, s in enumerate(c.supportingInfo): assert s.id and s.sequence == n + 1 + for pr in all(b, "Practitioner"): assert any(i.type.coding[0].code == "HPIN" and i.system == HPR for i in pr.identifier) + assert c.total.value == sum(it.net.value for it in c.item) + assert not any(it.productOrService.coding[0].code == "LM100" for it in c.item) or c.use == "claim" + assert no literal in the builder matches r"MAND\d+|MG\d+|/questionnaire/" +``` + +| Symptom | Refusal | +| --- | --- | +| an item without `id` | PAYR-1027 | +| a supportingInfo without `sequence` | PAYR-1019 | +| a Practitioner without `HPIN` | PAYR-1083 | +| a death claim without `ONS/DTM` | PAYR-1096, PAYR-1503 | +| a LAMA claim before surgery still carrying the package | PAYR-1362 | +| `LM100` on a pre-auth | PAYR-1270 | +| the consent form unanswered | PAYR-1256 (pre-auth), PAYR-1363 (claim) | +| a package's STG form unanswered | PAYR-1254, PAYR-1365 | +| a claim under its own number | ERR-PYR-CLM-007 | +| 121 after a rejection | PAYR-1214 | +| 151, 19 or 16 on `v1/claim/submit` to PMJAY | PAYR-1321 | +| a document outside pdf, jpg, jpeg, png; a Task the sandbox does not take; a misspelt intimation input on a reprocess | PAYR-1008 | diff --git a/plugins/nhcx/skills/nhcx-reprocess/flow/FLOW.md b/plugins/nhcx/skills/nhcx-reprocess/flow/FLOW.md new file mode 100644 index 000000000..312668e67 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-reprocess/flow/FLOW.md @@ -0,0 +1,228 @@ +# The flow: the one path a claim episode walks + +This is the reference flow for an NHCX provider desk: these steps, in this order, with these guards and these words. A build from this skill walks the same path. It does not redesign it, reorder it, merge steps, or invent screens the path does not have. Stage 4 copies it, stage 5 puts screens on it, stage 7 implements it step by step, stage 8 checks every step exists, and test drivers check the same through `flow.json`. + +## The shape + +One episode is one case (`claim` row). It has one list screen, one "new case" screen and one case screen. The case screen has tabs in the order the episode happens, and above the tabs one status line and the actions the case is waiting for. Everything else (inbox, payments across cases) is a view over the same rows. + +Tabs on the case screen, in this order and with these names: + +| # | Tab key | Tab label | Opens when | +| --- | --- | --- | --- | +| 1 | `eligibility` | Eligibility | always | +| 2 | `plan` | Insurance plan | always (empty until the plan is fetched) | +| 3 | `lines` | Line items | always (quoting refused until the plan is `ready`) | +| 4 | `validate` | Validate | always (the ruling on the quoted set) | +| 5 | `preauth` | Pre-authorisation | once the coverage verdict is `eligible` | +| 6 | `communication` | Communication | always (the payer's questions on both legs) | +| 7 | `claim` | Claim | always; its submit opens once a pre-auth is approved or partial | +| 8 | `payments` | Payments | always | + +The episode may also render on one page, with the same sections in the same order. Either shape is fine; the order and the gating are not negotiable. + +## Which skill builds which step + +Seven skills build this flow, one slice each (`core/LADDER.md`). `flow.json` names them per step in `skills`, the first named being the one that owns the step. + +| Steps | Skill | +| --- | --- | +| F1, F2, F3 | `nhcx-coverage` | +| F4, F7 | `nhcx-insurance` | +| F5, F6, F8, F9, F9a, F9c, F9d, F9e; F9b for a `resubmit` payer (19, 131) | `nhcx-preauth` | +| F10, F11; the claim query answer for a `resubmit` payer (161) | `nhcx-claim` | +| F9b and the claim query for a `communication` payer; F12b | `nhcx-communication` | +| F12 | `nhcx-payment` | +| F13 | `nhcx-reprocess` | + +The case screen, its tabs, the status line and actions, and the page-load polls are the foundation's (`core/FOUNDATION.md`): the first skill lays them out whole, and each skill fills its own tabs. + +## The status line and the actions + +Above the tabs: `stage / sub-stage` from `case_stage` (module 7.11) and the list from `next_actions`, first item highlighted. The labels are these, verbatim: + +| Stage | Sub-stage | Action offered (label, tab) | +| --- | --- | --- | +| any | an open query exists | "Answer the payer (n)", `communication` (leads every list) | +| `eligibility` | `draft`, `error`, `not-eligible` | "Check the cover", `eligibility` | +| `eligibility` | `eligible`, no plan `ready` | "Fetch the package master", `plan` | +| `eligibility` | plan ready, no lines | "Quote the treatment", `lines` | +| `eligibility` | lines quoted | "Send the pre-authorisation", `preauth` | +| `preauth` or `enhancement` | `queried` | "Answer the query", `preauth` (resubmit payer) or "Answer the payer's query", `communication` (communication payer) | +| `preauth` | `draft`, `refused` | "Send the pre-authorisation", `preauth` | +| `preauth` | `rejected` | "Send a fresh pre-authorisation", `preauth` | +| `preauth` | `approved`, `partial`, lines added since | "Send the enhancement (n added)", `preauth` | +| `preauth` | `approved`, `partial`, not discharged | "Record the discharge", `claim` | +| `preauth` | `approved`, `partial`, discharged | "File the claim", `claim` | +| `preauth` | `requested`, `answered`, `resubmitted` | "With the payer; ask where it stands", `preauth` | +| `claim` | `queried` | "Answer the claim query", `claim` or "Answer the payer's query", `communication` | +| `claim` | `rejected`, `partial` | "Ask for a reprocess", `claim` | +| `claim` | `requested`, `answered`, `resubmitted` | "With the payer; ask where it stands", `claim` | +| `claim` | `refused` | "Send the claim again", `claim` (while a send kind remains) else "Ask for a reprocess" | +| `claim` | `approved` | "Await the payment notice", `payments` | +| `payment` | a notice unacknowledged | "Acknowledge the payment notice", `payments` | +| `payment` | all acknowledged | "Settled", `payments` | + +## The steps + +Each step: where it happens, what must hold, what the user does, what the system does (module in brackets), what goes on the wire, what is stored, where the case stands afterwards, and what the screen shows next. Ids are `F1` to `F13` with letters for branches; `flow.json` carries the same ids. + +### F1. Policy search + +- Screen: Cases list, "New case", `GET /claims/new`. +- Holds: nothing. +- User: picks an identifier type (`MemberId`, `AbhaNumber`, `MobileNo`) and a value, presses "Search policies". +- System [7.4]: `search_policies` through the transport: the participant service's `participant/get/policies`; normalises each row (`member_id`, `policy_code` from `productid`, `payer_code` from `payerid`, `recipient_code` from `processingid`, `product_name`). NHCX-1016 (nothing linked) is an empty list, not an error. +- Screen: a table, one row per policy: beneficiary, product and policy, payer, ABHA, mobile, a "Select" button. No name and no photo yet; the payer returns those at F3. + +### F2. Open the case + +- Screen: the same, "Select" on a row; `POST /claims`. +- System [7.4, 7.2]: `create_claim` snapshots the policy (`member_id`, `policy_code`, `payer_code`, `recipient_code`, `policy_json`), mints the claim number, stamps `eligibility / draft`. +- Redirect: the case screen, Eligibility tab, "Claim opened." +- Next action: "Check the cover". + +### F3. Check the cover (coverage eligibility) + +- Screen: Eligibility tab, card "Coverage eligibility check": purpose select (`validation` default, `benefits`, `discovery`), policy code and member id shown from the snapshot, "Send to payer". +- Holds: member id; policy code for `validation` and `benefits`. +- System [7.4]: `run_check(purpose)`, workflow id = the claim number, status `checking`; the page shows "Awaiting payer" and refreshes; the answer arrives by callback [7.3] or poll. +- Wire: `v1/coverageeligibility/check`; `on_check` back. +- Stored: `txn_id`, `correlation_id`, `api_call_id`; on the answer `inforce`, `outcome`, `disposition`, allowed and used amounts, the payer's `Patient` (name, gender, DOB, address, ABHA, photo), `Coverage` class and period. +- After: `eligibility / eligible` or `not-eligible` (or `error` with the payer's words). A `ProtocolResponse` or a 404 on `txn/related` settles as `error`, never spins. +- Screen: card "Payer verdict": Sum insured, Utilised, Wallet balance (allowed less used), Disposition verbatim, In force, Pre-authorisation required, Checked at, Correlation. Beneficiary card fills with the payer's demographics. "Check again" allowed from any settled state. +- Next action: "Fetch the package master". + +### F4. Fetch the package master (insurance plan) + +- Screen: Insurance plan tab, "Fetch the plan" (or "Refresh"). +- Holds: `eligible`. +- System [7.5]: `reuse_plan` first (same policy, provider, payer, status `ready`: zero sends); else `request_plan`, status `fetching`, workflow id = the claim number. +- Wire: `v1/insuranceplan/request`; `on_request` back with the InsurancePlan and Questionnaires. +- Stored: `claim_plan` (`ready`, `empty` or `error`), `claim_plan_benefit` per package, `claim_plan_form` per url. Both published shapes merged on package code. +- Screen: a search over the master (name or code, specialty filter, procedure or implant), one row per package with rate, kind, "View"; a package view with rate, implants approved, tiers, conditions, documents wanted, the forms those point at as questions; an "All forms" page. Policy-wide requirements shown above the table. +- Next action: "Quote the treatment". + +### F5. Link the admission (integrate) or capture it (standalone) + +- Screen: Pre-authorisation tab, card "Link the admission" (opens once `eligible`). +- Holds: `eligible`. +- Integrate: list every current inpatient stay of the patient whose ABHA matches the payer's (digits only); "Link" stores `patient_id` and `encounter_id`, defaults the admission date from the encounter. Linking before `eligible` and to a stay that is not a current IPD admission is refused. "Unlink" keeps the draft. +- Standalone [7.13]: register the patient (from the payer's demographics) and admit them here; the same two keys are stored. +- Screen after: card "Linked admission" with ward, bed, admitted at, consultant. + +### F6. The dossier (pre-auth capture) + +- Screen: Pre-authorisation tab, once linked: the form, saved in one transaction by `save_preauth` [7.7 inputs]. +- Captured: admission date (required) and provisional discharge date (not before admission); ICD-10 diagnoses (at least one; read off the admission when it recorded them, else a picker); the treating doctor (the admission's consultant, else a picker; must have an HPIN); package case or non-package case toggle; documents (pdf, jpg, jpeg, png, each recorded against the payer requirement code it answers, else `ODN`). +- Estimated amount: always recomputed server-side from the lines (F7), never from the form. +- Guards: saving a package case with no line quoted is refused. + +### F7. Quote the treatment (lines from the plan) + +- Screen: Line items tab, "Choose line items", `GET /claims//lines`. Three parts: what is quoted (editable quantities, running total, "remove"); what the payer says goes with it (implants approved for the quoted procedures, the tiers each offers; anything already quoted drops out); the whole master to search. +- Holds: plan `ready`. Quoting anything before that is refused. +- System [7.5]: `add_line(kind, code, parent_code)`; price read from the plan at add time; `amount = rate x quantity` server-side; a tier is added through the procedure that offers it and carries `parent_code`. Refused: a code the plan lacks, a tier the procedure does not offer, a duplicate, a zero quantity. +- Forms: the chosen lines pull in the questionnaires the plan attaches (STG per package, policy forms always); they render on the Pre-authorisation tab and are answered there (`save_answers`, one row per question, file answers upload a document). +- Next action: "Send the pre-authorisation". + +### F8. Validate the set (auth requirements) + +- Screen: Validate tab, "Ask the payer" (also run silently before F9). +- Holds: at least one line. +- System [7.6]: `ensure_auth_requirements`: fingerprint the quoted set; send only when the fingerprint is new; never wait for the answer. +- Wire: `v1/coverageeligibility/check` with purpose `auth-requirements` and the items; `on_check` back (the PMJAY sandbox rarely answers). +- Stored: `claim_auth` (`checking` then `ready`), items authorised or excluded, requirements (document or form, code, url, stage `pre` or `post`, `at_preauth`). +- Screen: the ruling per line, the documents and forms it wants for each leg; the pre-auth and claim tabs read it to build their document and form cards. Without a ruling they fall back to the plan's list. + +### F9. Send the pre-authorisation + +- Screen: Pre-authorisation tab, card "Submit": what will be sent (lines, forms answered, documents attached, the total), "Send to payer". +- Holds (all before any HTTP call): `eligible`; an admission linked; an admission date; at least one diagnosis; at least one care team member with an HPIN; at least one line; every required form answered; every document the ruling or plan asks for at pre-auth attached. +- System [7.7]: `submit_preauth`: `preauth_send_kind` picks `preauth` (12); builds the Claim bundle (`preauth`, `request`); status `submitting`, `submission_kind`, `workflow_id`; stores the three ids; `thread_correlation_id` untouched until the payer answers. +- Wire: `v1/preauth/submit`, workflow 12. +- After: `preauth / requested`. +- Screen: "Awaiting payer", the timeline row for the send, Refresh. Next action: "With the payer; ask where it stands". + +#### F9a. The payer answers + +- Callback [7.3] or poll: first the acknowledgement (workflow 20, `outcome queued`, reason `submitted`): recorded, `preauth_ref` kept, the leg stays `submitting`. Then the decision on the same correlation id: `verdict_status` [7.8]. +- After: `approved` (21), `partial` (approved for less), `queried` (24), `rejected` (23). Never read `outcome` alone. +- Screen: Decision, Payer reference (`preAuthRef`), Approved amount (`total[benefit]`), Eligible amount, the item verdicts table (eligible, status, reason verbatim, eligible %, quantity), process notes verbatim. A door refusal shows as a flag with the payer's code and text, the thread restored. +- Next action per the table above. + +#### F9b. Answer a query + +- Resubmit payer (PMJAY): the query is inside the ClaimResponse (`query_note`). Screen: Pre-authorisation tab, the payer's words, a reply box, "Submit again". System: `submit_preauth(reply)` with kind `preauth_query_response` (19; 131 after an enhancement query), flow `queryupdate`, `NMI/CQD` = the reply, a new correlation id. After: `answered`, then the decision. +- Communication payer (generic): the query is a CommunicationRequest on a new thread, filed in `claim_query` (F12 inbox). Screen: Communication tab, the questions verbatim, a reply box, documents to attach (existing or new, each under the payer's code else `ODN`), "Send the reply". System [7.10]: `answer_query`: the TaskBundle reply on `v1/communication/on_request` with the request's correlation id and workflow id. The leg stays `queried` until the decision arrives on its own thread. An empty reply is refused before any HTTP call. + +#### F9c. Enhancement + +- Screen: Line items tab, add a line after a decision; the Pre-authorisation card shows "enhancement pending (n added)"; "Submit enhancement". +- Holds: `approved` or `partial`; no request in flight. +- System: `submit_preauth` with kind `enhancement` (13; `enhancement_resubmit` 131 on a query): the whole bundle again, every line old and new, same claim number, factors 1 and 0.5. After: `enhancement / requested`, then 22 (or 21 from the SHA), 231, 241. + +#### F9d. Cancel + +- Screen: Pre-authorisation tab, "Withdraw": a reason picker (the seven documented reasons) and a note, required for Other. Hidden once a claim has been raised; refused on a `rejected` pre-auth and twice. +- System [7.9]: `cancel_preauth`: Task `cancel`, workflow PC01, on its own thread (`cancel_correlation_id`), `cancelling`. +- After PC02: `cancelled`; the episode gets a fresh claim number, the withdrawn one stays on the leg. + +#### F9e. Predetermination (a quote) + +- Screen: Pre-authorisation tab, "Ask for a quote". +- System [7.7]: the very bundle F9 would send with `use predetermination`, on `v1/preauth/submit`, workflow 12, its own row (`asking` then `answered`). Nothing on the pre-auth changes. + +### F10. Record the discharge + +- Screen: Claim tab, card "Discharge": mode (Normal, LAMA, DAMA, Death), stage (Before, During, After surgery), discharge date and time, surgery date and time, death date and time (death only). +- Holds: a pre-auth `approved` or `partial`. +- Stored: on `claim_submission` (`draft`) or the encounter. +- Screen after: the claim card opens; for LAMA or DAMA before or during surgery it says the approved packages are voided and the claim will carry `LM100` only. +- Next action: "File the claim". + +### F11. File the claim + +- Screen: Claim tab, cards "Documents for the claim" (what the ruling deferred to this stage, plus the discharge summary, always), "Forms for the claim" (the consent again, and what the ruling deferred), "Everything attached for the claim" (any further pdf or image), "Submit the claim". +- Holds: discharge recorded; the discharge summary attached; every claim-stage form answered; amount not above the approved amount. +- System [7.7]: `submit_claim`: `claim_send_kind` (`claim` 15; `claim_query_response` 161 PMJAY or 151 generic; `claim_resubmit` 16 generic only); the Claim bundle (`claim`, `request`) under the pre-auth's claim number with `preAuthRef`, procedures `completed`, discharge scalars, `HDS`, `DIS`; `LM100` collapse when it applies. +- Wire: `v1/claim/submit`. +- After: `claim / requested`; then 25 (ack), 26 `approved`, 27 `queried`, 291 `rejected`, read as F9a. +- Screen: as the pre-auth card: decision, amounts, item verdicts with `deductible`, notes verbatim. + +#### F11, continued: claim query and reprocess + +- Query: as F9b, on the claim (161 or the Communication reply). +- Rejected or partial: "Ask for a reprocess" (F13). There is no claim resubmit on PMJAY. + +### F12. Payments + +- The payer starts it: `v1/paymentnotice/request` arrives on a new thread, matched by the claim number inside (a `CLN` identifier, then any untyped identifier on the notice, the reconciliation, the Task; never the bundle id), looked up against `claim_no` and every leg's `claim_ref`. +- System [7.10]: `record_payment`: one `claim_payment` row per notice, deduped on the notice's correlation id; details from the PaymentReconciliation; a payer that reuses the notice id updates the row. Then, at once and automatically, `acknowledge_payment`: Task `status` `completed`, output `paymentack`, to the notice's own sender, its correlation id echoed, workflow 17 (PMJAY) or the notice's own (generic). A failed acknowledgement is kept on the row; the notice is still recorded and the callback still answered 2xx. +- After: `payment / noticed` or `paid`. Paid is counted once per UTR, newest notice winning; an initiated notice without a UTR shows "Initiated, UTR awaited" and is not money received. +- Screen: Payments tab, one card per notice: status, amount, UTR as text, the breakdown, "Acknowledged at" or "Send the acknowledgement again". Across cases: the payments view. +- Next action: "Acknowledge the payment notice" while one is pending, else "Settled". + +### F12b. The inbox + +- Every CommunicationRequest is classified [7.10]: query, notification or note. Notifications are acknowledged at once (the payer's bundle back, Task `completed`) and the case left alone. Queries are filed `open` and lead every action list until answered (F9b). Notes are shown, never acted on. +- Screen: Communication tab on the case; the inbox view across cases, by kind and reason. + +### F13. The small exchanges + +- Status: "Ask where it stands" on the pre-auth and claim cards, while awaiting and after a decision; Task `status`, workflow = the leg's correlation id (fallback 13); not offered to a payer whose adapter refuses it (PMJAY, PAYR-1018). The answer fills the enquiry row; the leg is unchanged. +- Reprocess: on a decided claim not paid in full, "Send reprocess request" with a coded reason (`claimrejected`, `partialpayment`, `rejectiondisputed`), words, and documents; Task `reprocess`, workflow 36. The payer's `completed` Task (37) reopens the claim: the submission goes back to `requested` and the new verdict lands on the claim's own thread. +- Release: once part of an approved claim is paid, "Ask for the balance" with the amount owed; Task `release`, reason `partialpayment`, `valueMoney`, workflow 36. +- Each ask is its own `claim_enquiry` row on its own thread, shown on the card it belongs to, newest first. + +## What runs on every page load of the case + +In this order, before rendering, each bounded to one poll and a short timeout, never a send: coverage (`checking`), plan (`fetching`), ruling (`checking`), claim (`submitting`), predeterminations (`asking`), pre-auth (`submitting` or `cancelling`), enquiries (`asking`). Then the beneficiary card, the policy card, the verdict card, the status line and actions, the tabs. A "Refresh" button reloads the same tab. + +## What is not in the flow + +- No status control anywhere. Stage and sub-stage are derived. +- No manual acknowledgement of a payment notice as the only path; it goes automatically and the screen shows that it went. +- No "chase" button without the status exchange behind it. +- No separate discharge submission on PMJAY; the discharge rides on the claim. +- No claim resubmit on PMJAY; a decided claim is reprocessed. diff --git a/plugins/nhcx/skills/nhcx-reprocess/flow/flow.json b/plugins/nhcx/skills/nhcx-reprocess/flow/flow.json new file mode 100644 index 000000000..315d1a4b8 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-reprocess/flow/flow.json @@ -0,0 +1,818 @@ +{ + "source": "flow/FLOW.md", + "tabs": [ + { + "key": "eligibility", + "label": "Eligibility", + "opens": "always" + }, + { + "key": "plan", + "label": "Insurance plan", + "opens": "always" + }, + { + "key": "lines", + "label": "Line items", + "opens": "always; quoting refused until the plan is ready" + }, + { + "key": "validate", + "label": "Validate", + "opens": "always" + }, + { + "key": "preauth", + "label": "Pre-authorisation", + "opens": "coverage verdict eligible" + }, + { + "key": "communication", + "label": "Communication", + "opens": "always" + }, + { + "key": "claim", + "label": "Claim", + "opens": "always; submit once the pre-auth is approved or partial" + }, + { + "key": "payments", + "label": "Payments", + "opens": "always" + } + ], + "stages": [ + "eligibility", + "preauth", + "enhancement", + "claim", + "payment" + ], + "sub_stages": [ + "draft", + "checking", + "eligible", + "not-eligible", + "requested", + "resubmitted", + "answered", + "queried", + "approved", + "partial", + "rejected", + "cancelling", + "cancelled", + "refused", + "noticed", + "paid" + ], + "next_actions": [ + { + "when": "an open query exists", + "label": "Answer the payer (n)", + "tab": "communication", + "leads": true + }, + { + "stage": "eligibility", + "sub_stage": [ + "draft", + "error", + "not-eligible" + ], + "label": "Check the cover", + "tab": "eligibility" + }, + { + "stage": "eligibility", + "when": "no plan ready", + "label": "Fetch the package master", + "tab": "plan" + }, + { + "stage": "eligibility", + "when": "no lines", + "label": "Quote the treatment", + "tab": "lines" + }, + { + "stage": "eligibility", + "when": "lines quoted", + "label": "Send the pre-authorisation", + "tab": "preauth" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "queried" + ], + "label": "Answer the query", + "tab": "preauth", + "payer": "resubmit" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "queried" + ], + "label": "Answer the payer's query", + "tab": "communication", + "payer": "communication" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "draft", + "refused" + ], + "label": "Send the pre-authorisation", + "tab": "preauth" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "rejected" + ], + "label": "Send a fresh pre-authorisation", + "tab": "preauth" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "approved", + "partial" + ], + "when": "lines added since", + "label": "Send the enhancement (n added)", + "tab": "preauth" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "approved", + "partial" + ], + "when": "not discharged", + "label": "Record the discharge", + "tab": "claim" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "approved", + "partial" + ], + "when": "discharged", + "label": "File the claim", + "tab": "claim" + }, + { + "stage": [ + "preauth", + "enhancement" + ], + "sub_stage": [ + "requested", + "answered", + "resubmitted" + ], + "label": "With the payer; ask where it stands", + "tab": "preauth" + }, + { + "stage": "claim", + "sub_stage": [ + "queried" + ], + "label": "Answer the claim query", + "tab": "claim", + "payer": "resubmit" + }, + { + "stage": "claim", + "sub_stage": [ + "queried" + ], + "label": "Answer the payer's query", + "tab": "communication", + "payer": "communication" + }, + { + "stage": "claim", + "sub_stage": [ + "rejected", + "partial" + ], + "label": "Ask for a reprocess", + "tab": "claim" + }, + { + "stage": "claim", + "sub_stage": [ + "requested", + "answered", + "resubmitted" + ], + "label": "With the payer; ask where it stands", + "tab": "claim" + }, + { + "stage": "claim", + "sub_stage": [ + "refused" + ], + "label": "Send the claim again", + "tab": "claim", + "when": "a send kind remains, else Ask for a reprocess" + }, + { + "stage": "claim", + "sub_stage": [ + "approved" + ], + "label": "Await the payment notice", + "tab": "payments" + }, + { + "stage": "payment", + "when": "a notice unacknowledged", + "label": "Acknowledge the payment notice", + "tab": "payments" + }, + { + "stage": "payment", + "when": "all acknowledged", + "label": "Settled", + "tab": "payments" + } + ], + "steps": [ + { + "id": "F1", + "name": "Policy search", + "screen": "new case", + "tab": null, + "routes": [ + "GET /claims/new" + ], + "module": "7.4", + "skills": ["nhcx-coverage"], + "holds": [], + "user": "Search policies", + "sends": { + "path": "participant/get/policies", + "kind": "registry REST" + }, + "stores": [], + "after": null, + "shows": "one row per policy with Select" + }, + { + "id": "F2", + "name": "Open the case", + "screen": "new case", + "tab": null, + "routes": [ + "POST /claims" + ], + "module": "7.4", + "skills": ["nhcx-coverage"], + "holds": [], + "user": "Select", + "sends": null, + "stores": [ + "claim: member_id, policy_code, payer_code, recipient_code, policy_json, claim_no" + ], + "after": { + "stage": "eligibility", + "sub_stage": "draft" + }, + "next_action": "Check the cover" + }, + { + "id": "F3", + "name": "Check the cover", + "screen": "case", + "tab": "eligibility", + "routes": [ + "POST /claims//check" + ], + "module": "7.4", + "skills": ["nhcx-coverage"], + "holds": [ + "member id", + "policy code for validation and benefits" + ], + "user": "purpose, Send to payer", + "sends": { + "path": "v1/coverageeligibility/check", + "workflow": "", + "reply": "on_check" + }, + "stores": [ + "txn_id", + "correlation_id", + "api_call_id", + "inforce", + "outcome", + "disposition", + "allowed_amount", + "used_amount", + "patient demographics", + "coverage class and period" + ], + "after": { + "stage": "eligibility", + "sub_stage": "eligible|not-eligible|error" + }, + "shows": "Payer verdict: sum insured, utilised, wallet balance, disposition verbatim", + "next_action": "Fetch the package master" + }, + { + "id": "F4", + "name": "Fetch the package master", + "screen": "case", + "tab": "plan", + "routes": [ + "POST /claims//plan", + "GET /claims//plan/", + "GET /claims//plan/forms" + ], + "module": "7.5", + "skills": ["nhcx-insurance"], + "holds": [ + "eligible" + ], + "user": "Fetch the plan (reuse first)", + "sends": { + "path": "v1/insuranceplan/request", + "workflow": "", + "reply": "on_request" + }, + "stores": [ + "claim_plan", + "claim_plan_benefit", + "claim_plan_form" + ], + "after": { + "plan": "ready|empty|error" + }, + "shows": "searchable master, package view, all forms", + "next_action": "Quote the treatment" + }, + { + "id": "F5", + "name": "Link or capture the admission", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//link", + "POST /claims//unlink" + ], + "module": "7.13 or the HMIS", + "skills": ["nhcx-preauth"], + "holds": [ + "eligible" + ], + "user": "Link the admission", + "sends": null, + "stores": [ + "claim.patient_id", + "claim.encounter_id", + "admission date default" + ], + "after": null + }, + { + "id": "F6", + "name": "The dossier", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//preauth", + "POST /claims//documents", + "POST /claims//documents/required" + ], + "module": "7.7 inputs", + "skills": ["nhcx-preauth"], + "holds": [ + "linked" + ], + "user": "Save the dossier", + "sends": null, + "stores": [ + "claim_diagnosis", + "claim_care_team", + "claim_document (code, stage)", + "claim_item" + ], + "guards": [ + "admission date required", + "at least one diagnosis", + "doctor with HPIN", + "package case needs a line" + ] + }, + { + "id": "F7", + "name": "Quote the treatment", + "screen": "lines", + "tab": "lines", + "routes": [ + "GET /claims//lines", + "POST /claims//lines", + "POST /claims//lines/quantities", + "POST /claims//lines//delete", + "POST /claims//forms" + ], + "module": "7.5", + "skills": ["nhcx-insurance"], + "holds": [ + "plan ready" + ], + "user": "add procedure, implant or tier; quantities; answer the forms the lines pull in", + "sends": null, + "stores": [ + "claim_line (rate from the plan, parent_code on a tier)", + "claim_form_answer" + ], + "guards": [ + "code not in plan", + "tier not offered by the procedure", + "duplicate", + "zero quantity" + ], + "next_action": "Send the pre-authorisation" + }, + { + "id": "F8", + "name": "Validate the set", + "screen": "case", + "tab": "validate", + "routes": [ + "POST /claims//auth" + ], + "module": "7.6", + "skills": ["nhcx-preauth"], + "holds": [ + "at least one line" + ], + "user": "Ask the payer (validate)", + "sends": { + "path": "v1/coverageeligibility/check", + "purpose": "auth-requirements", + "workflow": "", + "reply": "on_check", + "awaited": false + }, + "stores": [ + "claim_auth (fingerprint)", + "claim_auth_item", + "claim_auth_requirement" + ], + "after": { + "auth": "checking|ready" + } + }, + { + "id": "F9", + "name": "Send the pre-authorisation", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//submit" + ], + "module": "7.7", + "skills": ["nhcx-preauth"], + "holds": [ + "eligible", + "linked", + "admission date", + "diagnosis", + "care team with HPIN", + "a line", + "required forms answered", + "required documents attached" + ], + "user": "Send to payer", + "sends": { + "path": "v1/preauth/submit", + "workflow": "12", + "kind": "preauth", + "reply": "on_submit 20 then 21|23|24" + }, + "stores": [ + "claim_preauth: submitting, submission_kind, workflow_id, txn_id, correlation_id, api_call_id, request_json" + ], + "after": { + "stage": "preauth", + "sub_stage": "requested" + }, + "next_action": "With the payer; ask where it stands" + }, + { + "id": "F9a", + "name": "The payer answers", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /nhcx/callback/v1/preauth/on_submit" + ], + "module": "7.8", + "skills": ["nhcx-preauth"], + "holds": [], + "user": null, + "reads": "20 queued (stay submitting, keep preauth_ref) then the decision via verdict_status", + "stores": [ + "status", + "preauth_ref", + "approved_amount", + "eligible_amount", + "items_json", + "query_note", + "thread_correlation_id" + ], + "after": { + "stage": "preauth", + "sub_stage": "approved|partial|queried|rejected" + }, + "shows": "decision, payer reference, approved amount, item verdicts, notes verbatim; door refusal as a flag" + }, + { + "id": "F9b", + "name": "Answer a query", + "screen": "case", + "tab": "preauth or communication", + "routes": [ + "POST /claims//submit (reply)", + "POST /claims//queries//reply" + ], + "module": "7.7 or 7.10", + "skills": ["nhcx-preauth", "nhcx-communication"], + "holds": [ + "queried" + ], + "user": "reply text and documents", + "sends": { + "resubmit": { + "path": "v1/preauth/submit", + "workflow": "19 or 131", + "flow": "queryupdate", + "new_thread": true + }, + "communication": { + "path": "v1/communication/on_request", + "workflow": "", + "correlation_id": "" + } + }, + "after": { + "stage": "preauth", + "sub_stage": "answered (resubmit) or queried until the decision (communication)" + } + }, + { + "id": "F9c", + "name": "Enhancement", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//submit" + ], + "module": "7.7", + "skills": ["nhcx-preauth"], + "holds": [ + "approved or partial", + "lines added", + "no request in flight" + ], + "user": "Submit enhancement", + "sends": { + "path": "v1/preauth/submit", + "workflow": "13 or 131", + "flow": "enhancement", + "whole_bundle": true + }, + "after": { + "stage": "enhancement", + "sub_stage": "requested" + } + }, + { + "id": "F9d", + "name": "Cancel", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//cancel" + ], + "module": "7.9", + "skills": ["nhcx-preauth"], + "holds": [ + "not rejected", + "not cancelled", + "no claim raised" + ], + "user": "Withdraw the pre-authorisation", + "sends": { + "path": "v1/task/submit", + "workflow": "PC01", + "task": "cancel", + "own_thread": true + }, + "after": { + "stage": "preauth", + "sub_stage": "cancelling then cancelled; fresh claim number" + } + }, + { + "id": "F9e", + "name": "Predetermination", + "screen": "case", + "tab": "preauth", + "routes": [ + "POST /claims//predetermination" + ], + "module": "7.7", + "skills": ["nhcx-preauth"], + "holds": [ + "as F9" + ], + "user": "Ask for a quote", + "sends": { + "path": "v1/preauth/submit", + "workflow": "12", + "use": "predetermination" + }, + "after": { + "predetermination": "asking then answered; the pre-auth unchanged" + } + }, + { + "id": "F10", + "name": "Record the discharge", + "screen": "case", + "tab": "claim", + "routes": [ + "POST /claims//discharge" + ], + "module": "7.7 inputs", + "skills": ["nhcx-claim"], + "holds": [ + "approved or partial" + ], + "user": "mode (normal, lama, dama, death), stage, discharge, surgery and death times", + "sends": null, + "stores": [ + "claim_submission draft: discharge_mode, discharge_stage, dates" + ], + "next_action": "File the claim" + }, + { + "id": "F11", + "name": "File the claim", + "screen": "case", + "tab": "claim", + "routes": [ + "POST /claims//claim", + "POST /claims//claim/documents" + ], + "module": "7.7", + "skills": ["nhcx-claim", "nhcx-communication"], + "holds": [ + "discharge recorded", + "discharge summary attached", + "claim-stage forms answered", + "amount not above approved" + ], + "user": "Submit the claim", + "sends": { + "path": "v1/claim/submit", + "workflow": "15 (161 or 151 query answer; 16 generic resubmit)", + "kind": "claim", + "under": "the pre-auth's claim number", + "reply": "on_submit 25 then 26|27|291" + }, + "after": { + "stage": "claim", + "sub_stage": "requested then approved|queried|rejected|partial" + } + }, + { + "id": "F12", + "name": "Payments", + "screen": "case", + "tab": "payments", + "routes": [ + "POST /nhcx/callback/v1/paymentnotice/request", + "POST /claims//payments//ack", + "GET /claims/payments" + ], + "module": "7.10", + "skills": ["nhcx-payment"], + "holds": [], + "user": null, + "reads": "PaymentNotice matched by claim number; deduped on its correlation id", + "sends": { + "path": "v1/paymentnotice/on_request", + "workflow": "17 (PMJAY) or the notice's own", + "correlation_id": "", + "to": "the notice's sender", + "automatic": true + }, + "after": { + "stage": "payment", + "sub_stage": "noticed|paid" + }, + "next_action": "Acknowledge the payment notice, then Settled" + }, + { + "id": "F12b", + "name": "The inbox", + "screen": "inbox", + "tab": "communication", + "routes": [ + "POST /nhcx/callback/v1/communication/request", + "GET /claims/inbox", + "POST /claims//queries//acknowledge" + ], + "module": "7.10", + "skills": ["nhcx-communication"], + "holds": [], + "reads": "classify: query | notification | note", + "sends": { + "notification": { + "path": "v1/communication/on_request", + "automatic": true + } + }, + "after": { + "query": "open, leads every action list" + } + }, + { + "id": "F13", + "name": "Status, reprocess, release", + "screen": "case", + "tab": "preauth or claim", + "routes": [ + "POST /claims//status", + "POST /claims//reprocess", + "POST /claims//release" + ], + "module": "7.9", + "skills": ["nhcx-reprocess"], + "holds": [ + "status: payer allows it", + "reprocess: claim decided and not paid in full", + "release: part paid" + ], + "sends": { + "path": "v1/task/submit", + "workflow": "leg correlation id (status) or 36", + "own_thread": true + }, + "after": { + "enquiry": "asking then answered|error; a reprocess reopens the claim to requested" + } + } + ], + "page_load_polls": [ + "coverage checking", + "plan fetching", + "ruling checking", + "claim submitting", + "predeterminations asking", + "preauth submitting or cancelling", + "enquiries asking" + ], + "not_in_the_flow": [ + "a status control", + "a manual-only payment acknowledgement", + "a chase button without the status exchange", + "a separate discharge submission on PMJAY", + "a claim resubmit on PMJAY" + ] +} \ No newline at end of file diff --git a/plugins/nhcx/skills/nhcx-reprocess/references/api-knowledge.md b/plugins/nhcx/skills/nhcx-reprocess/references/api-knowledge.md new file mode 100644 index 000000000..3b07e901d --- /dev/null +++ b/plugins/nhcx/skills/nhcx-reprocess/references/api-knowledge.md @@ -0,0 +1,400 @@ +# API knowledge: the nhcx-adapter contract (optional transport) and the HMIS endpoints that face it + +Read this file only when the transport is nhcx-adapter, and use nhcx-adapter only when the user has asked for it (`references/transport-knowledge.md` section 1). Otherwise the build reaches NHCX through the app's existing integration or its own transport, and `references/transport-knowledge.md` sections 3 and 4 replace everything here. + +This file describes nhcx-adapter (https://github.com/nha-in/nhcx-adapter) as its release ships it, and the HMIS side a build needs to face it. A release carries the binary, `config.sample.json`, `serve.sh`, `stop.sh`, `update.sh` and `README.md`. `nhcx-package/docs/02-Getting Started/10-NHCX Adapter.md` covers the same adapter. When a detail matters, check the release README and `config.sample.json` for the version you run. + +## 1. What the adapter is + +One binary, one `config.json`, no database. You POST plain FHIR to it. It mints the protocol ids, fetches the recipient's certificate, encrypts a compact JWE, posts to the NHCX gateway, and records the exchange in a file ledger. NHCX callbacks reach it encrypted; it decrypts them and POSTs plain FHIR to your HMIS. Both directions are synchronous; there is no queue (release README, "How it works"). + +The same binary can front several participants at once. Inbound, `x-hcx-recipient_code` picks the profile whose key decrypts and whose callback receives. Outbound, `x-hcx-sender_code` picks who sends (release README, "Hosting several participants"). Encrypting for a code the same adapter holds is allowed. So one adapter can host a hospital and a test payer together, and a test between them needs no second gateway. + +## 2. Configuration + +File: `config.sample.json` in the release. `${NAME}` reads an environment variable; `@file` reads a file next to the config. Unknown keys are rejected. + +| Key | Default | What it does | +| --- | --- | --- | +| `env` | `sandbox` | `sandbox` or `production`. Picks the gateway (`https://apisbx.abdm.gov.in/hcx/v1` or `https://apis.abdm.gov.in/hcx/v1`), registry, session endpoint and `X-CM-ID` (`sbx` or `abdm`). | +| `listen` | `127.0.0.1:8090` | The HTTP listener. | +| `publicUrl` | empty | How NHCX reaches the adapter. Register `/in` as the participant's `endpoint_url`. | +| `apiKey` | `${NHCX_ADAPTER_API_KEY}` | The key your HMIS presents on `/out`, `/fhir/out`, `/ledger*`, `/token`. Demanded in production, honoured but not demanded in sandbox. `requireApiKey: true` closes a sandbox adapter. | +| `participant.participantId` | none; the sample carries an example code | Your registry code. `@hcx` is added if missing. | +| `participant.clientId`, `clientSecret` | `${NHCX_CLIENT_ID}`, `${NHCX_CLIENT_SECRET}` | ABDM credentials that mint the session token. | +| `participant.privateKey` | `@private_key.pem` | The RSA key of your registered certificate. | +| `participants[]` | `[]` | Further hosted identities. Each needs only `participantId` and `callback`; the rest is inherited. | +| `callback.url` | `http://127.0.0.1:8765/nhcx/callback` in the sample | Where decrypted messages are POSTed. | +| `callback.appendPath` | `true` | Appends the NHCX path: `.../callback` receives `v1/preauth/on_submit` at `.../callback/v1/preauth/on_submit`. | +| `callback.timeoutSeconds` | `20` | One delivery. NHCX wants its 202 within 30 seconds. | +| `callback.apiKey` | empty | Sent to your HMIS as `Authorization: Bearer `. | +| `callback.routes` | `{}` | Per-path overrides, used exactly as written: `{"v1/preauth/on_submit": "http://preauth-svc/hook"}`. | +| `callback.also` | absent | Extra targets for the same delivery (two systems behind one participant code). Every target must accept or NHCX redelivers to all. | +| `ledger.enabled`, `ledger.dir`, `ledger.retentionDays`, `ledger.storeBodies` | `true`, `data/ledger`, `30`, `true` | The traffic ledger. A hand-written config that leaves out `retentionDays` keeps every day. | +| `maxBodyBytes` | 8 MiB in the v1.0.1 README | Caps request bodies on both surfaces. A PMJAY package master is far larger: set 100 MiB (`104857600`) explicitly. | +| `panel.password`, `panel.path` | empty, `/panel` | The browser console; off until a password is set. | +| `auth.mode`, `auth.tokenTtlSeconds` | `sessions`, `1200` | How the ABDM token is obtained. | + +Minimal working config for one hospital: + +```json +{ + "env": "sandbox", + "listen": "127.0.0.1:8090", + "publicUrl": "https:///in", + "apiKey": "${NHCX_ADAPTER_API_KEY}", + "participant": { + "participantId": "@hcx", + "clientId": "${NHCX_CLIENT_ID}", + "clientSecret": "${NHCX_CLIENT_SECRET}", + "privateKey": "@private_key.pem" + }, + "callback": { "url": "http://127.0.0.1:/nhcx/callback", "appendPath": true, "apiKey": "" } +} +``` + +Start it with `./nhcx-adapter serve`, or `./serve.sh` from the release archive; `./stop.sh` stops a background server. It checks token, participant record, certificate and registered endpoint first and offers to fix each in a terminal (release README, "Startup checks"). `./nhcx-adapter check --no-tui` is the same as a health gate. `serve --no-tui --skip-checks` starts it with no prompts and no checks, for a script that has already checked. + +## 3. Routes + +| Route | Auth | Does | +| --- | --- | --- | +| `POST /out/{path...}` | API key | Send. `path` is the NHCX API path, `v1/preauth/submit`. | +| `POST /fhir/out/{path...}` | API key | Same handler, hcxkit's prefix. The client in section 11 sends here. | +| `POST /in/{path...}` | none | NHCX delivers here. Register `/in`. | +| `POST /v1/{path...}` | none | Alias of `/in` for a registry `endpoint_url` of `/`. | +| `GET /ledger` | API key | Newest first. Filters: `direction, entity, kind, status, sender, recipient, participant, correlation_id, workflow_id, since, until, before, limit` (1 to 500). `since` and `until` take RFC 3339, a date, or a duration such as `24h`. | +| `GET /ledger/stats` | API key | Counts by direction, status, entity. | +| `GET /ledger/thread/{cid}` | API key | Every message on one correlation id plus the derived state. | +| `GET /ledger/{id}` | API key | One message in full, bundle included. | +| `GET /token`, `POST /token/refresh` | API key | The ABDM session token, for calls the adapter does not make (registry, PMJAY payer service). `?participant=` for a hosted identity. | +| `GET /healthz`, `GET /readyz` | none | Liveness; readiness is 503 until a token is held. | +| `GET /panel` | its own password | Operator console: Live, Ledger, Send, Lookup, Setup. | +| `/internal/*` | none | hcxkit-compatible console API, section 8. | + +API key check: `Authorization: Bearer ` first, then `X-Api-Key: `. Constant-time compare. A miss answers `401 {"ok":false,"error":{"code":"UNAUTHORIZED","message":"missing or invalid API key"}}`. + +## 4. The outbound envelope + +The body must be a JSON object. Header precedence, lowest to highest: + +1. HTTP request headers named `x-hcx-*`. +2. The `jwe_headers` object (hcxkit spelling). +3. Top-level `x-hcx-*` keys. +4. Top-level short aliases: `sender`, `recipient`, `correlation_id`, `request_id`, `api_call_id`, `workflow_id`, `status`. + +The payload is `fhir`, else `payload`, else the body itself when it carries `resourceType`. Otherwise `400 INVALID_ENVELOPE`. + +The protected header names: + +``` +x-hcx-api_call_id x-hcx-request_id x-hcx-correlation_id x-hcx-timestamp +x-hcx-status x-hcx-sender_code x-hcx-recipient_code x-hcx-workflow_id +``` + +Completion rules: + +- Sender and recipient codes get `@hcx` appended if missing. +- `api_call_id`, `request_id`, `correlation_id` are kept only when they are plain 8-4-4-4-12 UUIDs; anything else is replaced with a fresh UUID. So a response must carry the request's `correlation_id` as a UUID or the thread is lost. +- `x-hcx-status` defaults to `request.initiated`, or `response.complete` when the last path segment starts with `on_`. +- `x-hcx-timestamp` defaults to now as `YYYY-MM-DDThh:mm:ss±hhmm`. The zone has no colon: `+0530`, not `+05:30`. +- An empty `x-hcx-workflow_id` is dropped, not sent. +- On an `on_` path with no usable correlation id, the adapter threads the message to the newest inbound request of that entity from that recipient. Do not rely on it; send the id. + +What a hospital sends on a normal leg: + +```json +{ + "jwe_headers": { + "x-hcx-sender_code": "@hcx", + "x-hcx-recipient_code": "@hcx", + "x-hcx-workflow_id": "12" + }, + "fhir": { "resourceType": "Bundle", "type": "collection", "...": "..." } +} +``` + +Add `"x-hcx-correlation_id": ""` only on the two reply legs: the communication reply on `v1/communication/on_request` and the payment acknowledgement on `v1/paymentnotice/on_request`. + +## 5. The outbound answer + +The HTTP status is the NHCX gateway's own. Body: + +```json +{ + "ok": true, + "path": "v1/preauth/submit", + "url": "https://apisbx.abdm.gov.in/hcx/v1/preauth/submit", + "headers": { "x-hcx-correlation_id": "...", "x-hcx-api_call_id": "...", "x-hcx-request_id": "...", "x-hcx-workflow_id": "12", "x-hcx-status": "request.initiated", "x-hcx-timestamp": "...", "x-hcx-sender_code": "...", "x-hcx-recipient_code": "..." }, + "gateway_status": 202, + "response": { "...": "the NHCX 202 body" }, + "duration_ms": 412, + "ledger_id": "7UMV0007", + "txn_id": "7UMV0007", + "correlation_id": "...", + "request_id": "..." +} +``` + +Store three things on the leg: `txn_id` (the ledger id), `correlation_id` (the thread), and `headers["x-hcx-api_call_id"]`. Store them on every send. + +Local failures come back as `{"ok": false, "error": {"code", "message", "retryable"}, "request_id", "upstream_status", "upstream_body"}` with these statuses: `400` for `INVALID_ENVELOPE`, `INVALID_PAYLOAD`, `INVALID_BODY`, `INVALID_JWE`, `NO_PATH`, `NO_RECIPIENT`, `WRONG_RECIPIENT`, `BODY_READ`; `401` for the API key; `413` `BODY_TOO_LARGE`; `422` for `DECRYPT_FAILED`, `CERT_NOT_FOUND`, `SELF_ENCRYPTION_KEY`; `502` for any code starting `CALLBACK_`, `GATEWAY_`, `CERT_FETCH_`, `TOKEN_`; `501` `LEDGER_DISABLED`. A gateway refusal is recorded in the ledger as `rejected` with `GATEWAY_HTTP_`. + +## 6. The inbound callback your HMIS receives + +The adapter POSTs to `callback.url` plus the NHCX path. Body: + +```json +{ + "meta": { + "type": "in", + "payloadType": "fhir", + "path": "v1/preauth/on_submit", + "ip": "1.2.3.4", + "time": "", + "redelivery": false, + "participant": "@hcx" + }, + "jwe_headers": { + "alg": "RSA-OAEP-256", "enc": "A256GCM", + "x-hcx-api_call_id": "...", "x-hcx-correlation_id": "...", "x-hcx-request_id": "...", + "x-hcx-sender_code": "@hcx", "x-hcx-recipient_code": "@hcx", + "x-hcx-status": "response.partial", "x-hcx-timestamp": "...", "x-hcx-workflow_id": "20" + }, + "fhir": { "resourceType": "Bundle", "...": "..." } +} +``` + +`payloadType` is `fhir` for a bundle and `protocol` for a ProtocolResponse. A ProtocolResponse is a refusal. Then `fhir` is the plain JSON body with `type: "ProtocolResponse"`, `x-hcx-status: response.error` and `x-hcx-error_details` at its top level. + +HTTP headers on the delivery: + +| Header | Value | +| --- | --- | +| `X-Nhcx-Path` | `v1/preauth/on_submit` | +| `X-Nhcx-Payload-Kind` | `fhir` or `protocol` | +| `X-Nhcx-Correlation-Id` | the thread | +| `X-Nhcx-Api-Call-Id` | this delivery's id, stable across redeliveries | +| `X-Nhcx-Redelivery` | `true` when the ledger already holds this api_call_id (absent otherwise) | +| `X-Nhcx-Participant` | the hosted identity it was addressed to | +| `X-Hcxkit-Txn-Id` | equals `x-hcx-api_call_id` (what a kit-style backend dedupes on) | +| `X-Hcxkit-Type` | entity: `coverage`, `insurance`, `preauth`, `claim`, `task`, `payment`, `communication`, `status` | +| `X-Hcxkit-Flow` | `request` for an arriving response, `on_request` for an arriving request (inverted on purpose) | +| `X-Hcxkit-Payload-Kind` | same as `X-Nhcx-Payload-Kind` | +| `Authorization` | `Bearer ` when configured | + +Contract: answer any 2xx quickly. The adapter then answers NHCX with the 202 acceptance body and an `X-Nhcx-Ledger-Id` header: + +```json +{ + "timestamp": "11/09/2026 10:00:00:123", + "api_call_id": "...", "correlation_id": "...", + "result": { "sender_code": "...", "recipient_code": "...", "entity_type": "preauth", "protocol_status": "request.queued" }, + "error": { "code": "", "message": "" } +} +``` + +A non-2xx from your HMIS becomes `CALLBACK_HTTP_` and NHCX redelivers. NHCX makes five attempts, then drops the correlation id. Your handler must therefore be idempotent on `x-hcx-api_call_id`. Do not do slow work inside the callback: store the envelope, answer 200, apply it after. Apply a delivery on a context detached from the incoming request, so a gateway that hangs up cannot roll the write back. + +The HMIS callback handler: + +- Routes `POST /callback`, `POST /callback/` and `POST /nhcx/callback`. +- Takes an optional shared secret on the query string (`?token=`). +- Reads `X-Hcxkit-Type`, `X-Hcxkit-Flow` and `X-Hcxkit-Payload-Kind`. +- Archives the envelope before applying it. +- Answers `400` for an unreadable body, because redelivery cannot help. Anything unexpected becomes a 500, so the adapter retries. +- Returns `{"status": "settled" | "unmatched" | "ignored"}`. +- Routes by correlation id, never by path. + +## 7. The ledger + +Layout: `ledger.dir//.json`, one file per message, plus `/index.jsonl` with one summary line per message. Ids are eight base32 characters (alphabet `0-9A-V`), a day prefix and a counter that restarts each day: `7UMV0001` is the first message of its day. Pruned hourly by `retentionDays`. + +Entry fields: `id, direction (out|in), created_at, path, entity, action, kind (request|response), format (fhir|protocol|json), sender, recipient, correlation_id, api_call_id, request_id, workflow_id, hcx_status, status, error{code,message}, redelivery, duration_ms, peer{url,status_code,response}, also[], headers{}, fhir{}, fhir_summary{resource_type,bundle_type,entries,resource_types,focus,identifier,patient,outcome}`. + +`status` values: outbound `accepted`, `rejected`, `failed`; inbound `delivered`, `delivery_failed`, `rejected`. + +Thread: `{correlation_id, entity, workflow_id, counterparty, role (initiator|responder), state, started, updated, messages[]}`. `state` is derived by walking the messages in order: + +- `awaiting_response`: you sent a request. +- `awaiting_our_response`: a request reached you. +- `partial`: a `response.partial` arrived. +- `completed`: a response closed it. +- `error`: a rejection, a failed send or delivery, a protocol message, or an `error` status. +- `unknown`. + +Two ledger behaviours you rely on. An outbound `on_` response with no `correlation_id` is threaded to the newest matching inbound request. An inbound whose `api_call_id` was seen before is flagged `redelivery: true`. + +CLI, same data, no server needed for `follow`: + +```sh +nhcx-adapter ledger list --since 24h --entity preauth --status rejected +nhcx-adapter ledger follow --direction in +nhcx-adapter ledger show 7UMV0007 +nhcx-adapter ledger thread +nhcx-adapter ledger stats +nhcx-adapter decrypt --file body.json +nhcx-adapter cert +nhcx-adapter send --path v1/preauth/submit --recipient --file bundle.json +``` + +## 8. hcxkit-compatible endpoints + +A client written against hcxkit polls the adapter for the other side's answer instead of only waiting for its callback. The adapter serves the sliver of hcxkit's `/internal` API that such a client needs. None of these need the API key. Keep the adapter's port off any network you do not control (`nhcx-package/docs/02-Getting Started/10-NHCX Adapter.md`, "Before you expose it"). + +| Route | Body | Answers | +| --- | --- | --- | +| `GET /internal/config/get` | none | `{participant{participantId,name,callbackUrl}, participants[], CMID, env, urls{nhcx,participant,sessions}}` | +| `POST /internal/participants/search` | `{"participant_code": ""}` | `{participants:[registry record + participant_code, participant_name, endpoint_url, status, roles]}`; an unknown code is `{participants: []}` | +| `POST /internal/txn/related` | `{"txnId": ""}` | every ledger row on the same correlation id, both directions, as `{id, direction, status, sender, recipient, correlation_id, api_call_id, type, flow, created_at}`; `404 TXN_NOT_FOUND` when the ledger no longer holds it | +| `POST /internal/txn/fhir` | `{"txnId": ""}` | `{meta{type,payloadType,path,time}, jwe_headers, fhir}`, the same envelope shape a delivery carries | +| `POST /internal/txn/dispatch` | `{"txnId": ""}` | `{txnId, status}` with `dispatch_failed` for a failed or rejected send, `dispatched` for accepted or delivered, plus `errorCode`, `errorMessage` | +| `GET /internal/txn/list?limit=200` | none | the recent ledger, newest first, same row shape | +| `POST /internal/policies/search` | `{"identifiertype": "MemberId", "MobileNo" or "AbhaNumber", "identifiervalue": "..."}` (also `mobile`, `abhaNo`) | the ABDM registry's `participant/get/policies` answer, status passed through; "No policies found" is an error the caller reads as empty | +| `POST /internal/policies/abha/link`, `.../delink` | forwarded verbatim | registry answer | +| `POST /internal/participants/list` | forwarded verbatim | registry roster | +| `POST /internal/participants/certs` | `{"participantid": ""}` | `{participant_code, encryption_cert}` | +| `GET /internal/participants/saved` | none | the configured profiles | + +The polling pattern: + +1. After a send, call `/internal/txn/related` with the stored `txn_id`. +2. Take the inbound rows on the thread that were not sent by you. Keep only rows addressed to the participant the send came from. +3. Fetch each with `/internal/txn/fhir`, newest first. +4. Take the first whose bundle carries the resource the reply is made of (ClaimResponse, CoverageEligibilityResponse, InsurancePlan, Task). +5. Apply it through the same code path the callback uses. Dedupe on `x-hcx-api_call_id`. + +A `404` from `txn/related` means the ledger was reset. Settle the leg as an error instead of spinning. + +## 9. curl examples + +Set these once. The address is the adapter's default `listen`: + +```sh +export ADAPTER=http://127.0.0.1:8090 +export KEY= +export ME=@hcx +export PAYER=@hcx +``` + +Liveness and readiness: + +```sh +curl -s $ADAPTER/healthz +curl -s $ADAPTER/readyz +``` + +Send a coverage eligibility check. Write the envelope to a file first. The bundle is the package's validation request, `nhcx-package/fhir/B1/validation.json`, with your own identifiers substituted. Run this from the project root that holds `nhcx-package/`: + +```sh +python3 - <<'EOF' +import json, os +bundle = json.load(open("nhcx-package/fhir/B1/validation.json")) +env = {"jwe_headers": {"x-hcx-sender_code": os.environ["ME"], + "x-hcx-recipient_code": os.environ["PAYER"], + "x-hcx-workflow_id": ""}, + "fhir": bundle} +json.dump(env, open("/tmp/coverage-out.json", "w")) +EOF +curl -s $ADAPTER/fhir/out/v1/coverageeligibility/check \ + -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \ + --data-binary @/tmp/coverage-out.json +``` + +Read the answer back from the ledger with the `correlation_id` from that response: + +```sh +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger/thread/" +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger?direction=in&entity=coverageeligibility&since=1h" +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger/" +``` + +Same thread through the kit endpoints (no key): + +```sh +curl -s $ADAPTER/internal/txn/related -H 'Content-Type: application/json' -d '{"txnId":""}' +curl -s $ADAPTER/internal/txn/fhir -H 'Content-Type: application/json' -d '{"txnId":""}' +``` + +A session token for the PMJAY payer service or a registry call: + +```sh +curl -s -H "Authorization: Bearer $KEY" $ADAPTER/token +``` + +Simulate a delivery to your own callback while the adapter is not involved (useful for the callback handler's unit test). This is the exact shape the adapter posts. Wrap the package's bare payer bundle, here the pre-auth approval `nhcx-package/fhir/C5/C5-approved-wf21.json`, as `{"meta":{...},"jwe_headers":{...},"fhir":}` first: + +```sh +python3 - <<'EOF' +import json +bundle = json.load(open("nhcx-package/fhir/C5/C5-approved-wf21.json")) +env = {"meta": {"type": "in", "payloadType": "fhir", "path": "v1/preauth/on_submit"}, + "jwe_headers": {"x-hcx-correlation_id": "", "x-hcx-api_call_id": "", + "x-hcx-sender_code": "@hcx", + "x-hcx-recipient_code": "@hcx", + "x-hcx-status": "response.complete", "x-hcx-workflow_id": "21"}, + "fhir": bundle} +json.dump(env, open("/tmp/delivery.json", "w")) +EOF +curl -s -X POST "http://127.0.0.1:/nhcx/callback/v1/preauth/on_submit" \ + -H 'Content-Type: application/json' -H 'X-Nhcx-Path: v1/preauth/on_submit' \ + -H 'X-Nhcx-Payload-Kind: fhir' -H 'X-Nhcx-Correlation-Id: ' -H 'X-Nhcx-Api-Call-Id: ' \ + -H 'X-Hcxkit-Txn-Id: ' -H 'X-Hcxkit-Type: preauth' -H 'X-Hcxkit-Flow: request' -H 'X-Hcxkit-Payload-Kind: fhir' \ + -H 'Authorization: Bearer ' \ + --data-binary @/tmp/delivery.json +``` + +## 10. The HMIS-side endpoints a build exposes + +Use these as the model for what your HMIS needs. `` is the claim episode id. + +| Method | Path | Purpose | Leg | +| --- | --- | --- | --- | +| GET | `/claims`, `/claims/new`, `/claims/` | list, policy search, detail | none | +| POST | `/claims` | open an episode from a chosen policy | none | +| GET | `/claims//state` | the whole episode as JSON after the page-load polls | none | +| POST | `/claims//check` | coverage eligibility (validation, benefits, discovery) | `v1/coverageeligibility/check` | +| POST | `/claims//plan` | fetch or refresh the package master | `v1/insuranceplan/request` | +| GET | `/claims//plan/forms`, `.../forms/`, `.../plan/` | questionnaires and one package | none | +| POST | `/claims//link`, `/unlink` | attach or detach the admission | none | +| POST | `/claims//preauth` | save the dossier draft | none | +| GET, POST | `/claims//lines`, `.../lines/quantities`, `.../lines//delete` | procedure, implant and tier lines | none | +| POST | `/claims//forms` | save questionnaire answers | none | +| POST | `/claims//auth` | auth-requirements ruling | `v1/coverageeligibility/check` | +| POST | `/claims//submit` | pre-auth 12, query answer 19, enhancement 13, enhancement answer 131 | `v1/preauth/submit` | +| POST | `/claims//predetermination` | a quote | `v1/preauth/submit` | +| POST | `/claims//cancel` | cancel Task PC01 | `v1/task/submit` | +| POST | `/claims//status` | status enquiry Task | `v1/task/submit` | +| POST | `/claims//reprocess`, `/release` | reprocess or balance release, 36 | `v1/task/submit` | +| POST | `/claims//queries//reply`, `.../acknowledge` | communication reply or notification acknowledgement | `v1/communication/on_request` | +| POST | `/claims//discharge` | record how the stay ended | none | +| POST | `/claims//claim` | claim 15, query answer 161 or 151, resubmit 16 | `v1/claim/submit` | +| POST | `/claims//claim/documents`, `/documents`, `/documents/required`, `.../delete` | attachments | none | +| GET | `/claims//documents/` | view an attachment | none | +| POST | `/claims//payments//ack` | resend a payment acknowledgement | `v1/paymentnotice/on_request` | +| POST | `/v1/` under the registered `endpoint_url` (own transport), or `/callback`, `/callback/`, `/nhcx/callback` (nhcx-adapter) | a delivery | inbound | + +The HMIS configuration a build needs: + +- The transport's settings: for nhcx-adapter, its base URL (it listens on `127.0.0.1:8090` by default) and API key; for your own transport, the ABDM client id and secret, the private key, and the sessions, NHCX and registry addresses (`references/transport-knowledge.md` section 3). +- The payer's participant code (`1518@hcx` for the PMJAY SHA Himachal Pradesh sandbox) and the payer's name. +- The callback shared secret. +- A workflow-id override table, JSON, that overrides the per-payer table key by key, for example `cancel=122`. +- A map from payer code to payer adapter, for example `1518=pmjay,=generic`. +- The archive folder for cases, and a switch to turn the archive off. + +The sender code is not an environment variable. It is the facility's participant code, held in the HMIS's own settings. + +## 11. What the adapter client looks like in code + +The whole client is one function, `_api(path, payload, timeout, method, claim_id, use_case)`. It builds the URL from the base, adds `Authorization: Bearer` when a key is set, POSTs JSON, raises `GatewayError(message, status)` on any non-2xx or network failure, decodes JSON, and archives the envelope beside the case when `claim_id` is given. Every send in the module goes through it, which is what lets a test replace it with a stub: + +```python +posted = {} +def _ack(path, payload=None, **kw): + posted["path"], posted["payload"] = path, payload + return {"txn_id": "01PLAN", "correlation_id": "corr-plan-1"} +claims._api = _ack +``` + +Give your HMIS the same single door. diff --git a/plugins/nhcx/skills/nhcx-reprocess/references/errors-and-debugging.md b/plugins/nhcx/skills/nhcx-reprocess/references/errors-and-debugging.md new file mode 100644 index 000000000..9be844d82 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-reprocess/references/errors-and-debugging.md @@ -0,0 +1,167 @@ +# Errors and debugging + +Sources: + +- `nhcx-package/nhcx-error.yaml`: every NHCX, PAYR and ERR-PYR code, with the standard and reference payer readings side by side. +- `nhcx-package/docs/06-Reference/01-Error Codes.md`: the same codes as tables. +- `nhcx-package/docs/01-Overview/04-JWE, Status and Errors.md`, "Codes met live". +- `nhcx-package/docs/03-Building a Provider/11-PMJAY Sandbox Run.md`: one full case run, refusal by refusal. +- `nhcx-package/docs/06-Reference/02-Troubleshooting.md`. +- The nhcx-adapter release README, "Troubleshooting". + +The live readings are from runs against the PMJAY SHA Himachal Pradesh sandbox payer (`1518@hcx`). + +## 1. Where an error comes from + +Three places refuse a message, and the family of the code says which (`nhcx-error.yaml`, `spaces`): + +| Family | Who refused | How you hear it | +| --- | --- | --- | +| Gateway answers to your own send (`400`, `401`) | the exchange, before the message goes further | the HTTP answer to your POST on `/v1/...`; a `401` is an expired token or a missing `Bearer` | +| A delivery your key cannot open (own transport) | your receiving end | the JWE will not decrypt: the certificate on your participant record is not the key you hold | +| Adapter codes (`INVALID_ENVELOPE`, `CERT_NOT_FOUND`, `CALLBACK_HTTP_500`), nhcx-adapter only | nhcx-adapter, before or after the wire | the HTTP answer to your `/fhir/out` call, `{"ok": false, "error": {...}}` | +| `NHCX-*` | the exchange; the message never reached the payer | the HTTP answer to your call (`gateway_status` 4xx with `upstream_body`), or a `ProtocolResponse` delivered to your callback later | +| `PAYR-*`, `ERR-PYR-*` | the payer; the message reached it | a `ProtocolResponse` on your callback with `x-hcx-status: response.error` and `x-hcx-error_details {code, message}`, on the request's correlation id | + +A `ProtocolResponse` is plain JSON, not a bundle. The exchange delivers it with `type: ProtocolResponse` and the `x-hcx-` fields in the clear; nhcx-adapter passes it on with `X-Nhcx-Payload-Kind: protocol` and `fhir` set to the body. Read `fhir.type == "ProtocolResponse"` and `fhir["x-hcx-error_details"]`. Settle the leg as refused at the door with the payer's words, and keep the thread the payer last answered on. + +PAYR numbers are not globally unique. The same number means different things on different sheets (`nhcx-error.yaml` lists them under `collisions`), and the live sandbox reuses several with a meaning the published sheet does not give. Match on the message text and log both. + +## 2. PAYR and ERR codes met live + +The published text is from `nhcx-package/nhcx-error.yaml`. Where the standard and reference payer sheets collide, both readings are given. The live text and the fix are from the sandbox runs. + +| Code | Published text | Live text | What it means | Fix | +| --- | --- | --- | --- | --- | +| PAYR-1008 | Invalid FHIR bundle received (reference payer); Eligible coverage amount is insufficient (standard) | "Invalid content type" or "Invalid input, code and reason code" or "Invalid Base64" | Three faults on one code: a document outside pdf, jpg, jpeg, png and fhir+json; a Task code paired with a reason the scheme does not accept (every `status`, `reprocess`, `release` Task on the sandbox, and a reprocess with the intimation input misspelt); an attachment it will not decode | Check the content type. For a Task, the sandbox takes only one financial task code, `cancel` (`11-PMJAY Sandbox Run.md`, "What the sandbox will not take"). Spell the reprocess input `intimationNumber` | +| PAYR-1018 | Time limit for submission expired (standard); No task reason code received (reference payer) | asks for a `Task.reasonCode` on a status enquiry | The status Task is refused as incomplete; with a reason it is refused with PAYR-1008 | Do not offer a status enquiry on PMJAY; switch it off in the PMJAY payer adapter | +| PAYR-1019 | Requested additional information was not received in time (standard); Invalid sequence received in supporting info element (reference payer) | "Invalid sequence received in supporting info element" | A `supportingInfo` entry with no `sequence` | Number the whole list once it is assembled | +| PAYR-1027 | (item error family) | "Invalid item id found for item in claim component" | `Claim.item` has no element `id` (`Item/1`). Nothing to do with the package code | Put `id` on every item, procedure and supportingInfo | +| PAYR-1083 | (practitioner family) | "No HPR details found for the practitioner ... category code as HPIN" | The Practitioner carries no identifier typed `HPIN` | Add the `HPIN` identifier under `https://hpr.abdm.gov.in` | +| PAYR-1096, PAYR-1503 | (supporting-info value-type family) | the death date is missing | A death claim without the `ONS`/`DTM` entry | Add `ONS`/`DTM` with the death instant and answer the plan's death forms | +| PAYR-1214 | No previous preauthorization approved record found for the resubmission request | same | A 121 after a rejection | Send a fresh 12 | +| PAYR-1238 | Beneficiary is having an active preauthorization request at this hospital with reference number ... | same; the reference ends in the SHA's case id | Scheme rule, not a bundle fault: one live pre-auth per beneficiary per hospital. Perversely the first sign the bundle is right, because validation runs first | Cancel the other case (PC01) or let it be rejected; sweep before a run | +| PAYR-1245 | Rule failure | "Only one conservative procedure can be booked for a case" | The master's `ProcedureType`; an enhancement on a conservative case must add a medical package | Pick a package whose `ProcedureType` is medical | +| PAYR-1254, PAYR-1365 | Response for STG Questionnaire id ... is mandatory for procedure code ... | same | A package's treatment-guideline questionnaire unanswered | Answer every `/stgquestionnaire/` form the plan attaches to the quoted packages | +| PAYR-1256, PAYR-1363 | Response for Authentication Consent Questionnaire is missing | same | The plan's consent questionnaire unanswered where no biometric token was taken; 1256 on the pre-auth, 1363 on the claim | Answer the policy-level consent form on both legs | +| PAYR-1270 | Item LM100 is not applicable for preauthorization request | same | `LM100` on a pre-auth | Only a LAMA or DAMA claim before or during surgery carries it | +| PAYR-1321 | Error occurred while processing the request due to invalid workflow id | same | 151, 19 or 16 on `v1/claim/submit` | Answer a claim query on 161; never resubmit a decided claim, reprocess it | +| PAYR-1322 | No active case found for the given case number | "Active instance found for case number" | A request is already open on that case; the scheme takes one at a time | Wait about 30 seconds after a decision, then send again; up to three tries | +| PAYR-1362 | No procedure with code LM100 received with 'Requested' status | same | A LAMA or DAMA claim before or during surgery that still carries the package | Collapse the claim to one `LM100` line | +| PAYR-1367, PAYR-1368 | No biometric records found ... / units of cycle information received | same | A cyclic package (dialysis) claimed without a biometric record per cycle and cycle information | Do not claim a cyclic package unless the HMIS can produce both | +| PAYR-1401 | policy not allowed for the hospital | same | The plan was asked for under a policy the hospital is not empanelled under | Ask under the beneficiary's own policy code from the policy search | +| PAYR-1406 | Existing request with correlation id ... is in progress | same | A second plan request while one is still being served | Wait 15 to 60 minutes; reuse the master you hold | +| ERR-PYR-CLM-007 | on none of the published sheets; `nhcx-error.yaml` lists it as observed live | "No prior preauthorization or claim record found for case number" | The claim was sent under a number of its own instead of the pre-auth's | Send the claim under the pre-auth's claim number | + +Refusals arrive in order: the SHA validates the bundle first and applies the scheme's rules only to a bundle that passed. A refusal in the `PAYR-102x` block is structural, so check ids and sequences before values. + +## 3. Gateway protocol errors + +From `nhcx-package/nhcx-error.yaml` (the gateway space) and the live notes: + +| Code | Message | When you meet it | Fix | +| --- | --- | --- | --- | +| NHCX-1006 | Duplicate request. Request with same correlation id already exist | A request sent again on a correlation id the exchange already holds | Mint a fresh correlation id for every request; only a response echoes one | +| NHCX-1010 | No Data with given Correlation id for call back request | A response sent on a thread the exchange has retired: the request was redelivered five times without a 2xx, or the id was never a request | Acknowledge inbound requests at once; a payer that decides minutes later sends `outcome queued` first | +| NHCX-1012 | No records found with the requested api caller id | The sandbox's own `v1/status` route, whatever id you pass | Ask status as a Task on `v1/task/submit` | +| NHCX-1015 | Invalid response received from receiver (published); the registry answers "You are not authorized to update/modify details" | Updating a participant's endpoint or certificate with a client id that did not create it | Use the creator's credentials or the NHCX participant portal (nhcx-adapter release README, "Troubleshooting") | +| NHCX-1016 | Invalid Api Action / no policies found (the registry, on a policy search) | A policy search that finds nothing | Read it as an empty result | +| NHCX-1018 | Invalid ABHA number received | An ABHA not in `XX-XXXX-XXXX-XXXX` form on the envelope | Format it, or omit the header | + +With nhcx-adapter as the transport, its local codes and their HTTP statuses are in `api-knowledge.md` section 5. The ones you will meet first: + +- `CERT_NOT_FOUND`: the recipient has no certificate on the registry; nothing to fix locally. +- `SELF_ENCRYPTION_KEY`: the registry handed out your own certificate for another code; run `nhcx-adapter cert --refresh`. +- `DECRYPT_FAILED` on `/in`: your registered certificate is not the key you hold; run `nhcx-adapter check`. +- `WRONG_RECIPIENT` on `/in`: a message for a participant this adapter does not hold. +- `CALLBACK_HTTP_` and `CALLBACK_UNREACHABLE`: your HMIS refused or was down; NHCX will redeliver up to five times. +- `TOKEN_HTTP_401`: wrong `clientId` or `clientSecret`, or sandbox credentials against production. + +## 4. Reading a ledger thread + +The per-case archive is the first place to look, with any transport: every message sent and received, by correlation id, in `//transactions.txt` (step 4). With nhcx-adapter as the transport, its ledger also holds what reached it but not your HMIS; the commands below read it. + +Step 1. Find the thread. From the leg row's `correlation_id`, or from the case number in a summary: + +```sh +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger/thread/" | python3 -m json.tool +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger?since=2h&direction=in&limit=100" | python3 -c 'import json,sys; [print(r["id"], r["created_at"][11:19], r["direction"], r["path"], r["workflow_id"], r["hcx_status"], r["status"], r.get("fhir_summary",{}).get("outcome")) for r in json.load(sys.stdin)["items"]]' +nhcx-adapter ledger thread # no server needed +``` + +Step 2. Read the derived `state`: + +| state | Meaning | What to do | +| --- | --- | --- | +| `awaiting_response` | You sent a request and nothing came back | Wait; on the SHA a decision needs the desk. Check `peer.status_code` on the outbound row is 202 | +| `partial` | A `response.partial` arrived (20, 25, or the SHA's 37) | The payer has it. The decision comes on the same thread | +| `completed` | A `response.complete` arrived | The leg should be settled in the HMIS. If it is not, the callback failed or the reader misread it | +| `awaiting_our_response` | A request reached you (a CommunicationRequest, a payment notice) | Your reply is due on this correlation id | +| `error` | A rejection, a failed send or delivery, or a protocol message | Open the message with `error` or `format: protocol` | + +Step 3. Read one message in full, bundle included: + +```sh +curl -s -H "Authorization: Bearer $KEY" "$ADAPTER/ledger/" | python3 -m json.tool | less +``` + +On an inbound row, `peer.status_code` is what your callback answered and `peer.response` is its body. A `delivery_failed` row with a 500 is your handler raising. On an outbound row, `peer.status_code` is the gateway's answer and `peer.response` its body. A `rejected` row carries `GATEWAY_HTTP_` and the NHCX error in `peer.response`. + +Step 4. Compare with the HMIS's own archive for the case, `//transactions.txt`. Each line names the workflow id, correlation id, api call id, ledger id and file. + +- A message in the ledger and not in the archive is a callback that failed. +- A message in the archive marked `outcome=unmatched` is one the HMIS could not tie to a case: the correlation id is on no leg row, and the bundle names no claim number the HMIS knows. +- A message in neither is a send that never left; look at the HMIS's error on the leg row. + +Files, when the server is down: `//.json`, and `index.jsonl` in the same folder for the summaries. `ledger.dir` is `data/ledger` by default. + +## 5. Correlation mistakes + +Each of these was made once in a real build. + +- Answering on the wrong thread. A communication reply or a payment acknowledgement must carry the request's `x-hcx-correlation_id`; every other leg must not carry one. A PMJAY query answer (19, 131, 161) goes on a new correlation id; a same-thread answer is swallowed without a refusal. +- Sending a non-UUID correlation id. nhcx-adapter replaces anything that is not an 8-4-4-4-12 UUID with a fresh one, so the thread is silently lost; store what the transport returned, not what you sent. With your own transport, a request's correlation id is its own `api_call_id` and an answer echoes the request's. +- Matching by path or by header type. Route an inbound message by its correlation id first, then by the claim number inside the bundle. With nhcx-adapter, the `X-Hcxkit-Flow` header is inverted on purpose and must not be a filter. +- Closing a thread on the first reply. The acknowledgement and the decision share one correlation id; a settled-status guard throws the approval away. +- Losing the thread after a refusal at the door. A send refused with a ProtocolResponse went out under a correlation id the payer never took in. The case still lives on the thread the payer last answered; keep it as `thread_correlation_id`. +- Reusing a correlation id after an error. The exchange retires it; the next attempt needs a fresh one. +- Forgetting the workflow id on a reply. Some payers match the payment acknowledgement on the notice's own workflow id; PMJAY wants 17. + +## 6. Redelivery and deduplication + +NHCX redelivers an unacknowledged message up to five times and then drops the correlation id. The SHA redelivers a large plan answer on its own, two or three times about a minute apart, under the same `x-hcx-api_call_id`. A case archive showed it as three lines on one api call id. With `callback.also` configured, one delivery reaches every target, and a refusal by any one of them makes NHCX redeliver to all. + +So: + +- Dedupe on `x-hcx-api_call_id` (with nhcx-adapter, `X-Hcxkit-Txn-Id` carries the same value). Either store the last applied `api_call_id` on the leg row and ignore a repeat, or keep an inbound ledger keyed on it and answer `duplicate`. A payer that omits the id is deduped on identical outcome and adjudication. +- Dedupe payment notices and communication requests on their correlation id, with a unique index on each table. +- Answer 2xx before doing slow work. The exchange allows 30 seconds for the 202 receipt (nhcx-adapter gives your HMIS 20 of them, `callback.timeoutSeconds`); anything slower is a failed delivery. +- Un-record a delivery whose application failed for a passing reason (database away), so the redelivery is not waved off as a duplicate. +- With nhcx-adapter, treat `X-Nhcx-Redelivery: true` as a hint, not a rule: the ledger flag is per adapter process and is lost on a ledger reset. + +## 7. A send reported as failed can still have landed + +Seen live on the sandbox three times in one night. A pre-authorisation went out through nhcx-adapter, the connection dropped after the request had been written, and it answered the hospital `GATEWAY_UNREACHABLE` with HTTP 502. NHCX had taken the message: the SHA acknowledged it four seconds later on the correlation the adapter had minted. A hospital that treats that 502 as "not sent" sends again. The scheme refuses the duplicate (ERR-PYR-PRE-030 "Active instance found for case number", PAYR-1238 for a fresh pre-auth), and a live case stands at the payer that the hospital has no record of. + +So: + +- nhcx-adapter's failure body names the ids the message went out under: `ledger_id`, `txn_id`, `correlation_id`, `api_call_id`, `request_id` and the `headers` map. Keep them. With your own transport the ids are the ones you minted before sealing: store them before the POST, so a failed POST still has a thread to look for. +- Record the failed leg under that correlation, not as nothing. Carry the ids on the client's error and write them onto the leg row. +- When an answer arrives on a failed leg's correlation, revive it: the leg becomes a sent leg, the record moves from draft to with-the-payer, and the desk is not offered a second send. A protocol error answer revives nothing. +- Anything that creates a record before it sends must name that record in the refusal, or the record is orphaned where nobody can see it. An enhancement handler returns the child it raised alongside the gateway's words. + +## 8. Sandbox pace rules + +What the SHA Himachal Pradesh sandbox (`1518@hcx`) did across the runs. `nhcx-package/docs/03-Building a Provider/11-PMJAY Sandbox Run.md` records one such run in order. + +- One live pre-authorisation per beneficiary per hospital (PAYR-1238). Every HMIS that shares the facility's participant code shares the limit, so sweep before a run: withdraw every approved case without a claim, then wait ten seconds. +- One request at a time per case (PAYR-1322). About 30 seconds between a decision and the next leg; an enhancement refused with "Active instance" is resent up to three times. +- Decisions are taken on the NHCX Payer Service desk, not on the exchange (`nhcx-package/docs/03-Building a Provider/12-PMJAY Adjudication APIs.md`). A case has to be driven through roles: PPD-Trust decides a pre-auth; a claim walks CEX-Trust, CPD-Trust, the Medical Audit Committee, ACO-Trust, SHA-Trust and the Claim Review Committee. The desk answers "Event Meta Log not found" or "Case not found" until the exchange has delivered the request; retry every six seconds, up to 150 seconds. A decision the desk accepts is sometimes never sent; taken again a minute later it is answered in seconds, so decide up to four rounds of 90 seconds. +- An enhancement's query has to be taken a minute after the acknowledgement. +- A claim episode with a query answered and the roles walked takes about ten minutes. Run cases one at a time and allow 20 minutes per case. +- The plan answer arrives in pieces over a minute and is redelivered; expect the same api call id three times. +- The beneficiary registry behind the ABDM session refuses a search now and then while a token refreshes. Retry the search up to four times, 30 seconds apart. +- The sandbox approves a claim query answer at zero with "No query response comments received" when the `CQD` reply is missing, and sometimes even when it is present. Report it; do not assert on the amount. +- The status Task is refused on this sandbox: without a `Task.reasonCode` it answers PAYR-1018, with any reason code PAYR-1008. PMJAY decides on its own desk and answers no status enquiry, so do not offer one for it. Record the refusal on the enquiry row and move on. +- The reprocess Task is taken only under the standard's spelling, `intimationNumber`. Use that spelling on every Task (cancel included); the package's bundles carry it too. The SHA answers workflow 37, "Arbitration claim submission process completed successfully". +- A test payer you run yourself has none of these limits; six use cases ran in under four minutes against one. diff --git a/plugins/nhcx/skills/nhcx-reprocess/references/fhir-knowledge.md b/plugins/nhcx/skills/nhcx-reprocess/references/fhir-knowledge.md new file mode 100644 index 000000000..08ffbb6c6 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-reprocess/references/fhir-knowledge.md @@ -0,0 +1,206 @@ +# FHIR knowledge: every bundle sent and received + +Sources: the bundles under `nhcx-package/fhir` (the hospital pins in `B1` to `B9`, the payer answers in `C3` to `C11`, the live PMJAY hospital captures in `D1` to `D13`) and the chapters under `nhcx-package/docs/05-FHIR Reference`. Get the package as `references/material.md` says. + +## 1. Where the examples live + +| Set | Path | What it is | +| --- | --- | --- | +| Pinned hospital bundles | `nhcx-package/fhir/B1` to `B9`, the lower-case files (`B3/preauth-request.json`) | One bundle per message a hospital sends, written to the specification with placeholders. A build is held to these byte for byte. The pin map is in `references/material.md`. | +| Payer answers | `nhcx-package/fhir/C3` to `C11` | One file per message the payer sends: the generic answer and, where one exists, its `-pmjay` twin. Feed these into your readers. | +| Live hospital captures | `nhcx-package/fhir/D1` to `D13` (PMJAY) and the capitalised B files such as `B3/B3-request.json` (generic) | Bundles taken from the sandbox wire, with the beneficiary's identifiers replaced | +| The catalogue | `nhcx-package/fhir/index.yaml` | For each file: direction, side, scheme (`generic` or `pmjay`), workflow id, focal resource, origin. Origin `example` means placeholders, not a payload; `wire` means a capture. | +| The NRCeS IG's own example | `nhcx-package/fhir/B4/communication-request.json` | The communication TaskBundle for the payer's request comes from the IG | +| Your build's archive | `//NNN--.json` and `transactions.txt` (modules 7.1 and 7.3) | Every envelope one episode sent and received, in order | +| Chapters | `nhcx-package/docs/05-FHIR Reference/*.md` | Element by element: `08-Preauthorisation Request.md`, `12-Claim Request.md`, `13-Claim Response.md`, `17-Communication.md`, `15-Cancel, Reprocess and Shortfall.md`, `16-Payment Notice and Acknowledgement.md`, `06-Insurance Plan Response, Package-Based.md`, `19-Codes and Value Sets.md` | + +Pins, by leg. Paths are under `nhcx-package/fhir/`. + +| Leg | Provider pin | Payer answer or capture | +| --- | --- | --- | +| Coverage eligibility | `B1/discovery.json`, `B1/validation.json`, `B1/benefits.json`, `B1/auth-requirements.json` | `C3/validation-response.json`, `C3/discovery-response.json`, `C3/benefits-response.json`, `C3/C3-response-generic.json`; PMJAY `C3/coverage-eligibility.json`, `C3/C3-benefits-pmjay.json`, `C3/C3-response-pmjay.json` | +| Insurance plan | `B2/insurance-plan-request.json` | `C4/C4-response-pmjay.json` (package-based, abridged), `C4/C4-response-generic.json` (coverage-based) | +| Pre-auth 12, enhancement 13, query answer 19 or 131 | `B3/preauth-request.json`, `B3/preauth-enhancement.json`, `B3/preauth-queryupdate.json` | `C5/C5-received-wf20.json`, `C5/C5-approved-wf21.json`, `C5/preauth-queried.json`, `C5/C5-rejected-wf23.json`, `C5/C5-enhancement-approved-wf22.json`; PMJAY the `-pmjay` twins and `C5/C5-queried-wf24.json` | +| Cancel PC01 | `B3/preauth-cancel.json` | `C10/C10-cancelled-wfPC02.json`, `C10/C10-cancelled-wfPC02-pmjay.json` | +| Claim 15, query answer 161 | `B5/claim-request.json`, `B5/claim-queryupdate.json` | `C7/C7-received-wf25.json`, `C7/C7-approved-wf26.json`, `C7/claim-queried.json`, `C7/C7-rejected-wf291.json`; PMJAY the `-pmjay` twins, `C7/C7-approved-deduction-wf26-pmjay.json` and `C7/C7-queried-wf27.json` | +| Reprocess 36, release 36 | `B5/claim-reprocess.json`, `B5/claim-release.json` | `C10/C10-arbitration-wf37.json`, `C10/C10-arbitration-wf37-pmjay.json` | +| Payment acknowledgement | `B7/payment-notice-ack.json` | The notice you answer: `C9/C9-notice-wf30.json`; PMJAY `C9/payment-notice.json`, `C9/C9-notice-tds-wf30-pmjay.json` | +| Communication reply | `B4/communication-response.json` | `B4/communication-request.json` (the query you answer; the IG's example), `C6/C6-preauth-query-wf24.json` and `C6/C6-claim-query-wf27.json` (live, generic), `C6/C6-notification-wfN02.json` (PMJAY) | +| Status enquiry | None. The published call carries no bundle (`nhcx-package/docs/05-FHIR Reference/18-Predetermination, Status and Search.md`). | None captured | + +## 2. Conventions every hospital bundle follows + +From `nhcx-package/docs/05-FHIR Reference/01-Bundles and Conventions.md` and the pins: + +- `Bundle.type` is `collection`; `Bundle.meta.profile` names the NRCES bundle profile (`ClaimBundle`, `TaskBundle`, `CoverageEligibilityRequestBundle`); every resource names its own profile under `https://nrces.in/ndhm/fhir/r4/StructureDefinition/`. +- Every entry has an absolute `fullUrl` under one base, `https://nhcx.abdm.gov.in/...`, and every reference resolves to another entry. A thing that is genuinely not in the bundle is named by identifier, not by a URL. The chapter's rule 3 also accepts `urn:uuid:` references; parse both. +- `Bundle.id` is fixed per shape: `coverage-validation-request-generic`, `preauth-request-generic`, `preauth-enhancement-request-generic`, `claim-queryupdate-request-generic`, `preauth-cancel-request-generic`. +- No `meta.versionId`, no `meta.lastUpdated`, no bundle `timestamp` on a request. The communication reply and acknowledgement are the exception: the IG example carries `meta.lastUpdated` and `timestamp`, and the build writes them. +- Money carries `currency: INR`; the total equals the sum of the item nets; whole numbers are written as integers. +- Instants are IST with `+05:30`. The four coverage pins in `B1` stamp `created` at `+05:00`, so leave `created` out of the byte comparison. + +## 3. Coverage eligibility request + +Builder: `build_coverage_request`. Seven entries, in this order and at these urls: + +1. `CoverageEligibilityRequest` at `/coverage-eligibility/request`: `identifier: [{system: https://nhcx.abdm.gov.in}]`, `status active`, `priority normal`, `purpose: []`, `patient`, `created`, `enterer` (the PractitionerRole), `provider`, `insurer`, `facility` (the Location), `insurance: [{focal: true, coverage}]`, and `item[]` on `benefits` and `auth-requirements`. +2. `Patient` at `/patient`: identifiers typed `PMJAY` (NDHM identifier-type system) and `MB` (v2-0203), both the member id. Nothing else; demographics are the payer's to return. +3. `Organization` provider at `/provider`: identifier `NPI` under `https://nhcx.abdm.gov.in` = the facility's registry id (HFR id); `type prov`; `name`. +4. `Organization` payer at `/payer`: identifier `NIIP` = the participant code without `@hcx` (`1518`); `type pay`. +5. `Location` at `/location`: `name`, `managingOrganization` the provider. +6. `Coverage` at `/coverage`: identifier `NH` = the policy code, or `NONE` on a discovery; `status active`; `type HIP`; `subscriber`, `beneficiary`, `subscriberId` = member id; `relationship self`; `payor`. +7. `PractitionerRole` at `/practitioner-role`: `code` SNOMED `307988006` Medical technician. + +Items (`eligibility_item`): `category` under `https://nhcx.abdm.gov.in/category-code` (the specialty), `productOrService` under `https://nhcx.abdm.gov.in/product-code` (the package), `quantity.value` as an integer, and each ward tier quoted through the package as a `modifier` coding with code and display and no system. No money, no diagnosis, no sequence. + +The four purposes differ only in `purpose`, the Coverage identifier and whether `item` is present. + +Reader (`parse_validation_bundle`): the payer echoes the request's entries and appends its own, so take the last `CoverageEligibilityResponse`, `Patient` and `Coverage`. Read `insurance[0].inforce`, `outcome`, `disposition`, `item[].authorizationRequired`, the largest `benefit[].allowedMoney` with its `usedMoney`, the Patient's name, gender, birth date, address, `ABHA` identifier and photo, the Coverage's `class[0].name` and `period`. The SHA answers on workflow id `5` (`nhcx-package/fhir/C3/C3-response-pmjay.json`). + +Auth-requirements reader (`parse_auth_bundle`, with `supporting_entry`; examples `C3/C3-response-generic.json` and `C3/C3-response-pmjay.json`): one `insurance[0].item` per line quoted, each with `authorizationRequired`, `excluded`, `benefit[0]` and `authorizationSupporting[]`. Each supporting entry is a CodeableConcept whose `text` is free text the scheme overloads: `fullUrl: ` marks a form to answer; `Type: pre` or `Type: post` says which leg a document is due at; `Procedure Code: X` says for which line. The space after the colon is sometimes missing; match both. A form is always wanted at pre-auth; a document only when its stage is `pre`. + +## 4. Insurance plan request and the plan + +Request (`build_plan_request`): a `TaskBundle` with one entry, a `Task` at `https://nhcx.abdm.gov.in/insurance/request`: `status requested`, `intent order`, `code poll` on the HL7 financial task code system, inputs typed `policyNumber` and `providerId` under the NDHM task-input code system. No id, no timestamp, no requester. At least one input is mandatory. Bundle id `insurance-request-generic`. + +Answer: an `InsurancePlanBundle` with one `InsurancePlan`, an `Organization`, and one `Questionnaire` per form the plan names (the same form repeated once per benefit that needs it; collect by `url`). The parser (`parse_plan_bundle`) reads both published shapes and merges them on package code: + +- `plan[].specificCost[].category` (the specialty) then `benefit[].type` (the package) then `cost[]`: the cost typed `Procedure` is the package rate; `Stratification` and `Implant` costs are money paid over the rate, named by their `qualifiers[0]`. +- `coverage[].benefit[].limit[]`: the limit whose code is the package's own is the rate; the rest (STRAT codes, implants) are tiers. +- Extensions on the plan, the coverage and each benefit, matched by a squashed url family: `Claim-Condition` children name conditions (`ProcedureType`, `IsDayCare`, and so on); `Claim-SupportingInfoRequirement` children are one nested requirement per document, each with `category`, `code` (`MAND0409` and the like) and `documentationUrl` pointing at a Questionnaire. Requirements on the `InsurancePlan` resource itself are policy-wide (proof of identity, the consent forms). +- A `Questionnaire` under `/questionnaire/` is a policy form; under `/stgquestionnaire/` a treatment-guideline checklist. Questions live on `item.prefix` far more often than `item.text`; answer options are plain strings; `initialSelected` is the payer's default. + +Store it once per facility and policy and copy it onto later episodes (`reuse_plan`). The PMJAY master runs to tens of megabytes; the validator cannot check it whole. + +## 5. The Claim bundle: pre-authorisation, enhancement, query answer, claim, predetermination + +One document for every leg (`claim_bundle`). Entries, in order and at these urls: + +1. `Claim` at `https://nhcx.abdm.gov.in//`: leg `preauth`, `claim` or `predetermination`; flow `request`, `enhancement` or `queryupdate`. +2. `Patient` at `/patient`, `id 1`: identifiers `PMJAY` (member id), `ABHA` (when known), `MB` (member id); `name.text`, `telecom`, `gender`, `birthDate`. +3. `Organization` provider at `/provider`, `id 1`; `Organization` payer at `/payer`, `id 2` (as in section 3). +4. `Coverage` at `/coverage`, `id 1`: `NH` identifier = policy code, `subscriberId` = member id. +5. `Practitioner` at `/practitioner` (the second and later at `/practitioner/2` and so on), `id n`: identifiers `HPID` under `https://nhcx.abdm.gov.in`, `MD` (licence) when known, and `HPIN` under `https://hpr.abdm.gov.in`. PMJAY looks the practitioner up by the `HPIN` typed identifier and refuses a bundle without one with PAYR-1083. `qualification.code` under HL7 v2-0360 with the table's own display (`degree_coding`). +6. `Procedure` at `/procedure/n`, `id n`, one per package: `status preparation` before treatment, `completed` on the claim; `code` SNOMED `71388002` with `text` = the package display; `performedDateTime`. +7. `QuestionnaireResponse` at `/questionnaireresponse/n`, one per answered form: `questionnaire` = the plan's Questionnaire url, `status completed`, `subject` the Patient, `authored`, `item[].answer[]` typed by the question (`valueString`, `valueDateTime`, `valueBoolean`, `valueInteger`, `valueDecimal`, `valueAttachment`). + +The Claim itself: + +- `id` = the claim number; `identifier[0]` typed `CLN` under `https://nhcx.abdm.gov.in` = the claim number. Element ids on every list the payer indexes: `item[].id = Item/n`, `procedure[].id = Procedure/n`, `supportingInfo[].id = SupportingInformation/n`. PAYR-1027 is an item without one. +- `status active`, `type` SNOMED `737481003` inpatient care, `use` = `preauthorization`, `claim` or `predetermination`, `billablePeriod`, `created`, `insurer`, `provider`, `priority normal`. +- `careTeam[]`: sequence, provider reference, role `primary` for the first and `assist` after, `qualification` SNOMED specialty. +- `diagnosis[]`: ICD-10 under `http://hl7.org/fhir/sid/icd-10`, type `admitting`, `onAdmission yes`. +- `procedure[]`: sequence, `type` under `https://nhcx.abdm.gov.in/procedure-type` = the plan's `ProcedureType` condition lower-cased (`conservative`, `medical`, `surgical`), `date`, `procedureReference` with the package display. +- `insurance[0]`: `sequence 1`, `focal true`, `coverage`; on the claim `preAuthRef: [""]`. The pin carries the pre-auth's own claim number there (`B5/claim-request.json` quotes `B3/preauth-request.json`'s claim id). The build carries the payer's `ClaimResponse.preAuthRef`, which the live capture `nhcx-package/fhir/D9/D9-request.json` shows as `2026091110000810`. +- `item[]` (`claim_items`): one per procedure or implant, never per tier. `sequence`, `careTeamSequence`, `diagnosisSequence`, `procedureSequence` (its own Procedure), `informationSequence` (every supportingInfo), `category` under `ndhm-benefit-category` (the specialty), `productOrService` under `ndhm-procedure-code` (the package), `modifier[]` one coding per ward tier with code and display and no system, `programCode` `AB-PMJAY` under `ndhm-program-code` for PMJAY and none for a generic payer, `servicedPeriod` as dates, `quantity`, `unitPrice` = net divided by quantity, `factor` from the scheme's multiple-procedure rule (1, 0.5, 0.25 by cost rank; PMJAY only), `net` = the line plus its tiers. +- `total` = the sum of the nets. + +supportingInfo (`supporting_info`), every entry numbered once the list is assembled (PAYR-1019 is an entry without `sequence`): + +| When | category | code | value | +| --- | --- | --- | --- | +| every leg, one per attached document | `INV` (or the document's own category) under `ndhm-supportinginfo-category` | the plan's requirement code (`MAND0408`) under `https://nhcx.abdm.gov.in/document-code`, else `ODN` | `valueAttachment {contentType, data, title}` | +| every leg | `ONS` | `ADDD` | `valueString` admission instant | +| every leg | `OTH` | `EDT` | `valueString` admission instant | +| claim | `HDS` | the plan's summary code (`MAND0006` in the pin) else `HDS` | `valueAttachment` the discharge summary | +| claim, when a surgery time is known | `ONS` | `PSP` | `valueString` surgery instant | +| claim | `ONS` | `DSDE` | `valueString` discharge instant, or the death instant | +| claim, death only | `ONS` | `DTM` | `valueString` death instant (PAYR-1096 and PAYR-1503 without it) | +| claim | `DIS` | `DTH`, `LAMA`, `DAMA` or `DTM` | `valueString` the stage: `Before Surgery`, `During Surgery`, `After Surgery` | +| query answer (flow `queryupdate`) | `NMI` | `CQD` | `valueString` the desk's reply. The SHA reads its query response comments from here; an answer without one is decided as if none was given | +| every leg, one per answered form | `INF` (or `STG` for a treatment guideline) | `ODN` (or `STG`) | `valueReference` to the QuestionnaireResponse entry | + +Which forms ride (`required_forms`): with an auth-requirements ruling, the forms it named for the leg; without one, at pre-auth every guideline form the plan attaches to the quoted packages; and on both legs every policy-level form. The scheme refuses a pre-auth that answers neither biometrically nor with its Authentication Consent questionnaire (PAYR-1256, PAYR-1271), a claim without the consent answered again at discharge (PAYR-1363, PAYR-1364), and a package without its STG questionnaire (PAYR-1254, PAYR-1365). The live D4 capture carries two policy questionnaires; the live D9 claim carries four, including the Discharge Consent (`nhcx-package/fhir/D9/D9-request.json`). + +Which documents ride (`required_documents`, `preauth_documents`): the ruling's list for the leg, else the plan's list for the quoted packages at pre-auth and whatever was not attached there at the claim. A file attached against a requirement carries that requirement's code; a file nobody asked for carries `ODN`. Never drop one. Content types the scheme takes: pdf, jpg, jpeg, png (PAYR-1008 otherwise). + +The legs differ in these ways only: + +| Leg | flow | use | Procedure status | Extra | +| --- | --- | --- | --- | --- | +| Pre-auth 12 | `request` | `preauthorization` | `preparation` | | +| Enhancement 13 | `enhancement` | `preauthorization` | `preparation` | every line, old and new, under the same claim number; the costlier package at factor 1 and the other at 0.5 (the live capture `nhcx-package/fhir/D6/D6-enhancement.json` carries the two lines at 1 and 0.5) | +| Query answer 19 or 131 | `queryupdate` | `preauthorization` | `preparation` | the `NMI`/`CQD` reply | +| Claim 15 | `request` | `claim` | `completed` | discharge scalars, summary, `preAuthRef`, the claim under the pre-auth's number (ERR-PYR-CLM-007) | +| Claim query answer 161 | `queryupdate` | `claim` | `completed` | as the claim, plus `NMI`/`CQD` | +| Predetermination | `request` | `predetermination` | `preparation` | sent on `v1/preauth/submit` with workflow 12 | + +LAMA and DAMA before or during surgery (`claim_lines`): the claim carries one item, procedure `LM100` at the plan's rate (the sandbox prices it at zero), no tier, and the payer disqualifies every approved item (PAYR-1362 if the package is still there). After surgery the package stands and `LM100` is not used. PAYR-1270 is `LM100` on a pre-auth. + +## 6. The ClaimResponse you read + +Shape (`nhcx-package/docs/01-Overview/07-Payer Flexibility.md`, "Answer detail"): `ClaimResponse`, `Patient`, the two `Organization` entries, `Coverage`, in that order. Fields to read (`parse_claim_response`): + +- `use`: `preauthorization` or `claim`; a bundle with none is whatever you sent on that thread. +- `outcome`: `queued` (acknowledgement), `partial` (queried, or approved for less), `complete`, `error` (rejected). +- `adjudication[]` at claim level: the entry whose `category` is `status` carries `reason.coding.code`: `submitted`, `approved`, `queried`, `rejected`, `cancelled`. +- `preAuthRef`: the payer's case number; see `flow-knowledge.md` section 3 for which answers carry it. +- `identifier[0].value`: your claim number, echoed on every answer. +- `total[]`: a repeating list by `category`, never positional: `benefit` (granted this round), `eligible` (what the case stands at), `submitted`; PMJAY adds `tax` and `incentive`. +- `item[].adjudication[]` by category: `eligible` (amount), `status` (reason `Approved`, `Queried`, `Rejected`), `reason` (the desk's remark, pipe-delimited `USER~datetime~type~comment~trust`, kept verbatim), `eligpercent`, `eligquant`, `deductible` with its reason after a claim. +- `processNote[].text`. +- `type` is present only on the pre-auth acknowledgement (SNOMED `737481003`). + +The status rule (`verdict_status`): `queued` or reason `submitted` is still `submitting`; reason `cancelled` is `rejected`; reason `queried` is `queried`; outcome `error` is `rejected`; outcome `partial` is `partial` only with reason `approved`, else `queried`; outcome `complete` is `approved` with reason `approved` or none, else `queried`. Never read `outcome` alone. + +## 7. Task bundles the hospital sends + +A `TaskBundle` with the `Task` at `https://nhcx.abdm.gov.in//` followed by the provider and payer Organizations. The Task: `status requested` (`completed` on an acknowledgement), `intent order`, `code` on the HL7 financial task code system with no display, `description`, `authoredOn`, `requester` the provider, `owner` the payer. + +| Task | code | reasonCode (NDHM reason code system) | inputs | Other | +| --- | --- | --- | --- | --- | +| Cancel PC01 | `cancel` | one of `treatmentplanchanged`, `patientrequest`, `financialconstraints`, `alternativetreatment`, `duplicateclaim`, `administrativeerror`, `other` (with `other` the description is the only justification) | `claimNumber`, `intimationNumber` (both typed under `ndhm-task-input-type-code`) | anchor `/preauth/cancel` | +| Reprocess 36 | `reprocess` | `claimrejected`, `partialpayment` or `rejectiondisputed` with the reference's displays | `claimNumber`, `intimationNumber` (the standard's spelling), one `document` input per attachment as `valueAttachment` | `basedOn[0].identifier` typed `CLN`; `for.identifier` typed `PMJAY` on the scheme, `MB` elsewhere; anchor `/claim/reprocess` | +| Release 36 | `release` | `partialpayment` | `claimNumber`, `amount` as `valueMoney` under `https://nhcx.abdm.gov.in/task-input-type` | `basedOn` as above; anchor `/claim/release` | +| Status | `status` | none | `claimNumber` | anchor `//status`; not in the package, whose status call carries no bundle (`18-Predetermination, Status and Search.md`); refused by PMJAY | +| Payment acknowledgement 17 | `status`, `status completed` | none | none; `output[]`: `status` = `paymentack` under the NDHM task-output systems, and `claimNumber` | anchor `/payment/notice-ack` | + +The spelling rule: the input is `intimationNumber`, the standard's spelling, on every Task. A reprocess under any other spelling is refused with PAYR-1008 (proven live; `nhcx-package/docs/01-Overview/07-Payer Flexibility.md`, "One spelling on the Task"). The pinned cancel and reprocess Tasks carry the same spelling, so the offline comparison diffs them unchanged. + +## 8. Task answers you read + +`parse_task_response`: find the `Task`, then follow each `output[].valueReference` to the entry it names; when that is a `ClaimResponse`, read it with the same parser as a verdict. + +- PC02 (`nhcx-package/fhir/C10/C10-cancelled-wfPC02.json`): Task `completed`, code `approve`, `output[0]` an `include` reference to a `ClaimResponse` with adjudication reason `cancelled`, `use preauthorization`. Accept the cancel when the Task status is `completed` or `accepted` and the outcome is not `error`. Retire the claim number after an accepted cancel. +- 37 (`nhcx-package/fhir/C10/C10-arbitration-wf37.json`): Task `accepted`, code `approve`, a `ClaimResponse` with outcome `queued`, `use claim`. Put the claim leg back to `submitting`; the new verdict comes on the claim's own thread. +- A status answer: none captured in the package. A generic payer that answers a status Task sends a Task `completed`, code `status`, `output[]` with `claimNumber` and a `claimStatus` string; PMJAY refuses the enquiry instead. + +## 9. The communication loop + +The query, generic payer (`nhcx-package/fhir/C6/C6-preauth-query-wf24.json`; the IG's example at `nhcx-package/fhir/B4/communication-request.json`): a `TaskBundle` with a `Task` `poll`, `requested`, `intent order`, `reasonCode additionalinfo`, one `include` input pointing at the `CommunicationRequest`; the request with `identifier` (the claim number), `basedOn` the Claim, `payload[].contentString` one per ask, `reasonCode[].text` repeating them; then the Claim, Patient, the two Organizations, Practitioner and Coverage. It arrives on `v1/communication/request` on a new correlation id, with the queried leg's correlation id in `x-hcx-workflow_id` when the payer sends one. + +The notification, PMJAY (`nhcx-package/fhir/C6/C6-notification-wfN02.json`): a Task `poll`, `completed`, `intent proposal`, reason `information` under `http://terminology.hl7.org/CodeSystem/communication-category`, a `CommunicationRequest` with one `contentString`, and the two Organizations. + +Reader (`parse_communication_request`): the first `CommunicationRequest`; the claim numbers it names in `about[]`, `basedOn[]` and `identifier[]`; the asks from `payload[].contentString`, else `reasonCode[].text`, else the Task's `description`; the Task's `intent` and `reasonCode`. Match the claim by those numbers first, then by a request id already held, then by the correlation id of one of your sends, then by the workflow id as a thread. + +The reply (`build_communication_bundle`; pin `nhcx-package/fhir/B4/communication-response.json`): a `TaskBundle` with `meta.lastUpdated`, `identifier` under the payer system, `timestamp`, and entries in this order: + +1. `Task` at `urn:uuid:`: `status completed`, `intent order`, `code deliver` under `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-codes`, `authoredOn`, `requester` the provider, `owner` the payer, one `input` typed `include` (HL7 financialtaskinputtype) pointing at the Communication, `reasonCode` echoed from the request's Task when it carried one. +2. `Communication` at `urn:uuid:`: `identifier` echoed from the request, `basedOn: [{reference: }]`, `about: [{reference: }]`, `status completed`, `category notification`, `priority routine`, `recipient` the payer, `sender` the provider, `payload[]`: a `contentString` for the text, then one `contentAttachment {contentType, title, creation, data}` per document, each with an `extension` carrying the document code. The extension url is participant-defined (`17-Communication.md`): write it under your own system and keep one url. `inResponseTo` is never set: FHIR allows only a Communication there and the validator refuses a request. +3. The `CommunicationRequest` echoed as it arrived. +4. The case as the payer holds it, lifted from the queried leg's own bundle: `Claim`, `Patient`, provider `Organization`, payer `Organization`, `Practitioner`, `Coverage`. + +Envelope for the reply: `x-hcx-correlation_id` = the request's, `x-hcx-workflow_id` = the request's, else the queried leg's correlation id, else the claim number; sender and recipient swapped. + +The acknowledgement of a notification: the payer's own bundle sent back with `Task.status` set to `completed`, its intent and reason as sent, the provider Organization ahead of the payer's, a fresh `timestamp`. A request that came without a Task gets one built round it, coded `poll`, intent `proposal`, pointing at the request. The package's `B4/communication-acknowledgement.json` is a different shape: a `status` Task, `completed`, with a `status` output and the two Organizations, and no CommunicationRequest. + +## 10. The payment notice you read and the acknowledgement you send + +Notice (`nhcx-package/fhir/C9/C9-notice-wf30.json`; PMJAY `C9/payment-notice.json` and `C9/C9-notice-tds-wf30-pmjay.json`): a Task `deliver`, `requested`, with a `status` input; a `PaymentNotice` with a `CLN` identifier (the claim number), `amount`, `paymentStatus paid`; a `PaymentReconciliation` with the same identifier, `disposition`, `paymentDate`, `paymentAmount`, `paymentIdentifier` typed `UTR`, and `detail[]` lines (`RF` and `Payment` in `payment-notice.json`; `TDS` and `Payment` in the other two); the two Organizations. It arrives on `v1/paymentnotice/request` on a new thread, workflow 30, 31 or 33. + +Reader (`parse_payment_notice`): the claim number from the `CLN` identifier on the notice, the reconciliation, the Task, or the first entry's untyped identifier, never from the bundle identifier; the amount from the notice or `paymentAmount`; the UTR; the details. Dedupe on the notice's correlation id; a second notice with the same `PaymentNotice.id` updates the first (`record_payment`). Count money once per UTR (`paid_total`). + +Acknowledgement: the Task in section 7, sent on `v1/paymentnotice/on_request` to whoever sent the notice (not always the claim's payer), with `x-hcx-correlation_id` = the notice's and `x-hcx-workflow_id` = `17` for PMJAY or the notice's own id for a generic payer. + +## 11. Validating a bundle + +The package ships no validator. Use the HL7 FHIR validator (`validator_cli.jar`, from HL7) with the NRCeS IG package `ndhm.in`, version 6.5.0. A bundle refused with PAYR-1004 or PAYR-1008 goes through the validator before anything else (`nhcx-package/docs/06-Reference/02-Troubleshooting.md`). The rules it checks against are in `nhcx-package/docs/05-FHIR Reference/01-Bundles and Conventions.md`. + +```sh +java -Xmx4g -jar validator_cli.jar \ + -version 4.0.1 -ig -tx n/a -output result.json +``` + +Pass every file in one call; starting the JVM is the slow part. `-tx n/a` keeps the terminology checks offline; drop it to add them. A bundle passes when the output holds no issue of severity error or fatal. + +The provider pins carry 0 to 13 errors each and the SHA accepted every one as it stands. An error that says "a code the profile does not define" is the scheme's own vocabulary, not a fault to fix. A warning is advice. diff --git a/plugins/nhcx/skills/nhcx-reprocess/references/flow-knowledge.md b/plugins/nhcx/skills/nhcx-reprocess/references/flow-knowledge.md new file mode 100644 index 000000000..098cd9dbc --- /dev/null +++ b/plugins/nhcx/skills/nhcx-reprocess/references/flow-knowledge.md @@ -0,0 +1,206 @@ +# Flow knowledge: the claim episode, its workflow ids, the two payer kinds, the use cases + +Sources: the NHCX package, fetched by `scripts/fetch-package.sh` into `nhcx-package/` beside `nhcx-build/`. That means the overview chapters under `nhcx-package/docs/01-Overview`, the workflow sheet `nhcx-package/workflow.yaml`, the use-case catalogue `nhcx-package/usecases.yaml`, and the payer bundles under `nhcx-package/fhir/C3` to `nhcx-package/fhir/C11`. The published chapters live under `nhcx-package/docs/01-Overview`, `nhcx-package/docs/05-FHIR Reference` and `nhcx-package/docs/03-Building a Provider`. Everything else here was learnt live on the NHCX sandbox. + +## 1. The episode + +One hospital admission that an insurer pays for is one claim episode. Store it as one record with a claim number. Any number works if it is unique per hospital, short, sortable, and fits the payer's `CLN` identifier. The episode has these legs, each a separate exchange with its own correlation id: + +| Order | Leg | You send | Payer answers | Thread | +| --- | --- | --- | --- | --- | +| 1 | Policy lookup | The participant service's `participant/get/policies`, through the transport; the recipient of every later leg is the policy's `processingid` | synchronous JSON | none, plain REST | +| 2 | Coverage eligibility | `v1/coverageeligibility/check`, purpose `discovery`, `validation` or `benefits` | `on_check` | new per check | +| 3 | Insurance plan (package master) | `v1/insuranceplan/request` | `on_request` | new; one plan per facility and policy | +| 4 | Auth requirements | `v1/coverageeligibility/check`, purpose `auth-requirements`, with items | `on_check` (the PMJAY sandbox rarely answers; `nhcx-package/fhir/C3/C3-response-pmjay.json` is an SHA ruling, `C3/C3-response-generic.json` a generic one) | new per procedure set | +| 5 | Pre-authorisation | `v1/preauth/submit` wf 12 | `on_submit` 20 first, then 21, 23 or 24 | new; the acknowledgement comes first on the same thread | +| 5a | Pre-auth query answer | `v1/preauth/submit` wf 19 (PMJAY) or `v1/communication/on_request` (generic) | 21 or 23 | new (PMJAY) or the request's (generic) | +| 5b | Enhancement | `v1/preauth/submit` wf 13, the whole pre-auth again with the added line | 20 then 22, 231 or 241 (the SHA sandbox has also answered with 21) | new | +| 5c | Enhancement query answer | `v1/preauth/submit` wf 131 | 22 or 231 | new | +| 5d | Cancel | `v1/task/submit` wf PC01 | `task/on_submit` PC02 | new | +| 5e | Predetermination | `v1/preauth/submit`, `Claim.use = predetermination`, wf 12 | `on_submit` | new | +| 6 | Claim | `v1/claim/submit` wf 15, `Claim.use = claim`, under the pre-auth's number | 25 then 26, 27 or 291 | new | +| 6a | Claim query answer | `v1/claim/submit` wf 161 (PMJAY) or `v1/communication/on_request` (generic) | 26 or 291 | new (PMJAY) or the request's (generic) | +| 6b | Reprocess or release | `v1/task/submit` wf 36 | `task/on_submit` 37, then a fresh verdict on the claim's thread | new | +| 7 | Payment notice | the payer sends `v1/paymentnotice/request` wf 30 (31, 33) | you answer `v1/paymentnotice/on_request` wf 17 (PMJAY) or the notice's own id (generic) | the notice's | +| any | Status enquiry | `v1/task/submit`, Task code `status` | `task/on_submit` (generic); PMJAY refuses it | new | +| any | Communication | the payer sends `v1/communication/request` | you answer `v1/communication/on_request` | the request's | + +The payer's acknowledgement is `x-hcx-status: response.partial` and the decision is `response.complete`, on the same correlation id (`nhcx-package/docs/01-Overview/07-Payer Flexibility.md`, "Answer detail"). Read the acknowledgement as "the payer has it", never as a decision. Map `ClaimResponse.outcome` `queued`, or an adjudication reason `submitted`, to leg status `submitting` (`verdict_status`). + +## 2. Every workflow id + +The hospital's table. PMJAY and a generic payer differ in three rows: `claim_query_response`, `claim_resubmit` and `payment_ack`. + +| Kind | PMJAY | Generic | Path | Note | +| --- | --- | --- | --- | --- | +| `preauth` | `12` | `12` | `v1/preauth/submit` | A new pre-auth. Also a fresh request after a rejection: PMJAY refuses 121 there with PAYR-1214. | +| `preauth_resubmit` | `121` | `121` | `v1/preauth/submit` | Kept in the table. `preauth_send_kind` never picks it after a rejection. | +| `preauth_query_response` | `19` | `19` | `v1/preauth/submit` | The answer to a 24. A generic payer asks by communication instead, so this is a PMJAY leg. | +| `enhancement` | `13` | `13` | `v1/preauth/submit` | The whole pre-auth again under the parent's number, plus the added line. | +| `enhancement_resubmit` | `131` | `131` | `v1/preauth/submit` | The answer to a 241. | +| `cancel` | `PC01` | `PC01` | `v1/task/submit` | Task code `cancel`. The handbook's section 8.6 says 122 (`nhcx-package/docs/01-Overview/06-Workflow Codes.md`, "Reconciled Discrepancies and Authority Rules", takes PC01). If a payer insists on 122, override it per payer in configuration. | +| `claim` | `15` | `15` | `v1/claim/submit` | The final bill. | +| `claim_query_response` | `161` | `151` | `v1/claim/submit` | PMJAY refuses 151, 19 and 16 with PAYR-1321; 161 is taken. | +| `claim_resubmit` | none | `16` | `v1/claim/submit` | PMJAY has no claim resubmit. A decided claim goes back only as a reprocess. | +| `payment_ack` | `17` | none (echo the notice's own id) | `v1/paymentnotice/on_request` | `None` in the table means "echo". | +| `reprocess` | `36` | `36` | `v1/task/submit` | Task code `reprocess`; acknowledged on 37. | +| `release` | `36` | `36` | `v1/task/submit` | Task code `release`, reason `partialpayment`, an `amount` input. | +| status enquiry | the leg's correlation id, fallback `13` | same | `v1/task/submit` | The fallback id is `13`. The NHCX sandbox refuses `v1/status` with NHCX-1012. | +| coverage, plan, auth requirements | your case number | your case number | see section 1 | The sheet lists no code. Send the episode's case number. | + +The payer's ids you must branch on (`nhcx-package/workflow.yaml`, `nhcx-package/docs/01-Overview/06-Workflow Codes.md`), with what the sandbox actually sent: + +| Id | Meaning | Status word | +| --- | --- | --- | +| `20` | Pre-auth or enhancement received | `response.partial` | +| `21` | Pre-auth approved | `response.complete` | +| `22` | Enhancement approved. A generic payer sends 22. The SHA sandbox has answered an enhancement with 21, and `nhcx-package/fhir/C5/C5-enhancement-approved-wf22-pmjay.json` is an SHA answer on 22. Accept both. | `response.complete` | +| `23` | Pre-auth rejected | `response.complete` | +| `231` | Enhancement denied | `response.complete` | +| `24` | Pre-auth queried | the sheet says `request.initiated`; the SHA sent `response.complete` | +| `241` | Enhancement queried | as 24 | +| `25` | Claim received | `response.partial` | +| `26` | Claim approved | `response.complete` | +| `27` | Claim queried | as 24 | +| `28`, `29` | Claim in process, forwarded | `response.partial` | +| `291` | Claim rejected | `response.complete` | +| `251`, `252`, `253`, `254` | Reprocess received, approved, rejected, queried | listed; both live payers answer a 36 with 37 instead | +| `37` | Arbitration acknowledged (the reprocess taken) | `response.complete` (the SHA sent `response.partial`) | +| `PC02` | Cancellation done | `response.complete` | +| `30`, `31`, `33` | Payment initiated, processed, settled with UTR | `request.initiated`, new thread | +| `5` | The SHA's coverage eligibility and plan answers | `response.complete` (`nhcx-package/fhir/index.yaml` gives 5 for `C3/C3-response-pmjay.json` and `C4/C4-response-pmjay.json`) | +| `N02` | Notification to a provider (a PMJAY CommunicationRequest) | `request.initiated` | + +Other codes exist (10, 11, 14, 141, 18, 45 to 47, 181, 491, 34, 35, 38, 39, G11 to G13, RP1 to RP3, DC01, DC02, N01, N03, N04, the R-series). A hospital build sends none of them. See `nhcx-package/docs/01-Overview/06-Workflow Codes.md` for the full sheet and the seven codes the handbook and the sheet publish differently. + +## 3. Two kinds of payer + +Read `nhcx-package/docs/01-Overview/07-Payer Flexibility.md` in full. A generic payer is any payer on the exchange, IRDAI-regulated insurers and TPAs included (`nhcx-package/fhir/README.md`). The rule, as coded: + +| | PMJAY (`query_mode: resubmit`) | Generic (`query_mode: communication`) | +| --- | --- | --- | +| The query arrives as | a `ClaimResponse` on the case's own thread, `outcome: partial`, item status `Queried`, wf 24, 241 or 27 | a `CommunicationRequest` TaskBundle on `v1/communication/request`, on a new thread, wf 24, 241 or 27 | +| The answer | the whole bundle again on `v1/preauth/submit` or `v1/claim/submit`, wf 19, 131 or 161, a new correlation id, the reply text on the `NMI`/`CQD` supportingInfo entry | a Communication TaskBundle on `v1/communication/on_request`, the request's correlation id and workflow id echoed | +| A `CommunicationRequest` from this payer | always a notification: acknowledge and leave the case alone | classified (below) | + +Where the payer's case number arrives. The package files are under `nhcx-package/fhir/`; the rule is in `07-Payer Flexibility.md`, "When the case number arrives". + +| Answer | PMJAY | Generic | +| --- | --- | --- | +| 20 on a fresh pre-auth | The package says none, and `C5/C5-received-wf20-pmjay.json` carries none. A live SHA 20 has also carried the path form, `PMJAY/HP/S/2024/R2/`. Handle both. | present (`C5/C5-received-wf20.json`) | +| 20 on an enhancement | none; keep the parent's | present | +| 21, 23, 24 | the bare number (`C5/C5-approved-wf21-pmjay.json`, `C5/C5-rejected-wf23-pmjay.json`, `C5/C5-queried-wf24.json`) | present (`C5/C5-approved-wf21.json`, `C5/C5-rejected-wf23.json`) | +| 25 | the path form (`C7/C7-received-wf25-pmjay.json`) | present (`C7/C7-received-wf25.json`) | +| 26, 27, 291, PC02, 37 | none | none | + +So the brief's rule holds with care. A generic payer's `response.partial` acknowledgement carries the payer's case number. PMJAY's 25 carries it; its 20 may not. Read `ClaimResponse.preAuthRef` on every answer. Keep a value and never overwrite it with an empty one (`apply_preauth`). The bare number is what the payer service desk wants; the path form ends in it. + +`query_mode` lives on the payer adapter. Choose the adapter by the payer's participant code through configuration: `1518@hcx` is PMJAY, and an unmapped code is generic. + +### The classification rule + +`classify_communication(adapter, reason, intent)` applies these, in order: + +1. If the payer's `query_mode` is `resubmit`: notification. +2. Else if `Task.intent` is `proposal`: notification. If `order`: query. +3. Else look at `Task.reasonCode`: absent, `additionalinfo`, `questionnaire` or `query` is a query; anything else (`tatquery`, `grievance`, `walletupdate`, `policychange`, `claimarbitration`) is a notification. Fold `claimArbitartion` into `claimarbitration`. +4. A bare `Communication` with no `CommunicationRequest` is a note: recorded, shown, never acted on. + +Acknowledge a notification at once. Send the payer's own bundle back with `Task.status` flipped to `completed`, the reason echoed and the provider Organization first. File a query open for the desk, and answer it later with the TaskBundle reply (see `fhir-knowledge.md`). The reply names the request in `Communication.basedOn`, never `inResponseTo`. + +The live shapes. A generic payer's query (`nhcx-package/fhir/C6/C6-preauth-query-wf24.json`) carries a Task `poll`, `requested`, `intent order`, reason `additionalinfo`, and a CommunicationRequest with one `contentString` per ask and `basedOn` the Claim. PMJAY's notification (`nhcx-package/fhir/C6/C6-notification-wfN02.json`) carries a Task `poll`, `completed`, `intent proposal`, reason `information` under the HL7 communication-category system. + +## 4. Stage, sub-stage, next actions + +Stamp two words onto the episode after every leg write (`stamp_case`), and compute a next-action list from them. Copy the vocabulary; it is what a desk needs to see. + +Stages: `eligibility`, `preauth`, `enhancement`, `claim`, `payment`. + +Sub-stages: `draft`, `checking`, `eligible`, `not-eligible`, `requested`, `resubmitted`, `answered`, `queried`, `approved`, `partial`, `rejected`, `cancelling`, `cancelled`, `refused`, `noticed`, `paid`. + +How a send kind maps to a sub-stage: `preauth`, `claim`, `enhancement` set `requested`; `*_resubmit` sets `resubmitted`; `*_query_response` and `enhancement_resubmit` set `answered`. `requested`, `answered` and `resubmitted` mean "with the payer". + +Derivation (`case_stage`): a payment notice wins, then the filed claim, then the pre-auth (stage `enhancement` if the last submission kind was an enhancement), then a saved draft, then the eligibility status. An open communication query on a leg that is with the payer flips the sub-stage to `queried`, because a generic payer's query never touches the leg row. + +Next actions (`next_actions`) are `{label, tab, tone}`; the first is what the case waits for. Rules worth copying: + +- An unanswered query always leads with "Answer the payer (n)". +- The leg's own reply box is offered only for a `resubmit` payer. A `communication` payer's desk is sent to the communication tab. +- A claim refused at the door offers "send again" while `claim_send_kind` still yields a kind, else "Ask for a reprocess". +- After a rejection the pre-auth offers a fresh 12, not 121. + +## 5. Rules the exchange enforces that no document states + +Each was found live on the sandbox. + +- Acknowledge or lose the thread. NHCX redelivers an unanswered submission, then drops it and retires the correlation id; a verdict sent later is refused with NHCX-1010. Both live payers answer twice on one correlation: `outcome: queued` first, the decision after. Your reader must not close a thread on the first reply. +- One message is taken once. The SHA redelivers the same `api_call_id` two or three times, about a minute apart, and a transport can fan one delivery out to several receivers (nhcx-adapter's `callback.also`). Dedupe on `x-hcx-api_call_id`. +- One live pre-auth per beneficiary per hospital (PAYR-1238). Clear it with PC01 or a rejection (`nhcx-package/docs/03-Building a Provider/11-PMJAY Sandbox Run.md`, "PAYR-1238 An active preauthorisation exists"). Sweep live pre-auths before a test run. +- One request at a time per case (PAYR-1322, "Active instance found"). Wait about 30 seconds after a decision before the next leg. When a refusal says "Active instance", wait and resend, up to three times. +- One plan per facility and policy. Key it on policy code, provider id and payer. Copy the held master onto a new episode instead of asking again (`reuse_plan`). A PMJAY master runs to tens of megabytes; one fetched live was 56 MB. +- Never drop a document. A file nobody asked for by name goes under `ODN`, "other document". A file attached against a requirement carries that requirement's code (`attach_required_document`). Take the code list from the plan, not from a constant. +- Ask the auth-requirements check, never await it (`ensure_auth_requirements`). Fingerprint the quoted set (`procedure_set`) so an unchanged set is not asked twice. Send the quantity as a whole number. +- Tiers are modifiers, not lines. A ward or ICU tier rides on `Claim.item.modifier` under its procedure, and that item's `net` carries both. +- The claim goes under the pre-auth's number (ERR-PYR-CLM-007), and PMJAY bills the package alone at the whole amount (`11-PMJAY Sandbox Run.md`, "ERR-PYR-CLM-007" and "What the package master decides"). +- Answers to a PMJAY query go on a new correlation id (`07-Payer Flexibility.md`, "On the claim thread"). A same-thread answer is swallowed: no acknowledgement, no refusal, and the desk dies on the old id. +- Cancel retires the number. Give the episode a fresh claim number after an accepted PC01, and keep the withdrawn one on the leg. +- A send refused at the door keeps the case on the thread the payer last answered. An enhancement refused at the door leaves the pre-auth approved. + +## 6. The use-case catalogue + +Codes and titles are quoted from `nhcx-package/usecases.yaml`, rendered as `nhcx-package/docs/01-Overview/05-NHCX Use Cases.md`. "Proves" is what a test run must show for each one. "Package file" is the provider bundle the package holds for it, under `nhcx-package/fhir/`. + +### A: shared + +| Code | Title | What it proves | +| --- | --- | --- | +| A1 | Get participant list | You can find the payer's code in the registry (the participant service's `fetch/participants/list`). | +| A2 | Get policy | You can find a beneficiary's policy and the processor code that becomes `x-hcx-recipient_code` (the participant service's `participant/get/policies`). | +| A3 | Get public key | The transport fetches the recipient's certificate (`fetch/certs`) and caches it. | +| A4 | Get auth token | The transport holds an ABDM session token (the gateway's sessions call) and refreshes it. | +| A5 | Get status | A status Task on `v1/task/submit` gets a Task back (generic), or a PAYR-1018 then PAYR-1008 refusal (PMJAY). The package holds no bundle for A5 (`nhcx-package/fhir/README.md`). | +| A6 | Receive errors | Your callback accepts a `ProtocolResponse` on any path and answers 2xx. | + +### B: hospital on the generic network + +| Code | Title | Workflow | Proves | Package file | +| --- | --- | --- | --- | --- | +| B1 | Check coverage eligibility | none | The check goes out; `inforce` and the wallet come back. | `B1/B1-check.json` | +| B2 | Request insurance plan | none | The package master lands and is stored once per policy. | `B2/B2-request.json` | +| B3 | Submit pre-authorisation | 12, 13 | Sent, acknowledged on 20, decided on 21 or 23; an enhancement on 13 decided on 22. | `B3/B3-request.json`, `B3/B3-enhancement.json` | +| B4 | Respond to a communication | 24, 27 echoed | A CommunicationRequest is classified and the TaskBundle reply goes on the request's thread. | `B4/B4-preauth-query-answer.json`, `B4/B4-claim-query-answer.json` | +| B5 | Submit claim | 15 | The claim under the pre-auth's number, acknowledged 25, decided 26 or 291. | `B5/B5-request.json` | +| B6 | Search claims | none | Not built by these skills. | `B6/claim-search.json` (example) | +| B7 | Acknowledge payment notice | 30 echoed | The notice is filed by claim number, deduped by correlation id, acknowledged on `on_request`. | `B7/B7-acknowledgement.json` | +| B8 | Reprocess or cancel | 36, PC01 | A decided claim is reopened (37 then a new verdict); a live pre-auth is withdrawn (PC02). | `B8/B8-reprocess.json`, `B8/B8-cancel.json` | +| B9 | Submit predetermination | 12 | A quote comes back as a ClaimResponse; nothing else changes. | `B9/predetermination-request.json` (example); the answer is `C11/predetermination-response.json` | + +### C: payer answering (for reference; you build the reader, not the sender) + +C3 coverage answer, C4 plan answer, C5 pre-auth answers (20, 21, 22, 23, 24, 231, 241), C6 communication (24, 241, 27, N02), C7 claim answers (25, 26, 27, 28, 29, 291), C9 payment notice (30, 31, 33), C10 Task answers (PC02, 37, 251 to 254), C11 predetermination. Reader inputs: `nhcx-package/fhir/C3` to `nhcx-package/fhir/C11`. The files ending `-pmjay` are the SHA's own; the rest are the generic payer's. `nhcx-package/fhir/index.yaml` gives each file's scheme, workflow id and origin. The PMJAY captures have the beneficiary's identifiers replaced. + +### D: hospital on PMJAY + +| Code | Title | Workflow | Proves | Package file | +| --- | --- | --- | --- | --- | +| D1 | Fetch the insurance plan | none | The scheme's master, both `coverage[]` and `specificCost[]`, nested document requirements, questionnaires. | `D1/D1-request.json` | +| D2 | Authenticate the beneficiary | not NHCX | Biometric token or the consent questionnaire fallback. | none | +| D3 | Check coverage eligibility | none | The wallet answer on wf 5. | `D3/D3-check.json` | +| D4 | Submit pre-authorisation | 12 | Element ids, HPIN, consent QuestionnaireResponse, documents from the master; acknowledged 20, decided 21 or 23 with `preAuthRef`. | `D4/D4-request.json` | +| D5 | Resubmit pre-authorisation | 121 | Not reachable on the sandbox after a rejection (PAYR-1214); send a fresh 12. | none | +| D6 | Raise an enhancement | 13, 131 | A second package (medical, not conservative: PAYR-1245) under the parent's number; a 241 answered on 131. | `D6/D6-enhancement.json`, `D6/D6-enhancement-query-answer.json` | +| D7 | Answer a pre-authorisation query | 19 | The 24 answered as a fresh submit with `CQD` reply text, new correlation id, then 21. | `D7/D7-query-answer.json` | +| D8 | Cancel pre-authorisation | PC01 | Task `cancel` with `claimNumber` and `intimationNumber`; PC02 back. | `D8/D8-cancel.json` | +| D9 | Submit claim | 15 | Under the pre-auth's number, the package alone, discharge scalars, Discharge Consent answered, PDF documents; 25 then 26. | `D9/D9-request.json` | +| D10 | Answer a claim query | 161 | The 27 answered on 161 with a written reply; the sandbox approves at zero. | `D10/D10-query-answer.json` | +| D11 | Reprocess a rejected claim | 36 | Task `reprocess`, reason `claimrejected`, second input spelled `intimationNumber` on every Task (a reprocess under any other spelling is refused PAYR-1008). The SHA answers 37, "Arbitration claim submission process completed successfully", and reopens the case; a generic payer answers 37 too. | `D11/D11-reprocess.json` | +| D12 | Claim a shortfall | 36 | Task `reprocess` with `partialpayment` after a settled payment. Out of reach on the sandbox: its finance side issues the notice on its own schedule, and the combination is refused before notice 33 is acknowledged (`11-PMJAY Sandbox Run.md`, "What the sandbox will not take"). | none | +| D13 | Acknowledge the payment notice | 17 | Notice 30 filed and acknowledged on `on_request` with 17. | `D13/D13-acknowledgement.json` | + +Discharge variants the D9 claim must cover, each proven on the sandbox: normal after surgery; LAMA and DAMA before, during and after surgery; death before, during and after surgery. Before or during surgery, LAMA and DAMA collapse the claim to one `LM100` line; a death carries `ONS`/`DTM`. `nhcx-package/docs/03-Building a Provider/08-PMJAY Provider.md` states the LAMA and DAMA rule. + +## 7. What each payer sends back, in order + +A pre-authorisation on the SHA sandbox: 20 (`queued`, `response.partial`, `ClaimResponse.type` present only here, as in `nhcx-package/fhir/C5/C5-received-wf20-pmjay.json`), then 24 (query) or 21 or 23. A claim: 25, then 27 or 26 or 291. A cancel: PC02 as a Task `completed`, code `approve`, `output[0]` an `include` reference to a ClaimResponse whose adjudication reason is `cancelled` (`C10/C10-cancelled-wfPC02-pmjay.json`). A reprocess: 37 as a Task `accepted` with a `queued` ClaimResponse (`C10/C10-arbitration-wf37-pmjay.json`), then 26 or 291 on the claim's thread. A payment: 30 on a new thread with a Task `deliver`, a `PaymentNotice` and a `PaymentReconciliation` (`C9/payment-notice.json`). + +A generic payer sends the same ids with the generic differences: 22 for an enhancement, `preAuthRef` on every acknowledgement and every pre-auth decision, queries as CommunicationRequests, `response.complete` on 37. Its files are the ones without `-pmjay` under `nhcx-package/fhir/C5`, `C6`, `C7`, `C9` and `C10`. diff --git a/plugins/nhcx/skills/nhcx-reprocess/references/material.md b/plugins/nhcx/skills/nhcx-reprocess/references/material.md new file mode 100644 index 000000000..d8882931d --- /dev/null +++ b/plugins/nhcx/skills/nhcx-reprocess/references/material.md @@ -0,0 +1,120 @@ +# Material: where the pins, fixtures and docs live + +The stage and module files cite pins, payer fixtures and chapters. All of them come from one source, the NHCX package. This file says how to get it, what it holds, and which package file each citation means. + +## The package + +| Source | Has | Get it | +| --- | --- | --- | +| The NHCX package (`nhcx-package/`) | The docs, every API as a request, the FHIR bundles (the fifteen hospital pins, the payer answers, the live PMJAY captures with identifiers replaced), the field mappings per use case, `workflow.yaml`, `usecases.yaml`, `nhcx-error.yaml`, `baseurl.yaml`, a `MANIFEST` with a sha256 per file | `scripts/fetch-package.sh`, or by hand (below) | +| nhcx-adapter (optional: only when the user asks for it) | The binary, `config.sample.json`, `serve.sh`, `README.md` | The latest release of https://github.com/nha-in/nhcx-adapter, downloaded only when the user chose it (`references/transport-knowledge.md` section 5). Its contract is in `references/api-knowledge.md`. | + +By default `scripts/fetch-package.sh` takes the build attached to the latest GitHub release of `nha-in/nhcx-package`. It checks the download against the sha256 the release records. To use a different build, pass a link or a local path: `scripts/fetch-package.sh `. + +By hand: download the `nhcx-package-v.zip` asset from https://github.com/nha-in/nhcx-package/releases/latest. Unzip it beside `nhcx-build/`. It unpacks to `nhcx-package/`. + +Where the web is off, copy the package in. Do not try to fetch it. + +After unpacking, check it. `nhcx-package/MANIFEST` names the version and lists every file with its size and sha256. Verify at least the pins you will be held to. + +What the package holds: + +| Path | What it is | +| --- | --- | +| `nhcx-package/fhir/B1` to `B9` | Hospital bundles. Lower-case files (`preauth-request.json`) are the pins, written to the specification with placeholders. Capitalised files (`B3-request.json`) are live captures. | +| `nhcx-package/fhir/C3` to `C11` | Payer answers. A generic file and, where one exists, its `-pmjay` twin. | +| `nhcx-package/fhir/D1` to `D13` | Live PMJAY hospital captures, identifiers replaced | +| `nhcx-package/fhir/index.yaml` | The catalogue: for each file its direction, side, scheme (`generic` or `pmjay`), workflow id, focal resource, origin (`wire` or `example`) | +| `nhcx-package/docs/` | The chapters, `01-Overview` to `07-Go Live` | +| `nhcx-package/mappings/.yaml` | Field mappings per bundle; `A1.yaml` is the master dictionary | +| `nhcx-package/apis/` | Every API as a request (a Bruno collection) | +| `nhcx-package/workflow.yaml`, `usecases.yaml`, `nhcx-error.yaml`, `baseurl.yaml` | Workflow ids, use cases, error codes, base URLs | +| `nhcx-package/MANIFEST` | Version, and a size and sha256 per file | + +## The pin map + +Every hospital-side pin, and its file in the package. The fifteen hospital-built pins are the bytes a build is held to (canonical JSON). The last row is a payer's message, the reader's input. + +| Pin | Package | Module | +| --- | --- | --- | +| `coverage/discovery` | `nhcx-package/fhir/B1/discovery.json` | 7.4 | +| `coverage/validation` | `nhcx-package/fhir/B1/validation.json` | 7.4 | +| `coverage/benefits` | `nhcx-package/fhir/B1/benefits.json` | 7.4 | +| `coverage/authrequirements` | `nhcx-package/fhir/B1/auth-requirements.json` | 7.6 | +| `insurance` | `nhcx-package/fhir/B2/insurance-plan-request.json` | 7.5 | +| `preauth/request` | `nhcx-package/fhir/B3/preauth-request.json` | 7.7 | +| `preauth/enhancement` | `nhcx-package/fhir/B3/preauth-enhancement.json` | 7.7 | +| `preauth/queryupdate` | `nhcx-package/fhir/B3/preauth-queryupdate.json` | 7.7 | +| `preauth/cancel` | `nhcx-package/fhir/B3/preauth-cancel.json` | 7.9 | +| `claim/request` | `nhcx-package/fhir/B5/claim-request.json` | 7.7 | +| `claim/queryupdate` | `nhcx-package/fhir/B5/claim-queryupdate.json` | 7.7 | +| `claim/reprocess` | `nhcx-package/fhir/B5/claim-reprocess.json` | 7.9 | +| `claim/release` | `nhcx-package/fhir/B5/claim-release.json` | 7.9 | +| `communication/response` | `nhcx-package/fhir/B4/communication-response.json` | 7.10 | +| `payment/notice-ack` | `nhcx-package/fhir/B7/payment-notice-ack.json` | 7.10 | +| `communication/request` (a payer's message, the reader's input) | `nhcx-package/fhir/B4/communication-request.json`. It is the NRCeS IG's own example, with the Patient's name, identifier, birth date and phone replaced. | 7.10 | + +## The payer fixtures + +What the readers are fed. `generic` is what any payer on the exchange sends, IRDAI-regulated insurers and TPAs included. `pmjay` is the SHA's own message, a live capture with the beneficiary's identifiers replaced. Some identifiers are absent from the PMJAY files: `C5-received-wf20-pmjay.json` carries no `preAuthRef`. Read a value from the file before you assert it. Paths are under `nhcx-package/fhir/`. + +| Answer | Generic | PMJAY | Reader | +| --- | --- | --- | --- | +| Coverage, validation | `C3/validation-response.json` | `C3/coverage-eligibility.json` | 7.4 | +| Coverage, discovery | `C3/discovery-response.json` | none | 7.4 | +| Coverage, benefits | `C3/benefits-response.json` | `C3/C3-benefits-pmjay.json` | 7.4 | +| Coverage, auth-requirements | `C3/C3-response-generic.json` | `C3/C3-response-pmjay.json` (workflow 5) | 7.6 | +| Insurance plan | `C4/C4-response-generic.json` (coverage-based) | `C4/C4-response-pmjay.json` (package-based) | 7.5 | +| Pre-auth received 20 | `C5/C5-received-wf20.json` | `C5/C5-received-wf20-pmjay.json` | 7.8 | +| Pre-auth approved 21 | `C5/C5-approved-wf21.json` | `C5/C5-approved-wf21-pmjay.json` | 7.8 | +| Enhancement approved 22 | `C5/C5-enhancement-approved-wf22.json` | `C5/C5-enhancement-approved-wf22-pmjay.json` | 7.8 | +| Pre-auth rejected 23 | `C5/C5-rejected-wf23.json` | `C5/C5-rejected-wf23-pmjay.json` | 7.8 | +| Pre-auth queried 24 | `C5/preauth-queried.json` | `C5/C5-queried-wf24.json` | 7.8 | +| Claim received 25 | `C7/C7-received-wf25.json` | `C7/C7-received-wf25-pmjay.json` | 7.8 | +| Claim approved 26 | `C7/C7-approved-wf26.json` | `C7/C7-approved-wf26-pmjay.json`, `C7/C7-approved-deduction-wf26-pmjay.json` | 7.8 | +| Claim queried 27 | `C7/claim-queried.json` | `C7/C7-queried-wf27.json` | 7.8 | +| Claim rejected 291 | `C7/C7-rejected-wf291.json` | `C7/C7-rejected-wf291-pmjay.json` | 7.8 | +| Cancellation done PC02 | `C10/C10-cancelled-wfPC02.json` | `C10/C10-cancelled-wfPC02-pmjay.json` | 7.9 | +| Arbitration acknowledged 37 | `C10/C10-arbitration-wf37.json` | `C10/C10-arbitration-wf37-pmjay.json` | 7.9 | +| Query on the communication API, 24 and 27 | `C6/C6-preauth-query-wf24.json`, `C6/C6-claim-query-wf27.json` | none | 7.10 | +| Notification N02 | none | `C6/C6-notification-wfN02.json` | 7.10 | +| The query the reply answers | `B4/communication-request.json` (the IG's example) | none | 7.10 | +| Payment notice 30 | `C9/C9-notice-wf30.json` | `C9/payment-notice.json`, `C9/C9-notice-tds-wf30-pmjay.json` | 7.10 | +| Predetermination | `B9/predetermination-request.json` (the request), `C11/predetermination-response.json` | none | 7.7, 7.8 | + +`nhcx-package/fhir/index.yaml` catalogues every file: direction, side, scheme, workflow id, focal resource, origin (`wire` or `example`). An `example` file is placeholders written to the specification, not a payload. + +## The live hospital captures + +What a hospital actually sent, as the payer accepted it. The module files quote these shapes. Paths are under `nhcx-package/fhir/`. + +| Scheme | Files | +| --- | --- | +| PMJAY | `D1/D1-request.json` (plan), `D3/D3-check.json` (auth-requirements), `D4/D4-request.json` (pre-auth 12), `D6/D6-enhancement.json` (13), `D6/D6-enhancement-query-answer.json` (131), `D7/D7-query-answer.json` (19), `D8/D8-cancel.json` (PC01), `D9/D9-request.json` (claim 15), `D10/D10-query-answer.json` (161), `D11/D11-reprocess.json` (36), `D13/D13-acknowledgement.json` (17) | +| Generic | `B1/B1-check.json`, `B2/B2-request.json`, `B3/B3-request.json`, `B3/B3-enhancement.json`, `B4/B4-preauth-query-answer.json`, `B4/B4-claim-query-answer.json`, `B5/B5-request.json`, `B7/B7-acknowledgement.json`, `B8/B8-cancel.json`, `B8/B8-reprocess.json` | + +## The docs and the data files + +| Cited | Package | +| --- | --- | +| a chapter | `nhcx-package/docs/`, from `01-Overview` to `07-Go Live` | +| workflow ids (`references/flow-knowledge.md` section 2) | `nhcx-package/workflow.yaml`, the maintained source; rendered as `nhcx-package/docs/01-Overview/06-Workflow Codes.md` | +| use cases (`flow-knowledge.md` section 6) | `nhcx-package/usecases.yaml`; rendered as `nhcx-package/docs/01-Overview/05-NHCX Use Cases.md` | +| PAYR and ERR codes (`references/errors-and-debugging.md`) | `nhcx-package/nhcx-error.yaml` | +| field mappings per bundle (stage 4) | `nhcx-package/mappings/.yaml`; `A1.yaml` is the master dictionary | +| base URLs, sandbox and production | `nhcx-package/baseurl.yaml` | +| every API as a request | `nhcx-package/apis/` (a Bruno collection) | +| the bundle catalogue | `nhcx-package/fhir/index.yaml` | + +## What the package does not hold + +| Missing | Without it | +| --- | --- | +| A status-enquiry answer | None captured. The published status call carries no bundle either way (`nhcx-package/docs/05-FHIR Reference/18-Predetermination, Status and Search.md`). | +| A validator wrapper | Run the HL7 FHIR validator directly, as `references/fhir-knowledge.md` section 11 describes | +| Reference application source | The decisions are written into the module files and the references. Build from them. Record in `NOTES.md` where you would have wanted more. | +| End-to-end drivers and checkers | Write the stage 10 driver against your own build's state address | + +## Which is newer + +Where the references and the package disagree, the package is newer for the published facts (workflow ids, error text, base URLs). The references are newer for what was seen live (which ids a payer actually sent, which refusals mean what). Say which you followed in `NOTES.md`. diff --git a/plugins/nhcx/skills/nhcx-reprocess/references/testing-knowledge.md b/plugins/nhcx/skills/nhcx-reprocess/references/testing-knowledge.md new file mode 100644 index 000000000..4a24d7946 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-reprocess/references/testing-knowledge.md @@ -0,0 +1,405 @@ +# Testing knowledge + +Sources: the NHCX package, fetched by `scripts/fetch-package.sh` into `nhcx-package/` beside `nhcx-build/`. That means the pins and payer fixtures under `nhcx-package/fhir` (catalogued in `nhcx-package/fhir/index.yaml`), the use-case catalogue `nhcx-package/usecases.yaml`, and the chapters named below. Also what live runs on the NHCX sandbox taught. + +## 1. The pyramid + +| Rung | What it proves | Needs | How | +| --- | --- | --- | --- | +| 1. Offline | Every builder equals its pin (`created` excepted); every reader settles the right state from a payer fixture; the state machine refuses what it should | nothing running; a throwaway database; the transport's send stubbed; `nhcx-package/` | one suite in one process (sections 2 to 4) | +| 2. Validator | Every built bundle validates against the NRCeS profiles with no error you cannot explain | Java, the HL7 FHIR validator, the bundles your tests wrote | section 5 | +| 3. A generic payer on the sandbox | Every leg over the real exchange with a payer whose desk you can drive; queries as CommunicationRequests; payment released | the transport on the sandbox (your app's own, or nhcx-adapter when the user chose it), a generic payer you can drive, the sandbox reaching your callback | section 6 | +| 4. Live PMJAY sandbox | `1518@hcx`: the scheme's own refusals and rules, decisions taken on the payer service desk | the sandbox, a real beneficiary, patience | section 6 | + +Climb in order. Rungs 1 and 2 need no service and no consent. Rungs 3 and 4 put traffic on the live NHCX sandbox, and only the user starts them. + +## 2. Writing rung 1 for a new HMIS + +Build one suite with this shape, whatever the language: + +- One process, one seeded database under a temporary path, sections in the order the episode runs. `section(name)` starts a group; `check(label, condition, detail)` records one assertion and never raises. The run exits non-zero at the end if anything failed. +- The transport's `send` is one function, and the test replaces it. Every send goes through it; the test assigns a stub that records the path, recipient, workflow id, correlation id and bundle, and returns `{"txn_id": ..., "correlation_id": ..., "api_call_id": ...}`. Restore the real one in `finally`. The receiving end is tested apart from the door: for your own transport, seal a payer bundle with a test key pair, POST it, and check the 202 receipt and the envelope the door receives. +- Call the callback handler directly with an envelope, not over HTTP: `receive({"jwe_headers": {...}, "fhir": bundle}, "", "", "fhir")`. The return value is one of `settled`, `unmatched`, `ignored`. Feed it the payer bundles under `nhcx-package/fhir/C3` to `nhcx-package/fhir/C11`, both the generic files and the `-pmjay` ones. The auth-requirements rulings are `C3/C3-response-generic.json` (one line, 10 supporting entries) and `C3/C3-response-pmjay.json` (two lines, 22 entries). +- The pin comparison builds each bundle from the pin's own data and compares canonical JSON (`json.dumps(bundle, sort_keys=True)`) against the pin. The data is all in `nhcx-package/fhir/B3/preauth-request.json`: member `MD5SLS4X5`, policy `PMJAY/HP/S/G`, provider `IN1910000151`, payer `1518@hcx`, package `MG0111A` with tier `STRAT006b`, the four `MAND` documents. Drop from both sides only `created`. The bundle id and every entry's `fullUrl` are fixed strings in the pins (`preauth-request-generic`, `https://nhcx.abdm.gov.in/preauth/request`), and the build produces them as they are. +- The single-item pins carry `factor 0.5`. That contradicts the rule their own enhancement follows (`nhcx-package/fhir/B3/preauth-enhancement.json`: the costlier line 1, the next 0.5), so compare those with `factor` removed. Compare the cancel and reprocess pins as they are; they carry `intimationNumber`, the spelling the build sends. +- Read every expected value in a reader check from the fixture you feed: `preAuthRef`, amounts, claim numbers, the UTR. The PMJAY captures have the beneficiary's identifiers replaced, and some fields are absent (`C5/C5-received-wf20-pmjay.json` carries no `preAuthRef`). A typed literal tests your memory, not the reader. +- Negative checks are half the value. A code the plan does not carry is refused. A send while the leg is with the payer is refused. A redelivered api call id is ignored. A claim refused at the door goes back to `queried` with the question restored. A cancel while the payer holds the case is accepted, and a cancel of a rejected one is refused. +- Put the regression sections near the bottom. Each is a defect that reached working code, named after what went wrong. Add one each time the sandbox teaches you something. + +In a language whose JSON encoder does not sort keys, decode into a map and encode again before comparing, so key order cannot fail a check. Where a byte comparison is too strict, as with the wire captures, compare element by element. + +## 3. The test-case matrix + +One row per hospital-side use case. Preconditions are the state the HMIS must be in. The action is what the desk or the test does. The expected wire is what must go out and come back; the per-case archive shows it (and the adapter's ledger, when it is the transport). The expected state is what the HMIS must hold afterwards. Codes are those of `nhcx-package/usecases.yaml`. Workflow ids are the PMJAY table unless the row says generic. + +| Use case | Preconditions | Action | Expected wire | Expected state | +| --- | --- | --- | --- | --- | +| A5 Get status (generic) | A pre-auth or claim leg with the payer; a generic payer | Ask status for the leg | `v1/task/submit`, Task `status` with `claimNumber`, workflow = the leg's correlation id; a Task back with `claimStatus` | An enquiry row `answered` with the status word; the leg unchanged | +| A5 Get status (PMJAY) | as above; PMJAY | Ask status | the same Task; a ProtocolResponse PAYR-1018 (no reason) or PAYR-1008 (with one) | The enquiry row `error` with the payer's words; nothing else changes | +| B1 Check coverage eligibility | A patient with a member id and policy from the policy search; facility HFR id and participant code set | Validate, then discover | `v1/coverageeligibility/check` twice, new correlation each, workflow = the case number; `on_check` with the request echoed and a `CoverageEligibilityResponse` | `claim.status eligible`, `inforce 1`, allowed and used amounts, the payer's Patient demographics | +| B2 Request insurance plan | Eligible; no master held for this facility and policy | Fetch the plan | `v1/insuranceplan/request`, a Task `poll` with `policyNumber` and `providerId`; `on_request` with the InsurancePlan and Questionnaires | `claim_plan.status ready`, benefits with rates, tiers, requirements, forms by url; a second episode on the same policy copies it without a send | +| B3 Submit pre-authorisation | Plan ready; lines quoted from it; dossier saved; admission linked; documents and forms for the pre-auth stage attached | Submit | `v1/coverageeligibility/check` purpose `auth-requirements` first (sent, not awaited), then `v1/preauth/submit` workflow 12 equal to the pin but for identifiers; `on_submit` 20 (`queued`, `response.partial`) then 21 | `claim_preauth.status submitting` after the 20 with `preauth_ref` kept, `approved` after the 21 with `approved_amount`; stage `preauth`, sub-stage `approved` | +| B3 Auth-requirements ruling | The check sent with the pre-auth; the payer answers it | Nothing; read on arrival | inbound `on_check`, a CoverageEligibilityResponse with purpose `auth-requirements`, one `insurance[0].item` per quoted line with `authorizationRequired`, `excluded` and `authorizationSupporting[]` (`C3/C3-response-generic.json`, `C3/C3-response-pmjay.json`) | each quoted line holds its ruling and what is due at pre-auth (a form always, a document only when its `Type` is `pre`); the pre-auth leg unchanged | +| B3 Enhancement | Approved; a line added since (`enhancement_lines` non-empty) | Submit again | `v1/preauth/submit` workflow 13, every line old and new, factors 1 and 0.5; 20 then 22 (generic); the SHA has answered 21 or 22 | `submission_kind enhancement`, `enhancement_no 1`, `preauth_ref` kept, then `approved`; stage `enhancement` | +| B4 Respond to a communication (generic) | A pre-auth or claim with the payer; the payer sends a CommunicationRequest on a new thread | The desk replies with text and a document | inbound `v1/communication/request` with Task `poll`, reason `additionalinfo`; outbound `v1/communication/on_request` with the request's correlation id and workflow id, a TaskBundle: Task `deliver`, Communication `basedOn` the request, the request echoed, the case entries | `claim_query` row `kind query`, `status open` then `answered` with `reply_json`; the leg row untouched; sub-stage `queried` while open | +| B4 Notification | Any leg; the payer sends a CommunicationRequest with intent `proposal` or reason `tatquery` | Nothing; it is acknowledged on arrival | outbound `v1/communication/on_request` at once, the payer's bundle with `Task.status completed`, provider Organization first | `claim_query` row `kind notification`, `status acknowledged`; the case's stage unchanged | +| B5 Submit claim | Approved pre-auth; discharge recorded with mode and stage; claim-stage documents and forms attached | Submit the claim | `v1/claim/submit` workflow 15, `use claim`, `preAuthRef`, the discharge scalars, the summary; 25 (`queued`) then 26 | `claim_submission.status submitting` then `approved` with amounts and item verdicts; stage `claim` | +| B7 Acknowledge payment notice (generic) | An approved claim; the payer's desk releases payment | Nothing; acknowledged on arrival | inbound `v1/paymentnotice/request` workflow 30 on a new thread; outbound `v1/paymentnotice/on_request` with the notice's correlation id and its own workflow id echoed, Task `status completed` with `paymentack` | `claim_payment` row with amount, UTR, `ack_status sent`; stage `payment`, sub-stage `paid`; a redelivery of the notice is `ignored` | +| B8 Cancel | A pre-auth `submitting`, `approved`, `partial` or `queried` | Cancel with a reason | `v1/task/submit` workflow PC01, Task `cancel`, inputs `claimNumber` and `intimationNumber`; `task/on_submit` PC02 with a ClaimResponse adjudicated `cancelled` | `claim_preauth.status cancelling` then `cancelled`; the episode gets a fresh claim number, the old one stays on `claim_ref`; a cancel of a `rejected` pre-auth is refused before sending | +| B8 Reprocess (generic) | A claim `rejected` or `partial` | Reprocess with reason `claimrejected` and a document | `v1/task/submit` workflow 36, Task `reprocess`, `intimationNumber`, `basedOn` CLN, `document` inputs, `for` the member; 37 (Task `accepted`, ClaimResponse `queued`); then 26 on the claim's thread | The enquiry row `answered` with `reopened`; `claim_submission` back to `submitting`, then `approved` | +| B9 Submit predetermination | Eligible; dossier saved | Ask for a quote | `v1/preauth/submit` workflow 12 with `use predetermination`; a ClaimResponse back | A `claim_predetermination` row `answered` with `allowed_amount`; the pre-auth row untouched | +| D1 Fetch the insurance plan | Eligible on PMJAY | Fetch | as B2; the answer on workflow 5, both `specificCost[]` and `coverage[]`, nested document requirements, `/questionnaire/` and `/stgquestionnaire/` forms | as B2, with `ProcedureType` conditions and the consent forms among the policy documents | +| D2 Authenticate the beneficiary | A policy from the BIS | Not NHCX; take the consent questionnaire path | none | The consent form answered for the pre-auth stage | +| D3 Check coverage eligibility | as B1 with member `MD5SLS4X5` style ids | Validate | as B1; the answer on workflow 5 with the wallet | as B1 | +| D4 Submit pre-authorisation | as B3, plus: HPIN on the doctor, `Item/n` ids, consent and STG forms answered, documents under the plan's `MAND` codes | Submit | `v1/preauth/submit` workflow 12; 20 with the path-form `preAuthRef` or none (flow-knowledge.md section 3), then 21 with the bare number | as B3; `preauth_ref` = the bare case number after the 21 | +| D5 Resubmit pre-authorisation | A pre-auth `rejected` | Submit again | a fresh 12, never 121 | a new `submitting` round; 121 would be PAYR-1214 | +| D6 Raise an enhancement | Approved; a medical package added (not conservative) | Submit | workflow 13; 20 without `preAuthRef` (keep the parent's); 241 arrives as a ClaimResponse `partial` on the case thread; the desk answers on 131 with a `CQD` reply; then approved | `enhancement_no 1`; `queried` then `answered` then `approved`; a second conservative package would be PAYR-1245 | +| D7 Answer a pre-authorisation query | The 24 arrived as a ClaimResponse `partial`, item status `Queried` | The desk writes a reply and submits again | `v1/preauth/submit` workflow 19, flow `queryupdate`, `NMI`/`CQD` carrying the words, a new correlation id; 20 then 21 | `submission_kind preauth_query_response`, `query_note` holding the payer's question, then `approved`; an empty reply is refused before sending | +| D8 Cancel pre-authorisation | as B8 on PMJAY | Cancel | as B8 | as B8 | +| D9 Submit claim | as B5, plus: the claim under the pre-auth's claim number, the package alone at the whole amount, Discharge Consent answered, PDF documents | Submit | `v1/claim/submit` workflow 15; 25 with `preAuthRef` as a path; then 26 | as B5; item verdicts with `eligible`, `status Approved` | +| D9 LAMA or DAMA before or during surgery | Discharge mode `lama` or `dama`, stage `Before Surgery` or `During Surgery` | Submit the claim | one item `LM100`, no tier, `DIS` = `LAMA` or `DAMA` with the stage | approved; the package would be PAYR-1362 | +| D9 Death | Discharge mode `death` with a date and time | Submit the claim | `ONS`/`DTM` and `DSDE` with the death instant, `DIS`/`DTM`, the death forms | approved; without `DTM` PAYR-1096 | +| D10 Answer a claim query | The 27 arrived as a ClaimResponse `partial` | The desk writes a reply and submits again | `v1/claim/submit` workflow 161, `NMI`/`CQD`, a new correlation id; 25 then 26 | `submission_kind claim_query_response`, then `approved`, possibly at zero | +| D11 Reprocess a rejected claim | A claim `rejected` | Reprocess | as B8 reprocess; on the sandbox a ProtocolResponse PAYR-1008 | the enquiry row `error` with the refusal; on a generic payer as B8 | +| D12 Claim a shortfall | A settled payment short of the approved amount | Release with `partialpayment` and the amount | `v1/task/submit` workflow 36, Task `release`, `valueMoney` | an enquiry row; out of reach on the sandbox | +| D13 Acknowledge the payment notice | An approved claim; the SHA's finance side sends 30 | Nothing; acknowledged on arrival | outbound `v1/paymentnotice/on_request` with workflow 17, the notice's correlation id, to the notice's sender | as B7 | + +Cross-cutting rows every matrix needs: + +| Case | Action | Expected | +| --- | --- | --- | +| Redelivery | Deliver the same envelope twice | the second returns `ignored`; state unchanged | +| Unmatched | Deliver an answer on an unknown correlation id | `unmatched`; archived under `unmatched`; nothing changes | +| Refusal at the door | Deliver a ProtocolResponse on a leg's thread | the leg `error` (or `queried` restored for a query answer, `approved` restored for an enhancement) with the payer's words; `correlation_id` restored to `thread_correlation_id` | +| Ledger reset (nhcx-adapter only) | The adapter answers 404 on `txn/related` | the leg `error` with "send again"; no spinning | +| Stage after every write | Any of the above | `stage` and `sub_stage` on the episode agree with `case_stage` recomputed from the legs | + +## 4. A skeleton offline test + +Replace the placeholders marked `` with your HMIS's own. Every pin and payer answer is loaded from the package. + +```python +#!/usr/bin/env python3 +"""Offline NHCX checks for : builders against the package pins, readers against the payer fixtures. + + NHCX_PACKAGE=nhcx-package python3 nhcx_offline_test.py # exit 0 when every check passes +""" +from __future__ import annotations + +import copy +import json +import os +import tempfile + +PKG = os.environ.get("NHCX_PACKAGE", "nhcx-package") +GENERIC_PAYER = "" + +os.environ[""] = os.path.join(tempfile.mkdtemp(prefix="nhcx-test-"), "t.db") + +import as nhcx # noqa: E402 the module that owns transport, build_*, receive + +failures = 0 +current = "general" +tally: dict[str, list[int]] = {} + + +def section(name: str) -> None: + global current + current = name + tally.setdefault(name, [0, 0]) + print(f"\n-- {name} " + "-" * max(3, 60 - len(name))) + + +def check(label: str, condition: bool, detail: str = "") -> None: + global failures + tally.setdefault(current, [0, 0]) + tally[current][0 if condition else 1] += 1 + if not condition: + failures += 1 + print(f"[{' ok ' if condition else ' FAIL '}] {label}" + (f" ({detail})" if detail else "")) + + +def pin(rel: str) -> dict: + """A bundle from the package by its path under fhir/, e.g. pin("B3/preauth-request.json").""" + with open(os.path.join(PKG, "fhir", rel), encoding="utf-8") as fh: + return json.load(fh) + + +def resource(bundle: dict, kind: str) -> dict: + return next(e["resource"] for e in bundle["entry"] if e["resource"]["resourceType"] == kind) + + +def task_input(task: dict, code: str): + return next(i.get("valueString") for i in task.get("input", []) if i["type"]["coding"][0]["code"] == code) + + +def total(claim_response: dict, category: str): + return next((t["amount"].get("value") for t in claim_response.get("total", []) + if t["category"]["coding"][0]["code"] == category), None) + + +def normalised(bundle: dict, factor: bool = True) -> dict: + """Drop only `created`, which a builder stamps when it sends; with factor=False, the Claim items' factor too.""" + out = copy.deepcopy(bundle) + + def walk(node): + if isinstance(node, dict): + node.pop("created", None) + for value in node.values(): + walk(value) + elif isinstance(node, list): + for value in node: + walk(value) + + walk(out) + if not factor: + for entry in out["entry"]: + if entry["resource"]["resourceType"] == "Claim": + for item in entry["resource"].get("item", []): + item.pop("factor", None) + return out + + +def canonical(bundle: dict, factor: bool = True) -> str: + return json.dumps(normalised(bundle, factor), sort_keys=True, ensure_ascii=False) + + +def same(label: str, ours: dict, want: dict, factor: bool = True) -> None: + a, b = canonical(ours, factor), canonical(want, factor) + check(label, a == b, "" if a == b else a[:300]) + + +# The package pins' own data: nhcx-package/fhir/B3/preauth-request.json and B1/*.json. +# Every builder is fed this and must produce the pin. +REF = { + "claim_no": "VB26AA2600001", "member_id": "MD5SLS4X5", "policy": "PMJAY/HP/S/G", + "provider": {"id": "IN1910000151", "name": "Facility Name"}, + "payer": {"code": "1518@hcx", "id": "1518", "name": "Insurance Company"}, + "patient": {"name": "Patient Name", "gender": "male", "dob": "2004-09-18", + "phone": "9999999999", "abha": "91718280654077", "member_id": "MD5SLS4X5"}, + "practitioner": {"name": "Practitioner Name", "hpr_id": "982374978-2343", "license_no": "MCI-12345", + "qualification": "Doctor of Medicine", "qualification_code": "MD", + "specialty": "General medicine", "specialty_code": "394802001"}, + "diagnosis": {"code": "A97", "display": "Dengue"}, + "item": {"code": "MG0111A", "display": "Pleural Effusion", "category_code": "MG", + "category_display": "General Medicine", "quantity": 1, "unit_price": 3300, "net": 3300, + "kind": "Procedure", "procedure_type": "conservative"}, + "tier": {"code": "STRAT006b", "display": "HDU", "kind": "Stratification", "parent_code": "MG0111A"}, + # The benefits and auth-requirements pins quote a different package. + "coverage_item": {"code": "MG004C", "display": "Dengue shock syndrome (Dengue fever)", + "category_code": "MG", "category_display": "General Medicine", "quantity": 1, + "tier": {"code": "STRAT006c", "display": "ICU - Without Ventilator"}}, +} + + +def main() -> int: + section("coverage eligibility: ours is the pin") + for purpose, rel in (("discovery", "B1/discovery.json"), ("validation", "B1/validation.json"), + ("benefits", "B1/benefits.json"), ("auth-requirements", "B1/auth-requirements.json")): + want = pin(rel) + ours = nhcx.build_coverage_request((purpose, want)) + same(f"coverage {purpose}", ours, want) + + section("insurance plan request: ours is the pin") + same("plan request", nhcx.build_plan_request(REF["policy"], REF["provider"]["id"]), + pin("B2/insurance-plan-request.json")) + + section("claim bundles: ours is the pin") + ref_pa = pin("B3/preauth-request.json") + ref_pdf = next(si["valueAttachment"]["data"] for si in resource(ref_pa, "Claim")["supportingInfo"] + if "valueAttachment" in si) + dossier = (REF, ref_pdf, ref_pa) + same("preauth request", nhcx.build_preauth_bundle(dossier, flow="request"), ref_pa, factor=False) + ref_qu = pin("B3/preauth-queryupdate.json") + reply = next(si["valueString"] for si in resource(ref_qu, "Claim")["supportingInfo"] + if si["category"]["coding"][0]["code"] == "NMI") + same("preauth query update", + nhcx.build_preauth_bundle(dossier, flow="queryupdate", query_response=reply), + ref_qu, factor=False) + ref_cancel = pin("B3/preauth-cancel.json") + cancel = resource(ref_cancel, "Task") + reason = cancel["reasonCode"]["coding"][0] + same("preauth cancel", + nhcx.build_cancel_task(task_input(cancel, "claimNumber"), (reason["code"], reason["display"]), + cancel["authoredOn"], REF["provider"], REF["payer"]), + ref_cancel) + ref_ack = pin("B7/payment-notice-ack.json") + ack = resource(ref_ack, "Task") + acked_claim = next(o["valueString"] for o in ack["output"] if "valueString" in o) + same("payment acknowledgement", + nhcx.build_payment_ack(acked_claim, ack["authoredOn"], REF["provider"], REF["payer"]), + ref_ack) + + section("the transport is the one door, and it can be stubbed") + posted: list[dict] = [] + real_send = nhcx.transport.send + + def submitted(payer: str, corr: str): + def _send(path, bundle, recipient, workflow_id, correlation_id=None, **kw): + posted.append({"path": path, "recipient": recipient, "workflow_id": workflow_id, + "correlation_id": correlation_id, "bundle": bundle}) + return {"txn_id": "01TEST", "correlation_id": corr, "api_call_id": "acid-" + corr} + + seeded = (payer) # eligible, plan ready, lines quoted, dossier saved + nhcx.transport.send = _send + try: + nhcx.submit_preauth(seeded) + finally: + nhcx.transport.send = real_send + return seeded + + episode = submitted(REF["payer"]["code"], "corr-preauth-1") + sent = posted[-1] + leg = nhcx.preauth(episode) + check("the pre-auth goes out on the preauth route under workflow 12", + sent["path"] == "v1/preauth/submit" and str(sent["workflow_id"]) == "12") + check("no correlation id is passed on a request", sent["correlation_id"] is None) + check("the leg waits with the transport's ids", + leg["status"] == "submitting" and leg["txn_id"] == "01TEST" and leg["correlation_id"] == "corr-preauth-1") + + section("readers: the payer answers settle the right state") + + def deliver(bundle: dict, acid: str, workflow: str, status: str = "response.complete", + corr: str = "corr-preauth-1", sender: str = "1518@hcx") -> str: + return nhcx.receive({"jwe_headers": {"x-hcx-correlation_id": corr, + "x-hcx-api_call_id": acid, + "x-hcx-sender_code": sender, + "x-hcx-status": status, "x-hcx-workflow_id": workflow}, + "fhir": bundle}, "preauth", "request", "fhir") + + received = pin("C5/C5-received-wf20-pmjay.json") + before = nhcx.preauth(episode)["preauth_ref"] + check("the PMJAY acknowledgement leaves the leg waiting", + deliver(received, "acid-20", "20", "response.partial") == "settled" + and nhcx.preauth(episode)["status"] == "submitting") + check("an acknowledgement without preAuthRef overwrites nothing", + not resource(received, "ClaimResponse").get("preAuthRef") + and nhcx.preauth(episode)["preauth_ref"] == before) + check("the same api call id delivered again is ignored", + deliver(received, "acid-20", "20", "response.partial") == "ignored") + approval = pin("C5/C5-approved-wf21-pmjay.json") + approved = resource(approval, "ClaimResponse") + check("the approval settles the leg on the same thread with the payer's case number", + deliver(approval, "acid-21", "21") == "settled" + and nhcx.preauth(episode)["status"] == "approved" + and nhcx.preauth(episode)["approved_amount"] == total(approved, "benefit") + and nhcx.preauth(episode)["preauth_ref"] == approved["preAuthRef"]) + stage, sub_stage = nhcx.case_stage(episode) + check("the episode is stamped preauth / approved", (stage, sub_stage) == ("preauth", "approved")) + + other = submitted(GENERIC_PAYER, "corr-preauth-2") + generic = pin("C5/C5-received-wf20.json") + check("a generic payer's acknowledgement carries the case number, and it is kept", + deliver(generic, "acid-20g", "20", "response.partial", corr="corr-preauth-2", + sender=GENERIC_PAYER) == "settled" + and nhcx.preauth(other)["status"] == "submitting" + and nhcx.preauth(other)["preauth_ref"] == resource(generic, "ClaimResponse")["preAuthRef"]) + + section("auth requirements: the payer's ruling is read line by line") + for rel in ("C3/C3-response-generic.json", "C3/C3-response-pmjay.json"): + ruling = pin(rel) + answer = [e["resource"] for e in ruling["entry"] + if e["resource"]["resourceType"] == "CoverageEligibilityResponse"][-1] + want = {i["productOrService"]["coding"][0]["code"]: i.get("authorizationRequired") + for i in answer["insurance"][0]["item"]} + got = nhcx.parse_auth_bundle(ruling) # {procedure code: {"required": bool, "supporting": [...]}} + check(f"{rel}: one ruling per quoted line, required as the payer says", + {code: line["required"] for code, line in got.items()} == want) + + section("the query loop") + queried = pin("C5/C5-queried-wf24.json") + check("a PMJAY query is the leg queried, with the payer's words and case number kept", + deliver(queried, "acid-24", "24") == "settled" + and nhcx.preauth(episode)["status"] == "queried" + and bool(nhcx.preauth(episode)["query_note"]) + and nhcx.preauth(episode)["preauth_ref"] == resource(queried, "ClaimResponse")["preAuthRef"]) + try: + nhcx.submit_preauth(episode, reply="") + check("an empty reply is refused before sending", False) + except ValueError: + check("an empty reply is refused before sending", True) + check("a generic payer's CommunicationRequest is classified a query", + nhcx.classify_communication(nhcx.GENERIC_ADAPTER, "additionalinfo", "order") == "query" + and nhcx.classify_communication(nhcx.PMJAY_ADAPTER, "additionalinfo", "order") == "notification" + and nhcx.classify_communication(nhcx.GENERIC_ADAPTER, "tatquery", None) == "notification") + + section("refusal at the door") + refusal = {"type": "ProtocolResponse", "x-hcx-status": "response.error", + "x-hcx-correlation_id": "corr-preauth-1", + "x-hcx-error_details": {"code": "PAYR-1238", "message": "Beneficiary is having an active preauthorization request"}} + (episode) + check("a ProtocolResponse settles the leg as refused with the payer's words", + nhcx.receive({"jwe_headers": {"x-hcx-correlation_id": "corr-preauth-1"}, "fhir": refusal}, + "preauth", "request", "protocol") == "settled" + and nhcx.preauth(episode)["status"] == "error" + and "PAYR-1238" in (nhcx.preauth(episode)["error_message"] or "")) + + section("tasks and payment") + cancelled = pin("C10/C10-cancelled-wfPC02-pmjay.json") + verdict = resource(cancelled, "ClaimResponse")["adjudication"][0]["reason"]["coding"][0]["code"] + check("PC02 is read as an accepted cancellation", + nhcx.parse_task_response(cancelled)["adjudication"] == verdict == "cancelled") + arbitration = pin("C10/C10-arbitration-wf37-pmjay.json") + check("37 is read as the reprocess taken", + nhcx.parse_task_response(arbitration)["task_status"] == resource(arbitration, "Task")["status"]) + paid = pin("C9/payment-notice.json") + pn, pr = resource(paid, "PaymentNotice"), resource(paid, "PaymentReconciliation") + notice = nhcx.parse_payment_notice(paid) + check("the payment notice names the claim, the amount and the UTR", + notice["claim_ref"] == pn["identifier"][0]["value"] + and notice["amount"] == pn["amount"]["value"] + and notice["utr"] == pr["paymentIdentifier"]["value"]) + + print("\n" + "=" * 64) + total_checks = sum(ok + bad for ok, bad in tally.values()) + for name, (ok, bad) in tally.items(): + print(f" {name:44s} {ok:3d} passed {bad:2d} failed [{'FAIL' if bad else 'ok'}]") + print("=" * 64) + if failures: + print(f"{failures} of {total_checks} check(s) FAILED") + return 1 + print(f"all {total_checks} checks passed") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main()) +``` + +What each placeholder must do: + +- `` names the variable your HMIS reads its database path from, so the suite runs on a throwaway file. +- `` is the module that owns `transport`, the builders and `receive`. +- `` is the participant code of a generic payer (``) that your configuration maps to `query_mode: communication`. +- `` returns the dict your coverage builder takes, filled from `REF`. The discovery pin carries policy `NONE`. The benefits and auth-requirements pins quote `REF["coverage_item"]`. Copy the Location and PractitionerRole from the pin it is given. +- `` returns whatever your claim builder takes. That is the claim number, the item, the tier, the program `AB-PMJAY` and factors `(1, 0.5, 0.25)`. Add the four `MAND` documents (`MAND0408`, `MAND0455`, `MAND0409`, `MAND0570`, each with the pin's PDF), and copy the stay and procedure dates from the pin it is given. +- `` takes a payer code and inserts an eligible episode for that payer, with the plan and lines seeded straight into the database. +- `` puts the pre-auth row back to `submitting` on `corr-preauth-1`. + +Run the suite from the folder that holds `nhcx-package/`, or set `NHCX_PACKAGE` to its path. + +## 5. Running rung 2 + +Have your tests and live runs write every bundle they build into one archive folder. The package ships no validator. Run the HL7 FHIR validator with the NRCeS IG `ndhm.in` on the whole folder in one call, with the command and flags in `references/fhir-knowledge.md` section 11. + +Read the results in three piles. "A code the profile does not define" is the scheme's vocabulary, and it is expected. "A required element is missing" and "an id or value the base rules refuse" are yours to fix. Warnings are advice; the sandbox accepted every pin as it stands. Skip the package master; it exhausts the validator's memory. A live PAYR-1004 or PAYR-1008 is the first reason to run this rung again (`nhcx-package/docs/06-Reference/02-Troubleshooting.md`). + +## 6. Running rungs 3 and 4 + +Only the user runs these. Prepare what they start and the driver, then stop and ask. + +What the user starts: + +1. The transport. Your own or the app's existing one needs a participant record carrying its certificate and a public HTTPS `endpoint_url` the exchange can reach (`references/transport-knowledge.md` section 3). nhcx-adapter, only when the user chose it, comes from its release: `config.sample.json` filled in, started with `serve.sh`. +2. Your HMIS, reachable by the exchange through that transport. +3. For rung 3, a generic payer on the sandbox whose desk you can drive (``), mapped to `query_mode: communication`. For rung 4, nothing more: the PMJAY payer is `1518@hcx`, and its decisions are taken on the payer service desk. + +The driver is a script or a browser spec. It walks the matrix rows through the app's JSON state address or its own screens, one episode per test, in series, with a 20 minute timeout per episode. + +- Before a PMJAY run, sweep every live pre-auth for the beneficiaries the tests use. Cancel it on PC01, or have the desk reject it. Otherwise the first pre-auth is refused with PAYR-1238. +- One request at a time per case. Wait about 30 seconds after a decision before the next leg. On "Active instance found" (PAYR-1322), wait and resend, up to three times. +- Wait on the case's own state, never on a fixed sleep or a checklist. +- Log every verdict the sandbox gives, with its workflow id and words, so a refusal is a finding, not a mystery. +- Expect about four minutes for the rung 3 matrix and about ten minutes per episode on PMJAY. + +After the run, package its bundles by correlation id from the per-case archive: every message sent and received, filed under its case. With nhcx-adapter as the transport, `nhcx-adapter ledger thread ` gives the same conversation, with bodies only while `ledger.storeBodies` is true (`nhcx-package/docs/02-Getting Started/10-NHCX Adapter.md`). File each thread under its use case. diff --git a/plugins/nhcx/skills/nhcx-reprocess/references/transport-knowledge.md b/plugins/nhcx/skills/nhcx-reprocess/references/transport-knowledge.md new file mode 100644 index 000000000..a0838b9cd --- /dev/null +++ b/plugins/nhcx/skills/nhcx-reprocess/references/transport-knowledge.md @@ -0,0 +1,283 @@ +# Transport knowledge: how the build reaches NHCX + +Every NHCX message is a FHIR bundle sealed in a JWE, sent with an ABDM session token, and answered later on the sender's own callback. Something has to do that work. This file says which of three things does it for a build, what the rest of the build expects from it, and how to build it yourself. + +Section 3 is drawn from NHA's published chapters: `nhcx-package/docs/02-Getting Started` (01 to 09, and 11), `nhcx-package/docs/01-Overview/04-JWE, Status and Errors.md` and `nhcx-package/docs/06-Reference/03-Envelope Fields.md`. Open them when a detail matters. Where they and this summary differ, they win. + +## 1. Three transports + +| Transport | Choose it when | The build | +| --- | --- | --- | +| `existing` | Stage 0 found the app already speaks NHCX: its own client that seals and posts JWEs, a vendor gateway or middleware, an HCX SDK, callbacks under `/v1/...` | Keeps it. Wraps it behind the contract in section 2 and closes the gaps section 4 lists. Never replaces a working one. | +| `own` | The app has no NHCX integration, and the user has not asked for nhcx-adapter. This is the default. | Builds the protocol into the app (section 3): the session token, the key and certificate, the participant record, the recipient's certificate, sealing and sending, the callback and its receipt. | +| `adapter` | Only when the user asks for nhcx-adapter, by name or by asking for "the adapter" | Downloads it (section 5) and talks plain FHIR to it. `references/api-knowledge.md` is its contract. | + +The rules: + +- Never propose nhcx-adapter, and never choose it because it is easier. Use it only when the user has asked for it, and write their words into `nhcx-build/1-idea.md`. +- An app with an NHCX integration of its own keeps it, even when it is partial. Extend it; never put a second transport beside it. +- The choice is made once per app, at stage 1, from stage 0's verdict on `foundation.transport`. Every skill after the first reads it from `1-idea.md`. + +## 2. The contract every transport meets + +The rest of the build (modules 7.2 to 7.13) never sees the transport, only these functions: + +| Function | Takes | Gives | Notes | +| --- | --- | --- | --- | +| `send(path, bundle, recipient, workflow_id, correlation_id = null, ben_abha_id = null, claim_no, usecase)` | The NHCX path (`v1/preauth/submit`), the bundle, the recipient's participant code, the workflow id; a correlation id only when answering (the communication reply, the payment acknowledgement); the beneficiary's ABHA, else the episode's by `claim_no` | `{txn_id, correlation_id, api_call_id, raw}` | Raises `TransportError(code, message, protocol_response, retryable)` on a refusal. Archives the outbound message. Every leg stores the three ids. | +| The receiving end | A delivery from the exchange (`own`, `existing`) or from nhcx-adapter | Calls 7.3's `receive(envelope)` with `{meta: {path, payloadType, redelivery}, jwe_headers: {every x-hcx- field}, fhir: }`; `payloadType` is `fhir`, `protocol` or `error` | Answers the sender as its transport requires (section 3.9 for `own`). The door does the rest. | +| `policies(id_type, value)` | `AbhaNumber`, `MemberId` or `MobileNo`, and the value | The participant service's answer, raw | Module 7.4 normalises it (section 3.6). | +| `participants(role)` | `PAYER`, `PROVIDER` or `TPA` | The registry's list | Cached for the day. | +| `token()` | nothing | The ABDM session token | For calls the transport does not make itself, such as the PMJAY payer service. | +| `thread(correlation_id)`, `fetch_missed(txn_id)` | | The messages on one thread; a missed answer | Only nhcx-adapter keeps a ledger to answer these. With `own` and `existing`, `thread` reads the per-case archive and `fetch_missed` answers `unavailable`; a lost answer surfaces through `/v1/error` and the status exchange instead (section 3.10). | + +Two values every transport needs from the build, both from the policy lookup (section 3.6). The recipient is the policy's `processingid`, kept on the episode as `recipient_code`. The insurer is its `payerid`, kept as `payer_code`: it goes inside the bundle and chooses the payer adapter (module 7.11). And every message carries the beneficiary's ABHA number in `x-hcx-ben-abha-id`. + +A test replaces `send` with a stub of the same signature (stage 9). Nothing else in the build changes for a test. + +## 3. Building it yourself (`own`) + +Seven things, in this order (`01-The Base Framework.md`): a token, a key and certificate, a participant record, the payer and policy lookups, the recipient's certificate, sealing and sending, and the callback. The last two are the ones every message uses. + +### 3.1 Before you start + +| Need | Why | +| --- | --- | +| The facility's HFR id | The registry that vouches for a hospital | +| ABDM sandbox client id and secret, Milestone 1 completed | NHCX uses the same credentials; there is no separate login | +| A public HTTPS server in India with a domain name | The exchange calls your callback; it will not call an IP address or a port number | +| `openssl` where the private key will live | The key pair | +| A JOSE library | RSA-OAEP-256 with A256GCM: `jose` on Node, `jwcrypto` on Python, Nimbus on Java, `jose-jwt` on .NET | + +Ask the user for the credentials. Never write them, the token or the private key into code, a log or `nhcx-build/`. + +### 3.2 Addresses and headers + +From `nhcx-package/baseurl.yaml`: + +| Service | Sandbox | Production | +| --- | --- | --- | +| ABDM session token | `https://dev.abdm.gov.in/api/hiecm/gateway/v3/sessions` | `https://apis.abdm.gov.in` plus the same path; confirm it in the onboarding letter | +| NHCX exchange, every use-case call under `/v1` | `https://apisbx.abdm.gov.in/hcx` | Shared by NHA after sandbox exit | +| Participant service | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice` | `https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice` | + +Keep every address in configuration. Every call to the participant service and the use-case endpoints carries `Accept: application/json`, `Content-Type: application/json` and `bearer_auth: Bearer `. The header is `bearer_auth`, not `Authorization`; some NHA pages write `Authorization`, so send both with the same value. + +### 3.3 The session token + +`POST` to the sessions address with three headers, none optional: `REQUEST-ID` (a fresh UUID on every call), `TIMESTAMP` (UTC with milliseconds and a trailing `Z`, from the system clock) and `X-CM-ID` (`sbx` on the sandbox, `abdm` in production). The body is `{"clientId", "clientSecret", "grantType": "client_credentials"}`. The answer carries `accessToken` and `expiresIn`. + +- NHA's documents give its life as 300, 1200 and 6000 seconds. Rely on none: keep the token and when you got it, and fetch a new one when it is a few minutes old. +- On any `401`, get a new token and retry that call once. Never retry with the same token. +- Put `Bearer` and a space before the token. Without it, `401`. + +`03-Session Token.md` also shows the two timestamp shapes in ten languages: the gateway's UTC `...975Z`, the exchange's `+05:30`. + +### 3.4 Your key and certificate + +```bash +openssl genpkey -algorithm RSA -out private.key -pkeyopt rsa_keygen_bits:2048 +openssl req -new -key private.key -out request.csr +openssl x509 -req -in request.csr -signkey private.key -out certificate.crt -days 365 +base64 -w 0 certificate.crt > certificate.b64 # macOS: base64 -i certificate.crt -o certificate.b64 +``` + +`private.key` never leaves the server that receives callbacks. `certificate.b64` goes on the participant record as `encryption_cert`. Note the expiry: a lapsed certificate stops every sender. Replace it yearly (`04-Your Certificate.md`). + +### 3.5 The participant record + +On the sandbox, `POST /participant/create` with: + +| Field | Value | +| --- | --- | +| `linked_registry_codes` | `["10001"]` (HFR) | +| `registryid` | Your ABDM client id on the sandbox; the HFR id in production | +| `roles` | `["10001"]` (provider) | +| `participant_name`, `scheme_code`, `state`, `district`, `primaryEmail`, `phone`, `primaryMobile` | The facility's | +| `encryption_cert` | The base64 certificate | +| `endpoint_url` | The base of your callback server | + +The answer is your `participant_code`: the `x-hcx-sender_code` on everything you send. `participant/update` changes the certificate or the address. Production takes four steps with a passcode to the mobile on the HFR record (`v2/participant/create`, `validate`, `v2/participant/update`, `update/validate`), and `v2/update/cert` rotates only the certificate (`05-Creating and Updating a Participant.md`). + +The exchange appends the use-case path to `endpoint_url`: a pre-auth decision arrives at `/v1/preauth/on_submit`. Only the client id that created the record may change it; any other gets NHCX-1015. + +This is the user's onboarding, not the build's. The build writes the script or the settings screen; the user runs it with their credentials. Check it worked by fetching your own certificate back (section 3.7). + +### 3.6 The payer and the policy + +- Payers: `POST /fetch/participants/list` with `role` (`PAYER`, `PROVIDER`, `TPA`), `fromdate` and `todate` (`dd/MM/yyyy`), and optionally `entitytype` (`Gov`). There is no server-side search by name: fetch, filter locally, and cache for the day. +- Policies: `POST /participant/get/policies` with `identifiertype` and `identifiervalue`. Try `AbhaNumber` (no hyphens), then `MemberId`, then `MobileNo`, and stop at the first that returns a policy. Each policy carries `payerid`, `processingid`, `memberid`, `productid` and `productname`. The published answer is a sketch: read a real one before writing the parser, and keep it raw on the episode. +- Send to the processor. `processingid` is the envelope's recipient and whose certificate seals the message; `payerid` is the insurer named inside the bundle. They are the same when the insurer processes its own claims and differ when a TPA does. Addressing the `payerid` is the portal's seventh most common mistake. A policy with no `processingid` cannot be addressed: stop and say so (`06-Finding Participants and Policies.md`). + +### 3.7 The recipient's certificate + +`POST /fetch/certs` with `{"participantid": ""}`. The answer is PEM text: usually an X.509 certificate, sometimes a bare SPKI public key (anything under about 400 bytes). Load it as a certificate and take its key; if that fails, load it as a key. NHA does not publish the JSON envelope around it, so read one real answer first. Cache by participant code for 24 hours, and refresh early when the other side stops being able to open your messages (`07-Fetching a Recipient Certificate.md`). + +### 3.8 Sealing and sending + +The protected header (`08-Building and Sending a JWE.md`, `06-Reference/03-Envelope Fields.md`): + +| Field | Value | +| --- | --- | +| `alg`, `enc` | `RSA-OAEP-256`, `A256GCM`; not `RSA-OAEP` | +| `x-hcx-sender_code` | Your participant code | +| `x-hcx-recipient_code` | The policy's `processingid` on a request; the request's sender on an answer | +| `x-hcx-api_call_id` | A fresh UUID on every message, answers included | +| `x-hcx-request_id` | A UUID per request; optional, send it | +| `x-hcx-correlation_id` | On a request, this message's own `api_call_id`. On an answer, the request's `correlation_id`, so the two ids differ on an answer | +| `x-hcx-workflow_id` | The step code (`references/flow-knowledge.md` section 2). Optional in the specification, but payers key on it: send it wherever the sheet gives one | +| `x-hcx-timestamp` | ISO 8601 with `+05:30`, no milliseconds, from the system clock | +| `x-hcx-status` | `request.initiated` on a request; `response.complete` on an answer (an `on_` path) | +| `x-hcx-ben-abha-id` | The beneficiary's ABHA number without hyphens. Mandatory on every exchange | +| `x-hcx-use_case` | Optional: `New`, `Enhancement` or `Resubmit` on a pre-auth; `New` or `Resubmit` on a claim | + +Seal with the JOSE library: the bundle as plaintext, the recipient's public key, the header above as the protected header, compact serialisation (five parts, four dots). POST `{"payload": ""}` to `/v1/` with the headers of section 3.2. The sandbox collection also repeats the `x-hcx-` fields as HTTP headers; send them both ways. + +What comes back: + +| Answer | Means | The build | +| --- | --- | --- | +| `202` with a receipt (`protocol_status: request.queued`) | The envelope was valid and is queued. It is not the decision | Store `api_call_id` and `correlation_id`, and the archive id as `txn_id`; the leg waits | +| `400` | The envelope failed validation | Raise with the gateway's body; nothing went to the payer | +| `401` | The token expired, or `Bearer` is missing | New token, retry once | +| A connection dropped after the request was written | Unknown: it may have landed | Do not resend at once (`references/errors-and-debugging.md` section 7) | + +A correlation id that failed at the gateway is retired. The next attempt needs a fresh `api_call_id` and a fresh `correlation_id` (`01-Overview/04-JWE, Status and Errors.md`). + +### 3.9 Receiving + +Host these under `endpoint_url` (`09-Receiving a Callback.md`): `/v1/coverageeligibility/on_check`, `/v1/insuranceplan/on_request`, `/v1/preauth/on_submit`, `/v1/claim/on_submit`, `/v1/predetermination/on_submit`, `/v1/search/on_submit`, `/v1/communication/request`, `/v1/paymentnotice/request`, `/v1/task/on_submit`, `/v1/on_status` and `/v1/error`. Build one handler. The path gives the receipt's `entity_type`; the correlation id routes everything else (module 7.3). + +- The address: a domain over HTTPS with TLS 1.2 or newer, hosted in India, reachable from the exchange's outbound addresses `3.109.99.210`, `13.126.152.0` and `13.200.129.223`. +- The body: `{"type": "JWEPayload", "payload": ""}`; or, when the recipient refused your message, `{"type": "ProtocolResponse", "x-hcx-...": ..., "x-hcx-status": "response.error", "x-hcx-error_details": {code, message, trace}}` with the fields in the clear. `/v1/error` carries neither: it is a plain report of a request the exchange gave up on after five attempts. Store it whole and do not parse it against a fixed schema. +- Open a `JWEPayload` with your private key: the protected header comes out in the clear and the bundle is the plaintext. A failure to decrypt means the message was sealed for a certificate that is not the one on your participant record. +- Answer every delivery with `202` and the receipt within 30 seconds, `/v1/error` and unrecognised messages included. Not `200`, and not an empty body: + + ```json + {"timestamp": "dd/MM/yyyy HH:mm:ss:SSS", "api_call_id": "", "correlation_id": "", + "result": {"sender_code": "", "recipient_code": "", "entity_type": "preauth", "protocol_status": "request.queued"}, + "error": {"code": "", "message": ""}} + ``` + + `entity_type` is the path's second-to-last segment, or the last where that is `v1`, with `on_` stripped. +- Hand the door `{meta: {path, payloadType, redelivery}, jwe_headers, fhir}`: `payloadType` `fhir` with the bundle, `protocol` with the ProtocolResponse body as `fhir`, `error` with the `/v1/error` report. The door dedupes on `x-hcx-api_call_id`, archives, matches and applies, fast and with no outbound calls, so the receipt still goes inside the 30 seconds. +- The exchange signs its calls to you with a JWT (RS256; claims `jti`, `iss`, `sub`, `iat`, `exp`). No published source gives the NHCX public key or the header the token arrives in. Build the check with the key in configuration. While no key is configured, log that at every start, accept calls only from the three addresses above, and ask NHA for the key at onboarding. Never leave the check off silently. + +### 3.10 Status and the error endpoint + +- `/v1/status` asks the exchange what became of a message you sent. The payload is empty; `x-hcx-correlation_id` is that message's `api_call_id`. The answer arrives on `/v1/on_status` with `request.queued`, `request.dispatched` or `request.stopped` (redelivery exhausted; the correlation is retired). Call it when a case has been quiet longer than the payer's turnaround, never on a timer (`11-Status and Search.md`). `references/flow-knowledge.md` section 2 records what the sandbox did with it; keep the path configurable. This is not the claim's status Task of module 7.9. +- `/v1/error` is how you learn a request died. Without it a lost message is silent. + +With no ledger to poll, these two, the per-case archive and the receipts are what an `own` transport has. A leg with no answer stays waiting; it never turns into an error on a timer. + +### 3.11 Proving it + +The sandbox's dummy payer answers when you trigger it. Send it a bundle, then `POST https://apisbx.abdm.gov.in/pmjay/sbxhcx/dummyhcxpayer/process/request` with `{"action": "Approve" | "Reject" | "Query", "method": "Preauth" | "Claim", "correlationId": ""}`. Its answer reaching your `/v1/preauth/on_submit`, sealed or as a ProtocolResponse, proves the token, the participant record, the address, the sealing and the opening together (`09-Receiving a Callback.md`, "Closing the loop"). This is live traffic: stage 10, rung 3, started by the user. + +### 3.12 Pseudo code + +``` +settings.nhcx = {sessions, base, registry, cm_id, client_id, client_secret, # from configuration, never from code + private_key, signing_key} # signing_key empty until onboarding gives it + +function token(): + if cache.token and age(cache.at) < 240s: return cache.token + r = http_post(settings.nhcx.sessions, json = {clientId: settings.nhcx.client_id, clientSecret: settings.nhcx.client_secret, + grantType: "client_credentials"}, + headers = {"REQUEST-ID": uuid4(), "TIMESTAMP": utc_millis_z(), "X-CM-ID": settings.nhcx.cm_id}) + cache = {token: r.json().accessToken, at: now()} + return cache.token + +function authed_post(url, body, extra_headers = {}): + for attempt in (1, 2): + t = token() + r = http_post(url, json = body, timeout = 90, + headers = {"Accept": "application/json", "Content-Type": "application/json", + "bearer_auth": "Bearer " + t, "Authorization": "Bearer " + t} + extra_headers) + if r.status != 401: return r + cache.token = null # one retry, with a fresh token + return r + +function registry(path, body): return authed_post(settings.nhcx.registry + "/" + path, body) + +function recipient_key(code): # cached for 24 hours + if certs[code] and age(certs[code].at) < 24h: return certs[code].key + pem = pem_in(registry("fetch/certs", {participantid: code}).json()) # read one real answer first + key = try_certificate(pem).public_key() or load_public_key(pem) # X.509 first, bare SPKI second + certs[code] = {key, at: now()} + return key + +function send(path, bundle, recipient, workflow_id, correlation_id = null, ben_abha_id = null, claim_no = null, usecase = ""): + abha = digits(ben_abha_id or ben_abha(claim_no)) + if not recipient or not workflow_id or not abha: raise ValueError("recipient, workflow id and beneficiary ABHA are required") + answer = path.split("/")[-1].startswith("on_") + api_call_id = uuid4() + header = {"alg": "RSA-OAEP-256", "enc": "A256GCM", + "x-hcx-sender_code": with_hcx(settings.participant_code), "x-hcx-recipient_code": with_hcx(recipient), + "x-hcx-api_call_id": api_call_id, "x-hcx-request_id": uuid4(), + "x-hcx-correlation_id": correlation_id if answer else api_call_id, + "x-hcx-workflow_id": str(workflow_id), "x-hcx-timestamp": now_ist_seconds(), + "x-hcx-status": "response.complete" if answer else "request.initiated", + "x-hcx-ben-abha-id": abha} + jwe = jose_encrypt_compact(to_json(bundle), recipient_key(with_hcx(recipient)), protected = header) + r = authed_post(settings.nhcx.base + "/" + path, {"payload": jwe}, extra_headers = without(header, "alg", "enc")) + txn = archive.record(claim_no, usecase, "out", {path, header, bundle, status: r.status, response: r.text}) + if r.status >= 300: + raise TransportError(code = "GATEWAY_HTTP_" + r.status, message = r.text, retryable = r.status >= 500) + return {txn_id: txn, correlation_id: header["x-hcx-correlation_id"], api_call_id: api_call_id, raw: r.json()} + +route POST /v1/ # under endpoint_url; exempt from session auth and CSRF; the exchange's addresses only +function inbound(request, path): + verify_nhcx_jwt(request, settings.nhcx.signing_key) # when the key is configured; else logged at start, never silent + body = parse_json_or_null(request.body) + if path == "error": + env = {meta: {path: "v1/error", payloadType: "error"}, jwe_headers: {}, fhir: body} + elif body and body.type == "ProtocolResponse": + env = {meta: {path: "v1/" + path, payloadType: "protocol"}, jwe_headers: x_hcx_fields(body), fhir: body} + else: + try: header, plaintext = jose_decrypt_compact(body.payload, settings.nhcx.private_key) + except: archive.record(null, "undecryptable", "in", request.body); return 202, receipt({}, path, error = "DECRYPT_FAILED") + env = {meta: {path: "v1/" + path, payloadType: "fhir"}, jwe_headers: header, fhir: parse_json(plaintext)} + receive(env) # module 7.3: dedupe, archive, match, apply; fast, no sends + return 202, receipt(env.jwe_headers, path) # within 30 seconds + +function receipt(h, path, error = ""): + return {"timestamp": now_ist("dd/MM/yyyy HH:mm:ss:SSS"), + "api_call_id": h["x-hcx-api_call_id"], "correlation_id": h["x-hcx-correlation_id"], + "result": {"sender_code": h["x-hcx-sender_code"], "recipient_code": h["x-hcx-recipient_code"], + "entity_type": entity_type(path), "protocol_status": "request.queued"}, + "error": {"code": error, "message": ""}} + +function entity_type(path): # "v1/preauth/on_submit" -> "preauth"; "v1/on_status" -> "status" + parts = ("v1/" + path).split("/"); seg = parts[-2] if parts[-2] != "v1" else parts[-1] + return seg.removeprefix("on_") +``` + +## 4. Using an existing integration (`existing`) + +How stage 0 recognises one: `x-hcx-`, `JWEPayload`, `RSA-OAEP-256`, `A256GCM`, a JOSE library among the dependencies, `bearer_auth`, a sessions URL on the ABDM gateway, `participanthcxservice`, `fetch/certs`, `participant/get/policies`, routes ending in `on_submit`, `on_check` or `on_request`, a vendor's NHCX or HCX client library, a separate gateway service the app calls. + +What it must do, checked by running it offline with the network stubbed and a test key pair for the seal: + +| Contract item (section 2) | Look at | Common gap | +| --- | --- | --- | +| `send` emits the protected header of section 3.8 | What it seals or posts | No `x-hcx-ben-abha-id`; a request correlation id that is not its own `api_call_id`; UTC timestamps; `RSA-OAEP` | +| The recipient | Who it addresses | The `payerid` instead of the `processingid` | +| The three ids back to the caller | Its return value | Only a success flag; the ids stay inside it | +| Receiving: a `202` receipt within 30 seconds on every path, `/v1/error` included | Its callback handler | `200` or an empty body; no `/v1/error`; slow work before answering | +| Handing on the header and the bundle | What it gives the app | The bundle without the header; no ProtocolResponse path | +| Dedupe on `x-hcx-api_call_id` | Its store | None | +| A record of every message | Its logs | Bodies not kept | + +The build wraps it. 7.1's `send` calls the existing client and returns the three ids. The existing callback handler, after its receipt, calls 7.3's `receive` with the envelope of section 2. Each gap is closed in the existing code, in its style (stage 7, action `extend`). The existing transport is not rewritten, and no second one is added beside it. If it cannot be made to hand on the ids or the header, record `partial` and ask the user whether to extend it further or, with their agreement, build `own` in its place. + +## 5. nhcx-adapter, only when asked + +nhcx-adapter is NHA's optional single binary that does section 3 for you (`nhcx-package/docs/02-Getting Started/10-NHCX Adapter.md`, titled "Optional"). Use it only when the user has asked for it. Then: + +1. Get it, with the user's go-ahead, from https://github.com/nha-in/nhcx-adapter/releases (the latest). Each release carries one archive per platform, `nhcx-adapter___.tar.gz` (darwin, linux, windows, freebsd; amd64, arm64, 386), holding the binary, `config.sample.json`, `serve.sh`, `stop.sh`, `update.sh` and `README.md`. Put it in a folder of the user's, not in the skill. +2. Its contract is `references/api-knowledge.md`: configuration (section 2), routes (3), the outbound envelope and answer (4, 5), the delivery your HMIS receives (6), the ledger (7), the kit endpoints (8). +3. Onboarding is sections 3.1 to 3.5 again: credentials, a key, a participant record, a public address. The adapter can generate and register the key itself (`config init`, `cert generate`, its startup checks). +4. It does not queue or retry, does not build or validate bundles, and does not verify who sent an inbound message beyond decrypting it. Its `/internal/*` routes have no authentication: bind it to loopback. + +How it maps onto section 2: `send` POSTs `{jwe_headers, fhir}` to `/fhir/out/`; the receiving end is the HMIS route the adapter posts to (`api-knowledge.md` section 6); `policies` is `/internal/policies/search`; `thread` and `fetch_missed` are its ledger and `/internal/txn/*`. diff --git a/plugins/nhcx/skills/nhcx-reprocess/scripts/fetch-package.sh b/plugins/nhcx/skills/nhcx-reprocess/scripts/fetch-package.sh new file mode 100755 index 000000000..efbafa50b --- /dev/null +++ b/plugins/nhcx/skills/nhcx-reprocess/scripts/fetch-package.sh @@ -0,0 +1,122 @@ +#!/usr/bin/env bash +# Fetch the NHCX package and unpack it beside nhcx-build/ as nhcx-package/. +# +# scripts/fetch-package.sh [url-or-path] [target-dir] +# +# With no [url-or-path] (or "latest"), the zip is the build attached to the latest +# release of https://github.com/nha-in/nhcx-package (the nhcx-package-v.zip +# asset); its sha256 is checked against the digest GitHub records for the asset. +# Otherwise [url-or-path] is a link to the zip or a local path to it. +# [target-dir] defaults to the current directory. The zip unpacks to /nhcx-package/. +# +# Afterwards MANIFEST is checked: every file it lists must exist with the sha256 +# it records. Nothing is deleted; an existing nhcx-package/ is replaced. +set -euo pipefail + +repo="nha-in/nhcx-package" +src="${1:-latest}" +target="${2:-.}" +if [[ "$src" == "-h" || "$src" == "--help" ]]; then + echo "usage: $0 [latest|url-or-path-to-package.zip] [target-dir]" >&2 + exit 2 +fi + +download() { # + if command -v curl >/dev/null 2>&1; then + curl -fsSL -o "$2" "$1" + elif command -v wget >/dev/null 2>&1; then + wget -qO "$2" "$1" + else + echo "neither curl nor wget is available" >&2 + exit 1 + fi +} + +mkdir -p "$target" +tmp="$(mktemp -d)" +zip="$tmp/package.zip" +want_sha="" + +if [[ "$src" == "latest" ]]; then + # Ask the releases API for the latest release's zip asset and its digest. + api="https://api.github.com/repos/$repo/releases/latest" + if download "$api" "$tmp/release.json" 2>/dev/null; then + read -r tag url want_sha < <(python3 - "$tmp/release.json" <<'PY' +import json, sys +rel = json.load(open(sys.argv[1], encoding="utf-8")) +assets = [a for a in rel.get("assets", []) + if a["name"].startswith("nhcx-package") and a["name"].endswith(".zip")] +if not assets: + sys.exit(f"release {rel.get('tag_name')} has no nhcx-package*.zip asset") +a = assets[0] +digest = a.get("digest") or "" +print(rel["tag_name"], a["browser_download_url"], + digest.split(":", 1)[1] if digest.startswith("sha256:") else "") +PY + ) + else + # API unreachable or rate limited: read the tag off the releases/latest redirect + # and build the asset name from it. No digest to check in this case. + tag="$(curl -fsSIL -o /dev/null -w '%{url_effective}' "https://github.com/$repo/releases/latest")" + tag="${tag##*/}" + if [[ -z "$tag" || "$tag" == "latest" ]]; then + echo "could not resolve the latest release of $repo" >&2 + exit 1 + fi + url="https://github.com/$repo/releases/download/$tag/nhcx-package-v$tag.zip" + fi + echo "fetching $repo release $tag: $url" + download "$url" "$zip" + if [[ -n "$want_sha" ]]; then + got_sha="$(python3 -c 'import hashlib,sys; print(hashlib.sha256(open(sys.argv[1],"rb").read()).hexdigest())' "$zip")" + if [[ "$got_sha" != "$want_sha" ]]; then + echo "sha256 mismatch for $url: got $got_sha, release says $want_sha" >&2 + exit 1 + fi + fi +elif [[ -f "$src" ]]; then + cp "$src" "$zip" +else + download "$src" "$zip" +fi + +rm -rf "$target/nhcx-package" +unzip -q "$zip" -d "$target" +if [[ ! -f "$target/nhcx-package/MANIFEST" ]]; then + echo "unpacked, but $target/nhcx-package/MANIFEST is missing; is this the NHCX package?" >&2 + exit 1 +fi + +# Verify every file the MANIFEST lists. The MANIFEST is YAML; its file entries +# carry path, bytes and sha256 on separate lines. +python3 - "$target/nhcx-package" <<'PY' +import hashlib, os, re, sys +root = sys.argv[1] +text = open(os.path.join(root, "MANIFEST"), encoding="utf-8").read() +# Only the `files:` section lists a sha256 per path; the `contents:` summary above it +# lists directories. Parse entry by entry so a directory entry never borrows the next +# file's hash. +files_section = text.split("\nfiles:\n", 1)[1] if "\nfiles:\n" in text else "" +entries = [] +for chunk in re.split(r"\n\s*-\s+path:\s*", "\n" + files_section)[1:]: + path = chunk.split("\n", 1)[0].strip() + m = re.search(r"^\s+sha256:\s*([0-9a-f]{64})", chunk, re.M) + if path and m: + entries.append((path, m.group(1))) +bad = [] +for path, want in entries: + p = os.path.join(root, path) + if not os.path.isfile(p): + bad.append(f"missing {path}") + continue + got = hashlib.sha256(open(p, "rb").read()).hexdigest() + if got != want: + bad.append(f"sha256 mismatch {path}") +print(f"nhcx-package: {len(entries)} file(s) listed, {len(bad)} problem(s)") +for b in bad[:20]: + print(" " + b) +sys.exit(1 if bad else 0) +PY + +rm -rf "$tmp" +echo "ready: $target/nhcx-package (see references/material.md for the path map)" diff --git a/plugins/nhcx/skills/nhcx-reprocess/stages/0-capability-check.md b/plugins/nhcx/skills/nhcx-reprocess/stages/0-capability-check.md new file mode 100644 index 000000000..8186c3288 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-reprocess/stages/0-capability-check.md @@ -0,0 +1,92 @@ +# Stage 0: capability check + +Purpose: before anything is planned, find out what the app already does. For this skill's own capabilities, for the foundation it stands on, and for what it needs from the use cases before it, write one verdict each with the evidence that decides it. The verdicts decide what the later stages reuse, extend, build or wait for. Nothing is built twice, and nothing is reused on faith. + +## Inputs + +- This skill's `SKILL.md`, section "Capability check": its own capabilities (what to look for, what makes each present), and its prerequisites with the check that proves each present. The skills that own the prerequisites do not need to be installed; their checks are in this skill's `SKILL.md`. +- `core/FOUNDATION.md`: the six foundation capabilities. +- `nhcx-build/capabilities.json` and `nhcx-build/0-capability.md`, if another NHCX skill already ran on this app. +- The target: the codebase (integrate), or the folder where the standalone app lives or will live. +- The pins and payer fixtures each check names, in `nhcx-package/`. If it is not beside `nhcx-build/`, fetch it now (`scripts/fetch-package.sh`); `references/material.md` names each pin's file. + +## The verdicts + +| Verdict | Means | What happens next | +| --- | --- | --- | +| `present` | Located, and its check was run and observed passing | Reuse. Stage 7 builds nothing for it. Stage 8 still runs its Validate rows; stage 9 still tests it. | +| `partial` | Located, but its check fails; or it covers some legs or branches and not others; or it was located and could not be run | Extend. Stage 7 builds the difference, in the existing code. | +| `absent` | Searched for as the skill says and not found | Build. Stage 7 builds it. | +| `unknown` | Could not be searched: no code is reachable | Planned as absent; stage 0 runs again when the code is reachable. | +| `not applicable` | The mode or the scope excludes it: 7.13 in integrate mode, a leg the user marked out | Nothing. | + +For a prerequisite, a verdict of `absent` or `unknown` is a stop: see step 5. + +Present is a claim about behaviour. Code that looks right is `partial` until its check has run. + +## Do + +### 1. Find the target + +Integrate: the codebase root, its language and framework, enough to search and to run code offline (stage 3 does the full survey). Standalone: the app folder. If it is empty and no other NHCX skill has built anything there, every capability is `absent` and this stage is short. Write which in one line. + +If `nhcx-build/capabilities.json` exists, read it. A verdict another skill recorded is a lead, not a result. If the code changed since its date (the version control log says), run its check again; otherwise carry it forward with its evidence and date. + +### 2. Locate + +For each capability in the three lists (own, foundation, prerequisites), search for the markers: NHCX paths such as `v1/preauth/submit`, resource names such as `CoverageEligibilityRequest`, workflow ids as strings, table and column names. `SKILL.md` lists them for its own capabilities; for a prerequisite, the marker is what its check names. Record every hit as `path:line`. A hit in a comment, a dead branch or a test fixture is not the capability; say so. + +Look also for the same job done another way: a pre-auth sent to a TPA portal, an eligibility check recorded from a phone call, a payment keyed in from a bank statement. That is a host capability that stages 3 and 4 may link to. The NHCX capability is still `absent`. + +### 3. Check + +For every capability located, run the check `SKILL.md` names, offline: + +- a builder: feed it the pin's own data and compare its output with the pin (canonical JSON, `created` excluded, and only the exclusions the module names); +- a reader: feed it the payer fixture and read the state it settles; +- a sender: call it with the 7.1 stub, or a stub of the app's own client, and read what it posted; +- the door: call the handler with an envelope; +- a screen: render it on a seeded state and read the text. + +Use the app's own test runner where it can host the check, else a one-off script under `nhcx-build/0-capability/`. Nothing leaves the machine. + +Where the existing code cannot be called without the network or a running service, record `partial` with `not run: `. Never `present`. + +### 4. Decide + +One verdict per capability, with where (the paths), how (the command), observed (the output, or the first lines of the diff), and the action: reuse, extend, build or wait. For `partial`, name the difference: which pin fails and at which element, which branch is missing (a PMJAY query answer on 19 but none on 131), which column is missing. + +### 5. When a prerequisite is missing + +A prerequisite is a capability another skill owns that this skill's legs cannot run without. `SKILL.md` lists them with their checks. If one is `absent` or `unknown`: + +1. Stop and tell the user which capability is missing, which skill owns it, and what this skill cannot do without it. +2. Offer the two ways on: run the owning skill first (installing it if it is not beside this one; it is the default); or continue with this skill's offline work only (builders, readers and tests against seeded rows), with the live legs marked `later` in stage 1 and the dependency written in `NOTES.md`. +3. Never build another skill's capability inside this one. It would be built without that skill's checks. + +A `partial` prerequisite does not stop the skill. Its gap goes into stage 2's risk table. + +## Write + +- `nhcx-build/capabilities.json` from `templates/capabilities.json`: one entry per capability, keyed by id, with `skill`, `module`, `verdict`, `located`, `how`, `observed`, `action`, `checked_by` and `date`. Update the entries this skill checked; leave the others. +- `nhcx-build/0-capability.md` from `templates/0-capability.md`: a section headed with this skill's name, holding the three tables (own, foundation, prerequisites) and the summary line. +- The scratch checks under `nhcx-build/0-capability/`, kept: stage 8 runs them again. +- This skill's block in `nhcx-build/STATE.md` (create the file from `templates/STATE.md` if it does not exist), with stage 0's row closed and its evidence. + +## Gate + +- [ ] Every capability in this skill's list, every foundation capability, and every prerequisite has a verdict. +- [ ] Every `present` names the command run and its observed output. None rests on reading alone. +- [ ] Every `partial` names the difference. +- [ ] Every `absent` names what was searched for, so a reader can repeat the search. +- [ ] A missing prerequisite was put to the user, and the answer is recorded. +- [ ] `capabilities.json` parses and holds this skill's entries. + +## Common mistakes + +- Marking a capability present because its endpoint name appears in the code. The pin decides. +- Rebuilding a working NHCX transport or callback door because this skill did not write it. An app that already seals, sends and receives NHCX messages keeps its own; the verdict says reuse. +- Proposing nhcx-adapter for an app that lacks a transport. The transport is then `own`; the adapter is used only when the user asks for it. +- Treating a legacy TPA workflow as the NHCX capability. It is a host capability; the NHCX one is absent. +- Checking against the live sandbox. Stage 0 is offline; the live rungs are stage 10's, and the user's. +- Carrying another skill's verdict forward after the code changed. diff --git a/plugins/nhcx/skills/nhcx-reprocess/stages/1-idea.md b/plugins/nhcx/skills/nhcx-reprocess/stages/1-idea.md new file mode 100644 index 000000000..b9f391316 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-reprocess/stages/1-idea.md @@ -0,0 +1,80 @@ +# Stage 1: the idea + +Purpose: agree with the user what is being built before anything is designed. One page, shared by the seven skills. Wrong answers here cost the most later, so this is the one stage that always ends with a question to the user when it is first written. + +The first skill to reach this stage writes `1-idea.md` whole: the mode, the payers, the constraints, and a scope row for every step of the flow, each naming the skill that owns it. A later skill reads the page, confirms that the mode and the payers still hold, and marks its own rows. It asks the user only when it would change a row or an answer. + +## Inputs + +- This skill's section of `nhcx-build/0-capability.md`: what the app already does. A leg found present is still in scope: it is validated and tested, not rebuilt. Say so in the scope table's reason column. A prerequisite the user chose to wait for makes this skill's live legs `later`. +- `flow/FLOW.md`, whole. The build walks this path; the scope table below marks its steps in, later or out, and nothing else. `flow/flow.json` names the skills of each step in `skills`. +- What the user said. If they pasted a brief, quote it in the artefact. +- `references/flow-knowledge.md` sections 1, 3 and 6: the legs, the two payer kinds, the use-case catalogue. Read them so the scope table below uses the catalogue's codes. + +## Do + +Decide five things, in this order. A later skill confirms the first two and the fourth, and does the third for its own rows. + +### 1. Mode + +| Signal | Mode | +| --- | --- | +| A codebase, a database, a running system is named | `integrate` | +| "from scratch", "standalone", "a claims app", no existing system | `standalone` | +| Unclear | Ask. Do not guess; the two modes diverge at stage 3. | + +### 2. Payers + +Which participant codes the software will talk to, and which kind each is: + +| Payer | Participant code | Kind | Query mode | +| --- | --- | --- | --- | +| PMJAY (SHA Himachal Pradesh, sandbox) | `1518@hcx` | scheme | `resubmit` | +| A generic sandbox payer you can drive, for testing | from the participant registry | generic | `communication` | +| Any other insurer | from the registry | generic unless told otherwise | `communication` | + +Both kinds are in scope by default. A build that targets only one still keeps the payer adapter switch (module 7.11), because the second is one config line away. + +### 3. Scope of legs + +Copy the steps of `flow/flow.json` (F1 to F13 with their branches) into a scope table, with the skill that owns each (`skills`), and mark each `in`, `later` or `out`, with a reason; add the catalogue code from `flow-knowledge.md` section 6 beside each. The default scope for a first release is every hospital-side leg in `flow-knowledge.md` section 1. Cutting a leg is the user's call; propose it, do not decide it. Legs that are commonly `later`: predetermination, status enquiry (PMJAY refuses it), release of a shortfall (out of reach on the sandbox). + +A later skill changes only its own rows. + +### 4. Constraints + +Ask the codebase, not the user, where you can: + +- Language and framework (integrate: whatever the HMIS uses; standalone: Python standard library unless the user names another, because the module files' pseudo code maps onto it directly). +- The transport (`references/transport-knowledge.md` section 1): `existing` when stage 0 found the app already speaks NHCX; else `own`, built into the app from NHA's protocol; `adapter` (nhcx-adapter) only when the user has asked for it, their words quoted. Never propose the adapter. +- The inbound path. For `own`: a public HTTPS domain in India, registered as the participant's `endpoint_url` and reachable from the exchange. For `existing`: the app's own callback. For `adapter`: whether the app can receive the adapter's POST; if not, polling the adapter's ledger is the only inbound path. Write it down now. +- What onboarding needs from the user: the ABDM sandbox client id and secret (Milestone 1), the facility's HFR id, and a participant record carrying the build's certificate and callback address. +- Document storage: blob, filesystem, object store. +- Whether a background worker exists. Without one, polls happen on the request path. +- Anything the user forbids: new dependencies, schema changes to existing tables, a build step. + +### 5. Definition of done + +Write the compliance points from `core/LADDER.md` as they apply to this build, and the highest rung of the test pyramid the user wants climbed before handover (`references/testing-knowledge.md` section 1). The offline rung is never optional. + +## Write + +`nhcx-build/1-idea.md` from `templates/1-idea.md`. Keep the headings. Under two pages. A later skill edits only its scope rows and adds a line under "Agreed". + +## Gate + +- [ ] Mode is `integrate` or `standalone`, and the reason is one sentence. +- [ ] Every payer has a participant code and a query mode. +- [ ] The scope table has every step of the flow and every catalogue row, each with its skill, marked in, later or out. +- [ ] Constraints name the language, the transport (existing, own, or nhcx-adapter because the user asked for it), the inbound path and the document store. +- [ ] Definition of done names the target rung. +- [ ] The user has read the page and agreed, or a written brief stands in for the user. A later skill that changed nothing records that it confirmed the page. + +Record the gate in the Shared block of `nhcx-build/STATE.md`. + +## Common mistakes + +- Choosing `standalone` because the HMIS is unfamiliar. Unfamiliar is what stage 3 is for. +- Leaving PMJAY out because the user only named an insurer. PMJAY is the payer that refuses most; a build that handles it handles the rest. +- Dropping a leg from scope because stage 0 found it present. It stays in: present capabilities are validated and tested. +- Writing design here. Tables, screens and modules belong to stages 4 to 6. diff --git a/plugins/nhcx/skills/nhcx-reprocess/stages/10-run-tests.md b/plugins/nhcx/skills/nhcx-reprocess/stages/10-run-tests.md new file mode 100644 index 000000000..e7e5d8d32 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-reprocess/stages/10-run-tests.md @@ -0,0 +1,59 @@ +# Stage 10: run the tests + +Purpose: climb the pyramid as far as the user asked in stage 1, for this skill's rows, and record every rung honestly. Rung 1 you run yourself. Rungs 2 to 4 need services or live payers, and only the user starts those. + +## Inputs + +- `nhcx-build/1-idea.md` (the target rung), `nhcx-build/9-tests.md` (the run command, this skill's rows) +- This skill's `SKILL.md`: its stage 10 row (which matrix rows each rung walks) +- `references/testing-knowledge.md` sections 1, 5 and 6 +- `references/errors-and-debugging.md` sections 4 to 8 (reading the ledger, sandbox pace) + +## The rungs + +| Rung | What | Who starts it | Record | +| --- | --- | --- | --- | +| 1 Offline | The suite from stage 9, against the pins and fixtures, no network | you | the full output | +| 2 Validator | The HL7 FHIR validator on every bundle this skill builds, run as `references/fhir-knowledge.md` section 11 says | you, if Java and the validator are installed | one table: bundle, errors, warnings | +| 3 Generic payer | The transport on the sandbox (the app's own, or nhcx-adapter when the user chose it) and a generic sandbox payer whose desk you can drive; this skill's legs, every query as a CommunicationRequest, payment from its desk | the user | the ledger thread per leg, the state address after each | +| 4 PMJAY sandbox | SHA Himachal Pradesh, `1518@hcx`; sweep live pre-auths first; one request at a time per case, 30 seconds between; decisions on the payer service desk | the user | the ledger, the archive folder, every refusal verbatim | + +## Do + +### Rung 1 + +Run the command from `nhcx-build/9-tests.md`: the whole suite, not only this skill's tests, because a skill that extended a shared module can break another skill's test. Save the whole output to `nhcx-build/10-test-run/-rung1.log`. In `integrate` mode also run the HMIS's own suite and save it. A failure goes back to stage 7 (the module) or stage 9 (the test); record the fix and the re-run. Do not edit a test to make it pass unless the test was wrong, and say so. + +### Rung 2 + +If the validator runs, validate every bundle this skill's tests built (write them to a folder from the tests). Warnings are advice; the sandbox accepted every pin as it stands. Errors are findings. If it does not run, write `not run` and why. + +### Rungs 3 and 4 + +Prepare, do not run: + +1. The commands the user runs: the HMIS with its public callback (`own` or `existing`), nhcx-adapter with its filled config only when the user chose it, and the payer (rung 3). For `own`, the sandbox's dummy payer proves the loop first (`references/transport-knowledge.md` section 3.11). Write them into this skill's section of `nhcx-build/10-test-run.md` under "Runbook". +2. The driver: a script or a spec that walks this skill's matrix rows through the JSON state address, waiting on the case's own state and never on a fixed sleep, logging every verdict the payer gives. The earlier legs a row needs (an eligible case, an approved pre-auth) are reached by the earlier skills' drivers or through the app's own screens. +3. The sweep for rung 4: cancel or let expire every live pre-auth for the beneficiaries the tests use (PAYR-1238 otherwise). +4. Then stop and ask the user to start the services. When they have, run the driver, save its log, and package the run's bundles by correlation id from the per-case archive (or the adapter's ledger, when it is the transport). + +While a live run is going: one request at a time per case; wait about 30 seconds after a decision; on "Active instance found" wait and resend up to three times; on a refusal read the ledger thread before touching the code. + +## Write + +This skill's section of `nhcx-build/10-test-run.md` from `templates/10-test-run.md`: per rung, `passed`, `failed`, `not run` with the reason, the log path, and the findings (each a line: what, where, the PAYR or rule, the fix or the open question). The raw logs under `nhcx-build/10-test-run/`, named for the skill. + +## Gate + +- [ ] This skill's rung 1 log exists and shows every test in the suite passing, or the failures are listed as findings with a stage to return to. +- [ ] In `integrate` mode the HMIS's own suite log exists and passes. +- [ ] Rung 2 has a table or `not run` with a reason. +- [ ] Rungs 3 and 4 have a runbook and a driver for this skill's rows, and either a log or `not run: user has not started the services`. +- [ ] No rung is marked passed without a log. + +## Common mistakes + +- Starting a service yourself: the app's public callback, or nhcx-adapter. Only the user does. +- Running only this skill's tests at rung 1. A shared module may have broken another skill's. +- Sleeping a fixed time in a driver. Wait on the state address. +- Reading a refusal as a code bug before reading the ledger thread. Half of them are scheme rules (flow-knowledge section 5). diff --git a/plugins/nhcx/skills/nhcx-reprocess/stages/11-build-report.md b/plugins/nhcx/skills/nhcx-reprocess/stages/11-build-report.md new file mode 100644 index 000000000..4ea8a0806 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-reprocess/stages/11-build-report.md @@ -0,0 +1,64 @@ +# Stage 11: the report + +Purpose: one document a stranger can pick up to know what was built, what was found already there, what was proven, what was not, and what to do next. Written from the artefacts in `nhcx-build/`, not from memory. Its value is its honesty. + +`11-report.md` has a summary across the skills at the top and one section per skill below it. This skill writes its section and updates its row of the summary. + +## Inputs + +- Everything in `nhcx-build/`, `STATE.md` first, `NOTES.md` last +- This skill's sections of `0-capability.md`, `8-validation.md` and `10-test-run.md` + +## Do + +### 1. Read STATE.md + +Every gate row in this skill's block, and the foundation rows it built, with their evidence. A gate without evidence is reported as open, whatever you remember. + +### 2. Write this skill's section + +From `templates/11-report.md`, in this order: + +| Section | Holds | +| --- | --- | +| Capabilities | Every capability in this skill's section of `0-capability.md`: its verdict at stage 0, what was done (reused, extended, built), and its evidence after stage 8 | +| What was built | Each module part this skill built or extended, with its files and its record (`7-modules/7.N.md`) | +| Compliance | The seven points from `core/LADDER.md` for this skill's legs, each with the evidence path (the pin comparisons, the door tests, the screen tests, the rung logs) | +| The test pyramid | Per rung: passed, failed, not run, the log | +| Findings | Every failure from stages 8 and 10 with its resolution or its open state | +| Gaps | This skill's entries in `NOTES.md` folded in: what the skills did not say, what the docs did not say, what the sandbox did that no document states | +| Exceptions | Every accepted exception from stage 8 and the user's agreement | +| Runbook | How to start it, how to run the suite, how to run rungs 3 and 4, what to sweep first, where the archive and the ledger are | +| Next | The `later` legs from stage 1, the open gates, the rungs not climbed, and the skill to run next in the order `core/LADDER.md` gives | + +Then update this skill's row in the summary table: stages closed, rung reached, what it reused, extended and built, what is open. Mode, payers and "today a user can" are for the whole build; bring them up to date. + +### 3. Check the report against the rules + +- Every claim of "passes" has a log or a record path beside it. +- Every rung not run says so. +- Every capability reported as reused has its stage 8 evidence, not only stage 0's. +- No em dashes, short sentences, tables for facts. +- A stranger with this report and the target project could resume at the first open gate. + +## Write + +This skill's section of `nhcx-build/11-report.md`, and its summary row. Update `STATE.md` with the final gate. + +## Gate + +- [ ] Every section in the template is present in this skill's section. +- [ ] Every capability in this skill's section of `0-capability.md` appears under Capabilities. +- [ ] Every module part this skill touched appears in "What was built" or, if reused, under Capabilities. +- [ ] Every compliance point names evidence. +- [ ] The pyramid table matches this skill's section of `10-test-run.md`. +- [ ] This skill's entries in `NOTES.md` are folded into "Gaps" in full. +- [ ] The runbook has the start commands, the test command and the sweep. +- [ ] The summary table has this skill's row. + +## Common mistakes + +- Reporting the rung the user asked for as reached because the offline rung passed. +- Reporting a reused capability as working on the strength of stage 0 alone. +- Dropping a finding that was fixed. Fixed findings are the most useful part of the report for the next build. +- Writing the report before stage 10's logs exist. diff --git a/plugins/nhcx/skills/nhcx-reprocess/stages/2-planning.md b/plugins/nhcx/skills/nhcx-reprocess/stages/2-planning.md new file mode 100644 index 000000000..06c405cdc --- /dev/null +++ b/plugins/nhcx/skills/nhcx-reprocess/stages/2-planning.md @@ -0,0 +1,67 @@ +# Stage 2: planning + +Purpose: turn the idea and the capability check into this skill's schedule of gates, and add its block to the ledger every later stage writes to. This is bookkeeping, and it is short. + +## Inputs + +- `nhcx-build/1-idea.md` +- This skill's section of `nhcx-build/0-capability.md`: the verdict of every capability it owns or stands on +- `core/LADDER.md`, "The ladder"; this skill's `SKILL.md`, "The ladder, for this skill" +- `references/testing-knowledge.md` section 1 (the pyramid) and section 3 (the matrix), so the acceptance tests below are the matrix's rows and not invented ones + +## Do + +### 1. Size each stage + +For every stage 3 to 11, write one row for this skill: what it produces for this build, how big it is (small, medium, large), and what proves it done. "What proves it done" is the stage's gate, restated for this skill. + +For stage 7, list the modules this skill's `SKILL.md` names and the foundation modules, each with its verdict from stage 0 turned into an action: + +| Verdict | Action in stage 7 | +| --- | --- | +| `present` | reuse: nothing built; validated in stage 8, tested in stage 9 | +| `partial` | extend: the difference, in the existing code | +| `absent`, `unknown` | build | +| `not applicable` | nothing | + +Module 7.13 depends on the mode: + +| Module | integrate | standalone | +| --- | --- | --- | +| 7.1 to 7.12 | yes | yes | +| 7.13 standalone shell | no | yes | + +Module 7.12 (screens) is smaller in `integrate` mode when the HMIS already has patients, admissions and documents; the plan says which existing screens gain a panel and which are new. + +### 2. Order and dependencies + +The ladder is sequential by stage. Inside stage 7, foundation modules come first, then this skill's modules in the order of `stages/7-write-code/README.md`; the plan may not reorder them, because each module's validation assumes the ones before it exist. + +### 3. Risks + +Copy into a risk table the rules from `references/flow-knowledge.md` section 5 that touch this skill's legs; its `SKILL.md` names them in its stage 2 row. Each rule is a way the build fails live even when the offline tests pass. When this skill builds or extends a foundation module, add the foundation's rules too: acknowledge or lose the thread; one message is taken once (dedupe on `x-hcx-api_call_id`). Add every `partial` prerequisite from stage 0, and the build's own risks: a missing HPIN on the practitioner table, no inbound route to the HMIS, a plan master too large for the database column, a callback behind auth middleware. + +### 4. What the user must do + +List every point where the ladder stops for the user: agreeing stage 1, running an owning skill first when a prerequisite is missing, supplying participant credentials (the ABDM client id and secret), registering the participant's certificate and callback address, starting the services for stage 10 rungs 3 and 4 (the app's public callback, or nhcx-adapter when the user chose it), sweeping live pre-auths before a PMJAY run. + +## Write + +- This skill's section of `nhcx-build/2-planning.md`, from `templates/2-planning.md`. +- This skill's block in `nhcx-build/STATE.md` (created at stage 0 from `templates/STATE.md`), with a row per stage and a row per module part, each module row carrying its action. +- `nhcx-build/NOTES.md`, empty but for its heading, if it does not exist. + +## Gate + +- [ ] Every stage 3 to 11 has a row with a size and a proof, for this skill. +- [ ] Every module this skill touches, and every foundation module, has its verdict and its action; 7.13 is marked by mode. +- [ ] The risk table holds every rule this skill's `SKILL.md` names for stage 2, and the foundation's rules when this skill builds or extends a foundation module. +- [ ] The user-action list names the credentials and the service starts. +- [ ] STATE.md has this skill's block with a row per stage and per module part. + +## Common mistakes + +- Estimating in days. Estimate in size; the user turns size into time. +- Planning to skip stage 8 or 9 "for the first pass". They are what makes the report true. +- Planning to rebuild a capability stage 0 found present. +- Reordering modules so screens come first. Screens derive from messages; without readers there is nothing to derive from. diff --git a/plugins/nhcx/skills/nhcx-reprocess/stages/3-discovery.md b/plugins/nhcx/skills/nhcx-reprocess/stages/3-discovery.md new file mode 100644 index 000000000..9feb26eca --- /dev/null +++ b/plugins/nhcx/skills/nhcx-reprocess/stages/3-discovery.md @@ -0,0 +1,97 @@ +# Stage 3: discovery + +Purpose: find the surface you will build on. In `integrate` mode that is the HMIS; in `standalone` mode it is the runtime, the storage and the deployment target the user has chosen. Every answer names the file, table or endpoint that proves it. An answer without proof is a gap. + +`3-discovery.md` is shared by the seven skills: one row per concern, each naming the skill that answered it. This skill answers the rows its `SKILL.md` lists under "Host facts", and the framework and runtime rows if no skill has. A row an earlier skill answered with proof is reused; check it again only if the code changed since. + +Stage 0 looked for NHCX capabilities. This stage looks at the host: where patients, admissions, doctors, documents and bills live. + +## Inputs + +- `nhcx-build/1-idea.md`, `nhcx-build/2-planning.md`, this skill's section of `nhcx-build/0-capability.md` +- This skill's `SKILL.md`, "Host facts" +- The target codebase (integrate) or the chosen runtime (standalone) +- `stages/7-write-code/7.2-storage.md` (the claim tables) and `stages/7-write-code/7.13-standalone-shell.md` (patient, encounter, practitioner, document), as the shape to compare against + +## Do + +Answer in writing every question below that this skill's host facts name, plus the framework and runtime questions when they are not yet answered. Reading only; change nothing. + +### Framework and runtime + +| Question | Why it matters | +| --- | --- | +| Language, web framework, ORM, database engine, migration tool | Where a new table goes and how it is created | +| How configuration is read (env, file, database) | Where the transport's settings live: the participant code, and the client id and secret and the private key (`own`), or the adapter URL and key (`adapter`) | +| How the app exposes an HTTP endpoint an outside process can POST to; which auth middleware must be exempted | The callback door, module 7.3 | +| Background worker or scheduler, or none | Whether polls run on the request path or in a worker | +| How the app serves a page and what the screen conventions are | Module 7.12 must match them | +| How tests are run and where they live | Stage 9 must match them | + +### Patients + +| Question | Why it matters | +| --- | --- | +| The patient table, its primary key, the unique identifier (MRN) | `claim.patient_id` | +| Where name, gender, date of birth, phone, ABHA number live | The Patient resource in every bundle | +| Where a scheme member id (PMJAY id) and a policy code can be stored, per patient or per visit | The Coverage resource; the policy search result | + +### Admissions and encounters + +| Question | Why it matters | +| --- | --- | +| The inpatient encounter table: admission time, discharge time, ward or bed, admitting doctor, status | `billablePeriod`, `ONS/ADDD`, the care team | +| How discharge is recorded, and whether it can carry a mode (normal, LAMA, DAMA, death) and a stage (before, during, after surgery) | `DIS` and `DSDE` on the claim; the LM100 collapse | +| Diagnoses: SNOMED, ICD-10 or free text | The payer needs ICD-10 with a display | +| Procedures or surgeries, and whether a surgery time is recorded | `ONS/PSP` | + +### Billing + +| Question | Why it matters | +| --- | --- | +| Billing lines: code, quantity, unit price, net; which charge master | Lines are quoted from the payer's plan, not the HMIS master, but the two must be reconcilable | +| Whether a line can be tagged with a payer package code and a category | `claim_line` | +| Invoices and receipts: where a settlement amount and a UTR go | Payment notices, module 7.10 | + +### Documents + +| Question | Why it matters | +| --- | --- | +| Where PDFs and images live (blob column, filesystem, object store) | `valueAttachment` needs the bytes and the content type | +| Whether a file can be tagged with a payer document code and a stage (pre-auth or claim) | The plan's requirement codes; never `ODN` for a file that was asked for by name | +| Accepted content types | The scheme takes pdf, jpg, jpeg, png only (PAYR-1008) | + +### Doctors + +| Question | Why it matters | +| --- | --- | +| The practitioner table; an HPR id (HPIN); a licence number; a qualification string | PMJAY refuses a pre-auth without an HPIN typed identifier (PAYR-1083) | + +### Facility + +| Question | Why it matters | +| --- | --- | +| The facility's HFR id, name, phone; its NHCX participant code | The provider Organization; the sender code | + +### Standalone mode + +The same questions, answered for the runtime the user chose. Where the answer is "nothing exists yet", write what module 7.13 will create: `patient`, `encounter`, `practitioner`, `document`, `settings`. A standalone app still has to hold every fact the questions ask for; it simply has to capture it itself. + +## Write + +`nhcx-build/3-discovery.md` from `templates/3-discovery.md`: one table, concern by concern, columns `Concern | Where it lives (proof) | Gap | Answered by`. A gap is what stage 4 fills. Add rows; do not rewrite another skill's rows. + +## Gate + +- [ ] Every host fact this skill's `SKILL.md` names has a row, and so does every framework and runtime question. +- [ ] Every row that is not a gap names a file path, a table, or an endpoint. +- [ ] When this skill builds or extends the callback door, the callback route is answered: which URL, which middleware to exempt, or "no inbound route, poll only". +- [ ] When this skill's bundles carry a Practitioner, the HPIN question is answered; if the practitioner table has no HPR id, the gap says so. +- [ ] When this skill attaches documents, the document store is answered with content-type handling. + +## Common mistakes + +- Answering from the framework's documentation instead of the codebase. The proof column is the codebase. +- Skipping the discharge-mode question. A death claim without `DTM` is refused (PAYR-1096); the HMIS must be able to say the patient died and when. +- Treating "no background worker" as a blocker. Without one, polls run on the request path; it is a design input, not a stop. +- Answering every concern for every skill. Answer the ones this skill needs; the next skill adds its own. diff --git a/plugins/nhcx/skills/nhcx-reprocess/stages/4-flow-and-data-mapping.md b/plugins/nhcx/skills/nhcx-reprocess/stages/4-flow-and-data-mapping.md new file mode 100644 index 000000000..bf51c7991 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-reprocess/stages/4-flow-and-data-mapping.md @@ -0,0 +1,92 @@ +# Stage 4: flow and data mapping + +Purpose: decide where every fact the exchange needs comes from and where every fact the exchange returns goes, leg by leg. This is the design stage with the most rows; get it right and stages 6 and 7 are transcription. + +Two parts of this stage belong to the episode, not to one skill: the flow table (section 1) and the home of every table (section 2), with the matching order (section 4). The first skill to run this stage writes them whole, so every later skill builds on one design; a later skill checks them and adds only what its gaps need. The field mapping (section 3) is this skill's own bundles only. + +## Inputs + +- `nhcx-build/1-idea.md` (scope), `nhcx-build/3-discovery.md` (the surface and its gaps), this skill's section of `nhcx-build/0-capability.md` (what exists already) +- This skill's `SKILL.md`: its steps, legs, bundles and tables +- `flow/FLOW.md` and `flow/flow.json`: the steps this build implements. They are copied, not redesigned. +- `references/flow-knowledge.md` sections 1, 2, 4 and 5 +- `references/transport-knowledge.md` section 2 (what a send returns, what arrives at the door) +- `references/fhir-knowledge.md` sections 3 to 10 (what each bundle needs); `fhir/FHIR.md` for the exact elements, as the builders' data dictionaries name them +- `stages/7-write-code/7.2-storage.md`: the claim tables and the columns each must hold + +## Do + +### 1. The flow, for this build + +The first skill copies every step of `flow/flow.json` into the flow table, in order, with its id and its skills, and adds two columns for this build: the HMIS event it hangs off (admission, discharge, a desk action) and the mark from stage 1 (`in`, `later`, `out`). The steps, their order, their tabs, their guards and their action labels are the flow's; this build adds where each fact comes from, nothing else. Then note the payer branches as the flow has them (F9b, F11, F12: `19`/`131`/`161` resubmits against a Communication reply; `17` against an echoed id). The stage and sub-stage vocabulary is copied as is; do not rename it. + +Write the step ids into `mapping.json` under `flow.steps` and the eight tabs, in order and with their labels, under `flow.tabs`. + +A later skill checks its own steps' rows and fills their HMIS event where the first skill left it open. + +### 2. The episode tables + +The first skill gives every table below a home, not only its own. The home is one decision for the episode (sidecar tables, or columns on the HMIS's tables), and a skill that chose differently later would split the design. It writes the columns each table must hold, and the legs' columns under `legs`. Later skills read the homes and add only the columns their gaps need. + +For each table below, decide one of three homes and write it down: + +| Home | When | +| --- | --- | +| A new sidecar table keyed on the HMIS's own ids | Default. Keeps the HMIS schema untouched and the integration removable. | +| Columns added to an existing HMIS table | Only for a scalar the HMIS already half-holds (a member id on the visit, an HPIN on the doctor) | +| An existing table used as is (`existing`) | Only when it already holds every column named below. This is the home of a capability stage 0 found present: record its real name and its columns, and a gap for each column it lacks | + +| Table | Why it exists | Must hold | +| --- | --- | --- | +| `claim` | The episode: beneficiary, policy, payer, eligibility verdict, link to the admission, pre-auth draft, stage and sub-stage | claim number, member id, policy code, payer participant code, patient and encounter keys, `txn_id`, `correlation_id`, `stage`, `sub_stage` | +| `claim_plan`, `claim_plan_benefit`, `claim_plan_form` | The payer's package master, flattened; one per facility and policy, copied onto later episodes | packages with rate, kind, conditions, extras (tiers, implants), document requirements; questionnaires by url | +| `claim_auth`, `claim_auth_item`, `claim_auth_requirement` | The auth-requirements ruling on the quoted set | per line: authorised, excluded; per requirement: kind (document or form), code, url, stage | +| `claim_line` | What is quoted: procedures, implants, ward tiers with a parent procedure | code, kind, quantity, unit price, amount, parent code | +| `claim_form_answer` | Answers to the plan's questionnaires | url, linkId, answer, stage | +| `claim_preauth` | The pre-auth leg, one row rewritten each round (12, 19, 13, 131) | status, `txn_id`, `correlation_id`, `thread_correlation_id`, `api_call_id`, `preauth_ref`, `submission_kind`, `workflow_id`, request and response json, cancel fields | +| `claim_submission` | The claim leg plus the discharge | discharge mode, stage, dates; the same exchange columns as the pre-auth | +| `claim_query` | Every CommunicationRequest or Communication from the payer, classified | `correlation_id` (unique), request id, kind, reason code, status, reply fields | +| `claim_payment`, `claim_payment_detail` | Payment notices, matched by claim number, deduped by correlation id | amount, UTR, payment status, ack fields | +| `claim_enquiry` | Status, reprocess and release Tasks, one row per ask | kind, `correlation_id`, answer | +| `claim_predetermination` | A quote, one row per ask | as a pre-auth, without state effects | +| `claim_document` | Attachments with the payer's code, category and stage | bytes or a pointer, content type, code, stage | +| `claim_diagnosis`, `claim_care_team`, `claim_item` | ICD-10 codes, doctors, non-package items | as named | + +The rule that never bends: every leg row holds `txn_id`, `correlation_id` and `api_call_id` from the transport's answer, and `thread_correlation_id` separately, because a send refused at the door must not lose the thread the payer last answered on. + +### 3. Field mapping, per bundle + +For each bundle this skill sends (its `SKILL.md` lists them; `fhir-knowledge.md` sections 3, 4, 5, 7, 9, 10), one table: `FHIR element | Source (table.column or constant or payer answer) | Transform | Gap`. Do not fill values; name sources. The elements that are always mapped from a payer answer and never from the HMIS: package codes and rates (the plan), document codes and questionnaire urls (the plan or the ruling), `preAuthRef` (the ClaimResponse), the payer's own case number. + +For each bundle this skill reads (sections 6, 8, 9, 10 and the coverage answer in section 3), one table: `FHIR element | Destination | Rule`. The status rule for a ClaimResponse is `verdict_status`, copied verbatim; never read `outcome` alone. + +Where stage 0 found a builder or reader present, map what it does today, and name each element where it differs from the pin as a gap. + +### 4. Inbound matching + +Written once, by the first skill. Write the matching order as a numbered list: `x-hcx-correlation_id` against every leg table; then the claim number inside the bundle; then unmatched, archived, 2xx returned. Write the dedupe key: `x-hcx-api_call_id`. Write the archive path: `//NNN--.json` plus `transactions.txt`. A later skill adds its leg tables to the correlation order. + +## Write + +- `nhcx-build/4-flow-data-mapping.md` from `templates/4-flow-data-mapping.md`. The first skill writes the flow table, the table homes and the matching order at the top; each skill writes a section headed with its name holding its field mappings. +- `nhcx-build/mapping.json` in the shape of `templates/mapping.json`. The first skill writes `flow`, `episode`, `tables`, `legs` and `inbound` whole; every skill adds its bundles under `bundles`, each entry with `"skill"`. Stage 6 reads it. + +## Gate + +- [ ] The flow table has every step of `flow/flow.json`, in its order, with its id, its skills and an in/later/out mark; `mapping.json` `flow.steps` lists every id and `flow.tabs` the eight tabs verbatim. +- [ ] Every table above has a home in `mapping.json` under `tables`. +- [ ] Every leg table's columns in `mapping.json` include `txn_id`, `correlation_id`, `api_call_id` and `thread_correlation_id`. +- [ ] `mapping.json` `episode.columns` includes `stage` and `sub_stage`. +- [ ] Every bundle this skill sends has a source table; every element with no source is listed as a gap, not omitted. +- [ ] Where this skill's bundles carry a Practitioner, the HPIN element's source is named (or its gap is). +- [ ] Every capability stage 0 found present is mapped to what exists, with its differences from the pin as gaps. +- [ ] The matching order, the dedupe key and the archive path are written. + +## Common mistakes + +- Redesigning the flow: merging tabs, adding a "status" step, moving the discharge out of the claim tab. The flow is the reference flow; copy it. +- Giving homes only to this skill's tables when it is the first to run the stage. The next skill would choose differently. +- Mapping package rates to the HMIS charge master. Prices come from the plan; the master is for reconciliation. +- One `correlation_id` column on the episode instead of one per leg. Each leg is its own thread. +- Forgetting `thread_correlation_id`. It is the difference between a recoverable door refusal and a dead case. +- Mapping `Patient` demographics on the coverage request. Only the member id goes out; the payer returns the rest. diff --git a/plugins/nhcx/skills/nhcx-reprocess/stages/5-screen-plan.md b/plugins/nhcx/skills/nhcx-reprocess/stages/5-screen-plan.md new file mode 100644 index 000000000..9ec0d8bc2 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-reprocess/stages/5-screen-plan.md @@ -0,0 +1,74 @@ +# Stage 5: screen plan + +Purpose: decide the screens, and for every value on every screen, the received message it is derived from. The two honesty rules are the whole point of this stage, and a reviewer tests them before anything else. + +The case screen is the episode's (`foundation.screens`): its eight tabs, the status line and actions, the JSON state address and the cases list. The first skill to run this stage lays them out whole, every tab present with its opening condition. Each skill then plans the values and actions of its own tabs and screens, which its `SKILL.md` lists. + +## Inputs + +- `nhcx-build/1-idea.md`, `nhcx-build/3-discovery.md` (screen conventions), `nhcx-build/4-flow-data-mapping.md` +- This skill's `SKILL.md`: its tabs, its screens, its next actions +- `flow/FLOW.md` ("The shape", "The status line and the actions", every step's Screen line) and `flow/flow.json`: the screens are put on these steps, not invented. +- `references/flow-knowledge.md` section 4 (stage, sub-stage, next actions) +- `ui/UI-GUIDE.md`: the screens, a layout per screen, where every value comes from, the state words. Read it whole before planning. +- `nhcx-package/docs/03-Building a Provider/09-UI Guide.md` (the published source of the guide) + +## The two rules + +1. No screen shows a decision the exchange has not sent. Every state on every screen is derived from a stored message. A case with a request sent and no answer back reads as waiting, never approved, never rejected. That case exists only because module 7.3 kept a record of what was sent, so the screen must be able to render a leg with a request and no response. +2. Nothing the exchange already knows is typed. Payer names, policies, balances, package rates, the payer's own wording, `preAuthRef`, the approved amount, the UTR are rendered from the message that carried them. A package rate is never an editable field. + +## Do + +### 1. The screen list + +The case screen carries the eight tabs of `flow.json` `tabs`, in that order, with those labels, opening under those conditions. The status line and the action list above the tabs use the labels of `flow.json` `next_actions` verbatim. Then, minimum, once every skill has run: + +| Screen | Who | Shows | Derived from | Planned by | +| --- | --- | --- | --- | --- | +| Cases list | billing clerk | every episode, its stage and sub-stage, what it waits for | `claim.stage`, `sub_stage`, `next_actions` | the first skill | +| Case | everyone | the timeline of legs, the payer's answer verbatim, the actions open now | every leg row and its archived messages | the first skill; each skill its tabs | +| Inbox | desk | payer messages routed by kind: query, notification, note | `claim_query` | `nhcx-communication` | +| Payments | accounts | notices, deductions, UTR, reconciliation | `claim_payment`, `claim_payment_detail` | `nhcx-payment` | +| Find and cover | registration clerk | policy search, eligibility verdict, register or link | the policy search answer and the `on_check` bundle | `nhcx-coverage` | +| Plan | doctor | specialty, package, add-ons, tiers, the documents and forms the plan wants | `claim_plan_*`, `claim_auth_*` | `nhcx-insurance`, with the ruling from `nhcx-preauth` | + +`integrate` mode adds a panel to the HMIS's own admission screen linking the admission to its episode. `standalone` mode adds the capture screens module 7.13 describes (patient, admission, discharge, documents, settings). + +Where stage 0 found a screen present, plan what it shows today against the rules, and list every value that breaks one as a gap. + +### 2. Per screen, per value + +For every value on this skill's screens, one row: `Value | Message and element | Empty state`. The empty state is what the screen shows before the message arrives (for a decision: "waiting"; for a rate: nothing, the field does not exist yet). A value whose source is "the user types it" is allowed only for things the exchange cannot know: the discharge mode and dates, the desk's reply to a query, the documents, the questionnaire answers, the chosen lines. + +### 3. Actions + +Every action is one step of `flow.json` and carries its id in `step`. For every action this skill's screens offer, the leg it sends, the sub-stage that must hold for it to be offered, and the sub-stage it moves to. Take the offered-when rules from `next_actions` in flow-knowledge section 4: an unanswered query always leads; the reply box is offered only to a `resubmit` payer; after a rejection the pre-auth offers a fresh 12, not 121. + +### 4. Addresses and conventions + +Write the route for each screen in the HMIS's own style (from stage 3). The state of a case must also be readable as JSON at one address, because stage 10 drives the screens through it (for example `GET /claims//state`). Each skill adds its legs to what the address returns. + +## Write + +- `nhcx-build/5-screen-plan.md` from `templates/5-screen-plan.md`: the shell at the top (first skill), then a section per skill. +- `nhcx-build/screens.json` in the shape of `templates/screens.json`: the first skill writes `rules`, `tabs`, `state_address`, the cases list and the case screen; each skill adds its screens and actions. + +## Gate + +- [ ] `screens.json` `tabs` lists the eight tabs of `flow.json` in order with the same keys and labels. +- [ ] Every user-driven step this skill owns (its steps among F1 to F13, except F9a, F12 and F12b, which the payer starts) appears as an action with its `step` id, and every action's `label` is one of `flow.json` `next_actions` or the step's own button. +- [ ] `screens.json` holds the cases list, the case screen, and every screen this skill plans, each with a route (plus 7.13's in standalone mode). +- [ ] Every screen this skill plans has a `values` list and every value names a message element or is marked `typed` with a reason from the allowed list. +- [ ] Every decision-bearing value has an empty state of waiting. +- [ ] No `values` entry marks a rate, a payer name, a `preAuthRef` or a UTR as typed. +- [ ] Every action names its leg, its offered-when sub-stage and its resulting sub-stage. +- [ ] A JSON state address exists for a case. + +## Common mistakes + +- A status dropdown on the case. Status is derived; there is no dropdown. +- Showing `preAuthRef` from the pre-auth's own claim number. It comes from the ClaimResponse. +- Designing the desk's reply box for a `communication` payer on the leg. It belongs on the inbox item. +- Laying out only this skill's tab when it is the first to run the stage. The shell has all eight. +- Screens that need JavaScript. Forms post and the page re-renders; that is enough. diff --git a/plugins/nhcx/skills/nhcx-reprocess/stages/6-code-plan.md b/plugins/nhcx/skills/nhcx-reprocess/stages/6-code-plan.md new file mode 100644 index 000000000..2167000f1 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-reprocess/stages/6-code-plan.md @@ -0,0 +1,68 @@ +# Stage 6: code plan + +Purpose: turn the mapping, the screen plan and the capability verdicts into a list of modules with files, dependencies, the pin each is held to, and what this skill does to each. Stage 7 builds this list in order; stage 8 validates it in order. + +The transport's shape, the configuration, the archive and the test placement (sections 2 to 5) are the episode's: the first skill to run this stage writes them, and later skills use them. + +## Inputs + +- `nhcx-build/3-discovery.md`, `nhcx-build/4-flow-data-mapping.md`, `mapping.json`, `nhcx-build/5-screen-plan.md`, `screens.json` +- This skill's section of `nhcx-build/0-capability.md` and `nhcx-build/2-planning.md` (the action per module) +- `stages/7-write-code/README.md` and every `7.N-*.md` this skill touches: the module ladder is fixed; the plan decides the files +- `references/fhir-knowledge.md` section 1: where the pins live +- `fhir/FHIR.md`: the builders and readers the modules 7.4 to 7.10 implement, so the plan names them + +## Do + +### 1. Place each module + +For each module this skill touches (its `SKILL.md` lists them) and each foundation module it builds or extends, write: + +| Field | Meaning | +| --- | --- | +| `skills` | A map from skill to action: `build`, `extend` or `reuse`. A module another skill already placed keeps its entry; add this skill and its action | +| `files` | The files it creates or changes, in the target's layout and naming (from stage 3). For a reused or extended module, the files that exist | +| `depends_on` | The modules that must exist first; the ladder's order is the floor, the plan may add more | +| `held_to` | The pin in `nhcx-package/fhir` (its file, from `references/material.md`), the payer fixture, or the rule (for modules with no bundle) | +| `copy_from` | What the module follows: its own Pseudo code section and the `fhir/FHIR.md` section it names | +| `tables` | The tables from `mapping.json` it reads and writes | +| `screens` | The screens from `screens.json` it serves (7.12 and 7.13 only) | + +`modules.json` holds one entry per module, in ladder order (7.1 to 7.13), whichever skill adds it. + +### 2. The transport's shape + +Decide once, and every module uses it: the transport kind from stage 1, and the functions of the contract in `references/transport-knowledge.md` section 2: `send`, the receiving end that hands the door a normalised envelope, `policies`, `participants`, `token`, and `thread` and `fetch_missed` where the kind has them. Name them here so 7.4 to 7.10 call the same thing. A stub of `send`, recording the path, recipient, workflow id, correlation id and bundle and returning `{"txn_id", "correlation_id", "api_call_id"}`, is what stage 9 injects. When stage 0 found an existing transport, name its functions and what wraps them. + +### 3. Configuration + +List every setting and where it lives (from stage 3): the transport kind, participant code, facility HFR id and name, cases directory, per-payer overrides for workflow ids, and the transport's own. For `own`: the ABDM client id and secret, the private key, the sessions, NHCX and registry addresses, and the NHCX signing key once onboarding gives it. For `adapter`: its URL, API key and callback secret. For `existing`: whatever its client reads. Name the environment variables or config keys in the target's convention. + +### 4. The archive + +The per-case archive path from stage 4, and which module writes it (7.3 for inbound, 7.1 for outbound). + +### 5. Test placement + +Where the offline test lives (from stage 3's "how tests are run"), and how the pin comparison is wired: canonical JSON, `created` excluded, one comparison per pin. + +## Write + +- `nhcx-build/6-code-plan.md` from `templates/6-code-plan.md`: the episode sections once, the modules table, and this skill's section. +- `nhcx-build/modules.json` in the shape of `templates/modules.json`. + +## Gate + +- [ ] `modules.json` has an entry, in ladder order, for every module this skill touches and every foundation module (7.13 in standalone mode). +- [ ] Every entry this skill touches has non-empty `files`, `depends_on` (7.1 may be empty), `held_to` and `copy_from`, and this skill in `skills` with its action. +- [ ] Every pin this skill owns appears in some module's `held_to`. +- [ ] The transport kind and its functions are named. +- [ ] The configuration list includes the transport kind, the participant code, the cases directory, and every setting the chosen transport needs. +- [ ] The test file's location and the pin comparison rule are written. + +## Common mistakes + +- Splitting the claim bundle builder across modules by leg, or by skill. One builder, one `leg` and `flow` argument, is what the pins expect; `nhcx-claim` extends what `nhcx-preauth` built. +- Planning a second transport for the reply legs. Same function; the reply legs add `x-hcx-correlation_id` to the headers. +- Planning new files for a module stage 0 found present. +- Planning the screens before the readers exist in the dependency list. diff --git a/plugins/nhcx/skills/nhcx-reprocess/stages/7-write-code/7.1-config-and-transport.md b/plugins/nhcx/skills/nhcx-reprocess/stages/7-write-code/7.1-config-and-transport.md new file mode 100644 index 000000000..2ad046569 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-reprocess/stages/7-write-code/7.1-config-and-transport.md @@ -0,0 +1,131 @@ +# Module 7.1: configuration and the NHCX transport + +Purpose: the one path every message leaves by, whichever transport carries it. The settings, the transport chosen at stage 1 behind one `send`, the policy lookup, and the outbound half of the per-case archive. + +Skills: the foundation (`core/FOUNDATION.md`). Built whole by the first skill whose stage 0 finds it absent; every skill sends through it. + +## Depends on + +Nothing. First module. + +## Inputs + +- `nhcx-build/1-idea.md`: the transport, `existing`, `own`, or `adapter` because the user asked for it +- `nhcx-build/6-code-plan.md` sections 2 to 4 (the transport's functions, the configuration keys, the archive path) +- `references/transport-knowledge.md` section 2 (the contract), and section 3 (`own`), 4 (`existing`) or 5 (`adapter`) for the kind chosen +- With `adapter` only: `references/api-knowledge.md` sections 2 to 5, 7, 8 and 11 + +## Build + +### Settings + +Read from the target's configuration mechanism (stage 3). + +| Setting | Transport | Meaning | +| --- | --- | --- | +| transport kind | all | `existing`, `own` or `adapter` | +| participant code | all | The hospital's, with `@hcx`: `x-hcx-sender_code` | +| facility HFR id, name, phone | all | The provider Organization | +| cases directory | all | The per-case archive root | +| per-payer workflow id overrides | all | Optional, for a payer that insists on a code the table does not carry (`cancel` as 122) | +| ABDM client id and secret | own | The session token (`transport-knowledge.md` section 3.3) | +| private key | own | The PEM behind the certificate on the participant record, read from a file or a secret store | +| sessions, NHCX and registry addresses, `X-CM-ID` | own | From `nhcx-package/baseurl.yaml`; the sandbox by default | +| NHCX signing key | own | For the exchange's JWT on inbound calls. Empty until onboarding gives it, and logged while empty | +| adapter URL, adapter API key, callback secret | adapter | `references/api-knowledge.md` section 2. Also fill the adapter's `config.sample.json` into `nhcx-build/adapter.config.json`, secrets as `${ENV}` placeholders | +| whatever the existing client reads | existing | Named here, not duplicated | + +Secrets are read from configuration: never in code, never in `nhcx-build/`. + +### The transport + +One `send` with the signature in `transport-knowledge.md` section 2, and beside it `policies`, `participants`, `token`, `thread` and `fetch_missed`. What sits under them depends on the kind: + +| Kind | `send` | `policies`, `participants`, `token` | `thread`, `fetch_missed` | +| --- | --- | --- | --- | +| `own` | Seal and post (`transport-knowledge.md` sections 3.3 to 3.8): the token, the recipient's certificate, the protected header, a compact JWE, `{"payload"}` to `/v1/`, a `401` retried once | The participant service directly (sections 3.6 and 3.7) | `thread` reads the per-case archive; `fetch_missed` answers `unavailable` | +| `existing` | Calls the app's own client and maps its answer onto `{txn_id, correlation_id, api_call_id}` (section 4) | The app's own calls, or the participant service directly | What the app keeps; else as `own` | +| `adapter` | POSTs `{jwe_headers, fhir}` to `/fhir/out/` with the bearer key (`api-knowledge.md` sections 4 and 5) | `/internal/policies/search`, `/internal/participants/list`, `/token` | The adapter's ledger and `/internal/txn/*` (`api-knowledge.md` sections 7 and 8) | + +Common to every kind: + +1. A send without a recipient, a workflow id or the beneficiary's ABHA is refused before anything goes on the wire. +2. The recipient is the policy's processor: `recipient_of(row)` is `claim.recipient_code`, else `claim.payer_code` for an episode opened before the processor was kept. +3. A correlation id is passed only on the two answer legs, the communication reply and the payment acknowledgement. On a request the transport mints it (`own`: the message's own `api_call_id`). +4. A refusal raises `TransportError(code, message, protocol_response, retryable)`: the gateway's status and body (`own`), the adapter's `error.code` and `upstream_body` (`adapter`), or the existing client's error. A ProtocolResponse inside it is a refusal at the door; the caller records the payer's words. +5. The outbound message is archived before `send` returns: `//NNN--out.json` with what was sent and what came back, and a `transactions.txt` line (sequence, time, direction, path, workflow id, correlation id, api call id, txn id, outcome). With `own`, the archive entry is the `txn_id`. +6. The caller stores `txn_id`, `correlation_id` and `api_call_id` on the leg. + +## Rules + +- Use nhcx-adapter only when the user asked for it; `1-idea.md` records their words. Never propose it. +- Keep an existing NHCX integration and wrap it. Never put a second transport beside it. +- Seal and open JWEs only for `own`, and only with a JOSE library: `RSA-OAEP-256`, `A256GCM`, compact serialisation. Never hand-roll the cryptography. +- The workflow id goes out on every leg that has one; `x-hcx-ben-abha-id` goes out on every message. +- The sandbox refuses sends faster than one per 30 seconds per case (PAYR-1322). The transport does not throttle; the caller does. Say so in the docstring. +- The private key never leaves the server that receives callbacks, and never enters a log. + +## Validate + +- [ ] A send with no recipient, no workflow id or no beneficiary ABHA is refused before anything goes on the wire. +- [ ] The protected header of a send carries every mandatory field under the protocol's rules: sender and recipient with `@hcx`, a fresh `api_call_id`, a `correlation_id` equal to the `api_call_id` on a request and to the request's on an answer, the workflow id, `x-hcx-timestamp` in ISO 8601 with `+05:30`, `x-hcx-status` `request.initiated` or `response.complete`, and `x-hcx-ben-abha-id`. Observed on what the transport emits: the JWE header opened with a test key pair (`own`), the posted `jwe_headers` with the adapter's completion rules (`adapter`), the existing client's output (`existing`). +- [ ] The recipient is the episode's `recipient_code`, the policy's `processingid`, whenever the episode has one. +- [ ] A refusal raises `TransportError` carrying the code and the words the exchange or the adapter gave. With `own`, a `401` is retried once with a fresh token, and a second `401` raises. +- [ ] The archive file and the `transactions.txt` line exist after a send, with the sequence number zero-padded to three digits. +- [ ] Secrets are read from configuration, not present in code or in `nhcx-build/`. +- [ ] With `own`: a bundle sealed for a test certificate opens with its private key to the same bytes and the same protected header; the token is reused while fresh and fetched again when stale; a recipient's certificate is fetched once and then read from the cache. + +## Tests + +- Stub the HTTP layer and assert the URL, the headers and the body of one send with and one without a correlation id: `bearer_auth` and `{"payload"}` for `own`; the bearer key and `{jwe_headers, fhir}` for `adapter`. +- `own`: seal with a test key pair and open it again; check the header fields above; a `401` then a `202` sends twice with two tokens; a certificate in SPKI form loads as well as an X.509 one. +- `adapter`: a `502` with a ProtocolResponse `upstream_body` raises an error whose text carries the payer's `x-hcx-error_details` message; a `404` from `txn/related` is terminal, not retried. +- The archive sequence increments across two sends on one case. + +## Pseudo code + +The `own` transport's token, certificate cache, sealing and receiving end: `references/transport-knowledge.md` section 3.12. The adapter client: `references/api-knowledge.md` section 11. What every kind shares: + +``` +settings = { + transport: env("NHCX_TRANSPORT", "own"), # own | existing | adapter; adapter only when the user asked for it + participant_code: env("NHCX_PARTICIPANT_CODE"), # "@hcx" + facility: {hfr_id: env("NHCX_HFR_ID"), name: env("NHCX_FACILITY_NAME"), phone: ...}, + cases_dir: env("NHCX_CASES_DIR", "data/cases"), + workflow_overrides: parse_json(env("NHCX_WORKFLOW_IDS", "{}")), # {"1518@hcx": {"cancel": "122"}} + nhcx: {sessions: env("NHCX_SESSIONS_URL", "https://dev.abdm.gov.in/api/hiecm/gateway/v3/sessions"), # own + base: env("NHCX_BASE_URL", "https://apisbx.abdm.gov.in/hcx"), + registry: env("NHCX_REGISTRY_URL", "https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice"), + cm_id: env("NHCX_CM_ID", "sbx"), + client_id: env("NHCX_CLIENT_ID"), client_secret: env("NHCX_CLIENT_SECRET"), + private_key: read_secret(env("NHCX_PRIVATE_KEY_FILE")), signing_key: env("NHCX_SIGNING_KEY", "")}, + adapter: {url: env("NHCX_ADAPTER_URL"), api_key: env("NHCX_ADAPTER_API_KEY"), # adapter only + callback_secret: env("NHCX_CALLBACK_SECRET")}, +} + +transport = {"own": OwnTransport, "existing": ExistingTransport, "adapter": AdapterTransport}[settings.transport]() +# each offers send, policies, participants, token, thread, fetch_missed (transport-knowledge.md section 2) + +function recipient_of(row): return row.recipient_code or row.payer_code + +function ben_abha(claim_no): # the payer's Patient from the coverage answer, else the HMIS patient + row = claim_by_no(claim_no) + return digits(abha_in(row.patient_json) or patient(row.patient_id).abha) + +function with_hcx(code): return code if code.endswith("@hcx") else code + "@hcx" + +# the archive, outbound half; 7.3 writes the inbound half through the same function +function archive.record(claim_no, usecase, direction, payload): + folder = settings.cases_dir + "/" + (claim_no or "unmatched"); mkdir(folder) + n = next_sequence(folder) # 001, 002, ... + write(folder + f"/{n:03d}-{usecase}-{direction}.json", pretty(payload)) + append(folder + "/transactions.txt", f"{n:03d} {now()} {direction} {payload.path} wf={payload.workflow_id} " + f"cid={payload.correlation_id} acid={payload.api_call_id} txn={payload.txn_id} {payload.outcome}") + return f"{claim_no or 'unmatched'}/{n:03d}" +``` + +## Done when + +- Validate passes for the transport chosen. +- `own`: the onboarding the user must do is written into `nhcx-build/7-modules/7.1.md`: the credentials, the key and certificate, the participant record, the `endpoint_url`, and the NHCX signing key to ask NHA for. `adapter`: `nhcx-build/adapter.config.json` exists with placeholders. `existing`: the wrapper and every gap it closed are listed. +- `nhcx-build/7-modules/7.1.md` is written. diff --git a/plugins/nhcx/skills/nhcx-reprocess/stages/7-write-code/7.10-communication-and-payment.md b/plugins/nhcx/skills/nhcx-reprocess/stages/7-write-code/7.10-communication-and-payment.md new file mode 100644 index 000000000..271d56732 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-reprocess/stages/7-write-code/7.10-communication-and-payment.md @@ -0,0 +1,124 @@ +# Module 7.10: communication and payment + +Purpose: the two legs the payer starts. A CommunicationRequest is classified as a query, a notification or a note and answered accordingly; a PaymentNotice is recorded, matched to its claim, and acknowledged. + +Skills: `nhcx-communication` (classification, the notification acknowledgement, the reply) and `nhcx-payment` (the payment notice and its acknowledgement). Validate rows 1, 3, 4 and 5 are the communication half's; rows 2, 6 and 7 the payment half's; row 8 is both. + +## Depends on + +7.1 to 7.3, 7.7, 7.11 (for the payer's query mode; build 7.11's adapter table first if not yet). + +## Inputs + +- `references/flow-knowledge.md` section 3 (the two payer kinds, the classification rule) and section 1 rows "Payment notice" and "Communication" +- `references/fhir-knowledge.md` sections 9 and 10 +- Pins: `nhcx-package/fhir/B4/communication-request.json` (the payer's message), `B4/communication-response.json` (the reply), `nhcx-package/fhir/B7/payment-notice-ack.json` +- Payer messages: `nhcx-package/fhir/C6/C6-preauth-query-wf24.json` and `C6/C6-claim-query-wf27.json` (generic queries), `C6/C6-notification-wfN02.json` (PMJAY notification), `nhcx-package/fhir/C9/*.json` (payment notices) + +## Build + +### Classification + +`classify_communication(adapter, reason_code, intent) -> kind`, in order: a `resubmit` payer's request is a notification; `intent proposal` is a notification, `order` a query; then `reasonCode`: absent, `additionalinfo`, `questionnaire`, `query` is a query, anything else (`tatquery`, `grievance`, `walletupdate`, `policychange`, `claimarbitration`, with `claimArbitartion` folded in) a notification. A bare `Communication` with no request is a note: recorded, shown, never acted on. + +### Receiving + +`parse_communication_request(bundle)`: the Task's status, intent, reason; the CommunicationRequest's id, `basedOn` (the Claim), one question per `payload[].contentString`; the leg asked about (from the Claim's `use` or the `basedOn` identifier). Store a `claim_query` row keyed on the message's correlation id with `kind`, `stage`, `questions_json`, status `open`. + +### Acknowledging a notification + +`build_acknowledgement_bundle(query_id)`: the payer's own bundle sent back with `Task.status` flipped to `completed`, the reason echoed and the provider Organization first, on `v1/communication/on_request` with the request's correlation id and workflow id echoed in `jwe_headers`. Sent by `acknowledge_notification` from outside the callback (the desk's next request, or a worker). Status `acknowledged`. + +### Answering a query (communication payer) + +`build_communication_bundle(query_id, text, document_ids)`: a TaskBundle with a Task `deliver`, `completed`, including the Communication; the Communication `basedOn` the request (never `inResponseTo`) and `about` the Claim, its text a `contentString`, each document a `contentAttachment` under the document-type extension (its url is participant-defined: read it from configuration; the pin comparison takes the pin's own url); the CommunicationRequest echoed; then the Claim, Patient, provider Organization, payer Organization, Practitioner and Coverage lifted from the queried leg's bundle as sent. This bundle carries `meta.lastUpdated` and `timestamp` (the IG example does). Sent on `v1/communication/on_request` with the request's correlation id and workflow id. Status `answered`. + +For a `resubmit` payer the answer is not here: it is 7.7's query answer on a fresh thread. The inbox item for a PMJAY query is the leg's `query_note`, and its reply box calls `submit_preauth` or `submit_claim` with the reply. + +### Payment notice + +`parse_payment_notice(bundle)`: `PaymentNotice.amount`, `paymentStatus`, `paymentDate`, the `request` reference's identifier (the claim number), `payment` identifier (the UTR when settled), the `PaymentReconciliation` details when present. `record_payment` matches the claim number, dedupes on the correlation id, stores `claim_payment` and `claim_payment_detail`, and stamps the episode `payment`/`noticed` or `paid`. + +### Payment acknowledgement + +`build_payment_ack(payment_id)`: a TaskBundle in the shape of `B7/payment-notice-ack.json`, sent on `v1/paymentnotice/on_request` with the notice's correlation id and, for PMJAY, workflow `17`; for a generic payer the notice's own workflow id echoed (`None` in the adapter table means echo). Sent by `acknowledge_payment` from outside the callback. `ack_status` `sent` or `error`. + +## Rules + +- The reply names the request in `Communication.basedOn`, never `inResponseTo`. +- A `resubmit` payer's CommunicationRequest is always a notification, whatever it says. +- A notification is acknowledged at once and the case is left alone. +- The acknowledgement and the reply are the only two sends that carry `x-hcx-correlation_id` (with the payment acknowledgement). + +## Validate + +- [ ] `B4/communication-response.json` pin: the builder fed the request pin (`B4/communication-request.json`) and the pre-auth pin (`B3/preauth-request.json`) produces the response pin byte for byte (`meta.lastUpdated`, `timestamp` and `authoredOn` excluded). +- [ ] `B7/payment-notice-ack.json` pin comparison passes. +- [ ] Classification: the generic query (`C6/C6-preauth-query-wf24.json`: `intent order`, `additionalinfo`) is a query; the PMJAY notification (`C6/C6-notification-wfN02.json`: `intent proposal`, `information`) is a notification; the same PMJAY bundle under a `communication` adapter with `intent order` is a query; a bare Communication is a note. +- [ ] The reply's `Communication.basedOn` names the request and `inResponseTo` is absent. +- [ ] The acknowledgement and the reply carry `x-hcx-correlation_id` equal to the request's; the workflow id is echoed. +- [ ] Two deliveries of one notice create one `claim_payment` row. +- [ ] The PMJAY acknowledgement carries workflow `17`; the generic one echoes the notice's. +- [ ] No send happens inside the callback (7.1 stub sees zero sends during receipt). + +## Tests + +- The two pin comparisons. +- Classification table as a parametrised test. +- B6, B7, C6, D8, D13 and the notification rows from the matrix. + +## Pseudo code + +Classification, the acknowledgement, the reply and the payment reader: `fhir/FHIR.md` sections 7 and 8. Wiring: + +``` +APPLY["inbound_request"] = function (row, env): + kind = resource_types(env.fhir) + if "PaymentNotice" in kind: record_payment(row, env) + elif "CommunicationRequest" in kind: receive_communication(row, env) + elif "Communication" in kind: record_note(row, env) # a bare Communication: shown, never acted on + +function receive_communication(row, env): + p = fhir.parse_communication_request(env.fhir); adapter = payers.for_claim(row) + kind = fhir.classify_communication(adapter, p.reason, p.intent) + q = insert("claim_query", {claim_id: row.id, correlation_id: env.jwe_headers["x-hcx-correlation_id"], request_id: p.request_id, + workflow_id: env.jwe_headers["x-hcx-workflow_id"], sender_code: env.jwe_headers["x-hcx-sender_code"], + kind, stage: leg_asked_about(row, p), reason_code: p.reason, intent: p.intent, questions_json: p.questions, + request_json: env.fhir, status: "open", received_at: now()}) + if kind == "notification": enqueue(acknowledge_notification, q.id) # sent outside the callback + +function acknowledge_notification(query_id): + q = query(query_id); row = claim(q.claim_id) + bundle = fhir.build_acknowledgement_bundle(q.request_json, settings.facility) + r = transport.send("v1/communication/on_request", bundle, q.sender_code, workflow_id = q.workflow_id, correlation_id = q.correlation_id, claim_no = row.claim_no, usecase = "communication-ack") + update(q, {status: "acknowledged", reply_txn_id: r.txn_id, reply_api_call_id: r.api_call_id, replied_at: now()}) + +function answer_query(query_id, text, document_ids): # communication payer + q = query(query_id); row = claim(q.claim_id) + if payers.for_claim(row).query_mode == "resubmit": return submit_preauth(row.id, reply = text) if q.stage == "preauth" else submit_claim(row.id, reply = text) + sent = (preauth(row.id) if q.stage == "preauth" else submission(row.id)).request_json + bundle = fhir.build_communication_bundle(q, text, [doc_with_bytes(i) for i in document_ids], sent, settings.facility, payer_of(row), now_ist()) + r = transport.send("v1/communication/on_request", bundle, q.sender_code, workflow_id = q.workflow_id, correlation_id = q.correlation_id, claim_no = row.claim_no, usecase = "communication-reply") + update(q, {status: "answered", reply_text: text, reply_document_ids: document_ids, reply_txn_id: r.txn_id, replied_at: now()}); stamp_case(row.id) + +function record_payment(row, env): + p = fhir.parse_payment_notice(env.fhir) + pay = insert_or_ignore("claim_payment", {claim_id: row.id, correlation_id: env.jwe_headers["x-hcx-correlation_id"], workflow_id: env.jwe_headers["x-hcx-workflow_id"], + sender_code: env.jwe_headers["x-hcx-sender_code"], amount: p.amount, payment_status: p.payment_status, payment_date: p.payment_date, + utr: p.utr, notice_json: env.fhir, ack_status: "pending", received_at: now()}) + if not pay: return # the unique constraint caught a redelivery + for d in p.details: insert("claim_payment_detail", {payment_id: pay.id, type: d.type, amount: d.amount}) + enqueue(acknowledge_payment, pay.id) + +function acknowledge_payment(payment_id): + pay = payment(payment_id); row = claim(pay.claim_id); adapter = payers.for_claim(row) + bundle = fhir.payment_ack(submission(row.id).claim_ref or row.claim_no, now_ist(), settings.facility, payer_of(row)) + wf = adapter.workflow_ids.payment_ack or pay.workflow_id # 17 for PMJAY; echo for a generic payer + r = transport.send("v1/paymentnotice/on_request", bundle, pay.sender_code, workflow_id = wf, correlation_id = pay.correlation_id, claim_no = row.claim_no, usecase = "payment-ack") + update(pay, {ack_status: "sent", ack_txn_id: r.txn_id, ack_api_call_id: r.api_call_id, acked_at: now()}); stamp_case(row.id) +``` + +## Done when + +- Validate passes. +- `nhcx-build/7-modules/7.10.md` is written. diff --git a/plugins/nhcx/skills/nhcx-reprocess/stages/7-write-code/7.11-state-and-payer-adapters.md b/plugins/nhcx/skills/nhcx-reprocess/stages/7-write-code/7.11-state-and-payer-adapters.md new file mode 100644 index 000000000..94fbfc313 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-reprocess/stages/7-write-code/7.11-state-and-payer-adapters.md @@ -0,0 +1,145 @@ +# Module 7.11: state and payer adapters + +Purpose: two small tables of truth the whole build reads. The payer adapter says how a payer behaves; the stage machine says where an episode stands and what it waits for. + +Skills: the foundation (`core/FOUNDATION.md`). The first skill builds the payer adapter table whole; each skill adds the `case_stage` branches and the `next_actions` rows for its own legs. + +## Depends on + +7.2. (7.7 to 7.10 call it; build the adapter table as early as 7.4 needs the participant codes.) + +## Inputs + +- `references/flow-knowledge.md` sections 2, 3 and 4, whole +- `nhcx-build/1-idea.md` (the payers in scope) + +## Build + +### The payer adapter + +A table keyed by participant code (normalised: `1518` and `1518@hcx` are one key), each entry holding: + +| Field | PMJAY | Generic | +| --- | --- | --- | +| `query_mode` | `resubmit` | `communication` | +| `workflow_ids` | the PMJAY column of flow-knowledge section 2 | the generic column; `payment_ack` is `None` (echo) | +| `program_code` | `AB-PMJAY` | none | +| `auth_requirements` | asked | asked | +| `status_enquiry` | refused; do not offer | offered | +| `claim_resubmit` | none; reprocess only | `16` | +| `payer_system` | the identifier system for the payer Organization | same | + +`adapter_for(participant_code)` returns the entry or the generic default. `for_claim(row)` reads the episode's payer code. Overrides from configuration (7.1) merge on top, per payer, so a payer that insists on `cancel` as 122 is one config line. + +### Stage and sub-stage + +Stages: `eligibility`, `preauth`, `enhancement`, `claim`, `payment`. Sub-stages: `draft`, `checking`, `eligible`, `not-eligible`, `requested`, `resubmitted`, `answered`, `queried`, `approved`, `partial`, `rejected`, `cancelling`, `cancelled`, `refused`, `noticed`, `paid`. Send kind to sub-stage: `preauth`, `claim`, `enhancement` set `requested`; `*_resubmit` sets `resubmitted`; `*_query_response` and `enhancement_resubmit` set `answered`. `requested`, `answered`, `resubmitted` mean "with the payer". + +`case_stage(row, ...) -> (stage, sub_stage)`: a payment notice wins, then the filed claim, then the pre-auth (stage `enhancement` if the last submission kind was one), then a saved draft, then the eligibility status. An open communication query on a leg that is with the payer flips the sub-stage to `queried`. + +`stamp_case(claim_id)`: recompute and write both onto the episode. Called after every leg write by 7.3, 7.4 to 7.10. + +### Next actions + +The table in `flow/FLOW.md` ("The status line and the actions") and `flow/flow.json` `next_actions` is the specification; the labels are used verbatim. + +`next_actions(claim_id) -> [{label, tab, tone}]`, first is what the case waits for: an unanswered query always leads with "Answer the payer (n)"; the leg's own reply box only for a `resubmit` payer, a `communication` payer is sent to the inbox; a claim refused at the door offers "send again" while `claim_send_kind` still yields a kind, else "Ask for a reprocess"; after a rejection the pre-auth offers a fresh 12; a payer whose adapter refuses status enquiry never gets a "Ask status" action. + +## Rules + +- An unmapped payer is generic. +- The two words are derived, never set by a screen. +- Stamp after every write. A test that checks state after every step is what makes stage 8 possible. + +## Validate + +- [ ] `adapter_for("1518@hcx")` and `adapter_for("1518")` return the PMJAY entry; an unknown code returns generic. +- [ ] The PMJAY `workflow_ids` table equals flow-knowledge section 2's PMJAY column for every kind listed; the generic table has `payment_ack` as echo and `claim_query_response` as `151`. +- [ ] A configuration override for one kind changes only that kind. +- [ ] `case_stage` on each seeded state (draft; checking; eligible; pre-auth submitting; approved; queried by communication; enhancement requested; claim submitting; payment noticed; paid) returns the expected pair (write the table in the test). +- [ ] `next_actions` leads with the query when one is open; offers no status enquiry for PMJAY; offers a fresh 12 after a rejection. +- [ ] For every row of `flow.json` `next_actions`, the seeded state yields that label, character for character. +- [ ] After every leg write in 7.4 to 7.10, `claim.stage` and `sub_stage` equal `case_stage` recomputed. + +## Tests + +- A parametrised table for `case_stage`. +- A parametrised table for `next_actions`. +- The adapter lookups and the override. + +## Pseudo code + +``` +QUERY_MODE_RESUBMIT = "resubmit"; QUERY_MODE_COMMUNICATION = "communication" + +PMJAY = {"name": "PMJAY", "query_mode": QUERY_MODE_RESUBMIT, "program_code": "AB-PMJAY", "auth_requirements": true, + "status_enquiry": false, "payer_system": "https://nhcx.abdm.gov.in", + "workflow_ids": {"preauth": "12", "preauth_resubmit": "121", "preauth_query_response": "19", "enhancement": "13", "enhancement_resubmit": "131", + "cancel": "PC01", "claim": "15", "claim_query_response": "161", "claim_resubmit": null, "payment_ack": "17", "reprocess": "36", "release": "36"}} +GENERIC = {"name": "generic", "query_mode": QUERY_MODE_COMMUNICATION, "program_code": null, "auth_requirements": true, "status_enquiry": true, + "payer_system": "https://nhcx.abdm.gov.in", + "workflow_ids": {... as PMJAY except "claim_query_response": "151", "claim_resubmit": "16", "payment_ack": null}} # null = echo the notice's id +ADAPTERS = {"1518": PMJAY} # keyed without @hcx + +function adapter_for(participant_code): + key = (participant_code or "").split("@")[0] + base = deepcopy(ADAPTERS.get(key, GENERIC)) + for (k, v) in settings.workflow_overrides.get(with_hcx(key), {}): base.workflow_ids[k] = v + return base + +function for_claim(row): return adapter_for(row.payer_code) + +STAGES = ["eligibility", "preauth", "enhancement", "claim", "payment"] +KIND_TO_SUB = {"preauth": "requested", "claim": "requested", "enhancement": "requested", "preauth_resubmit": "resubmitted", "claim_resubmit": "resubmitted", + "preauth_query_response": "answered", "claim_query_response": "answered", "enhancement_resubmit": "answered"} +WITH_PAYER = {"requested", "answered", "resubmitted"} + +function leg_sub_stage(leg): + if leg.status == "submitting": return KIND_TO_SUB.get(leg.submission_kind, "requested") + return {"approved": "approved", "partial": "partial", "queried": "queried", "rejected": "rejected", "error": "refused", + "cancelling": "cancelling", "cancelled": "cancelled", "draft": "draft"}.get(leg.status, leg.status) + +function case_stage(row): + paid = sum(p.amount for p in payments(row.id) if p.payment_status in ("paid", "cleared")) + if payments(row.id): return ("payment", "paid" if paid > 0 else "noticed") + cs = submission(row.id) + if cs and cs.status != "draft": + sub = leg_sub_stage(cs) + if sub in WITH_PAYER and "claim" in open_query_stages(row): sub = "queried" + return ("claim", sub) + pa = preauth(row.id) + if pa and pa.status != "draft": + stage = "enhancement" if pa.submission_kind in ("enhancement", "enhancement_resubmit") else "preauth" + sub = leg_sub_stage(pa) + if sub in WITH_PAYER and "preauth" in open_query_stages(row): sub = "queried" + return (stage, sub) + if pa: return ("preauth", "draft") + return ("eligibility", {"checking": "checking", "eligible": "eligible", "not-eligible": "not-eligible"}.get(row.status, "draft")) + +function stamp_case(claim_id): (s, sub) = case_stage(claim(claim_id)); update(claim(claim_id), {stage: s, sub_stage: sub}) + +function next_actions(claim_id): + row = claim(claim_id); adapter = for_claim(row); out = []; pa = preauth(claim_id); cs = submission(claim_id) + open_q = open_queries(claim_id) + if open_q: out.append({label: f"Answer the payer ({len(open_q)})", tab: "communication" if adapter.query_mode == "communication" else ("claim" if open_q[0].stage == "claim" else "preauth"), tone: "primary"}) + if row.status in ("draft", "not-eligible", "error"): out.append({label: "Check cover", tab: "cover", tone: "primary"}) + elif not row.plan_id: out.append({label: "Fetch the plan", tab: "plan", tone: "primary"}) + elif not pa or pa.status == "draft": out.append({label: "Submit the pre-authorisation", tab: "preauth", tone: "primary"}) + elif pa.status == "queried" and adapter.query_mode == "resubmit": out.append({label: "Answer the query", tab: "preauth", tone: "primary"}) + elif pa.status == "rejected": out.append({label: "Send a fresh pre-authorisation", tab: "preauth", tone: "primary"}) # 12, never 121 + elif pa.status == "error": out.append({label: "Send again", tab: "preauth", tone: "warn"}) + elif pa.status in ("approved", "partial") and (not cs or cs.status == "draft"): + out.append({label: "Discharge and claim", tab: "claim", tone: "primary"}) + if enhancement_lines(claim_id): out.append({label: "Send the enhancement", tab: "lines", tone: "default"}) + out.append({label: "Cancel the pre-authorisation", tab: "preauth", tone: "danger"}) + elif cs and cs.status == "error": out.append({label: "Send again" if claim_send_kind(claim_id) else "Ask for a reprocess", tab: "claim", tone: "warn"}) + elif cs and cs.status == "rejected": out.append({label: "Ask for a reprocess", tab: "claim", tone: "warn"}) + for p in payments(claim_id): if p.ack_status != "sent": out.append({label: "Acknowledge the payment", tab: "payments", tone: "default"}) + if adapter.status_enquiry and (pa or cs): out.append({label: "Ask status", tab: "enquiries", tone: "default"}) + return out +``` + +## Done when + +- Validate passes. +- `nhcx-build/7-modules/7.11.md` is written. diff --git a/plugins/nhcx/skills/nhcx-reprocess/stages/7-write-code/7.12-screens.md b/plugins/nhcx/skills/nhcx-reprocess/stages/7-write-code/7.12-screens.md new file mode 100644 index 000000000..130115d38 --- /dev/null +++ b/plugins/nhcx/skills/nhcx-reprocess/stages/7-write-code/7.12-screens.md @@ -0,0 +1,124 @@ +# Module 7.12: screens + +Purpose: the screens in `screens.json`, built the way the target builds screens, every value derived from a stored message, plus the JSON state address a driver reads. + +Skills: the foundation (`core/FOUNDATION.md`) builds the case screen shell: all eight tabs, the status line, the state address, the page-load polls, the cases list. Each skill fills its own tabs and screens, and adds its legs to the state address. + +## Depends on + +7.1 to 7.11. Screens come last because they render what the readers stored. + +## Inputs + +- `nhcx-build/5-screen-plan.md`, `nhcx-build/screens.json` +- `nhcx-build/3-discovery.md` (screen conventions, helpers, styling) +- `nhcx-package/docs/03-Building a Provider/09-UI Guide.md` +- `ui/UI-GUIDE.md` for the route shape, the state address and the helper vocabulary; two or three route modules of the target for its conventions + +## Build + +### The case screen walks the flow + +Tabs in the order and with the labels of `flow.json` `tabs`; the Pre-authorisation tab appears once the verdict is `eligible`. Above the tabs the status line and the actions from 7.11. Each step F1 to F13 has its control on the tab the flow names, offered only when the step's `holds` hold. The page-load polls run in the order `flow.json` `page_load_polls` gives, bounded, before rendering. + +### Every screen in `screens.json` + +For each screen: the route, the handler, the render. Each value in the screen's `values` list is rendered from the element it names; the empty state is what shows before the message arrived. A decision-bearing value with no message renders as waiting. There is no status control anywhere. + +### The case screen + +The timeline: one row per leg row and per archived message, in time order, with direction, path, workflow id label (7.8's labels), status word, and the payer's words verbatim (`disposition`, item remarks, process notes, `x-hcx-error_details` on a refusal). The actions open now are `next_actions` from 7.11, rendered as buttons that post to the senders; the first action is highlighted. Each pane (cover, plan, lines, forms, documents, pre-auth, communication, claim, payments) shows only when its leg exists. + +### The JSON state address + +`GET /state` returns everything the case screen shows, as JSON, after the same polls the screen runs: stage, sub-stage, next actions, each leg's status and ids, the inbox items, the payments. Stage 10's drivers read this. + +### Polling on the request path + +Where there is no worker, the case screen and the state address run 7.3's poll fallback for any leg that is `submitting` or `checking` before rendering. Bound it: one poll per leg per request, a short timeout, and never a send. + +### Standalone mode + +Also the capture screens from 7.13, in the same style. + +## Rules + +- No screen shows a decision the exchange has not sent. +- Nothing the exchange already knows is typed. Rates, payer names, `preAuthRef`, the approved amount, the UTR and the payer's wording are rendered, never fields. +- An unknown case is a 404, never an invented page. +- Screens answer within two seconds; the poll is bounded. +- Forms post and the page re-renders; no client-side rendering is needed. + +## Validate + +- [ ] The case page's tabs are the eight of `flow.json`, in order, with those labels (string test on the HTML). +- [ ] Every step of `flow.json` with a `routes` entry answers on that route (or the plan's equivalent recorded in `screens.json`). +- [ ] Every route in `screens.json` answers 200 for a seeded case and 404 for an unknown one. +- [ ] A case with a pre-auth `submitting` and no answer renders "waiting" (or the plan's word) and neither "approved" nor "rejected" appears on the page. +- [ ] After a 21 is applied (`nhcx-package/fhir/C5/C5-approved-wf21.json`), the page shows its `preAuthRef` and approved amount verbatim. +- [ ] After a payment notice is applied (`nhcx-package/fhir/C9/C9-notice-wf30.json`), the payments screen shows its UTR verbatim. +- [ ] After a query is applied, the inbox shows the request's `contentString` text verbatim. +- [ ] No `` or `, unless spec.typed +``` + +### Which actions to offer + +``` +function actions(case): + out = [] + q = open_queries(case) + if q: out.append(action("Answer the payer (n)", tab = inbox if payer.query_mode == communication else leg_tab)) + leg = current_leg(case) + if leg.status == "rejected" and leg.kind == "preauth": out.append(action("Send a fresh pre-authorisation", sends = 12)) + if leg.status == "approved" and no_request_in_flight(case) and leg.kind == "preauth": + out.append(action("Enhance", sends = 13)); out.append(action("Cancel", sends = PC01)); out.append(action("Discharge and claim", tab = claim)) + if leg.kind == "claim" and leg.status == "rejected": out.append(action("Ask for a reprocess", sends = 36)) + if payer.status_enquiry: out.append(action("Ask status", sends = task status)) + for notice in unacknowledged_notices(case): out.append(action("Acknowledge payment", sends = 17 or echo)) + return out +``` + +## Component vocabulary (suggested, for a standalone build) + +A suggested set of helpers. Server-rendered HTML from Python functions returning strings, styled by the 0build kit 0.5.4 from jsDelivr. Components: `z-card`, `z-button`, `z-input`, `z-select`, `z-table`, `z-nav`, `z-tab` with `data-z-switcher`, `z-alert`, `z-badge`, `z-breadcrumb`. Utilities take values through custom properties (`class="display-grid gap" style="--gap: 4"`). Helpers a screen needs: `page`, `card`, `stack`, `table`, `grid`, `field`, `text_input`, `select`, `button`, `post_button`, `confirm_form`, `badge`, `when`, `muted`, `dl`, `tabs`, `stat`, `empty_state`. Tables cap at about eight columns; merge facts into a main line with a muted sub-line. Every state-changing action that is not a full form is a `post_button`; destructive ones confirm. + +In `integrate` mode use the HMIS's own components and conventions; the layouts above are the content, not the markup. diff --git a/scripts/build-nav.mjs b/scripts/build-nav.mjs index f936b2d96..9dc96c423 100644 --- a/scripts/build-nav.mjs +++ b/scripts/build-nav.mjs @@ -8,6 +8,7 @@ import {existsSync, readFileSync, readdirSync, writeFileSync} from 'node:fs'; import {join, dirname} from 'node:path'; import {fileURLToPath} from 'node:url'; +import {moduleLabel} from './emit-page-markdown.mjs'; const root = join(dirname(fileURLToPath(import.meta.url)), '..'); const docsRoot = join(root, 'site', 'docs'); @@ -134,7 +135,7 @@ writeFileSync( const lines = ['# ABDM Developer Portal', '']; lines.push( - '> Documentation for integrating with ABDM, India\'s health data exchange: the HIE-CM gateway milestones M1 to M3, the ABHA, HPR and HFR registries, and UHI. Nothing here has been run against the ABDM sandbox unless a page says so, so treat request and response shapes as unconfirmed.', + '> Documentation for integrating with ABDM, India\'s health data exchange: the HIE-CM gateway milestones M1 to M3, the ABHA, HPR and HFR registries, UHI, and the NHCX claims exchange between hospitals and insurers. Nothing here has been run against the ABDM sandbox unless a page says so, so treat request and response shapes as unconfirmed.', ); lines.push(''); // The links below are the pages themselves, because this index is written @@ -160,19 +161,35 @@ writeFileSync( lines.push( `- [Agent skills](${siteUrl}${base}/skills): one markdown file per module, carrying its endpoints, error codes and test cases.`, ); - // One llms.txt per HIE-CM API module (m1, m2, ..., gateway, p1, ...), so - // an agent does not have to guess the module's llms.txt URL. Written by - // scripts/emit-page-markdown.mjs as a postbuild step; listed here from - // the same docs tree so a module without a build directory is not listed. - const apiDir = join(docsRoot, 'hiecm', 'v3', 'api'); - if (existsSync(apiDir)) { - const moduleIds = readdirSync(apiDir, {withFileTypes: true}) - .filter((e) => e.isDirectory() && !e.name.startsWith('_') && !e.name.startsWith('.')) + // One llms.txt per API module of every gateway (HIE-CM m1, m2, ..., + // gateway, p1, ...; NHCX claim, preauth, ...), so an agent does not have to + // guess a module's llms.txt URL. Written by scripts/emit-page-markdown.mjs + // as a postbuild step; listed here from the same docs tree so a module + // without a build directory is not listed. HIE-CM is listed first. + const visible = (e) => e.isDirectory() && !e.name.startsWith('_') && !e.name.startsWith('.'); + const apiRoots = []; + for (const platform of readdirSync(docsRoot, {withFileTypes: true}).filter(visible)) { + for (const version of readdirSync(join(docsRoot, platform.name), {withFileTypes: true}).filter(visible)) { + const dir = join(docsRoot, platform.name, version.name, 'api'); + if (existsSync(dir)) apiRoots.push({platform: platform.name, version: version.name, dir}); + } + } + const hiecmFirst = (p) => (p === 'hiecm' ? 0 : 1); + apiRoots.sort( + (a, b) => + hiecmFirst(a.platform) - hiecmFirst(b.platform) || + a.platform.localeCompare(b.platform) || + a.version.localeCompare(b.version), + ); + for (const {platform, version, dir} of apiRoots) { + const moduleIds = readdirSync(dir, {withFileTypes: true}) + .filter(visible) .map((e) => e.name) .sort(); for (const moduleId of moduleIds) { + const label = moduleLabel({platform, version, moduleId}, apiSidebar); lines.push( - `- [${moduleId.toUpperCase()} module index](${siteUrl}${base}/docs/hiecm/v3/api/${moduleId}/llms.txt): per-page links for the ${moduleId.toUpperCase()} module.`, + `- [${label} module index](${siteUrl}${base}/docs/${platform}/${version}/api/${moduleId}/llms.txt): per-page links for the ${label} module.`, ); } } diff --git a/scripts/emit-page-markdown.mjs b/scripts/emit-page-markdown.mjs index d708d7376..0b125f850 100644 --- a/scripts/emit-page-markdown.mjs +++ b/scripts/emit-page-markdown.mjs @@ -297,6 +297,22 @@ function* walk(dir) { } } +/** + * How a module is named in prose and in the llms.txt index. + * + * HIE-CM module ids are already the name a reader knows (M1, P2, GATEWAY), so + * they upper-case straight through. Another gateway's ids are not, so the + * label comes from the API sidebar and is prefixed with the gateway, which is + * what distinguishes an NHCX module from an HIE-CM one in a flat list. + */ +export function moduleLabel({platform, version, moduleId}, sidebar = []) { + if (platform === 'hiecm') return moduleId.toUpperCase(); + const entry = sidebar.find( + (s) => s.platform === platform && s.version === version && s.moduleId === moduleId, + ); + return `${platform.toUpperCase()} ${entry?.label ?? moduleId}`; +} + /** * Where a page is actually published. * diff --git a/scripts/verify-nhcx.sh b/scripts/verify-nhcx.sh new file mode 100644 index 000000000..b4aa2a407 --- /dev/null +++ b/scripts/verify-nhcx.sh @@ -0,0 +1,274 @@ +#!/bin/sh +# Runs the read-only, synchronous NHCX endpoint atoms against the sandbox and +# captures redacted evidence, so a verifier can compare each answer with the +# atom's "How you know it worked" section. It never sets verified itself. +# +# NHCX_CLIENT_ID=... NHCX_CLIENT_SECRET=... \ +# NHCX_PARTICIPANT_CODE= \ +# sh scripts/verify-nhcx.sh +# +# Required: +# NHCX_CLIENT_ID, NHCX_CLIENT_SECRET ABDM sandbox client credentials +# NHCX_PARTICIPANT_CODE participant code read by search, +# details and fetch/certs +# Optional (the call is skipped when its inputs are unset): +# NHCX_IDENTIFIER_TYPE, NHCX_IDENTIFIER_VALUE +# AbhaNumber, MemberId or MobileNo and its value, for the two +# get/policies calls. Use a test beneficiary only. +# NHCX_CASE_ID, NHCX_PMJAY_PAYER_CODE +# scheme case id and PMJAY payer code (no @hcx), for get/user-role +# NHCX_ROLE (PAYER), NHCX_FROM_DATE (01/04/2021), NHCX_TO_DATE (today), +# NHCX_SKIP_GET_SESSION=1 to leave out /get/session +# +# Calls, one per atom under catalogue/nhcx/endpoints/: +# session-token.md POST gateway /api/hiecm/gateway/v3/sessions +# fetch-participants-list.md POST /fetch/participants/list +# participant-search.md POST /participant/search +# participant-details.md POST /participant/details +# fetch-certs.md POST /fetch/certs +# get-session.md POST /get/session, then /fetch/certs with it +# participant-get-policies.md POST /participant/get/policies (optional) +# v2-participant-get-policies.md POST /V2/participant/get/policies (optional) +# payer-service-get-user-role.md POST .../v1/get/user-role (optional) +# Nothing here creates, updates, links, delinks or submits. +# +# Secrets: credentials, tokens and request bodies reach curl on stdin, never on +# the command line, where ps would show them. Tokens are held in shell +# variables only. Every address must be https, curl is limited to https, and no +# call follows a redirect, which would resend the token header to another host. +# Evidence files carry named placeholders in place of tokens, credentials, +# cookies, mobile numbers, emails, OTPs and Aadhaar numbers, and the client +# secret and every token are also masked wherever they appear verbatim, as in +# an error text that echoes them. Do not run this with set -x. +set -eu + +: "${NHCX_CLIENT_ID:?set NHCX_CLIENT_ID}" +: "${NHCX_CLIENT_SECRET:?set NHCX_CLIENT_SECRET}" +: "${NHCX_PARTICIPANT_CODE:?set NHCX_PARTICIPANT_CODE to the participant code to read}" + +SESSIONS_URL=${NHCX_SESSIONS_URL:-https://dev.abdm.gov.in/api/hiecm/gateway/v3/sessions} +REGISTRY_BASE=${NHCX_REGISTRY_BASE:-https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice} +GET_SESSION_URL=${NHCX_GET_SESSION_URL:-https://apisbx.abdm.gov.in/get/session} +USER_ROLE_URL=${NHCX_USER_ROLE_URL:-https://apisbx.abdm.gov.in/pmjay/sbxhcx/nhcxpayerservice/v1/get/user-role} +CM_ID=${NHCX_CM_ID:-sbx} +ROLE=${NHCX_ROLE:-PAYER} +FROM_DATE=${NHCX_FROM_DATE:-01/04/2021} +TO_DATE=${NHCX_TO_DATE:-$(date +%d/%m/%Y)} +TIMEOUT=60 + +# Every call carries a credential or a token, so none may leave over plain HTTP. +for url in "$SESSIONS_URL" "$REGISTRY_BASE" "$GET_SESSION_URL" "$USER_ROLE_URL"; do + case "$url" in + https://*) ;; + *) echo "Refusing to send credentials to a non-https address: $url" >&2; exit 1 ;; + esac +done + +OUT=$(mktemp -d "${TMPDIR:-/tmp}/nhcx-verify.XXXXXX") +export OUT + +ts() { date -u +%Y-%m-%dT%H:%M:%S.000Z; } +rid() { + if command -v uuidgen >/dev/null 2>&1; then uuidgen | tr 'A-Z' 'a-z' + else python3 -c 'import uuid; print(uuid.uuid4())'; fi +} +# Escapes a value for a JSON string or a curl config string. The value moves +# through the printf builtin and a pipe, so it never appears in argv. +esc() { printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g'; } +# Writes the request as run, with placeholders, next to its evidence. +note() { printf '%s\n' "$2" > "$OUT/$1.request"; } + +# Reads curl's "-D - -w __STATUS__" output on stdin, redacts it, writes +# NAME.headers and NAME.body, prints the status and a head of the body on +# stderr, and prints the named top-level field (a token) on stdout. +RECORD=$(cat <<'PY' +import json, os, re, sys +name = sys.argv[1] +key = sys.argv[2] if len(sys.argv) > 2 else "" +out = os.environ["OUT"] +raw = sys.stdin.buffer.read().decode("utf-8", "replace") +m = re.search(r"\n?__STATUS__(\d{3})\s*$", raw) +status = m.group(1) if m else "000" +if m: + raw = raw[:m.start()] +headers, body = "", raw +while body.startswith("HTTP/"): + cut, width = body.find("\r\n\r\n"), 4 + if cut < 0: + cut, width = body.find("\n\n"), 2 + if cut < 0: + headers, body = headers + body, "" + break + headers += body[:cut] + "\n\n" + body = body[cut + width:] +secret_header = re.compile(r"^(set-cookie|cookie|authorization|proxy-authorization|bearer_auth|x-auth-token)\s*:", re.I) +lines = [] +for line in headers.replace("\r", "").split("\n"): + if secret_header.match(line): + line = line.split(":", 1)[0] + ": " + lines.append(line) +secret_key = re.compile(r"(^token$|access_?token|refresh_?token|id_?token|secret|password|passcode|otp|aadhaar|mobile|phone|email)", re.I) +jwt = re.compile(r"eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+") +def scrub(v, k=""): + if isinstance(v, dict): + return {kk: scrub(vv, kk) for kk, vv in v.items()} + if isinstance(v, list): + return [scrub(x, k) for x in v] + if k and secret_key.search(k) and v not in (None, ""): + return "" + if isinstance(v, str): + return jwt.sub("", v) + return v +found = "" +try: + doc = json.loads(body) + if key and isinstance(doc, dict) and isinstance(doc.get(key), str): + found = doc[key] + clean = scrub(doc) + pretty, flat = json.dumps(clean, indent=2), json.dumps(clean) +except ValueError: + text = jwt.sub("", body) + text = re.sub(r"(?", text) + text = re.sub(r"(?", text) + pretty = flat = text +# What this run knows to be secret is masked wherever it appears, in any shape: +# the client secret, the token sent with this call, and a token this response +# carries. Scrubbing by key name and by JWT shape alone misses an error text +# that echoes a secret, and a token that is not a JWT. +literals = [(os.environ.get("NHCX_CLIENT_SECRET", ""), ""), + (os.environ.get("REDACT_TOKEN", ""), ""), + (found, "")] +def mask(text): + for value, label in literals: + if value and len(value) >= 4: + text = text.replace(value, label) + return text +lines = [mask(line) for line in lines] +pretty, flat = mask(pretty), mask(flat) +with open(os.path.join(out, name + ".headers"), "w") as f: + f.write("\n".join(lines)) +with open(os.path.join(out, name + ".body"), "w") as f: + f.write(pretty) +with open(os.path.join(out, "summary.txt"), "a") as f: + f.write("%s HTTP %s\n" % (name, status)) +sys.stderr.write("== %s: HTTP %s\n %s\n" % (name, status, flat[:300].replace("\n", " "))) +if key: + sys.stderr.write(" %s %s\n" % (key, "present (%d chars)" % len(found) if found else "absent")) +sys.stdout.write(found) +PY +) +record() { python3 -c "$RECORD" "$@"; } + +# POST to the participant service with the three headers every registry +# atom sends. The token reaches curl as a config line on stdin. +registry() { # name path json-body body-as-recorded + note "$1" "POST $REGISTRY_BASE$2 +Accept: application/json +Content-Type: application/json +bearer_auth: Bearer +$4" + # The token and the body both reach curl as config lines on stdin, so neither + # appears in argv, where ps would show a beneficiary identifier. + RESP=$(printf 'header = "bearer_auth: Bearer %s"\ndata = "%s"\n' "$TOKEN" "$(esc "$3")" | + curl -s -m "$TIMEOUT" --proto =https -D - -w '\n__STATUS__%{http_code}' -K - \ + -X POST "$REGISTRY_BASE$2" \ + -H 'Accept: application/json' \ + -H 'Content-Type: application/json') || RESP='__STATUS__000' + printf '%s' "$RESP" | REDACT_TOKEN="$TOKEN" python3 -c "$RECORD" "$1" >/dev/null +} + +echo "Evidence directory: $OUT" + +# session-token.md +note session-token "POST $SESSIONS_URL +Content-Type: application/json +REQUEST-ID: +TIMESTAMP: +X-CM-ID: $CM_ID +{\"clientId\":\"\",\"clientSecret\":\"\",\"grantType\":\"client_credentials\"}" +RESP=$(printf '{"clientId":"%s","clientSecret":"%s","grantType":"client_credentials"}' \ + "$(esc "$NHCX_CLIENT_ID")" "$(esc "$NHCX_CLIENT_SECRET")" | + curl -s -m "$TIMEOUT" --proto =https -D - -w '\n__STATUS__%{http_code}' \ + -X POST "$SESSIONS_URL" \ + -H 'Content-Type: application/json' \ + -H "REQUEST-ID: $(rid)" \ + -H "TIMESTAMP: $(ts)" \ + -H "X-CM-ID: $CM_ID" \ + -d @-) || RESP='__STATUS__000' +TOKEN=$(printf '%s' "$RESP" | record session-token accessToken) +RESP= +if [ -z "$TOKEN" ]; then + echo "No accessToken from the session call. The participant service calls need one; stopping." >&2 + echo "Evidence in $OUT/" + exit 1 +fi + +# fetch-participants-list.md +BODY="{\"role\":\"$ROLE\",\"fromdate\":\"$FROM_DATE\",\"todate\":\"$TO_DATE\"}" +registry fetch-participants-list /fetch/participants/list "$BODY" "$BODY" + +# participant-search.md and participant-details.md +BODY="{\"participant_code\":\"$NHCX_PARTICIPANT_CODE\"}" +registry participant-search /participant/search "$BODY" "$BODY" +registry participant-details /participant/details "$BODY" "$BODY" + +# fetch-certs.md +BODY="{\"participantid\":\"$NHCX_PARTICIPANT_CODE\"}" +registry fetch-certs /fetch/certs "$BODY" "$BODY" + +# participant-get-policies.md and v2-participant-get-policies.md +if [ -n "${NHCX_IDENTIFIER_TYPE:-}" ] && [ -n "${NHCX_IDENTIFIER_VALUE:-}" ]; then + BODY="{\"identifiertype\":\"$NHCX_IDENTIFIER_TYPE\",\"identifiervalue\":\"$(esc "$NHCX_IDENTIFIER_VALUE")\"}" + SHOWN="{\"identifiertype\":\"$NHCX_IDENTIFIER_TYPE\",\"identifiervalue\":\"\"}" + registry participant-get-policies /participant/get/policies "$BODY" "$SHOWN" + registry v2-participant-get-policies /V2/participant/get/policies "$BODY" "$SHOWN" +else + echo "== get/policies: skipped, NHCX_IDENTIFIER_TYPE and NHCX_IDENTIFIER_VALUE are unset" >&2 +fi + +# payer-service-get-user-role.md +if [ -n "${NHCX_CASE_ID:-}" ] && [ -n "${NHCX_PMJAY_PAYER_CODE:-}" ]; then + BODY="{\"caseid\":\"$(esc "$NHCX_CASE_ID")\",\"payerid\":\"$(esc "$NHCX_PMJAY_PAYER_CODE")\"}" + note payer-service-get-user-role "POST $USER_ROLE_URL +accept: application/json +Content-Type: application/json +bearer_auth: Bearer +{\"caseid\":\"\",\"payerid\":\"$NHCX_PMJAY_PAYER_CODE\"}" + # No --location: curl would resend the custom token header to any host a + # redirect names. The body goes on stdin with the token, never in argv. + RESP=$(printf 'header = "bearer_auth: Bearer %s"\ndata = "%s"\n' "$TOKEN" "$(esc "$BODY")" | + curl -s -m "$TIMEOUT" --proto =https -D - -w '\n__STATUS__%{http_code}' -K - \ + --request POST "$USER_ROLE_URL" \ + --header 'accept: application/json' \ + --header 'Content-Type: application/json') || RESP='__STATUS__000' + printf '%s' "$RESP" | REDACT_TOKEN="$TOKEN" python3 -c "$RECORD" payer-service-get-user-role >/dev/null +else + echo "== get/user-role: skipped, NHCX_CASE_ID and NHCX_PMJAY_PAYER_CODE are unset" >&2 +fi + +# get-session.md, then its exit condition: /fetch/certs with that token +if [ "${NHCX_SKIP_GET_SESSION:-0}" != 1 ]; then + note get-session "POST $GET_SESSION_URL +Content-Type: application/x-www-form-urlencoded +client_id=&client_secret=&grant_type=client_credentials" + RESP=$(printf 'data-urlencode = "client_id=%s"\ndata-urlencode = "client_secret=%s"\n' \ + "$(esc "$NHCX_CLIENT_ID")" "$(esc "$NHCX_CLIENT_SECRET")" | + curl -s -m "$TIMEOUT" --proto =https -D - -w '\n__STATUS__%{http_code}' -K - \ + -X POST "$GET_SESSION_URL" \ + -H 'Content-Type: application/x-www-form-urlencoded' \ + --data-urlencode 'grant_type=client_credentials') || RESP='__STATUS__000' + GS_TOKEN=$(printf '%s' "$RESP" | record get-session access_token) + RESP= + if [ -n "$GS_TOKEN" ]; then + TOKEN=$GS_TOKEN + BODY="{\"participantid\":\"$NHCX_PARTICIPANT_CODE\"}" + registry get-session-then-fetch-certs /fetch/certs "$BODY" "$BODY" + fi + GS_TOKEN= +fi +TOKEN= + +echo +echo "Done. Evidence in $OUT/ (summary.txt, and NAME.request, .headers, .body per call)." +echo "Tokens, credentials and contact numbers are replaced with placeholders. A get/policies" +echo "body can still carry beneficiary details: review it before sharing or recording." diff --git a/site/README.md b/site/README.md index 3d7d9aee3..2dbdc1ed4 100644 --- a/site/README.md +++ b/site/README.md @@ -5,7 +5,8 @@ API references, generated from [`../catalogue`](../catalogue). Nothing under `docs/`, `static/specs/` or `static/skills/` is hand-edited — all three are overwritten by the build: pages from the catalogue's atoms, specs from its OpenAPI files, and skills by `scripts/build-skills.mjs` -(which also copies in the committed skills from `plugins/abdm/skills/`). +(which also copies in the committed skills from +`plugins/abdm-integrators-assistant/skills/` and `plugins/nhcx/skills/`). ```bash npm install diff --git a/site/docs/nhcx/v1/README.md b/site/docs/nhcx/v1/README.md index c025be915..74a1cdb7e 100644 --- a/site/docs/nhcx/v1/README.md +++ b/site/docs/nhcx/v1/README.md @@ -1,17 +1,17 @@ # NHCX V1 -The sections of this version. Each folder is a sidebar section; `index.md` -here is the landing page readers see first. - -| Folder | Renders as | -| --- | --- | -| `getting-started/` | Overview tab, first section: orientation, onboarding, glossary | -| `registries/` | Overview tab: the registries this gateway touches | -| `concepts/` | Overview tab: core concepts, one page per concept | -| `api/` | API references tab: module guide pages; endpoint pages are generated from the OpenAPI specs | -| `reference/` | API references tab: cross-module reference material | - -Drop a `.md` file in the right folder and it renders. Order pages with -`sidebar_position` in the frontmatter; name and order a folder with -`_category_.json`. +Ported from the NHCX package by its `make ekadocs` target (`system/build-ekadocs.mjs`). +Everything in this folder is replaced on every port, so change the package and port again +rather than editing a page here. +| Folder | Renders as | From the package | +| --- | --- | --- | +| `index.md` | The landing page | `docs/01-Overview/01-Introduction.md` | +| `getting-started/` | Overview tab: the base framework, first to last | `docs/02-Getting Started`, and the glossary | +| `roles/` | Overview tab: one path per role | `docs/03-Building a Provider`, `docs/04-Building a Payer` | +| `registries/` | Overview tab: participants and policies | `docs/01-Overview/03-Participants and Policies.md` | +| `concepts/` | Overview tab: how a claim moves, use cases, workflow codes, PMJAY | `docs/01-Overview` | +| `go-live/` | Overview tab: leaving the sandbox | `docs/07-Go Live` | +| `troubleshooting/` | Overview tab: what to check, by the symptom you see | `docs/08-Troubleshooting` | +| `api/` | API references tab: one module per Bruno folder | `apis/` | +| `reference/` | API references tab: lookups, and the FHIR bundles under `fhir/` | `docs/06-Reference`, `docs/05-FHIR Reference` | diff --git a/site/docs/nhcx/v1/api/README.md b/site/docs/nhcx/v1/api/README.md index 58eeaecf2..b0076a97f 100644 --- a/site/docs/nhcx/v1/api/README.md +++ b/site/docs/nhcx/v1/api/README.md @@ -1,10 +1,5 @@ # API references -Module guide pages live here, one folder per module. The endpoint pages, each -module's `_category_.json` and everything under `endpoints/` are generated -from `catalogue/openapi/nhcx/v1/` on every build; never edit them by hand. - -Hand-written pages for a module (overview `index.md`, `user-journey`, `apis`, -`sequence`) sit in the module's folder next to the generated content and are -ordered by `sidebar_position` (10, 20, 30; generated errors pages use 98). - +One module per folder of the package's Bruno collection. `index.md` in each module is the +overview the port writes. `endpoints/`, `errors.md` and `_category_.json` are generated +from `catalogue/openapi/nhcx/v1/` by the site's build, as for every gateway. diff --git a/site/docs/nhcx/v1/api/adjudicator/_category_.json b/site/docs/nhcx/v1/api/adjudicator/_category_.json new file mode 100644 index 000000000..7d8d05b70 --- /dev/null +++ b/site/docs/nhcx/v1/api/adjudicator/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "PMJAY adjudicator", + "position": 13 +} diff --git a/site/docs/nhcx/v1/api/adjudicator/index.md b/site/docs/nhcx/v1/api/adjudicator/index.md new file mode 100644 index 000000000..18dbec23f --- /dev/null +++ b/site/docs/nhcx/v1/api/adjudicator/index.md @@ -0,0 +1,37 @@ +--- +title: PMJAY adjudicator +sidebar_label: Overview +sidebar_position: 0 +description: "The PMJAY adjudicator calls on NHCX: what each one does, the hosts they go to, and the guides that use them." +verification: unverified +source: nhcx-package/apis/12-adjudicator +generated: true +--- + +# PMJAY adjudicator + +A PMJAY case is not decided over NHCX. + +## Calls + +| Call | Method and path | What it does | +| --- | --- | --- | +| [Adjudicator: role for a case](/docs/nhcx/v1/api/adjudicator/endpoints/adjudicator-adjudicator-role) | `POST /pmjay/sbxhcx/nhcxpayerservice/v1/get/user-role` | Asks the NHCX Payer Service which role in the State Health Agency's Transaction Management System holds a PMJAY case, and so which actions may be taken on it next. | +| [Adjudicator: act on a case](/docs/nhcx/v1/api/adjudicator/endpoints/adjudicator-adjudicator-process) | `POST /pmjay/hcx/nhcxpayerservice/wrapper/process/case` | Approves, rejects, queries or forwards a PMJAY case in the State Health Agency's Transaction Management System, as the role that currently holds it. | +| [Dummy payer, act on a request](/docs/nhcx/v1/api/adjudicator/endpoints/adjudicator-dummy-payer-process-request) | `POST /process/request` | Makes the sandbox dummy payer, participant `1000003538@hcx`, approve, reject or query a pre-authorisation or claim you have submitted, by correlation ID. | +| [Dummy payer, send a payment notice](/docs/nhcx/v1/api/adjudicator/endpoints/adjudicator-dummy-payer-paymentnotice-init) | `POST /paymentNotice/init` | Makes the sandbox dummy payer send a payment notice to the provider named, on `/v1/paymentnotice/request`. | + +## Base URLs + +| Environment | Base URL | +| --- | --- | +| Sandbox, Dummy payer. | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/dummyhcxpayer` | + +## Guides that use these calls + +- [Receiving a callback](/docs/nhcx/v1/getting-started/receiving-a-callback) +- [Get your sandbox credentials](/docs/nhcx/v1/getting-started/get-your-sandbox-credentials) +- [PMJAY sandbox run](/docs/nhcx/v1/roles/provider/pmjay-sandbox-run) +- [PMJAY adjudication APIs](/docs/nhcx/v1/roles/provider/pmjay-adjudication-apis) + +The whole specification, with a request you can send from the page, is the [PMJAY adjudicator API reference](/reference/nhcx-adjudicator). diff --git a/site/docs/nhcx/v1/api/biometric/_category_.json b/site/docs/nhcx/v1/api/biometric/_category_.json new file mode 100644 index 000000000..583ad89be --- /dev/null +++ b/site/docs/nhcx/v1/api/biometric/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "ABHA biometric authentication", + "position": 15 +} diff --git a/site/docs/nhcx/v1/api/biometric/index.md b/site/docs/nhcx/v1/api/biometric/index.md new file mode 100644 index 000000000..454dc908e --- /dev/null +++ b/site/docs/nhcx/v1/api/biometric/index.md @@ -0,0 +1,36 @@ +--- +title: ABHA biometric authentication +sidebar_label: Overview +sidebar_position: 0 +description: "The ABHA biometric authentication calls on NHCX: what each one does, the hosts they go to, and the guides that use them." +verification: unverified +source: nhcx-package/apis/14-biometric +generated: true +--- + +# ABHA biometric authentication + +PMJAY requires proof that the beneficiary was physically present. + +## Calls + +| Call | Method and path | What it does | +| --- | --- | --- | +| [Biometric auth init](/docs/nhcx/v1/api/biometric/endpoints/biometric-auth-init) | `POST /hcx/abha/biometric/auth/init` | Starts a fingerprint or iris authentication of a PMJAY beneficiary against the ABHA registry and returns the `txnId` the verify call needs. | +| [Biometric auth verify](/docs/nhcx/v1/api/biometric/endpoints/biometric-auth-verify) | `POST /hcx/abha/biometric/auth/verify` | Completes the authentication started by `Biometric auth init` with the captured PID block, and returns the beneficiary's user token, valid thirty minutes. | +| [Biometric auth refresh token](/docs/nhcx/v1/api/biometric/endpoints/biometric-auth-refresh-token) | `GET /hcx/abha/biometric/auth/refresh/token` | Exchanges the refresh token from `Biometric auth verify` for a new thirty-minute user token without a fresh capture. | +| [Face auth init](/docs/nhcx/v1/api/biometric/endpoints/biometric-faceauth-init) | `POST /pmjay/sbxhcx/abdmproxy/abha/biometric/faceauth/init` | Starts a face authentication on the ABDM proxy host and returns the `txnId` the rest of the face flow quotes. | +| [Face auth capture PID](/docs/nhcx/v1/api/biometric/endpoints/biometric-faceauth-capture-pid) | `POST /pmjay/sbxhcx/abdmproxy/abha/biometric/capture/pid` | Polls for the face capture the patient completes in the ABHA app after scanning the QR code for the `txnId` from `Face auth init`. | +| [Face auth verify](/docs/nhcx/v1/api/biometric/endpoints/biometric-faceauth-v2-auth-verify) | `POST /pmjay/sbxhcx/abdmproxy/abha/biometric/v2/auth/verify` | Completes a face authentication with the encrypted Aadhaar number, the Aadhaar-linked mobile and the `txnId`, and returns the beneficiary's user token. | + +## Base URLs + +| Environment | Base URL | +| --- | --- | +| Sandbox. | `https://apisbx.abdm.gov.in` | + +## Guides that use these calls + +- [Biometric authentication](/docs/nhcx/v1/roles/provider/biometric-authentication) + +The whole specification, with a request you can send from the page, is the [ABHA biometric authentication API reference](/reference/nhcx-biometric). diff --git a/site/docs/nhcx/v1/api/claim/_category_.json b/site/docs/nhcx/v1/api/claim/_category_.json new file mode 100644 index 000000000..8e3d2c92a --- /dev/null +++ b/site/docs/nhcx/v1/api/claim/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Claim", + "position": 6 +} diff --git a/site/docs/nhcx/v1/api/claim/index.md b/site/docs/nhcx/v1/api/claim/index.md new file mode 100644 index 000000000..0e0338ec7 --- /dev/null +++ b/site/docs/nhcx/v1/api/claim/index.md @@ -0,0 +1,46 @@ +--- +title: Claim +sidebar_label: Overview +sidebar_position: 0 +description: "The Claim calls on NHCX: what each one does, the hosts they go to, and the guides that use them." +verification: unverified +source: nhcx-package/apis/05-claim +generated: true +--- + +# Claim + +The claim is where money actually moves. + +## Calls + +| Call | Method and path | What it does | +| --- | --- | --- | +| [Claim submit](/docs/nhcx/v1/api/claim/endpoints/claim-v1-claim-submit) | `POST /v1/claim/submit` | Provider submits the final itemised Claim bundle (Claim.use claim), or a claim query response or resubmission; NHCX routes it to the payer. | +| [Claim callback](/docs/nhcx/v1/api/claim/endpoints/claim-v1-claim-on-submit) | `POST /v1/claim/on_submit` | Payer returns interim (response.partial) and final (response.complete) ClaimResponseBundles for a claim to the provider via NHCX. | +| [Claim submit (internal) (adapter)](/docs/nhcx/v1/api/claim/endpoints/claim-internal-v1-claim-submit) | `POST /internal/v1/claim/submit` | Internal twin of /v1/claim/submit (operationId claimSubmitPostInternal) with the same JWEPayload body and response set. | +| [Claim callback (internal) (adapter)](/docs/nhcx/v1/api/claim/endpoints/claim-internal-v1-claim-on-submit) | `POST /internal/v1/claim/on_submit` | Internal twin of /v1/claim/on_submit (operationId claimOnSubmitPostInternal) taking the same bare object body. | + +## Callbacks you host + +The exchange posts these to the `endpoint_url` you registered. Answer each with HTTP 202 first. + +| Path | Hosted by | +| --- | --- | +| `/v1/claim/submit` | The payer | +| `/v1/claim/on_submit` | The provider | + +## Base URLs + +| Environment | Base URL | +| --- | --- | +| Sandbox, NHCX exchange. | `https://apisbx.abdm.gov.in/hcx` | +| Production. | `https://apisprod.nha.gov.in/hcx` | + +## Guides that use these calls + +- [Claim request](/docs/nhcx/v1/reference/fhir/claim-request) +- [Claim response](/docs/nhcx/v1/reference/fhir/claim-response) +- [Claim query and answer](/docs/nhcx/v1/reference/fhir/claim-query-and-answer) + +The whole specification, with a request you can send from the page, is the [Claim API reference](/reference/nhcx-claim). diff --git a/site/docs/nhcx/v1/api/communication/_category_.json b/site/docs/nhcx/v1/api/communication/_category_.json new file mode 100644 index 000000000..9220fa183 --- /dev/null +++ b/site/docs/nhcx/v1/api/communication/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Communication", + "position": 8 +} diff --git a/site/docs/nhcx/v1/api/communication/index.md b/site/docs/nhcx/v1/api/communication/index.md new file mode 100644 index 000000000..9a547f454 --- /dev/null +++ b/site/docs/nhcx/v1/api/communication/index.md @@ -0,0 +1,44 @@ +--- +title: Communication +sidebar_label: Overview +sidebar_position: 0 +description: "The Communication calls on NHCX: what each one does, the hosts they go to, and the guides that use them." +verification: unverified +source: nhcx-package/apis/07-communication +generated: true +--- + +# Communication + +Every other NHCX exchange is provider-initiated and expects a matching response. + +## Calls + +| Call | Method and path | What it does | +| --- | --- | --- | +| [Communication request](/docs/nhcx/v1/api/communication/endpoints/communication-v1-communication-request) | `POST /v1/communication/request` | Payer pushes a Task plus Communication bundle to a provider mid-claim: TAT alerts, wallet or policy changes, grievances or extra-information requests. | +| [Communication acknowledgement callback](/docs/nhcx/v1/api/communication/endpoints/communication-v1-communication-on-request) | `POST /v1/communication/on_request` | Provider returns the acknowledgement Task bundle for a payer communication, echoing the reason code and correlation id so the payer can close the loop. | +| [Communication request (internal variant) (adapter)](/docs/nhcx/v1/api/communication/endpoints/communication-internal-v1-communication-request) | `POST /internal/v1/communication/request` | Internal twin of /v1/communication/request: same JWEPayload body, description and 202 envelope, operationId communicationRequestPostInternal. | +| [Communication acknowledgement callback (internal variant) (adapter)](/docs/nhcx/v1/api/communication/endpoints/communication-internal-v1-communication-on-request) | `POST /internal/v1/communication/on_request` | Internal twin of /v1/communication/on_request: the provider acknowledgement Task bundle, operationId communicationOnRequestPostInternal. | + +## Callbacks you host + +The exchange posts these to the `endpoint_url` you registered. Answer each with HTTP 202 first. + +| Path | Hosted by | +| --- | --- | +| `/v1/communication/request` | The provider | +| `/v1/communication/on_request` | The payer | + +## Base URLs + +| Environment | Base URL | +| --- | --- | +| Sandbox, NHCX exchange. | `https://apisbx.abdm.gov.in/hcx` | +| Production. | `https://apisprod.nha.gov.in/hcx` | + +## Guides that use these calls + +- [Communication](/docs/nhcx/v1/reference/fhir/communication) + +The whole specification, with a request you can send from the page, is the [Communication API reference](/reference/nhcx-communication). diff --git a/site/docs/nhcx/v1/api/eligibility/_category_.json b/site/docs/nhcx/v1/api/eligibility/_category_.json new file mode 100644 index 000000000..a395ae3a8 --- /dev/null +++ b/site/docs/nhcx/v1/api/eligibility/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Coverage eligibility", + "position": 3 +} diff --git a/site/docs/nhcx/v1/api/eligibility/index.md b/site/docs/nhcx/v1/api/eligibility/index.md new file mode 100644 index 000000000..6d313cf02 --- /dev/null +++ b/site/docs/nhcx/v1/api/eligibility/index.md @@ -0,0 +1,45 @@ +--- +title: Coverage eligibility +sidebar_label: Overview +sidebar_position: 0 +description: "The Coverage eligibility calls on NHCX: what each one does, the hosts they go to, and the guides that use them." +verification: unverified +source: nhcx-package/apis/02-eligibility +generated: true +--- + +# Coverage eligibility + +Coverage eligibility is the pre-check a hospital desk runs before committing a patient to a cashless pathway. + +## Calls + +| Call | Method and path | What it does | +| --- | --- | --- | +| [Coverage eligibility check](/docs/nhcx/v1/api/eligibility/endpoints/eligibility-v1-coverageeligibility-check) | `POST /v1/coverageeligibility/check` | Provider asks the payer, via NHCX, whether a beneficiary's policy is in force, what it covers and which documents a preauth will need. | +| [Coverage eligibility callback](/docs/nhcx/v1/api/eligibility/endpoints/eligibility-v1-coverageeligibility-on-check) | `POST /v1/coverageeligibility/on_check` | Payer returns the CoverageEligibilityResponse (policy in force, benefits, auth requirements) or an error to the provider through NHCX. | +| [Coverage eligibility check (internal) (adapter)](/docs/nhcx/v1/api/eligibility/endpoints/eligibility-internal-v1-coverageeligibility-check) | `POST /internal/v1/coverageeligibility/check` | Internal twin of /v1/coverageeligibility/check with the same JWEPayload body and response set; only the operationId differs. | +| [Coverage eligibility callback (internal) (adapter)](/docs/nhcx/v1/api/eligibility/endpoints/eligibility-internal-v1-coverageeligibility-on-check) | `POST /internal/v1/coverageeligibility/on_check` | Internal twin of /v1/coverageeligibility/on_check taking the same bare object body; only the operationId differs. | + +## Callbacks you host + +The exchange posts these to the `endpoint_url` you registered. Answer each with HTTP 202 first. + +| Path | Hosted by | +| --- | --- | +| `/v1/coverageeligibility/check` | The payer | +| `/v1/coverageeligibility/on_check` | The provider | + +## Base URLs + +| Environment | Base URL | +| --- | --- | +| Sandbox, NHCX exchange. | `https://apisbx.abdm.gov.in/hcx` | +| Production. | `https://apisprod.nha.gov.in/hcx` | + +## Guides that use these calls + +- [Coverage eligibility request](/docs/nhcx/v1/reference/fhir/coverage-eligibility-request) +- [Coverage eligibility response](/docs/nhcx/v1/reference/fhir/coverage-eligibility-response) + +The whole specification, with a request you can send from the page, is the [Coverage eligibility API reference](/reference/nhcx-eligibility). diff --git a/site/docs/nhcx/v1/api/index.md b/site/docs/nhcx/v1/api/index.md deleted file mode 100644 index 3528f5e27..000000000 --- a/site/docs/nhcx/v1/api/index.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: NHCX API reference -sidebar_label: API reference -description: What is published for the NHCX gateway today. -verification: unverified -source: NHCX__NHCX-Website_DocumentDetails.md ---- - -# NHCX API reference - -No specification is published here for NHCX, and no endpoint on this gateway has been documented here yet. - -[The NHCX introduction](/docs/nhcx/v1) lists what the documentation set covers, so you can see what exists and where it lives. diff --git a/site/docs/nhcx/v1/api/insurance-plan/_category_.json b/site/docs/nhcx/v1/api/insurance-plan/_category_.json new file mode 100644 index 000000000..97506a899 --- /dev/null +++ b/site/docs/nhcx/v1/api/insurance-plan/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Insurance plan", + "position": 10 +} diff --git a/site/docs/nhcx/v1/api/insurance-plan/index.md b/site/docs/nhcx/v1/api/insurance-plan/index.md new file mode 100644 index 000000000..c57dd52c8 --- /dev/null +++ b/site/docs/nhcx/v1/api/insurance-plan/index.md @@ -0,0 +1,45 @@ +--- +title: Insurance plan +sidebar_label: Overview +sidebar_position: 0 +description: "The Insurance plan calls on NHCX: what each one does, the hosts they go to, and the guides that use them." +verification: unverified +source: nhcx-package/apis/09-insurance-plan +generated: true +--- + +# Insurance plan + +Policies have traditionally been PDFs that hospital desks interpret by hand, producing ambiguity about benefits, claim conditions and documents, and rework and rejections downstream. + +## Calls + +| Call | Method and path | What it does | +| --- | --- | --- | +| [Insurance plan request](/docs/nhcx/v1/api/insurance-plan/endpoints/insurance-plan-v1-insuranceplan-request) | `POST /v1/insuranceplan/request` | Provider sends a Task with code poll naming a policy number and/or its HFR id to fetch the payer's machine-readable InsurancePlan for that pairing. | +| [Insurance plan callback](/docs/nhcx/v1/api/insurance-plan/endpoints/insurance-plan-v1-insuranceplan-on-request) | `POST /v1/insuranceplan/on_request` | Payer returns the InsurancePlan collection Bundle (InsurancePlan, Organization, optional Questionnaire) under the request correlation id. | +| [Insurance plan request (internal variant) (adapter)](/docs/nhcx/v1/api/insurance-plan/endpoints/insurance-plan-internal-v1-insuranceplan-request) | `POST /internal/v1/insuranceplan/request` | Internal twin of /v1/insuranceplan/request on the insuranceplanhcxservice: same TaskBundle payload, same 202 envelope, distinct operationId. | +| [Insurance plan callback (internal variant) (adapter)](/docs/nhcx/v1/api/insurance-plan/endpoints/insurance-plan-internal-v1-insuranceplan-on-request) | `POST /internal/v1/insuranceplan/on_request` | Internal twin of /v1/insuranceplan/on_request: the payer InsuranceplanBundle callback with identical semantics, distinct operationId. | + +## Callbacks you host + +The exchange posts these to the `endpoint_url` you registered. Answer each with HTTP 202 first. + +| Path | Hosted by | +| --- | --- | +| `/v1/insuranceplan/request` | The payer | +| `/v1/insuranceplan/on_request` | The provider | + +## Base URLs + +| Environment | Base URL | +| --- | --- | +| Sandbox, NHCX exchange. | `https://apisbx.abdm.gov.in/hcx` | +| Production. | `https://apisprod.nha.gov.in/hcx` | + +## Guides that use these calls + +- [Insurance plan request](/docs/nhcx/v1/reference/fhir/insurance-plan-request) +- [Insurance plan response](/docs/nhcx/v1/reference/fhir/insurance-plan-response-overview) + +The whole specification, with a request you can send from the page, is the [Insurance plan API reference](/reference/nhcx-insurance-plan). diff --git a/site/docs/nhcx/v1/api/onboarding/_category_.json b/site/docs/nhcx/v1/api/onboarding/_category_.json new file mode 100644 index 000000000..21bdf9ef3 --- /dev/null +++ b/site/docs/nhcx/v1/api/onboarding/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Onboarding", + "position": 12 +} diff --git a/site/docs/nhcx/v1/api/onboarding/index.md b/site/docs/nhcx/v1/api/onboarding/index.md new file mode 100644 index 000000000..ab2b05872 --- /dev/null +++ b/site/docs/nhcx/v1/api/onboarding/index.md @@ -0,0 +1,37 @@ +--- +title: Onboarding +sidebar_label: Overview +sidebar_position: 0 +description: "The Onboarding calls on NHCX: what each one does, the hosts they go to, and the guides that use them." +verification: unverified +source: nhcx-package/apis/11-onboarding +generated: true +--- + +# Onboarding + +Nothing moves through NHCX until both the sender and the recipient exist in the participant registry, which the platform treats as the source of truth for who may exchange claims data. + +## Calls + +| Call | Method and path | What it does | +| --- | --- | --- | +| [Participant create (v1)](/docs/nhcx/v1/api/onboarding/endpoints/onboarding-participant-create) | `POST /participant/create` | Creates a participant record in the NHCX registry from a full v1 profile and returns the generated participant_code. | +| [Participant create (v2)](/docs/nhcx/v1/api/onboarding/endpoints/onboarding-v2-participant-create) | `POST /v2/participant/create` | Registry-linked creation: registry type and ID, role codes, endpoint URL and contacts; returns participantid and a transactionid for /validate. | +| [HEM-entity participant create](/docs/nhcx/v1/api/onboarding/endpoints/onboarding-v2-participant-hementity-create) | `POST /v2/participant/hementity/create` | Creates a hospital (HEM-entity) participant from the full empanelment payload (bank, tax, beds, specialities, doctors); returns status and hospitalid. | +| [Validate participant creation](/docs/nhcx/v1/api/onboarding/endpoints/onboarding-validate) | `GET /validate` | Confirms a participant creation by presenting the SMS passcode and the transactionId returned by /v2/participant/create. | +| [Validate participant update](/docs/nhcx/v1/api/onboarding/endpoints/onboarding-update-validate) | `GET /update/validate` | Confirms a participant update by presenting the SMS passcode and the transactionId returned by /v2/participant/update. | + +## Base URLs + +| Environment | Base URL | +| --- | --- | +| Sandbox, Participant service. | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice` | +| Production. | `https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice` | + +## Guides that use these calls + +- [Creating and updating a participant](/docs/nhcx/v1/getting-started/creating-and-updating-a-participant) +- [Your callback URL is rejected or never called](/docs/nhcx/v1/troubleshooting/your-callback-url-is-rejected) + +The whole specification, with a request you can send from the page, is the [Onboarding API reference](/reference/nhcx-onboarding). diff --git a/site/docs/nhcx/v1/api/other/_category_.json b/site/docs/nhcx/v1/api/other/_category_.json new file mode 100644 index 000000000..8245417a7 --- /dev/null +++ b/site/docs/nhcx/v1/api/other/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Other", + "position": 14 +} diff --git a/site/docs/nhcx/v1/api/other/index.md b/site/docs/nhcx/v1/api/other/index.md new file mode 100644 index 000000000..c472088c6 --- /dev/null +++ b/site/docs/nhcx/v1/api/other/index.md @@ -0,0 +1,59 @@ +--- +title: Other +sidebar_label: Overview +sidebar_position: 0 +description: "The Other calls on NHCX: what each one does, the hosts they go to, and the guides that use them." +verification: unverified +source: nhcx-package/apis/13-other +generated: true +--- + +# Other + +Claims are often not fully approved first time, for mundane reasons: missing documents, policy interpretation differences, package or pricing discrepancies. + +## Calls + +| Call | Method and path | What it does | +| --- | --- | --- | +| [Task submit (reprocess or cancel)](/docs/nhcx/v1/api/other/endpoints/other-v1-task-submit) | `POST /v1/task/submit` | Provider sends a FHIR Task asking the payer to reprocess a rejected or short-paid claim or to cancel a preauth; Task.code and reasonCode set the intent. | +| [Task callback (reprocess or cancel outcome)](/docs/nhcx/v1/api/other/endpoints/other-v1-task-on-submit) | `POST /v1/task/on_submit` | Payer returns a Task bundle with Task.status completed whose Task.output references a ClaimResponse carrying the reprocess or cancellation outcome. | +| [Task submit (internal variant) (adapter)](/docs/nhcx/v1/api/other/endpoints/other-internal-v1-task-submit) | `POST /internal/v1/task/submit` | Internal twin of /v1/task/submit on the taskhcxservice, operationId hcxTaskPostInternal, with the same JWEPayload Task body and 202 envelope. | +| [Task callback (internal variant) (adapter)](/docs/nhcx/v1/api/other/endpoints/other-internal-v1-task-on-submit) | `POST /internal/v1/task/on_submit` | Internal twin of /v1/task/on_submit (hcxOnTaskPostInternal): the payer Task bundle wrapping the ClaimResponse outcome of a reprocess or cancel. | +| [Notification subscribe](/docs/nhcx/v1/api/other/endpoints/other-v1-notification-subscribe) | `POST /v1/notification/subscribe` | A Beneficiary Service Provider (PHR app) subscribes an ABHA id to notification topics; NHCX persists it synchronously, Last-Linked-Wins per ABHA id. | +| [Notification on_subscribe](/docs/nhcx/v1/api/other/endpoints/other-v1-notification-on-subscribe) | `POST /v1/notification/on_subscribe` | BSP-side subscription acknowledgement; the same name denotes the callback where NHCX pushes claim-event notifications for a subscribed ABHA id. | +| [Delete records (troubleshooting)](/docs/nhcx/v1/api/other/endpoints/other-v1-delete) | `POST /v1/delete` | Internal troubleshooting operation on the claim service that deletes records by correlationid and action; not part of the business transaction flows. | +| [OpenAPI 3 document (status service)](/docs/nhcx/v1/api/other/endpoints/other-v3-api-docs) | `GET /v3/api-docs` | Serves the status service's OpenAPI 3 document, optionally filtered by a group query parameter; a discovery endpoint, not a protocol API. | +| [Swagger 2 document (status service)](/docs/nhcx/v1/api/other/endpoints/other-v2-api-docs) | `GET /v2/api-docs` | Serves the status service's Swagger 2 document, optionally filtered by a group query parameter; a discovery endpoint, not a protocol API. | +| [Swagger resources list](/docs/nhcx/v1/api/other/endpoints/other-swagger-resources) | `GET /swagger-resources` | Lists the Swagger resources (API document locations) exposed by the status service; used by Swagger UI, not by integrations. | +| [Swagger UI configuration](/docs/nhcx/v1/api/other/endpoints/other-swagger-resources-configuration-ui) | `GET /swagger-resources/configuration/ui` | Returns the Swagger UI display configuration for the status service; consumed by Swagger UI, not by integrations. | +| [Swagger security configuration](/docs/nhcx/v1/api/other/endpoints/other-swagger-resources-configuration-security) | `GET /swagger-resources/configuration/security` | Returns the Swagger UI security configuration for the status service; consumed by Swagger UI, not by integrations. | +| [Status callback](/docs/nhcx/v1/api/other/endpoints/other-v1-on-status) | `POST /v1/on_status` | The answer to a status request, delivered to the sender that asked. | +| [Error report (callback)](/docs/nhcx/v1/api/other/endpoints/other-v1-error) | `POST /v1/error` | Where the exchange tells a sender that a request could not be delivered after five attempts. | + +## Callbacks you host + +The exchange posts these to the `endpoint_url` you registered. Answer each with HTTP 202 first. + +| Path | Hosted by | +| --- | --- | +| `/v1/task/submit` | The payer | +| `/v1/task/on_submit` | The provider | +| `/v1/on_status` | The provider | +| `/v1/error` | Every participant | + +## Base URLs + +| Environment | Base URL | +| --- | --- | +| Sandbox, NHCX exchange. | `https://apisbx.abdm.gov.in/hcx` | +| Production. | `https://apisprod.nha.gov.in/hcx` | + +## Guides that use these calls + +- [Cancel, reprocess and shortfall](/docs/nhcx/v1/reference/fhir/cancel-reprocess-and-shortfall) +- [Predetermination, status and search](/docs/nhcx/v1/reference/fhir/predetermination-status-and-search) +- [Notifications and patient apps](/docs/nhcx/v1/reference/notifications-and-patient-apps) +- [Accepted with 202, and no callback arrives](/docs/nhcx/v1/troubleshooting/accepted-then-no-callback) + +The whole specification, with a request you can send from the page, is the [Other API reference](/reference/nhcx-other). diff --git a/site/docs/nhcx/v1/api/payment-notice/_category_.json b/site/docs/nhcx/v1/api/payment-notice/_category_.json new file mode 100644 index 000000000..fab1d2a96 --- /dev/null +++ b/site/docs/nhcx/v1/api/payment-notice/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Payment notice", + "position": 7 +} diff --git a/site/docs/nhcx/v1/api/payment-notice/index.md b/site/docs/nhcx/v1/api/payment-notice/index.md new file mode 100644 index 000000000..fc39d40d7 --- /dev/null +++ b/site/docs/nhcx/v1/api/payment-notice/index.md @@ -0,0 +1,44 @@ +--- +title: Payment notice +sidebar_label: Overview +sidebar_position: 0 +description: "The Payment notice calls on NHCX: what each one does, the hosts they go to, and the guides that use them." +verification: unverified +source: nhcx-package/apis/06-payment-notice +generated: true +--- + +# Payment notice + +Every other flow exchanges decisions; the payment notice is the only one that tells the hospital whether the money actually moved. + +## Calls + +| Call | Method and path | What it does | +| --- | --- | --- | +| [Payment notice request](/docs/nhcx/v1/api/payment-notice/endpoints/payment-notice-v1-paymentnotice-request) | `POST /v1/paymentnotice/request` | Payer pushes a Task bundle with PaymentNotice and PaymentReconciliation (amount, TDS, UTR) to the provider via NHCX after approving a claim. | +| [Payment notice request (internal) (adapter)](/docs/nhcx/v1/api/payment-notice/endpoints/payment-notice-internal-v1-paymentnotice-request) | `POST /internal/v1/paymentnotice/request` | Internal twin of /v1/paymentnotice/request (operationId paymentNoticeRequestPostInternal) with the same JWEPayload body and response set. | +| [Payment notice acknowledgement](/docs/nhcx/v1/api/payment-notice/endpoints/payment-notice-v1-paymentnotice-on-request) | `POST /v1/paymentnotice/on_request` | Provider acknowledges a payment notice with a Task bundle (status completed, output paymentack), closing the payment lifecycle via NHCX. | +| [Payment notice acknowledgement (internal) (adapter)](/docs/nhcx/v1/api/payment-notice/endpoints/payment-notice-internal-v1-paymentnotice-on-request) | `POST /internal/v1/paymentnotice/on_request` | Internal twin of /v1/paymentnotice/on_request (operationId paymentNoticeOnRequestPostInternal) with the same JWEPayload body and response set. | + +## Callbacks you host + +The exchange posts these to the `endpoint_url` you registered. Answer each with HTTP 202 first. + +| Path | Hosted by | +| --- | --- | +| `/v1/paymentnotice/request` | The provider | +| `/v1/paymentnotice/on_request` | The payer | + +## Base URLs + +| Environment | Base URL | +| --- | --- | +| Sandbox, NHCX exchange. | `https://apisbx.abdm.gov.in/hcx` | +| Production. | `https://apisprod.nha.gov.in/hcx` | + +## Guides that use these calls + +- [Payment notice and acknowledgement](/docs/nhcx/v1/reference/fhir/payment-notice-and-acknowledgement) + +The whole specification, with a request you can send from the page, is the [Payment notice API reference](/reference/nhcx-payment-notice). diff --git a/site/docs/nhcx/v1/api/preauth/_category_.json b/site/docs/nhcx/v1/api/preauth/_category_.json new file mode 100644 index 000000000..1d41cdc32 --- /dev/null +++ b/site/docs/nhcx/v1/api/preauth/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Pre-authorisation", + "position": 4 +} diff --git a/site/docs/nhcx/v1/api/preauth/index.md b/site/docs/nhcx/v1/api/preauth/index.md new file mode 100644 index 000000000..861ae7b7e --- /dev/null +++ b/site/docs/nhcx/v1/api/preauth/index.md @@ -0,0 +1,48 @@ +--- +title: Pre-authorisation +sidebar_label: Overview +sidebar_position: 0 +description: "The Pre-authorisation calls on NHCX: what each one does, the hosts they go to, and the guides that use them." +verification: unverified +source: nhcx-package/apis/03-preauth +generated: true +--- + +# Pre-authorisation + +Pre-authorisation is the provider's formal request for the payer's approval to deliver a specific treatment to a covered beneficiary. + +## Calls + +| Call | Method and path | What it does | +| --- | --- | --- | +| [Pre-authorisation submit](/docs/nhcx/v1/api/preauth/endpoints/preauth-v1-preauth-submit) | `POST /v1/preauth/submit` | Provider submits, resubmits, enhances or answers a query on a pre-authorisation Claim bundle (Claim.use preauthorization); NHCX routes it to the payer. Also sent as pre-authorisation enhancement. | +| [Pre-authorisation submit (internal) (adapter)](/docs/nhcx/v1/api/preauth/endpoints/preauth-internal-v1-preauth-submit) | `POST /internal/v1/preauth/submit` | Internal twin of /v1/preauth/submit (operationId preauthSubmitPostInternal) with the same JWEPayload body and response set. | +| [Pre-authorisation callback](/docs/nhcx/v1/api/preauth/endpoints/preauth-v1-preauth-on-submit) | `POST /v1/preauth/on_submit` | Payer returns the ClaimResponseBundle for a pre-authorisation (approved, partially approved, queried or rejected) to the provider via NHCX. | +| [Pre-authorisation callback (internal) (adapter)](/docs/nhcx/v1/api/preauth/endpoints/preauth-internal-v1-preauth-on-submit) | `POST /internal/v1/preauth/on_submit` | Internal twin of /v1/preauth/on_submit (operationId preauthOnSubmitPostInternal) with the same JWEPayload body and response set. | + +## Callbacks you host + +The exchange posts these to the `endpoint_url` you registered. Answer each with HTTP 202 first. + +| Path | Hosted by | +| --- | --- | +| `/v1/preauth/submit` | The payer | +| `/v1/preauth/on_submit` | The provider | + +## Base URLs + +| Environment | Base URL | +| --- | --- | +| Sandbox, NHCX exchange. | `https://apisbx.abdm.gov.in/hcx` | +| Production. | `https://apisprod.nha.gov.in/hcx` | + +## Guides that use these calls + +- [Building and sending a JWE](/docs/nhcx/v1/getting-started/building-and-sending-a-jwe) +- [Preauthorisation request](/docs/nhcx/v1/reference/fhir/preauthorisation-request) +- [Preauthorisation response](/docs/nhcx/v1/reference/fhir/preauthorisation-response) +- [Preauthorisation enhancement](/docs/nhcx/v1/reference/fhir/preauthorisation-enhancement) +- [Preauthorisation query and answer](/docs/nhcx/v1/reference/fhir/preauthorisation-query-and-answer) + +The whole specification, with a request you can send from the page, is the [Pre-authorisation API reference](/reference/nhcx-preauth). diff --git a/site/docs/nhcx/v1/api/predetermination/_category_.json b/site/docs/nhcx/v1/api/predetermination/_category_.json new file mode 100644 index 000000000..e5bae320c --- /dev/null +++ b/site/docs/nhcx/v1/api/predetermination/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Predetermination", + "position": 5 +} diff --git a/site/docs/nhcx/v1/api/predetermination/index.md b/site/docs/nhcx/v1/api/predetermination/index.md new file mode 100644 index 000000000..72b08c59c --- /dev/null +++ b/site/docs/nhcx/v1/api/predetermination/index.md @@ -0,0 +1,42 @@ +--- +title: Predetermination +sidebar_label: Overview +sidebar_position: 0 +description: "The Predetermination calls on NHCX: what each one does, the hosts they go to, and the guides that use them." +verification: unverified +source: nhcx-package/apis/04-predetermination +generated: true +--- + +# Predetermination + +A hospital planning a treatment can learn the benefit a payer would approve for it before the patient is admitted, and plan the admission and the patient's share of the cost around the answer. + +## Calls + +| Call | Method and path | What it does | +| --- | --- | --- | +| [Predetermination request](/docs/nhcx/v1/api/predetermination/endpoints/predetermination-v1-predetermination-submit) | `POST /v1/predetermination/submit` | Provider asks the payer what it would approve for a proposed treatment before committing to a pre-authorisation. | +| [Predetermination callback](/docs/nhcx/v1/api/predetermination/endpoints/predetermination-v1-predetermination-on-submit) | `POST /v1/predetermination/on_submit` | Payer returns its estimate for a predetermination request to the provider: a `ClaimResponse` with `use` `predetermination` and the benefit it would approve. | + +## Callbacks you host + +The exchange posts these to the `endpoint_url` you registered. Answer each with HTTP 202 first. + +| Path | Hosted by | +| --- | --- | +| `/v1/predetermination/submit` | The payer | +| `/v1/predetermination/on_submit` | The provider | + +## Base URLs + +| Environment | Base URL | +| --- | --- | +| Sandbox, NHCX exchange. | `https://apisbx.abdm.gov.in/hcx` | +| Production. | `https://apisprod.nha.gov.in/hcx` | + +## Guides that use these calls + +- [Predetermination, status and search](/docs/nhcx/v1/reference/fhir/predetermination-status-and-search) + +The whole specification, with a request you can send from the page, is the [Predetermination API reference](/reference/nhcx-predetermination). diff --git a/site/docs/nhcx/v1/api/registry/_category_.json b/site/docs/nhcx/v1/api/registry/_category_.json new file mode 100644 index 000000000..8957ff92d --- /dev/null +++ b/site/docs/nhcx/v1/api/registry/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Participant registry", + "position": 11 +} diff --git a/site/docs/nhcx/v1/api/registry/index.md b/site/docs/nhcx/v1/api/registry/index.md new file mode 100644 index 000000000..adb0eb7c7 --- /dev/null +++ b/site/docs/nhcx/v1/api/registry/index.md @@ -0,0 +1,59 @@ +--- +title: Participant registry +sidebar_label: Overview +sidebar_position: 0 +description: "The Participant registry calls on NHCX: what each one does, the hosts they go to, and the guides that use them." +verification: unverified +source: nhcx-package/apis/10-registry +generated: true +--- + +# Participant registry + +Every NHCX API call, whether a registry lookup, a certificate fetch or a claim submission, is rejected unless it carries a valid Bearer token, so this is the first call any integration makes and... + +## Calls + +| Call | Method and path | What it does | +| --- | --- | --- | +| [Get session token](/docs/nhcx/v1/api/registry/endpoints/registry-get-session) | `POST /get/session` | Exchanges the participant's client_id and client_secret (OAuth 2.0 client credentials) for a Bearer access_token valid for 1200 seconds. | +| [Participant update (v1)](/docs/nhcx/v1/api/registry/endpoints/registry-participant-update) | `POST /participant/update` | Updates a participant's registry record; participant_code and roles are mandatory, every other field (certificate, endpoint, contacts, status) is optional. | +| [Participant certificate and bridge update (v2)](/docs/nhcx/v1/api/registry/endpoints/registry-v2-participant-update) | `POST /v2/participant/update` | Stages a change to a participant encryption certificate and/or endpoint URL; returns a transactionid for passcode confirmation via /update/validate. | +| [Participant search](/docs/nhcx/v1/api/registry/endpoints/registry-participant-search) | `POST /participant/search` | Reads a participant's full registry record by participant_code, including roles, status, encryption_cert and endpoint_url. | +| [Participant details (v2 search)](/docs/nhcx/v1/api/registry/endpoints/registry-participant-details) | `POST /participant/details` | V2 variant of participant search: takes participant_code and returns the matching full registry records. | +| [Fetch participants list](/docs/nhcx/v1/api/registry/endpoints/registry-fetch-participants-list) | `POST /fetch/participants/list` | Payer discovery: lists participants filtered by role, registration date window and optional entity type; the first step of the cashless workflow. | +| [Fetch certificate](/docs/nhcx/v1/api/registry/endpoints/registry-fetch-certs) | `POST /fetch/certs` | Returns a participant's public encryption certificate (PEM X.509 or SPKI key) by participantid; cache it for 24 hours and use it to build the JWE. | +| [Fetch certificate path](/docs/nhcx/v1/api/registry/endpoints/registry-fetch-certs-path) | `POST /fetch/certs/path` | Companion to /fetch/certs: takes the same participantid body and returns a string described as the participant's certificate path. | +| [Update certificate (v2, no passcode)](/docs/nhcx/v1/api/registry/endpoints/registry-v2-update-cert) | `POST /v2/update/cert` | Replaces a participant's public encryption certificate by participantId without passcode validation; the same schema is echoed back on success. | +| [Get linked registry master (internal)](/docs/nhcx/v1/api/registry/endpoints/registry-get-linked-registry-mst) | `POST /get/linked/registry/mst` | Internal-use participant-service operation that fetches the linked registry master; listed in the OpenAPI but not intended for integrators. | +| [Link ABHA number to policies](/docs/nhcx/v1/api/registry/endpoints/registry-participant-link-abha-policy) | `POST /participant/link/abha/policy` | Payer-side write that links a beneficiary's ABHA number and member id to one or more products, so provider policy lookups can find them. | +| [Link ABHA number to policies (V2)](/docs/nhcx/v1/api/registry/endpoints/registry-v2-participant-link-abha-policy) | `POST /V2/participant/link/abha/policy` | V2 variant of the ABHA policy link; same ParticipantLinkAbhaRequest body and ParticipantLinkAbhaResponse as the unversioned call. | +| [Initiate ABHA policy link (v2)](/docs/nhcx/v1/api/registry/endpoints/registry-v2-participant-link-abha-policy-init) | `POST /v2/participant/link/abha/policy/init` | First half of the two-step v2 link: submits the ABHA policy link request, to be confirmed with a passcode via the validate endpoint. | +| [Validate ABHA policy link (v2)](/docs/nhcx/v1/api/registry/endpoints/registry-v2-participant-link-abha-policy-validate) | `GET /v2/participant/link/abha/policy/validate` | Second half of the two-step v2 link: confirms an initiated ABHA policy link with the passcode and transactionId query parameters. | +| [De-link ABHA policies](/docs/nhcx/v1/api/registry/endpoints/registry-participant-delink-abha-policy) | `POST /participant/delink/abha/policy` | Removes specific products from a member's policy link for a payer, keyed on payerid, memberid and the products listed. | +| [De-link ABHA policies (V2)](/docs/nhcx/v1/api/registry/endpoints/registry-v2-participant-delink-abha-policy) | `POST /V2/participant/delink/abha/policy` | V2 variant of the ABHA policy de-link; same ParticipantDeLinkAbhaRequest body and response as the unversioned call. | +| [Get beneficiary policies](/docs/nhcx/v1/api/registry/endpoints/registry-participant-get-policies) | `POST /participant/get/policies` | Looks up the policies linked to a beneficiary by ABHA number, member id or mobile number, returning the payer and product details needed for claims. | +| [Get beneficiary policies (V2)](/docs/nhcx/v1/api/registry/endpoints/registry-v2-participant-get-policies) | `POST /V2/participant/get/policies` | V2 variant of the beneficiary policy lookup; same FetchParticipantPoliciesRequest body and ParticipantListResponse as the unversioned call. | +| [Update ABHA number](/docs/nhcx/v1/api/registry/endpoints/registry-update-abhanumber) | `POST /update/abhanumber` | Replaces a placeholder (dummy) ABHA number with the beneficiary's real ABHA number in the ABHA_AUTH_TRANSACTION table. | +| [Link payer product](/docs/nhcx/v1/api/registry/endpoints/registry-product-link) | `POST /product/link` | Registers a product (product id and name) against a payer's participant code, so that it can be referenced in ABHA policy links. | +| [De-link payer product](/docs/nhcx/v1/api/registry/endpoints/registry-product-delink) | `POST /product/delink` | Removes a product (product id and name) from a payer's participant code in the registry. | +| [Get product owner](/docs/nhcx/v1/api/registry/endpoints/registry-product-getowner) | `POST /product/getowner` | Resolves a product id to the participant code of the payer that owns it. | +| [Get product id and name](/docs/nhcx/v1/api/registry/endpoints/registry-participant-getproductidname) | `POST /participant/getProductIdName` | Retrieving API described as generating the product id and product name; declared with a bare string request body and a participant-code response. | + +## Base URLs + +| Environment | Base URL | +| --- | --- | +| Sandbox, Participant service. | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice` | +| Production. | `https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice` | + +## Guides that use these calls + +- [Creating and updating a participant](/docs/nhcx/v1/getting-started/creating-and-updating-a-participant) +- [Finding participants and policies](/docs/nhcx/v1/getting-started/finding-participants-and-policies) +- [Fetching a recipient certificate](/docs/nhcx/v1/getting-started/fetching-a-recipient-certificate) +- [Get your sandbox credentials](/docs/nhcx/v1/getting-started/get-your-sandbox-credentials) +- [Quickstart](/docs/nhcx/v1/getting-started/quickstart) +- [The recipient cannot decrypt your message](/docs/nhcx/v1/troubleshooting/the-recipient-cannot-decrypt) + +The whole specification, with a request you can send from the page, is the [Participant registry API reference](/reference/nhcx-registry). diff --git a/site/docs/nhcx/v1/api/session/_category_.json b/site/docs/nhcx/v1/api/session/_category_.json new file mode 100644 index 000000000..487914d6f --- /dev/null +++ b/site/docs/nhcx/v1/api/session/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Session", + "position": 2 +} diff --git a/site/docs/nhcx/v1/api/session/index.md b/site/docs/nhcx/v1/api/session/index.md new file mode 100644 index 000000000..722474332 --- /dev/null +++ b/site/docs/nhcx/v1/api/session/index.md @@ -0,0 +1,33 @@ +--- +title: Session +sidebar_label: Overview +sidebar_position: 0 +description: "The Session calls on NHCX: what each one does, the hosts they go to, and the guides that use them." +verification: unverified +source: nhcx-package/apis/01-session +generated: true +--- + +# Session + +The token does not come from NHCX. + +## Calls + +| Call | Method and path | What it does | +| --- | --- | --- | +| [Session token](/docs/nhcx/v1/api/session/endpoints/session-session-token) | `POST /api/hiecm/gateway/v3/sessions` | Mints the ABDM gateway session token that every NHCX call carries, from the client ID and secret issued for Milestone 1. | + +## Base URLs + +| Environment | Base URL | +| --- | --- | +| Sandbox, ABDM session token. | `https://dev.abdm.gov.in` | +| Production. ABDM's published production gateway. Confirm it in your onboarding letter. | `https://apis.abdm.gov.in` | + +## Guides that use these calls + +- [Session token](/docs/nhcx/v1/getting-started/session-token) +- [Quickstart](/docs/nhcx/v1/getting-started/quickstart) + +The whole specification, with a request you can send from the page, is the [Session API reference](/reference/nhcx-session). diff --git a/site/docs/nhcx/v1/api/status/_category_.json b/site/docs/nhcx/v1/api/status/_category_.json new file mode 100644 index 000000000..76c004b5c --- /dev/null +++ b/site/docs/nhcx/v1/api/status/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Status and search", + "position": 9 +} diff --git a/site/docs/nhcx/v1/api/status/index.md b/site/docs/nhcx/v1/api/status/index.md new file mode 100644 index 000000000..bc1163890 --- /dev/null +++ b/site/docs/nhcx/v1/api/status/index.md @@ -0,0 +1,46 @@ +--- +title: Status and search +sidebar_label: Overview +sidebar_position: 0 +description: "The Status and search calls on NHCX: what each one does, the hosts they go to, and the guides that use them." +verification: unverified +source: nhcx-package/apis/08-status +generated: true +--- + +# Status and search + +Asynchronous exchanges lose messages, stall in queues and outlive the shift of the desk operator who started them. + +## Calls + +| Call | Method and path | What it does | +| --- | --- | --- | +| [Status check](/docs/nhcx/v1/api/status/endpoints/status-v1-status) | `POST /v1/status` | Sender asks NHCX where its own in-flight request stands; the gateway answers request.queued or request.dispatched, and only dispatched yields a callback. | +| [Search submit](/docs/nhcx/v1/api/status/endpoints/status-v1-search-submit) | `POST /v1/search/submit` | Authorised entity such as NHA or IRDAI sends a Task to retrieve claim information for a case; the payer returns the documents on the search callback. | +| [Search result callback](/docs/nhcx/v1/api/status/endpoints/status-v1-search-on-submit) | `POST /v1/search/on_submit` | Callback returning a search result for task type code=poll; for a claim-document search the payload is the ClaimResponse for the reference number. | + +## Callbacks you host + +The exchange posts these to the `endpoint_url` you registered. Answer each with HTTP 202 first. + +| Path | Hosted by | +| --- | --- | +| `/v1/status` | The payer | +| `/v1/search/submit` | The payer | +| `/v1/search/on_submit` | The provider | + +## Base URLs + +| Environment | Base URL | +| --- | --- | +| Sandbox, NHCX exchange. | `https://apisbx.abdm.gov.in/hcx` | +| Production. | `https://apisprod.nha.gov.in/hcx` | + +## Guides that use these calls + +- [Predetermination, status and search](/docs/nhcx/v1/reference/fhir/predetermination-status-and-search) +- [Accepted with 202, and no callback arrives](/docs/nhcx/v1/troubleshooting/accepted-then-no-callback) +- [Responses arrive against the wrong request](/docs/nhcx/v1/troubleshooting/responses-arrive-against-the-wrong-request) + +The whole specification, with a request you can send from the page, is the [Status and search API reference](/reference/nhcx-status). diff --git a/site/docs/nhcx/v1/concepts/README.md b/site/docs/nhcx/v1/concepts/README.md deleted file mode 100644 index 97d322116..000000000 --- a/site/docs/nhcx/v1/concepts/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Core concepts - -One page per concept a developer must hold to integrate with NHCX. Explain -in plain words, link every mention of another concept, endpoint or glossary -term to its page. - diff --git a/site/docs/nhcx/v1/concepts/_category_.json b/site/docs/nhcx/v1/concepts/_category_.json index 819caeee0..543b1dd31 100644 --- a/site/docs/nhcx/v1/concepts/_category_.json +++ b/site/docs/nhcx/v1/concepts/_category_.json @@ -1,5 +1,4 @@ { "label": "Core concepts", - "position": 4, - "className": "sidebar-icon sidebar-icon--shapes" + "position": 5 } diff --git a/site/docs/nhcx/v1/concepts/how-claims-move-on-nhcx.md b/site/docs/nhcx/v1/concepts/how-claims-move-on-nhcx.md new file mode 100644 index 000000000..2ca460588 --- /dev/null +++ b/site/docs/nhcx/v1/concepts/how-claims-move-on-nhcx.md @@ -0,0 +1,156 @@ +--- +title: How claims move on NHCX +sidebar_label: How claims move on NHCX +sidebar_position: 2 +description: End-to-end claim journey in plain language +verification: unverified +source: nhcx-package/docs/01-Overview/02-How Claims Move on NHCX.md +generated: true +--- + +# How claims move on NHCX + +This chapter describes how a health insurance claim moves from point of care to settlement, comparing traditional email-and-portal workflows with the National Health Claims Exchange (NHCX) paradigm. + +--- + +## 1. What Is Claim Settlement? + +Claim settlement is the end-to-end process by which a policyholder's or treating hospital's request for payment of medical expenses is evaluated, approved, and fulfilled by an insurer or State Health Agency (SHA): +- **Cashless Treatment**: The beneficiary receives inpatient care without paying out-of-pocket expenses up to policy limits or package rates, executed between an empanelled hospital (Provider) and the insurer/payer. +- **Reimbursement**: The beneficiary pays the hospital directly upon discharge and subsequently files for reimbursement from the insurer. +- **The Core Participants**: + - **Provider**: The treating hospital and its Hospital Management Information System (HMIS). + - **Payer**: The insurance company, SHA, or Third-Party Administrator (TPA) adjudicating and settling the claim. + - **Exchange**: The NHCX gateway orchestrating routing, security envelopes, protocol audit, and asynchronous delivery. + +--- + +## 2. From Fragmented Portals to a Unified Exchange + +Historically, hospitals interacted with insurers through email correspondence or by logging into 30+ proprietary insurer and TPA portals: +- **Duplication & Cost**: Every insurer required distinct logins, document formats, and upload conventions, creating administrative bottlenecks. +- **Unstructured Scans**: Clinical summaries and bills were transmitted as scanned PDFs or image attachments, requiring manual scrutiny by claim processing doctors and preventing automated adjudication. + +### The NHCX Solution +NHCX operates as a national clearinghouse (analogous to a financial securities exchange or UPI): +1. **Single Connection**: A hospital integrates once with the gateway and immediately reaches all registered insurance companies and state schemes. +2. **Structured FHIR Payloads**: Transactions travel as machine-readable HL7 FHIR Release 4 bundles. Diagnoses (ICD-10), procedures/packages (SNOMED / Scheme masters), observations (LOINC), and itemized tariffs are transmitted as structured data, enabling rules-based auto-adjudication. +3. **End-to-End Encryption**: Payloads are sealed inside JSON Web Encryption (JWE) containers using the recipient's public key; the gateway inspects only routing headers and never sees protected health data. + +--- + +## 3. The Asynchronous Request and Callback Pattern + +Claim decisions cannot be processed synchronously; medical pre-authorisation reviews may require minutes to hours, while complex claim scrutinies may take days. NHCX therefore implements a strict asynchronous two-step exchange for every substantive action: + +1. **Action Request**: The initiator invokes an action endpoint (e.g., `POST /v1/preauth/submit`). + - The exchange validates the envelope headers, verifies the sender, and responds immediately with an **HTTP 202 Accepted receipt**. + - This initial receipt confirms message ingestion into the gateway queue. It is **not** an adjudication decision. +2. **Adjudication Callback**: The recipient decrypts the bundle, processes the business decision, and sends an asynchronous response to the matching callback endpoint (e.g., `POST /v1/preauth/on_submit`). + - The exchange delivers the response to the initiator's registered webhook, which in turn returns an HTTP 202 receipt. + +```mermaid +sequenceDiagram + box Provider side + participant P as Hospital (Provider) + end + box Exchange + participant X as NHCX Gateway + end + box Payer side + participant Y as Insurer / SHA (Payer) + end + P->>X: POST /v1/preauth/submit + X-->>P: 202 Accepted (Receipt: queued & routed) + X->>Y: Delivers encrypted payload + Y-->>X: 202 Accepted + Note over Y: Clinical & financial adjudication + Y->>X: POST /v1/preauth/on_submit (Decision) + X-->>Y: 202 Accepted + X->>P: Delivers decision to Provider callback + P-->>X: 202 Accepted +``` + +--- + +## 4. The 10 Steps of Claim Settlement on NHCX + +The traditional ten stages of claim settlement map directly onto NHCX exchanges. + +### Step 1: Intimation + +Absorbed into eligibility and preauthorisation. There is no separate intimation call; the patient's arrival is declared in the eligibility check or in the preauthorisation. + +### Step 2: Policy verification by the hospital + +On `/v1/coverageeligibility/check`. The provider asks whether the beneficiary's policy is active, in force and within its limits. + +### Step 3: Beneficiary and tie-up verification by the payer + +On `/v1/coverageeligibility/on_check`. The payer confirms member validity, empanelment status and benefit limits in one round trip. + +### Step 4: Treatment plan intimation + +On `/v1/preauth/submit`. The admission and the planned package codes reach the payer. + +### Step 5: Preauthorisation + +On `/v1/preauth/on_submit`. The payer issues the authorisation with its financial limit, and its own case number in `preAuthRef`. + +### Step 6: Enhancement + +On `/v1/preauth/submit` again, with the header `x-hcx-use_case: Enhancement`. The hospital asks for a longer stay or a further surgical package. + +### Step 7: Discharge and document submission + +On `/v1/claim/submit`. The structured discharge summary, operative notes, diagnostic reports and the itemised bill under category `MB`. + +### Step 8: Payer query and resolution + +On `/v1/communication/request` from a private insurer, or on the case's own thread under PMJAY. The payer asks for clinical clarification and the provider answers with supporting evidence. + +### Step 9: Claim adjudication + +On `/v1/claim/on_submit`. The final decision: approved, rejected, or approved with line-item deductions. + +### Step 10: Payment and reconciliation + +On `/v1/paymentnotice/request`. The settlement advice with the bank UTR, TDS and deductions, which the provider acknowledges. + +--- + +## 5. End-to-End Claim Lifecycle Flow + +```mermaid +flowchart TD + + A[Patient Arrives at Hospital] --> B[Coverage Eligibility Check] + B --> C[Fetch Insurance Plan & Tariff Master] + C --> D[Submit Preauthorisation Request] + D --> Q1{Payer Adjudication} + Q1 -- Query Raised --> D3[Answer Query with Documents] --> Q1 + Q1 -- Approved --> E[Inpatient Admission & Treatment] + E --> E2{Case Requires Extension?} + E2 -- Yes --> F[Submit Enhancement Request] --> Q1 + E2 -- No --> G[Discharge Patient & Submit Claim] + G --> Q2{Payer Adjudication} + Q2 -- Query Raised --> G3[Submit Additional Documents] --> Q2 + Q2 -- Decided --> H[Claim Adjudication Decision] + H --> I[Payer Issues Payment Notice with UTR] + I --> J[Hospital Acknowledges Settlement] + H -. Rejected or Partial Shortfall .-> K["Task: Reprocess or Arbitration"] + D -. Voluntary Withdrawal .-> L["Task: Cancel Preauth"] + +``` + +--- + +## 6. What Every Participant Must Implement + +- **The Provider (Hospital HMIS)**: + - Initiates outbound API requests for eligibility, preauthorisation, claim submission, search, and tasks (cancellation, reprocess). + - Hosts inbound callback webhooks for preauth decisions, claim verdicts, payer communications, and payment notices. +- **The Payer (Insurer, SHA, TPA)**: + - Hosts inbound callback endpoints for eligibility checks, plan inquiries, preauthorisations, claims, and tasks. + - Initiates outbound communications, adjudication responses, and payment notices. diff --git a/site/docs/nhcx/v1/concepts/index.md b/site/docs/nhcx/v1/concepts/index.md deleted file mode 100644 index 494211479..000000000 --- a/site/docs/nhcx/v1/concepts/index.md +++ /dev/null @@ -1,62 +0,0 @@ ---- -title: Core concepts -sidebar_label: What a claim is made of -description: What a claim is made of on NHCX, at the level the documentation set records. -verification: unverified -source: NHCX__NHCX-Website_DocumentDetails.md -sidebar_position: 4 ---- - -# Core concepts - -This page records what the NHCX documentation set covers. An index is not a -specification: it names what each document covers without describing it. Nothing here has been -read from a payload or run against the exchange, and the rows are cited so you can go to the -source. - -## A claim is a FHIR bundle - -[FHIR](/docs/nhcx/v1/getting-started/glossary#fhir) is the format ABDM uses for clinical data, and NHCX uses it -for claims. Row 11 of [the index](/docs/nhcx/v1) holds which bundle to use per use case, which -value sets to build it from and which values are mandatory, one tab per use case. Row 14 is the -FHIR implementation guide covering both ABDM and NHCX. Row 2 introduces the standards. - -A claim being FHIR does not make it a health record. Records move on -[HIE-CM](/docs/nhcx/v1/getting-started/glossary#hie-cm), under a consent artefact, and a claim carries no consent -of its own. - -## A workflow status travels in the protected header - -Each message carries a protected header, and in it a workflow status code that says where the -request has reached. Row 12 is the sheet of those codes. It is updated when codes change, which -means the codes are data your integration should read rather than constants to compile in. - -## A request cycle is closed by a protocol response - -A call is not finished when it is accepted. The sender has to send a protocol response back to -close the cycle. Row 15 covers that, together with how to handle error scenarios. Row 18 is the -sheet of every error code and scenario, by use case, for the bridge and for NHCX. - -## The two ends and the exchange - -A provider submits, a payer adjudicates, NHCX routes. Rows 9 and 10 hold the use cases each side -must cover for sandbox exit: which API, at whose end, which bundle, which status and the callback -logic. Row 8 covers policy linking and de-linking for a payer or TPA. Row 19 is the dummy payer -implementation, which is what a provider tests against before a real payer exists. - -## Tokens and keys - -Row 3 covers generating a token with the ABDM API for the NHCX APIs, so the session is ABDM's, -not a separate one. Row 20 covers generating the encryption certificate, a public and private key -pair. - -## What is missing - -No endpoint, no request shape, no response shape and no test case for this gateway is documented -in this portal. Row 23 is the Swagger for the use case APIs and the participant service, and it -is the first thing to read when this section is filled in. - -## Next - -- [Registries](/docs/nhcx/v1/registries), who is registered on NHCX -- [NHCX](/docs/nhcx/v1), the full document index diff --git a/site/docs/nhcx/v1/concepts/jwe-status-and-errors.md b/site/docs/nhcx/v1/concepts/jwe-status-and-errors.md new file mode 100644 index 000000000..7fbc9c052 --- /dev/null +++ b/site/docs/nhcx/v1/concepts/jwe-status-and-errors.md @@ -0,0 +1,227 @@ +--- +title: JWE, status and errors +sidebar_label: JWE, status and errors +sidebar_position: 4 +description: Envelope/letter model, cross-gateway relay, unified correlation ID, status lifecycle (`request.stopped`) +verification: unverified +source: nhcx-package/docs/01-Overview/04-JWE, Status and Errors.md +generated: true +--- + +# JWE, status and errors + +The previous chapter got you onto the network. This one is about what a message is, how to tell where it is in its life, and what to do when it is refused. None of it belongs to any single use case, and all of it applies to every one. + +## Envelope and letter + +Picture a sealed letter inside an addressed envelope. + +The envelope is what the exchange reads. It carries who sent the message and who it is for, a number for this particular call and a number for the whole conversation it belongs to. It also carries which step of the claim it represents, the time, and a status word saying whether this is a request going out or an answer coming back. The exchange uses these to route and to keep records. + +The letter is the FHIR bundle. It is sealed with the receiver's public key before it leaves the sender, so the exchange can carry it but cannot read it. Only the receiver can open it. + +A few facts can be written on the outside of the envelope as well, for example the amount claimed. These are called domain headers. They let the exchange keep an audit trail without opening anything. + +This split explains a pattern that runs through the rest of the documentation. If the envelope is wrong, the exchange rejects the message and the sender hears immediately. If the letter is wrong, the receiver rejects it and the sender hears later, on the callback. Two kinds of error, from two different places. + +## One exchange or several + +NHCX is designed so that more than one exchange instance can run, and messages can be relayed between them. A participant's address carries the instance after the `@`, as in `1518@hcx`. When a hospital and its payer are on the same instance, that instance delivers the message. When they are on different instances, the hospital's instance relays it to the payer's. Each instance does its own registry lookup, validation, audit and routing, and the answer, the payment notice and its acknowledgement come back the same way. An exchange that relays is a participant with the role `HIE/HIO.NHCX`, and it cannot see the payload. + +The Technical Specifications appendix names three cases that need a relay: + +1. The provider is on one instance and the payer for the policy's scheme is on another. +2. A beneficiary is treated in a network hospital in another state, and that hospital is on a different instance from the payer. +3. A top-up case, where the primary insurance is handled by a payer on one instance and the secondary insurance by a payer on another. + +## Every field on the envelope + +The format is JWE, and every NHCX field on it starts with `x-hcx-`. + +| Field | In plain words | +| :---- | :---- | +| `sender_code` | Who is sending. Your participant ID. | +| `recipient_code` | Who it is for. For a provider, the processor code from the policy lookup. | +| `api_call_id` | A fresh number for this one call. | +| `request_id` | A number for this request. | +| `correlation_id` | A number for the whole conversation. The same on the request and on every answer to it. | +| `workflow_id` | Which step of the claim this is. The codes are listed in the Workflow Codes chapter. | +| `timestamp` | When it was sent. | +| `status` | Whether this is a request going out or an answer coming back, and how far along. | +| `ben-abha-id` | The beneficiary's ABHA number, without hyphens. Mandatory on every exchange, including those with no beneficiary in the payload. | +| `use_case` | Optional, and the field that distinguishes an enhancement from a resubmission at the protocol layer. The permitted values differ by exchange: `New`, `Enhancement` or `Resubmit` on preauthorisation and status, `New` or `Resubmit` on a claim. | +| `error_details`, `debug_details`, `debug_flag` | Used only when something has gone wrong. The specification gives `debug_flag` as `Error`, `Info` or `Debug`; the workbook and the samples send `INFO`. Envelope Fields says which to send. | + +Two more fields, `alg` and `enc`, name the encryption used. The specification says `RSA-OAEP` with `A256GCM`; the handbook and the live samples use `RSA-OAEP-256`. Follow the samples. + +The serialisation is contested too. The message-security page says to assemble the result in flattened JSON serialisation; the FAQ and the handbook both say compact serialisation, the five-part dot-separated string, and every sample is compact. Build compact. + +**Domain headers** are a few facts written on the outside of the envelope for the exchange's records, such as the amount claimed, so it can keep an audit trail without opening the letter. Envelope Fields gives their naming convention and the ones the sources name. + +## The same conversation + +Three of the numbers above are unique identifiers in the UUID format. `api_call_id` is new every time. `request_id` is new per request. `correlation_id` is the thread that ties an entire transaction together. + +The correlation ID rule is unified and consistent across the network: +1. **On an outbound request**: The initiator sets `correlation_id = api_call_id`. +2. **On an inbound response**: The responder echoes the request's `correlation_id` (which equals the request's `api_call_id`) while generating a brand-new `api_call_id` for the response itself. +3. **On a status query (`/v1/status`)**: The caller sets `correlation_id` to the specific `api_call_id` of the target transaction being checked. + +If a request fails at the gateway layer, the exchange retires that correlation ID. Any subsequent retry must generate a fresh `api_call_id` and fresh `correlation_id`; reusing a failed correlation ID causes silent drops. + +The timestamp is contested on two axes. Format: the protocol page defines it as a Unix timestamp, and the sample header in Common Mistakes carries epoch milliseconds, while the handbook and FAQ both use ISO 8601. Zone: the FAQ says UTC with a trailing `Z`, the handbook says Indian time with `+05:30` and that UTC will fail validation. The sample bundles use ISO with `+05:30`. It is a validated field; establish the form with the payer before building. + +## Status words + +The `status` field says how far along a message is. Only a few values exist, and they pair with the workflow code: the code says which step, the status says where that step stands. + +- `request.initiated` is what an initiator sends. It means "I am starting this". +- `response.partial` is what a responder sends to say "received, working on it", or to give an interim answer. +- `response.complete` is a final answer. +- `response.error` means the message was refused. + +Three more are the exchange's internal lifecycle statuses: +- `request.queued`: The message passed gateway schema and protected header validation and sits in the exchange's dispatch queue. +- `request.dispatched`: The exchange successfully delivered the JWE payload to the recipient's registered callback URL. +- `request.stopped`: The exchange permanently terminated message delivery after exhausting its internal retry schedule (due to recipient timeout, connection drop, or HTTP 5xx failures). A transition to `request.stopped` retires that `correlation_id` forever. Senders must never retry a message with a stopped correlation ID; any subsequent attempt must generate a brand-new `api_call_id` and fresh `correlation_id`. + +The Open Protocol page carries a different seven-value set entirely, `request.initiate`, `request.retry`, `response.success`, `response.fail` and three more. None appears in the workflow sheet, in any sample or in the gateway's validation. It is a superseded draft. + +Put together, a preauthorisation's life reads like this. + +| Who sends | Workflow code | Status | Meaning | +| :---- | :---- | :---- | :---- | +| Provider | 12 | `request.initiated` | New preauthorisation | +| Payer | 20 | `response.partial` | Received, under review | +| Payer | 24 | `request.initiated` | Query raised. The payer is now the initiator. | +| Provider | 19 | `response.complete` | Query answered | +| Payer | 21 | `response.complete` | Approved | + +Using the wrong status is the first item on the portal's list of common mistakes. The full table of which status goes with which code is in the Workflow Codes chapter. + +```mermaid +sequenceDiagram + box Provider side + participant P as Provider + end + box Payer side + participant Y as Payer + end + P->>Y: 12, request.initiated: new preauthorisation + Y-->>P: 20, response.partial: received + Y->>P: 24, request.initiated: query, payer now initiates + P-->>Y: 19, response.complete: query answered + Y-->>P: 21, response.complete: approved +``` + +## The receipt + +When a message reaches the exchange, or reaches your callback, the receiver answers straight away with `202 Accepted` and a short receipt. The receipt repeats the call and correlation numbers, names sender and recipient, says what kind of message it was, and gives a protocol status of `request.queued`, `request.dispatched` or `request.error`. It is not the decision. It says only that the message was taken in. + +Your own callback endpoint must send exactly this receipt, within 30 seconds. Anything else, including a slow `200`, is read as a failed delivery. + +## When a message is refused + +Refusals come from two places, and the envelope-and-letter split above says which. + +**The exchange refuses the envelope.** A missing header, an unknown recipient, an expired token, a bad status value. The sender hears at once, in the response to its own call. + +**The receiver refuses the letter.** It could not decrypt the bundle, or the bundle failed validation. The receiver sends back a **protocol response** on the callback: the same envelope fields, `status` set to `response.error`, and a short code, message and trace in `error_details`. The exchange logs the header part for audit. Business reasons, such as "this patient is not covered", travel inside a sealed response instead, so the exchange never sees them. + +Error codes come in families. `PAYR-` codes are the payer's, and read like plain sentences: not registered with this payer for this policy, policy does not exist, coverage balance insufficient, claim amount exceeds the preauthorisation, duplicate claim. Gateway and bridge codes cover the envelope side. The full sheet, updated 11 August 2026, is on the portal. + +**Retries and the error API.** If your callback does not send a proper receipt, the exchange tries five times and then drops the request, retiring its correlation ID. It then reports the failure to the original sender on a separate endpoint, `/v1/error`, which every participant must host. A system without it never learns that its request died. + +## Codes met live + +The error table reads like a list of code lookups, and several of the codes mean something else in the running sandbox. From the September 2026 run: + +| Code | The message | What it turned out to mean | +| :---- | :---- | :---- | +| `PAYR-1027` | Invalid item id found for item in claim component | `Claim.item` has no FHIR element `id` (`Item/1`). Nothing to do with the package code | +| `PAYR-1083` | No HPR details found for the practitioner … category code as HPIN | The `Practitioner` carries no identifier typed `HPIN` | +| `PAYR-1238` | Beneficiary is having an active preauthorization request at this hospital with reference number … | Scheme rule, not a bundle fault: one live preauthorisation per beneficiary per hospital. The reference number ends in the SHA's case id | +| `PAYR-1401` | Policy not allowed for the hospital | The plan was asked for under a policy the hospital is not empanelled under; ask under the beneficiary's own | +| `PAYR-1019` | Invalid sequence received in supporting info element | A `supportingInfo` entry with no `sequence`; number the whole list once it is assembled | +| `PAYR-1256`, `PAYR-1363` | Response for Authentication Consent Questionnaire is missing | The plan's consent questionnaire, unanswered, where no biometric token was taken | +| `PAYR-1008` | Invalid content type … / Invalid input, code and reason code | Two different faults on one code: a document outside pdf, jpg, jpeg, png and fhir+json; or a Task code paired with a reason the scheme does not accept | +| `PAYR-1245` | Only one conservative procedure can be booked for a case | The master's `ProcedureType`; an enhancement on a conservative case must add a medical package | +| `ERR-PYR-CLM-007` | No prior preauthorization or claim record found for case number | The claim was sent under a number of its own instead of the pre-authorisation's | +| `PAYR-1322` | Active instance found for case number | A request is already open on that case; the scheme takes one at a time | + +`NHCX-1010`, *no data with given correlation id for call back request*, belongs beside them and is the exchange's own. It is what a payer hears when it answers a submission it left silent. NHCX redelivers an unanswered request, drops it after a few tries and retires the correlation, so a verdict taken minutes later has nowhere to land. The remedy is the one the live PMJAY payer uses: acknowledge the submission at once with a `ClaimResponse` whose `outcome` is `queued`, and send the decision later on the same thread. + +Two things follow. A refusal in the `PAYR-102x` block is structural, so check ids and sequences before values. And the refusals arrive in order: the SHA validates the bundle first and applies the scheme's rules only to a bundle that passed, so `PAYR-1238` is, perversely, the first sign the bundle is right. + +## The mistakes everyone makes + +The portal keeps a list. In plain words: + +1. Wrong status word for the leg of the message. +2. No `/v1/error` endpoint, so failures go unnoticed. +3. Answering a callback with something other than `202` and the receipt. +4. Missing or malformed envelope headers. +5. In production, the wrong registry ID: providers send the HFR ID, payers the IRDAI ID without leading zeros. +6. Forgetting the `Accept: application/json` header. +7. Addressing the insurer's code instead of the processor's. +8. Reusing a correlation ID, especially after an error. +9. Retrying on a `401` with the same expired token instead of fetching a new one. +10. Trying to de-link a policy from a participant that did not link it. + +## Everything is logged + +The exchange records every call it receives: the envelope, the encryption details, sender and recipient, and whether validation passed. It never records the letter. Participants can query the audit trail for their own transactions, and NHA publishes reports from it for payers, providers, regulators and observers. + +## What to send when the sources disagree + +This chapter and the ones after it flag every place the published documents contradict each other, which is the honest thing to do but leaves you with a decision to make on each one. This section makes those decisions once. Every value here is what the published sample payloads actually carry, and where no sample settles it the entry says so rather than inventing a ruling. + +Send these. If a payer rejects one, that rejection is better evidence than anything here, and you should follow it. + +### Key wrapping algorithm + +Send `RSA-OAEP-256`. The handbook, the samples and the Postman collection agree. One protocol page says `RSA-OAEP`; it is outnumbered. + +### Content encryption + +Send `A256GCM`. Uncontested in the samples. + +### Serialisation + +Send the compact serialisation, five parts. The message-security page says flattened JSON. The FAQ, the handbook and every sample use compact. + +### Timestamp format + +Send ISO 8601 with `+05:30`. The samples use it throughout. Accept a Unix epoch on the way in. + +### Correlation ID on a response + +Copy the request's `correlation_id`. Settled. On a **request** set it to that message's own `api_call_id`; on a **response** echo the request's `correlation_id`. The workbook has 25 correlation rows: 8 state the request half, 16 the response half, and 1 gives the status enquiry its own rule. The two halves are one rule, not a clash. Envelope Fields has the table. + +### api_call_id + +Send a fresh UUID on every message, including responses. So a response and its request never share one. + +### Identifier type for an ABHA number + +Send `ABHA`. From the NRCeS identifier-type code system, not the HL7 `JHN`. + +### Cancellation Task input name + +Send `intimationNumber`, on the cancel Task as on the reprocess. + +### entity_type in a receipt + +Derive it from the path. The second-to-last segment, or the last where that is `v1`, with `on_` stripped. + +Two points looked unanswerable in earlier versions of this documentation. Both are answered in the sources, and the answers are recorded here. + +**The workflow code for eligibility, insurance plan, search, predetermination and status.** The workflow sheet lists none because the header is optional. `x-hcx-workflow_id` is marked Optional on all twenty-five rows on which it appears, across all ten sheets of the NHCX Requests and Responses workbook, including the CoverageEligibility and Insurance Plan sheets. Send the step code where the sheet gives one. Send nothing where it does not. There is nothing to negotiate. + +The field also carries two readings, which is why it looks unresolved. The Workflow Status Sheet treats it as a step code; the protocol pages define it as an identifier that "may span over a series of message exchanges" for one case. Envelope Fields sets both out. + +**Domain headers.** These are named, and they have a convention. The format is `x-hcx--`, with the use case under sixteen characters and the parameter under thirty-two. The Notification Integration document names four in use: `x-hcx-amount_submitted`, `x-hcx-benefit-category_type`, `x-hcx-benefit_code` and `x-hcx-action`. The eObjects page adds a `Usage` header on the Claim carrying `preauthorization` or `claim`. And the access-control policy requires an insurance marketplace to carry the beneficiary's consent in a domain header before it may be given individual claim data. + +Send none to a payer that has not asked for one. But they exist, and Envelope Fields collects them. + +The full field table, with the obligation of every header and the rules that govern it, is Envelope Fields in the Reference section. Every error code either side can send is Error Codes in the same section. diff --git a/site/docs/nhcx/v1/concepts/nhcx-use-cases.md b/site/docs/nhcx/v1/concepts/nhcx-use-cases.md new file mode 100644 index 000000000..e1df35a34 --- /dev/null +++ b/site/docs/nhcx/v1/concepts/nhcx-use-cases.md @@ -0,0 +1,991 @@ +--- +title: NHCX Use Cases +sidebar_label: NHCX Use Cases +sidebar_position: 5 +description: Catalog of all 40 NHA use cases across A, B, C, D, E series +verification: unverified +source: nhcx-package/docs/01-Overview/05-NHCX Use Cases.md +generated: true +--- + +# NHCX Use Cases + +A use case covers each stage of the claims lifecycle: onboarding providers and payers onto the network, verifying coverage, seeking preauthorisation, submitting claims, exchanging supporting information, and reconciling payments. Between them they deliver the core objectives of standardisation, traceability, and predictable auto-adjudication across India's National Health Claims Exchange (NHCX). + +## Key Use Cases Overview + +- **Onboarding Providers and Payers**: Onboard participants onto NHCX to validate and route requests to target applications. +- **Check Coverage Eligibility**: Called by providers to verify beneficiary coverage, policy validity, sum insured, sub-limits, and document requirements. +- **Preauth Request Submission**: Submitted by providers before admission or planned surgery. Payers respond with line-item adjudication via `on_submit`. +- **Predetermination Request**: Inquires expected coverage and deductible calculations for planned procedures without reserving policy balance. +- **Claim Request Submission**: Submitted by providers upon discharge with final bill, discharge summary, and itemised claims. +- **Communication Request**: Enables payers to query providers for additional documents (`additionalinfo`), flag turnaround-time breaches (`tatquery`), or issue policy updates. +- **Payment Notice & Reconciliation**: Payers notify providers of bank transfers (UTR), detailing claimed, approved, TDS, and settled amounts. +- **Reprocess / Cancel / Shortfall**: Providers appeal rejected claims (`reprocess`), request partial payment balance (`partialpayment`), or cancel approved preauthorisations. +- **Beneficiary Notifications**: Push notifications to personal health record (PHR) apps on claim status changes. + +--- + +## Master Use Cases Matrix + +All 40 NHA use cases by role, each with its API call and callback. + +### Shared + +#### A1 Get participant list + +The participants in the registry, by role. + +**API Call:** `/fetch/participants/list` + +#### A2 Get policy + +The policies a beneficiary holds, by mobile number or ABHA. + +**API Call:** `/participant/get/policies` + +#### A3 Get public key + +The recipient's certificate, which is what the bundle is encrypted with. + +**API Call:** `/fetch/certs` + +#### A4 Get auth token + +The ABDM session token every NHCX call carries, minted with the Milestone 1 client id and secret. + +**API Call:** `/get/session` + +#### A5 Get status + +Where any request you made got to, by its correlation id. + +**API Call:** `/v1/status` +**Callback:** `/v1/on_status` + +#### A6 Receive errors + +Where the exchange tells you a request could not be delivered after five attempts. + +**API Call:** hosted only +**Callback:** `/v1/error` + +### Provider + +#### B1 Check coverage eligibility + +Is the policy in force, what is left in the wallet, and what must be attached. + +**API Call:** `/v1/coverageeligibility/check` +**Callback:** `/v1/coverageeligibility/on_check` + +#### B2 Request insurance plan + +A Task with code poll, keyed on policy number and provider id. + +**API Call:** `/v1/insuranceplan/request` +**Callback:** `/v1/insuranceplan/on_request` + +#### B3 Submit pre-authorisation + +Permission to treat. + +**API Call:** `/v1/preauth/submit` +**Callback:** `/v1/preauth/on_submit` + +#### B4 Respond to a communication + +Acknowledge or answer a message the payer sent about a case. + +**API Call:** `/v1/communication/on_request` +**Callback:** `/v1/communication/request` + +#### B5 Submit claim + +Reimbursement after discharge. + +**API Call:** `/v1/claim/submit` +**Callback:** `/v1/claim/on_submit` + +#### B6 Search claims + +Look up claim information by criteria. + +**API Call:** `/v1/search/submit` +**Callback:** `/v1/search/on_submit` + +#### B7 Acknowledge payment notice + +The receipt for a payment notice, as a Task on this endpoint. + +**API Call:** `/v1/paymentnotice/on_request` +**Callback:** `/v1/paymentnotice/request` + +#### B8 Reprocess or cancel + +One endpoint, several jobs, told apart by the Task's code and reason: reprocess with claimrejected, shortfall with partialpayment, cancel. + +**API Call:** `/v1/task/submit` +**Callback:** `/v1/task/on_submit` + +#### B9 Submit predetermination + +What would the payer approve for this treatment? + +**API Call:** `/v1/predetermination/submit` +**Callback:** `/v1/predetermination/on_submit` + +### PMJAY + +#### D1 Fetch the insurance plan + +Keyed on provider id, policy code and participant id. + +**API Call:** `/v1/insuranceplan/request` +**Callback:** `/v1/insuranceplan/on_request` + +#### D2 Authenticate the beneficiary + +Fingerprint, iris or face; all three must be built. + +**API Call:** ABHA biometric auth init and verify (not NHCX) + +#### D3 Check coverage eligibility + +Validation after registration returns the wallet, one benefit entry per wallet with allowed and used. + +**API Call:** `/v1/coverageeligibility/check` +**Callback:** `/v1/coverageeligibility/on_check` + +#### D4 Submit pre-authorisation + +Not more than one day before admission, with the biometric token or the consent response, the documents the auth-requirements answer asked for, the STG questionnaire for each package, and the registration and admission dates as supporting info. + +**API Call:** `/v1/preauth/submit` +**Callback:** `/v1/preauth/on_submit` + +#### D5 Resubmit pre-authorisation + +Revises an approved or rejected case for a different amount or package. + +**API Call:** `/v1/preauth/submit` +**Callback:** `/v1/preauth/on_submit` + +#### D6 Raise an enhancement + +Adds to an approved pre-authorisation, as many times as needed until discharge, one at a time, and only for packages whose plan flag allows it. + +**API Call:** `/v1/preauth/submit` +**Callback:** `/v1/preauth/on_submit` + +#### D7 Answer a pre-authorisation query + +The query arrived as a ClaimResponse on 24, on the case's own thread, with the question in the item adjudication, not on the communication API. + +**API Call:** `/v1/preauth/submit` +**Callback:** `/v1/preauth/on_submit` + +#### D8 Cancel pre-authorisation + +A Task with code cancel, the case number as input and one of seven reasons: treatmentplanchanged, patientrequest, financialconstraints, alternativetreatment, duplicateclaim, administrativeerror, other. + +**API Call:** `/v1/task/submit` +**Callback:** `/v1/task/on_submit` + +#### D9 Submit claim + +There is no discharge submission: the claim asserts the discharge and carries its details. + +**API Call:** `/v1/claim/submit` +**Callback:** `/v1/claim/on_submit` + +#### D10 Answer a claim query + +As D7, on the claim endpoint: the query is a ClaimResponse on 27, the answer a fresh submit on 161. + +**API Call:** `/v1/claim/submit` +**Callback:** `/v1/claim/on_submit` + +#### D11 Reprocess a rejected claim + +An appeal, not a resubmission: a Task with code reprocess and reason claimrejected, a supporting document attached, no amount. + +**API Call:** `/v1/task/submit` +**Callback:** `/v1/task/on_submit` + +#### D12 Claim a shortfall + +The same Task with reason partialpayment and an amount capped at the difference, allowed only after payment notice 33 has arrived and been acknowledged with 17. + +**API Call:** `/v1/task/submit` +**Callback:** `/v1/task/on_submit` + +#### D13 Acknowledge the payment notice + +Three notices may arrive: 30 when the transfer is initiated, 31 when the bank processes it, 33 when it settles with the UTR. + +**API Call:** `/v1/paymentnotice/on_request` +**Callback:** `/v1/paymentnotice/request` + +### Payer + +#### C1 Link ABHA with policy + +Tie the ABHA number, mobile and member id to the policy's products at policy creation, naming the payer and the processor. + +**API Call:** `/participant/link/abha/policy` + +#### C2 De-link ABHA from policy + +Undo C1. + +**API Call:** `/participant/delink/abha/policy` + +#### C3 Respond to coverage eligibility + +The eligibility and plan details for the beneficiary asked about. + +**API Call:** `/v1/coverageeligibility/on_check` +**Callback:** `/v1/coverageeligibility/check` + +#### C4 Respond to insurance plan request + +The plan as a benefit structure. + +**API Call:** `/v1/insuranceplan/on_request` +**Callback:** `/v1/insuranceplan/request` + +#### C5 Respond to pre-authorisation + +The adjudicated pre-authorisation. + +**API Call:** `/v1/preauth/on_submit` +**Callback:** `/v1/preauth/submit` + +#### C6 Raise a communication + +A message about a case, typed by its reason code: additionalinfo, tatquery for a turnaround breach, grievance, walletupdate, policychange, claimArbitration. + +**API Call:** `/v1/communication/request` +**Callback:** `/v1/communication/on_request` + +#### C7 Respond to claim + +The adjudicated claim, item by item, with any deduction and its reason. + +**API Call:** `/v1/claim/on_submit` +**Callback:** `/v1/claim/submit` + +#### C8 Respond to search + +The ClaimResponse objects matching the criteria asked for. + +**API Call:** `/v1/search/on_submit` +**Callback:** `/v1/search/submit` + +#### C9 Send payment notice + +The money, on a new thread of its own, with the reconciliation itemised by type: approved, claimed, tds, servicetax, advance, recovered, penality. + +**API Call:** `/v1/paymentnotice/request` +**Callback:** `/v1/paymentnotice/on_request` + +#### C10 Respond to a Task + +The answer to a reprocess, shortfall or cancel. + +**API Call:** `/v1/task/on_submit` +**Callback:** `/v1/task/submit` + +#### C11 Respond to predetermination + +What the payer would approve for the proposed treatment. + +**API Call:** `/v1/predetermination/on_submit` +**Callback:** `/v1/predetermination/submit` + +### Patient app + +#### E1 Subscribe to notifications + +A patient app subscribes when the beneficiary logs in with their ABHA, and the most recent subscription wins. + +**API Call:** `/v1/notification/subscribe` +**Callback:** `/v1/notification/on_subscribe` + +--- + +## Shared Use Cases (Payer and Provider) + +The following use cases are common to both Payer and Provider participants on the NHCX platform. None of them carries a workflow code, because they are registry and session calls rather than claim transactions. + +### A1: Get participant list + +- **Role / Side:** `shared` +- **API Called:** `/fetch/participants/list` +- **Carries JWE:** `false` +- **Simulator Console:** `/participants` +- **Data Element Mapping:** `package/mappings/A1.yaml` + +The participants in the registry, by role. How a provider finds a payer and a payer finds a provider. + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `roles` | Requested Role Filter | Request | `array[string]` | `1..*` | `Request.roles` | `["payor"]` | | +| `participantCode` | Participant ID (@hcx) | Response | `string` | `1..1` | `Organization.identifier[system=https://nhcx.gov.in].value` | `1000003538@hcx` | also at `Header.x-hcx-recipient_code` | +| `participantName` | Entity Name | Response | `string` | `1..1` | `Organization.name` | `State Health Agency Himachal` | | +| `endpointUrl` | Gateway Callback URL | Response | `url` | `1..1` | `Endpoint.address` | `https://payer.example.org/nhcx/v1` | | +| `encryptionCertPath` | Encryption Certificate Path | Response | `url` | `1..1` | `Response.encryption_cert_path` | `https://apisbx.abdm.gov.in/certs/1000003538.pem` | | + +NRCeS profiles: [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html). + +### A2: Get policy + +- **Role / Side:** `shared` +- **API Called:** `/participant/get/policies` +- **Carries JWE:** `false` +- **Simulator Console:** `/search` +- **Data Element Mapping:** `package/mappings/A2.yaml` + +The policies a beneficiary holds, by mobile number or ABHA. Each names the insurer and the processor, and the processor is the recipient for every claim-side call. + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `mobile` | Beneficiary Mobile | Request | `string` | `0..1` | `Patient.telecom[system=phone].value` | `9876543210` | | +| `abhaNumber` | ABHA Number | Request | `string` | `0..1` | `Patient.identifier[type=ABHA].value` | `91234567890123` | | +| `policyNumber` | Discovered Policy Number | Response | `string` | `1..1` | `Coverage.identifier[0].value` | `POL-HOSP-2026-0045` | | +| `insurerId` | Insurer Participant Code | Response | `string` | `1..1` | `Organization[type=pay].identifier[system=https://nhcx.gov.in].value` | `1000003538@hcx` | | +| `processorId` | Claim Processor Participant Code | Response | `string` | `1..1` | `Organization[type=tpa].identifier[system=https://nhcx.gov.in].value` | `1000004520@hcx` | | + +NRCeS profiles: [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html), [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html), [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html). + +### A3: Get public key + +- **Role / Side:** `shared` +- **API Called:** `/fetch/certs` +- **Carries JWE:** `false` +- **Simulator Console:** `/participants` +- **Data Element Mapping:** `package/mappings/A3.yaml` + +The recipient's certificate, which is what the bundle is encrypted with. Fetched before anything is addressed to a participant. + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `participantCode` | Target Participant Code | Request | `string` | `1..1` | `Request.participant_code` | `1000003538@hcx` | | +| `certData` | Public Key PEM Certificate | Response | `string` | `1..1` | `Response.certs[0]` | `-----BEGIN CERTIFICATE----- MIIBIjANBgkqhkiG9w0BAQEFAAO...` | | + +### A4: Get auth token + +- **Role / Side:** `shared` +- **API Called:** `/get/session` +- **Carries JWE:** `false` +- **Simulator Console:** `/session` +- **Data Element Mapping:** `package/mappings/A4.yaml` + +The ABDM session token every NHCX call carries, minted with the Milestone 1 client id and secret. + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `clientId` | Client ID | Request | `string` | `1..1` | `Request.clientId` | `SBX_001205` | | +| `clientSecret` | Client Secret | Request | `string` | `1..1` | `Request.clientSecret` | `secret_xyz` | | +| `accessToken` | Bearer Access Token | Response | `string` | `1..1` | `Header.Authorization` | `eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...` | also at `Header.bearer_auth` | +| `expiresIn` | Token Validity Seconds | Response | `integer` | `1..1` | `Response.expiresIn` | `3600` | | + +### A5: Get status + +- **Role / Side:** `shared` +- **API Called:** `/v1/status` +- **Callback API:** `/v1/on_status` +- **Carries JWE:** `true` +- **Simulator Console:** `/status` +- **Data Element Mapping:** `package/mappings/A5.yaml` +- **FHIR Reference:** [Predetermination, Status and Search, A5](/docs/nhcx/v1/reference/fhir/predetermination-status-and-search#a5-get-status-shared) + +Where any request you made got to, by its correlation id. The sandbox's own status page answers without a token. + +### A6: Receive errors + +- **Role / Side:** `shared` +- **API Called:** `(hosted only)` +- **Callback API:** `/v1/error` +- **Carries JWE:** `false` +- **Data Element Mapping:** `package/mappings/A6.yaml` + +Where the exchange tells you a request could not be delivered after five attempts. Without it a sender never learns that a request died, which looks exactly like a case still under review. + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `correlationId` | Failed Transaction ID | Error | `uuid` | `1..1` | `Header.x-hcx-correlation_id` | `4f9d2b80-13b4-4e2a-9e12-8f9024a56789` | | +| `errorCode` | Error Code | Error | `string` | `1..1` | `Error.code` | `ERR_RECIPIENT_UNREACHABLE` | | +| `errorMessage` | Error Description | Error | `string` | `1..1` | `Error.message` | `Recipient gateway timed out after 5 attempts` | | + +## Provider Use Cases + +The following use cases are initiated by Provider participants (hospitals, daycare centers) to verify coverage, submit preauthorisations, answer queries, submit claims, and reconcile payments. + +### B1: Check coverage eligibility + +- **Role / Side:** `provider` +- **API Called:** `/v1/coverageeligibility/check` +- **Callback API:** `/v1/coverageeligibility/on_check` +- **Workflow ID:** `none; sits beside registration 10 and admission 11` +- **Carries JWE:** `true` +- **Data Element Mapping:** `package/mappings/B1.yaml` +- **FHIR Reference:** [Coverage Eligibility Request, B1](/docs/nhcx/v1/reference/fhir/coverage-eligibility-request#b1-check-coverage-eligibility-provider) +- **Sample FHIR Bundles (5):** `B1-check.json`, `auth-requirements.json`, `benefits.json`, `discovery.json`, `validation.json` + +Is the policy in force, what is left in the wallet, and what must be attached. One endpoint, four purposes: discovery, validation, benefits, auth-requirements. + +### B2: Request insurance plan + +- **Role / Side:** `provider` +- **API Called:** `/v1/insuranceplan/request` +- **Callback API:** `/v1/insuranceplan/on_request` +- **Carries JWE:** `true` +- **Data Element Mapping:** `package/mappings/B2.yaml` +- **FHIR Reference:** [Insurance Plan Request, B2](/docs/nhcx/v1/reference/fhir/insurance-plan-request#b2-request-insurance-plan-provider) +- **Sample FHIR Bundles (2):** `B2-request.json`, `insurance-plan-request.json` + +A Task with code poll, keyed on policy number and provider id. The answer is the policy as a benefit structure: packages, rates, documents, questionnaires. + +### B3: Submit pre-authorisation + +- **Role / Side:** `provider` +- **API Called:** `/v1/preauth/submit` +- **Callback API:** `/v1/preauth/on_submit` +- **Workflow ID:** `12 new, 121 resubmission, 13 enhancement; under PMJAY 19 answers a query and 131 an enhancement query` +- **Carries JWE:** `true` +- **Data Element Mapping:** `package/mappings/B3.yaml` +- **FHIR Reference:** [Preauthorisation Request, B3](/docs/nhcx/v1/reference/fhir/preauthorisation-request#b3-submit-pre-authorisation-provider) +- **Sample FHIR Bundles (6):** `B3-enhancement.json`, `B3-request.json`, `preauth-cancel.json`, `preauth-enhancement.json`, `preauth-queryupdate.json`, `preauth-request.json` + +Permission to treat. A resubmission, an enhancement and a query answer all reuse the same bundle with a new correlation id and the original reference; only the workflow code tells them apart. The acknowledgement on 20 brings the payer's own case number, and the desk files everything under it. + +### B4: Respond to a communication + +- **Role / Side:** `provider` +- **API Called:** `/v1/communication/on_request` +- **Callback API:** `/v1/communication/request` +- **Workflow ID:** `24, 241 or 27, echoed from the payer's request` +- **Carries JWE:** `true` +- **Data Element Mapping:** `package/mappings/B4.yaml` +- **FHIR Reference:** [Communication, B4](/docs/nhcx/v1/reference/fhir/communication#b4-respond-to-a-communication-provider) +- **Sample FHIR Bundles (5):** `B4-claim-query-answer.json`, `B4-preauth-query-answer.json`, `communication-acknowledgement.json`, `communication-request.json`, `communication-response.json` + +Acknowledge or answer a message the payer sent about a case. A generic or IRDAI payer raises its query here, as a CommunicationRequest task bundle carrying 24, 241 or 27; the answer is a Communication task bundle on on_request that echoes the request's correlation id and workflow id. The payer's reason code says what kind of message it was. + +### B5: Submit claim + +- **Role / Side:** `provider` +- **API Called:** `/v1/claim/submit` +- **Callback API:** `/v1/claim/on_submit` +- **Workflow ID:** `15 claim, 161 query answer under PMJAY, 14 provisional discharge where a payer supports one` +- **Carries JWE:** `true` +- **Data Element Mapping:** `package/mappings/B5.yaml` +- **FHIR Reference:** [Claim Request, B5](/docs/nhcx/v1/reference/fhir/claim-request#b5-submit-claim-provider) +- **Sample FHIR Bundles (5):** `B5-request.json`, `claim-queryupdate.json`, `claim-release.json`, `claim-reprocess.json`, `claim-request.json` + +Reimbursement after discharge. The amount may not exceed what the pre-authorisation approved. The acknowledgement on 25 brings the payer's case number. PMJAY takes a claim query answer on 161 only; 151, 19 and 16 are refused with PAYR-1321. + +### B6: Search claims + +- **Role / Side:** `provider` +- **API Called:** `/v1/search/submit` +- **Callback API:** `/v1/search/on_submit` +- **Carries JWE:** `true` +- **Data Element Mapping:** `package/mappings/B6.yaml` +- **FHIR Reference:** [Predetermination, Status and Search, B6](/docs/nhcx/v1/reference/fhir/predetermination-status-and-search#b6-search-claims-provider) +- **Sample FHIR Bundles (1):** `claim-search.json` + +Look up claim information by criteria. The provider sandbox exit checklist names /v1/search/submit for claim search, while the Technical Specifications route /search/submit from NHA through NHCX to the payer: a cross-payer search for NHA or a regulator. A provider's search over its own cases is /claim/search in the protocol, which the access-control policy allows for requests that originated from the provider. No source confirms which of the two the sandbox accepts from a provider. + +### B7: Acknowledge payment notice + +- **Role / Side:** `provider` +- **API Called:** `/v1/paymentnotice/on_request` +- **Callback API:** `/v1/paymentnotice/request` +- **Workflow ID:** `30 echoed from the notice on the generic network; 17 under PMJAY` +- **Carries JWE:** `true` +- **Data Element Mapping:** `package/mappings/B7.yaml` +- **FHIR Reference:** [Payment Notice and Acknowledgement, B7](/docs/nhcx/v1/reference/fhir/payment-notice-and-acknowledgement#b7-acknowledge-payment-notice-provider) +- **Sample FHIR Bundles (2):** `B7-acknowledgement.json`, `payment-notice-ack.json` + +The receipt for a payment notice, as a Task on this endpoint. The notice arrives on a new thread of its own; a generic payer takes the acknowledgement with the notice's 30 echoed, PMJAY with 17. + +### B8: Reprocess or cancel + +- **Role / Side:** `provider` +- **API Called:** `/v1/task/submit` +- **Callback API:** `/v1/task/on_submit` +- **Workflow ID:** `PC01 cancel, 36 reprocess or shortfall` +- **Carries JWE:** `true` +- **Data Element Mapping:** `package/mappings/B8.yaml` +- **FHIR Reference:** [Cancel, Reprocess and Shortfall, B8](/docs/nhcx/v1/reference/fhir/cancel-reprocess-and-shortfall#b8-reprocess-or-cancel-provider) +- **Sample FHIR Bundles (2):** `B8-cancel.json`, `B8-reprocess.json` + +One endpoint, several jobs, told apart by the Task's code and reason: reprocess with claimrejected, shortfall with partialpayment, cancel. A reprocess goes on 36 and is acknowledged on 37; a cancel goes on PC01 and is done on PC02. Both carry the input intimationNumber. A supporting document is mandatory on a reprocess. + +### B9: Submit predetermination + +- **Role / Side:** `provider` +- **API Called:** `/v1/predetermination/submit` +- **Callback API:** `/v1/predetermination/on_submit` +- **Carries JWE:** `true` +- **Data Element Mapping:** `package/mappings/B9.yaml` +- **FHIR Reference:** [Predetermination, Status and Search, B9](/docs/nhcx/v1/reference/fhir/predetermination-status-and-search#b9-submit-predetermination-provider) +- **Sample FHIR Bundles (1):** `predetermination-request.json` + +What would the payer approve for this treatment? Same bundle shape as a pre-authorisation, asked before committing to one. + +## PMJAY Scheme Use Cases + +The following use cases govern the Pradhan Mantri Jan Arogya Yojana (AB PM-JAY) cashless lifecycle as detailed in the official NHA PMJAY Handbook. They follow strict Standard Treatment Guidelines (STG), mandatory biometrics, package rules, and Turnaround Time (TAT) auto-approvals. + +### D1: Fetch the insurance plan + +- **Role / Side:** `pmjay` +- **API Called:** `/v1/insuranceplan/request` +- **Callback API:** `/v1/insuranceplan/on_request` +- **Carries JWE:** `true` +- **Data Element Mapping:** `package/mappings/D1.yaml` +- **FHIR Reference:** [Insurance Plan Request, D1](/docs/nhcx/v1/reference/fhir/insurance-plan-request#d1-fetch-the-insurance-plan-pmjay) +- **Sample FHIR Bundles (1):** `D1-request.json` + +Keyed on provider id, policy code and participant id. The answer is the scheme configuration for this hospital: specialities, packages, rates, Claim-Condition flags, mandatory documents and questionnaires. Over twenty megabytes; store it queryable, version it, refresh weekly and on any policychange communication. + +### D2: Authenticate the beneficiary + +- **Role / Side:** `pmjay` +- **API Called:** `ABHA biometric auth init and verify (not NHCX)` +- **Carries JWE:** `false` +- **Data Element Mapping:** `package/mappings/D2.yaml` + +Fingerprint, iris or face; all three must be built. Success yields a user token valid thirty minutes that rides on the eligibility check and the pre-authorisation; a fresh one rides on the claim. Where biometrics are impossible, a signed exemption consent and the matching questionnaire stand in, except on a cyclic case. + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `abhaNumber` | ABHA Number | Auth | `string` | `1..1` | `Patient.identifier[type=ABHA].value` | `91234567890123` | | +| `authMode` | Authentication Mode | Auth | `string` | `1..1` | `Request.authMode` | `DEMOGRAPHICS` | | +| `authToken` | Biometric Consent Token | Auth | `string` | `1..1` | `Response.token` | `bio-token-778899` | | + +NRCeS profiles: [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html). + +### D3: Check coverage eligibility + +- **Role / Side:** `pmjay` +- **API Called:** `/v1/coverageeligibility/check` +- **Callback API:** `/v1/coverageeligibility/on_check` +- **Carries JWE:** `true` +- **Data Element Mapping:** `package/mappings/D3.yaml` +- **FHIR Reference:** [Coverage Eligibility Request, D3](/docs/nhcx/v1/reference/fhir/coverage-eligibility-request#d3-check-coverage-eligibility-pmjay) +- **Sample FHIR Bundles (1):** `D3-check.json` + +Validation after registration returns the wallet, one benefit entry per wallet with allowed and used. Benefits and auth-requirements before a pre-authorisation return what the package needs attached. Register only after coverage is validated, and validate again every time treatment is added. + +### D4: Submit pre-authorisation + +- **Role / Side:** `pmjay` +- **API Called:** `/v1/preauth/submit` +- **Callback API:** `/v1/preauth/on_submit` +- **Workflow ID:** `12` +- **Carries JWE:** `true` +- **Simulator Console:** `/builder?family=preauth&usecase=initiate` +- **Data Element Mapping:** `package/mappings/D4.yaml` +- **FHIR Reference:** [Preauthorisation Request, D4](/docs/nhcx/v1/reference/fhir/preauthorisation-request#d4-submit-pre-authorisation-pmjay) +- **Sample FHIR Bundles (1):** `D4-request.json` + +Not more than one day before admission, with the biometric token or the consent response, the documents the auth-requirements answer asked for, the STG questionnaire for each package, and the registration and admission dates as supporting info. Auto-approved only if it is the first pre-authorisation for the case and every package allows it. + +### D5: Resubmit pre-authorisation + +- **Role / Side:** `pmjay` +- **API Called:** `/v1/preauth/submit` +- **Callback API:** `/v1/preauth/on_submit` +- **Workflow ID:** `121` +- **Carries JWE:** `true` +- **Simulator Console:** `/builder?family=preauth&usecase=resubmit` +- **Data Element Mapping:** `package/mappings/D5.yaml` +- **FHIR Reference:** [Preauthorisation Request, D5](/docs/nhcx/v1/reference/fhir/preauthorisation-request#d5-resubmit-pre-authorisation-pmjay) + +Revises an approved or rejected case for a different amount or package. Nullifies every earlier instance; the payer treats it as the new base request. + +### D6: Raise an enhancement + +- **Role / Side:** `pmjay` +- **API Called:** `/v1/preauth/submit` +- **Callback API:** `/v1/preauth/on_submit` +- **Workflow ID:** `13, and 131 to answer an enhancement query raised on 241` +- **Carries JWE:** `true` +- **Simulator Console:** `/builder?family=preauth&usecase=enhance` +- **Data Element Mapping:** `package/mappings/D6.yaml` +- **FHIR Reference:** [Preauthorisation Enhancement, D6](/docs/nhcx/v1/reference/fhir/preauthorisation-enhancement#d6-raise-an-enhancement-pmjay) +- **Sample FHIR Bundles (2):** `D6-enhancement-query-answer.json`, `D6-enhancement.json` + +Adds to an approved pre-authorisation, as many times as needed until discharge, one at a time, and only for packages whose plan flag allows it. The bundle carries the approved items and the ones now sought. A query on it arrives as a ClaimResponse on 241, on the case's own thread, and is answered by a fresh submit on 131. + +### D7: Answer a pre-authorisation query + +- **Role / Side:** `pmjay` +- **API Called:** `/v1/preauth/submit` +- **Callback API:** `/v1/preauth/on_submit` +- **Workflow ID:** `19` +- **Carries JWE:** `true` +- **Simulator Console:** `/builder?family=preauth&usecase=query-answer` +- **Data Element Mapping:** `package/mappings/D7.yaml` +- **FHIR Reference:** [Preauthorisation Query and Answer, D7](/docs/nhcx/v1/reference/fhir/preauthorisation-query-and-answer#d7-answer-a-pre-authorisation-query-pmjay) +- **Sample FHIR Bundles (1):** `D7-query-answer.json` + +The query arrived as a ClaimResponse on 24, on the case's own thread, with the question in the item adjudication, not on the communication API. Answer with a fresh submit of the same bundle shape on this code, never as a new 12, which opens a second case. + +### D8: Cancel pre-authorisation + +- **Role / Side:** `pmjay` +- **API Called:** `/v1/task/submit` +- **Callback API:** `/v1/task/on_submit` +- **Workflow ID:** `PC01` +- **Carries JWE:** `true` +- **Simulator Console:** `/builder?family=preauth&usecase=cancel` +- **Data Element Mapping:** `package/mappings/D8.yaml` +- **FHIR Reference:** [Cancel, Reprocess and Shortfall, D8](/docs/nhcx/v1/reference/fhir/cancel-reprocess-and-shortfall#d8-cancel-pre-authorisation-pmjay) +- **Sample FHIR Bundles (1):** `D8-cancel.json` + +A Task with code cancel, the case number as input and one of seven reasons: treatmentplanchanged, patientrequest, financialconstraints, alternativetreatment, duplicateclaim, administrativeerror, other. Allowed at any point until the claim is raised. + +### D9: Submit claim + +- **Role / Side:** `pmjay` +- **API Called:** `/v1/claim/submit` +- **Callback API:** `/v1/claim/on_submit` +- **Workflow ID:** `15` +- **Carries JWE:** `true` +- **Simulator Console:** `/builder?family=claim&usecase=submit` +- **Data Element Mapping:** `package/mappings/D9.yaml` +- **FHIR Reference:** [Claim Request, D9](/docs/nhcx/v1/reference/fhir/claim-request#d9-submit-claim-pmjay) +- **Sample FHIR Bundles (1):** `D9-request.json` + +There is no discharge submission: the claim asserts the discharge and carries its details. Four dates, the discharge type under category DIS with the stage as its value, a fresh biometric token, and LM100 as the single procedure in place of the approved items on a LAMA or DAMA discharge before or during surgery. The amount may not exceed what was approved. + +### D10: Answer a claim query + +- **Role / Side:** `pmjay` +- **API Called:** `/v1/claim/submit` +- **Callback API:** `/v1/claim/on_submit` +- **Workflow ID:** `161` +- **Carries JWE:** `true` +- **Simulator Console:** `/builder?family=claim&usecase=query-answer` +- **Data Element Mapping:** `package/mappings/D10.yaml` +- **FHIR Reference:** [Claim Query and Answer, D10](/docs/nhcx/v1/reference/fhir/claim-query-and-answer#d10-answer-a-claim-query-pmjay) +- **Sample FHIR Bundles (1):** `D10-query-answer.json` + +As D7, on the claim endpoint: the query is a ClaimResponse on 27, the answer a fresh submit on 161. The sandbox refuses 151, 19 and 16 with PAYR-1321. The final adjudication then arrives with outcome complete and, often, a deductible adjudication naming why the eligible amount is less than the claimed one. + +### D11: Reprocess a rejected claim + +- **Role / Side:** `pmjay` +- **API Called:** `/v1/task/submit` +- **Callback API:** `/v1/task/on_submit` +- **Workflow ID:** `36` +- **Carries JWE:** `true` +- **Simulator Console:** `/builder?family=claim&usecase=reprocess` +- **Data Element Mapping:** `package/mappings/D11.yaml` +- **FHIR Reference:** [Cancel, Reprocess and Shortfall, D11](/docs/nhcx/v1/reference/fhir/cancel-reprocess-and-shortfall#d11-reprocess-a-rejected-claim-pmjay) +- **Sample FHIR Bundles (1):** `D11-reprocess.json` + +An appeal, not a resubmission: a Task with code reprocess and reason claimrejected, a supporting document attached, no amount. Raise it the moment the rejection arrives. Once only; the Claim Review Committee is final. + +### D12: Claim a shortfall + +- **Role / Side:** `pmjay` +- **API Called:** `/v1/task/submit` +- **Callback API:** `/v1/task/on_submit` +- **Workflow ID:** `36` +- **Carries JWE:** `true` +- **Simulator Console:** `/builder?family=claim&usecase=shortfall` +- **Data Element Mapping:** `package/mappings/D12.yaml` +- **FHIR Reference:** [Cancel, Reprocess and Shortfall, D12](/docs/nhcx/v1/reference/fhir/cancel-reprocess-and-shortfall#d12-claim-a-shortfall-pmjay) + +The same Task with reason partialpayment and an amount capped at the difference, allowed only after payment notice 33 has arrived and been acknowledged with 17. Once only, and never after a reprocess. + +### D13: Acknowledge the payment notice + +- **Role / Side:** `pmjay` +- **API Called:** `/v1/paymentnotice/on_request` +- **Callback API:** `/v1/paymentnotice/request` +- **Workflow ID:** `17` +- **Carries JWE:** `true` +- **Simulator Console:** `/builder?family=paymentnotice&usecase=acknowledge` +- **Data Element Mapping:** `package/mappings/D13.yaml` +- **FHIR Reference:** [Payment Notice and Acknowledgement, D13](/docs/nhcx/v1/reference/fhir/payment-notice-and-acknowledgement#d13-acknowledge-the-payment-notice-pmjay) +- **Sample FHIR Bundles (1):** `D13-acknowledgement.json` + +Three notices may arrive: 30 when the transfer is initiated, 31 when the bank processes it, 33 when it settles with the UTR. The reconciliation splits the amount into what was paid and what was deducted as tax. Keep the UTR; it is the reference for any dispute. + +## Payer Use Cases + +The following use cases are implemented by Payer participants (Insurance Companies and Third Party Administrators) to respond to provider inquiries, adjudicate claims, raise queries, and settle payments. + +### C1: Link ABHA with policy + +- **Role / Side:** `payer` +- **API Called:** `/participant/link/abha/policy` +- **Carries JWE:** `false` +- **Simulator Console:** `/participants` +- **Data Element Mapping:** `package/mappings/C1.yaml` + +Tie the ABHA number, mobile and member id to the policy's products at policy creation, naming the payer and the processor. This is what makes A2 answer. + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `abhaNumber` | ABHA Number | Link | `string` | `1..1` | `Patient.identifier[type=ABHA].value` | `91234567890123` | | +| `policyNumber` | Policy Number | Link | `string` | `1..1` | `Coverage.identifier[0].value` | `POL-HOSP-2026-0045` | | +| `payerId` | Insurer Participant Code | Link | `string` | `1..1` | `Organization.identifier.value` | `1000003538@hcx` | | + +NRCeS profiles: [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html), [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html), [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html). + +### C2: De-link ABHA from policy + +- **Role / Side:** `payer` +- **API Called:** `/participant/delink/abha/policy` +- **Carries JWE:** `false` +- **Data Element Mapping:** `package/mappings/C2.yaml` + +Undo C1. Only the party named as payer or processor on the link may do this. + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `abhaNumber` | ABHA Number | Delink | `string` | `1..1` | `Patient.identifier[type=ABHA].value` | `91234567890123` | | +| `policyNumber` | Policy Number | Delink | `string` | `1..1` | `Coverage.identifier[0].value` | `POL-HOSP-2026-0045` | | + +NRCeS profiles: [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html), [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html). + +### C3: Respond to coverage eligibility + +- **Role / Side:** `payer` +- **API Called:** `/v1/coverageeligibility/on_check` +- **Callback API:** `/v1/coverageeligibility/check` +- **Carries JWE:** `true` +- **Data Element Mapping:** `package/mappings/C3.yaml` +- **FHIR Reference:** [Coverage Eligibility Response, C3](/docs/nhcx/v1/reference/fhir/coverage-eligibility-response#c3-respond-to-coverage-eligibility-payer) +- **Sample FHIR Bundles (7):** `C3-benefits-pmjay.json`, `C3-response-generic.json`, `C3-response-pmjay.json`, `benefits-response.json`, `coverage-eligibility.json`, `discovery-response.json`, `validation-response.json` + +The eligibility and plan details for the beneficiary asked about. A payer may instead answer with a forward instruction, asking the exchange to pass the request to another payer. + +### C4: Respond to insurance plan request + +- **Role / Side:** `payer` +- **API Called:** `/v1/insuranceplan/on_request` +- **Callback API:** `/v1/insuranceplan/request` +- **Carries JWE:** `true` +- **Data Element Mapping:** `package/mappings/C4.yaml` +- **FHIR Reference:** [Insurance Plan Response Overview, C4](/docs/nhcx/v1/reference/fhir/insurance-plan-response-overview#c4-respond-to-insurance-plan-request-payer) +- **Sample FHIR Bundles (2):** `C4-response-generic.json`, `C4-response-pmjay.json` + +The plan as a benefit structure. Under PMJAY this is the scheme configuration for one hospital and can exceed twenty megabytes. + +### C5: Respond to pre-authorisation + +- **Role / Side:** `payer` +- **API Called:** `/v1/preauth/on_submit` +- **Callback API:** `/v1/preauth/submit` +- **Workflow ID:** `20 received, 21 approved, 23 rejected, 24 queried, 22 enhancement approved, 231 denied, 241 queried` +- **Carries JWE:** `true` +- **Data Element Mapping:** `package/mappings/C5.yaml` +- **FHIR Reference:** [Preauthorisation Response, C5](/docs/nhcx/v1/reference/fhir/preauthorisation-response#c5-respond-to-pre-authorisation-payer) +- **Sample FHIR Bundles (10):** `C5-approved-wf21-pmjay.json`, `C5-approved-wf21.json`, `C5-enhancement-approved-wf22-pmjay.json`, `C5-enhancement-approved-wf22.json`, `C5-queried-wf24.json`, `C5-received-wf20-pmjay.json`, `C5-received-wf20.json`, `C5-rejected-wf23-pmjay.json`, `C5-rejected-wf23.json`, `preauth-queried.json` + +The adjudicated pre-authorisation. The acknowledgement on 20 travels as response.partial and carries the payer's own case number; the decisions travel as response.complete. Read outcome and the adjudication amounts together: complete covers approval and denial alike. Under PMJAY a query is this ClaimResponse on 24 or 241, on the case's own thread. + +### C6: Raise a communication + +- **Role / Side:** `payer` +- **API Called:** `/v1/communication/request` +- **Callback API:** `/v1/communication/on_request` +- **Workflow ID:** `24, 241, 27 for a generic payer's queries; N02 and the intimation codes for the rest` +- **Carries JWE:** `true` +- **Data Element Mapping:** `package/mappings/C6.yaml` +- **FHIR Reference:** [Communication, C6](/docs/nhcx/v1/reference/fhir/communication#c6-raise-a-communication-payer) +- **Sample FHIR Bundles (3):** `C6-claim-query-wf27.json`, `C6-notification-wfN02.json`, `C6-preauth-query-wf24.json` + +A message about a case, typed by its reason code: additionalinfo, tatquery for a turnaround breach, grievance, walletupdate, policychange, claimArbitration. A generic or IRDAI payer raises its document queries here, as a CommunicationRequest task bundle carrying 24, 241 or 27, and takes the answer as a Communication task bundle on on_request echoing the correlation id and workflow id. PMJAY does not use it for queries; its query is the ClaimResponse on the case's own thread. + +### C7: Respond to claim + +- **Role / Side:** `payer` +- **API Called:** `/v1/claim/on_submit` +- **Callback API:** `/v1/claim/submit` +- **Workflow ID:** `25 received, 26 approved, 27 queried, 28 in process, 29 forwarded, 291 denied` +- **Carries JWE:** `true` +- **Data Element Mapping:** `package/mappings/C7.yaml` +- **FHIR Reference:** [Claim Response, C7](/docs/nhcx/v1/reference/fhir/claim-response#c7-respond-to-claim-payer) +- **Sample FHIR Bundles (9):** `C7-approved-deduction-wf26-pmjay.json`, `C7-approved-wf26-pmjay.json`, `C7-approved-wf26.json`, `C7-queried-wf27.json`, `C7-received-wf25-pmjay.json`, `C7-received-wf25.json`, `C7-rejected-wf291-pmjay.json`, `C7-rejected-wf291.json`, `claim-queried.json` + +The adjudicated claim, item by item, with any deduction and its reason. The acknowledgement on 25 travels as response.partial with the payer's case number. Under PMJAY a query is this ClaimResponse on 27, answered by a fresh submit on 161. + +### C8: Respond to search + +- **Role / Side:** `payer` +- **API Called:** `/v1/search/on_submit` +- **Callback API:** `/v1/search/submit` +- **Carries JWE:** `true` +- **Data Element Mapping:** `package/mappings/C8.yaml` +- **FHIR Reference:** [Predetermination, Status and Search, C8](/docs/nhcx/v1/reference/fhir/predetermination-status-and-search#c8-respond-to-search-payer) +- **Sample FHIR Bundles (1):** `search-response.json` + +The ClaimResponse objects matching the criteria asked for. + +### C9: Send payment notice + +- **Role / Side:** `payer` +- **API Called:** `/v1/paymentnotice/request` +- **Callback API:** `/v1/paymentnotice/on_request` +- **Workflow ID:** `30 initiated, 31 processed, 33 settled` +- **Carries JWE:** `true` +- **Data Element Mapping:** `package/mappings/C9.yaml` +- **FHIR Reference:** [Payment Notice and Acknowledgement, C9](/docs/nhcx/v1/reference/fhir/payment-notice-and-acknowledgement#c9-send-payment-notice-payer) +- **Sample FHIR Bundles (3):** `C9-notice-tds-wf30-pmjay.json`, `C9-notice-wf30.json`, `payment-notice.json` + +The money, on a new thread of its own, with the reconciliation itemised by type: approved, claimed, tds, servicetax, advance, recovered, penality. The bank's UTR rides on the settled notice. + +### C10: Respond to a Task + +- **Role / Side:** `payer` +- **API Called:** `/v1/task/on_submit` +- **Callback API:** `/v1/task/submit` +- **Workflow ID:** `251 acknowledged, 252 approved, 253 rejected, 254 queried, PC02 cancelled, 37 arbitration acknowledged` +- **Carries JWE:** `true` +- **Data Element Mapping:** `package/mappings/C10.yaml` +- **FHIR Reference:** [Cancel, Reprocess and Shortfall, C10](/docs/nhcx/v1/reference/fhir/cancel-reprocess-and-shortfall#c10-respond-to-a-task-payer) +- **Sample FHIR Bundles (4):** `C10-arbitration-wf37-pmjay.json`, `C10-arbitration-wf37.json`, `C10-cancelled-wfPC02-pmjay.json`, `C10-cancelled-wfPC02.json` + +The answer to a reprocess, shortfall or cancel. A cancellation done is PC02 and carries the case's ClaimResponse in its output; a reprocess on 36 is acknowledged on 37 as arbitration. Both payers answer this way. + +### C11: Respond to predetermination + +- **Role / Side:** `payer` +- **API Called:** `/v1/predetermination/on_submit` +- **Callback API:** `/v1/predetermination/submit` +- **Carries JWE:** `true` +- **Data Element Mapping:** `package/mappings/C11.yaml` +- **FHIR Reference:** [Predetermination, Status and Search, C11](/docs/nhcx/v1/reference/fhir/predetermination-status-and-search#c11-respond-to-predetermination-payer) +- **Sample FHIR Bundles (1):** `predetermination-response.json` + +What the payer would approve for the proposed treatment. + +## Beneficiary & Patient App Use Cases + +Personal health record apps and beneficiary portals register on NHCX to receive real-time updates on a patient's claims and authorizations. + +### E1: Subscribe to notifications + +- **Role / Side:** `patient` +- **API Called:** `/v1/notification/subscribe` +- **Callback API:** `/v1/notification/on_subscribe` +- **Workflow ID:** `N01 to a payer, N02 to a provider, N03 to a beneficiary, N04 acknowledgement` +- **Carries JWE:** `false` +- **Data Element Mapping:** `package/mappings/E1.yaml` + +A patient app subscribes when the beneficiary logs in with their ABHA, and the most recent subscription wins. Topics: workflow_events for claim progress, network_events for exchange maintenance, participant_events for changes to payers and providers. + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `abhaNumber` | Beneficiary ABHA | Subscription | `string` | `1..1` | `Patient.identifier[type=ABHA].value` | `91234567890123` | | +| `topic` | Subscription Topic | Subscription | `string` | `1..*` | `Subscription.criteria` | `workflow_events` | | +| `endpointUrl` | Push Notification URL | Subscription | `url` | `1..1` | `Subscription.channel.endpoint` | `https://phrapp.example.org/webhook/claims` | | + +NRCeS profiles: [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html). + +--- + +## FHIR Builder Use Cases + +The NHCX FHIR Builder provides pre-configured templates and presets for generating conforming bundles across claim lifecycle stages: + +| Bundle | Step | Label | Template | Endpoint | Flow | Description | +| :--- | :--- | :--- | :--- | :--- | :--- | :--- | +| `coverage` | `discovery` | **Discovery** | `coverage-eligibility` | `v1/coverageeligibility/check` | `request` | Which policy does this beneficiary hold? The fallback when policy lookup has not answered it. | +| `coverage` | `validation` | **Validation** | `coverage-eligibility` | `v1/coverageeligibility/check` | `request` | Is the policy in force today, and what is left in the wallet. Called after registration. | +| `coverage` | `auth-requirements` | **Auth-requirements** | `coverage-eligibility` | `v1/coverageeligibility/check` | `request` | Is this package covered here, and what must the pre-authorisation carry. The call to make before every pre-authorisation. | +| `coverage` | `benefits` | **Benefits** | `coverage-eligibility` | `v1/coverageeligibility/check` | `request` | How much cover remains, against which packages. Called before a pre-authorisation. | +| `insurance` | `request` | **Fetch the plan** | `insurance-plan` | `v1/insuranceplan/request` | `request` | A poll Task keyed on the policy number and the provider id. The answer is the policy as a benefit structure. | +| `preauth` | `initiate` | **Initiate** | `claim` | `v1/preauth/submit` | `request` | The first pre-authorisation for a case: permission to treat. | +| `preauth` | `resubmit` | **Resubmit** | `claim` | `v1/preauth/submit` | `request` | Revise an approved or rejected case. Nullifies every earlier instance; keep the same case number. | +| `preauth` | `enhance` | **Enhancement** | `claim` | `v1/preauth/submit` | `request` | Add to an approved pre-authorisation. Quote its approval reference, and only add packages the plan allows to be enhanced. | +| `preauth` | `query-answer` | **Answer a query** | `claim` | `v1/preauth/submit` | `request` | The payer asked for more. Same bundle, same case number, the extra documents attached; never a fresh 12. | +| `preauth` | `predetermination` | **Predetermination** | `claim` | `v1/predetermination/submit` | `request` | What would the payer approve for this treatment? Asked before committing to a pre-authorisation, on its own endpoint. | +| `preauth` | `cancel` | **Cancel** | `claim-cancel` | `v1/task/submit` | `request` | Withdraw an active pre-authorisation with a Task. Allowed at any point until the claim is raised. | +| `claim` | `submit` | **Submit** | `claim` | `v1/claim/submit` | `request` | Reimbursement after discharge. Under PMJAY this also asserts the discharge, so it carries the discharge type and dates. | +| `claim` | `query-answer` | **Answer a query** | `claim` | `v1/claim/submit` | `request` | The claim processing doctor asked for more. Same bundle, same case number, the extra evidence attached. | +| `claim` | `reprocess` | **Reprocess** | `claim-reprocess` | `v1/task/submit` | `request` | Appeal a rejected claim with a Task and a supporting document. Once only; the Committee is final. | +| `claim` | `shortfall` | **Shortfall** | `claim-release` | `v1/task/submit` | `request` | The claim was paid short. Ask for the difference, after payment notice 33 has been acknowledged. | +| `paymentnotice` | `acknowledge` | **Acknowledge** | `payment-ack` | `v1/paymentnotice/on_request` | `on_request` | The receipt for a payment notice. Acknowledging does not resolve whatever the notice was about. | +| `search` | `search` | **Search** | `search` | `v1/search/submit` | `request` | Where a case got to, asked as a Task. Check Status answers the same question without a bundle. | + +--- + +## The 100 Official NHCX Test Use Cases + +NHA specifies a formal test matrix of 100 numbered use cases covering every scenario an integrator must demonstrate for network certification. The complete reference manifest is preserved at `fixtures/usecases.txt`. + +| Case IDs | Scenario Category | Exchanges Involved | Key Verification Criteria | Fixture Reference | +| :--- | :--- | :--- | :--- | :--- | +| **1 to 3** | Insurance Plan | `/insuranceplan/request` & `on_request` | Plan query (`Task` poll), package master response (`InsurancePlan`), error response | `fixtures/reference/provider/insurance/` | +| **4 to 7** | Coverage Validation | `/coverageeligibility/check` & `on_check` | Purpose `validation`. Checks policy in force, active dates, error handling | `fixtures/reference/provider/coverage/validation/` | +| **8 to 10** | Coverage Discovery | `/coverageeligibility/check` & `on_check` | Purpose `discovery`. Discovers policy from ABHA when policy number unknown | `fixtures/reference/provider/coverage/discovery/` | +| **11 to 13** | Auth-Requirements | `/coverageeligibility/check` & `on_check` | Purpose `auth-requirements`. Returns mandatory document codes (`MAND...`) | `fixtures/reference/provider/coverage/authrequirements/` | +| **14 to 16** | Preauth with Biometric Token | `/preauth/submit` & `on_submit` | Valid biometric token in header/token. Ack (wf20) & approval (wf21) | `fixtures/reference/provider/preauth/request/` | +| **17 to 19** | Preauth without Token (Consent) | `/preauth/submit` & `on_submit` | Physical consent form uploaded in supportingInfo questionnaire | `fixtures/collection/provider/preauth/` | +| **20 to 22** | Preauth Newborn Registration | `/preauth/submit` & `on_submit` | Newborn registered under mother's ABHA/PMJAY policy, birth certificate | [`docs/05-FHIR Reference/12-Claim Request.md`](/docs/nhcx/v1/reference/fhir/claim-request) | +| **23 to 25** | Preauth with STG | `/preauth/submit` & `on_submit` | Standard Treatment Guidelines questionnaire answered under supportingInfo | `fixtures/collection/pmjay-payer/insurance/` | +| **26 to 28** | Preauth with Implant & Attendant | `/preauth/submit` & `on_submit` | Implant product details and attendant certification included | `fixtures/reference/provider/preauth/request/` | +| **29 to 31** | Preauth Query & Resolution | `/preauth/submit` / `/communication/` | Payer queries additional remarks/documents; provider answers (wf19/131) | `fixtures/reference/provider/preauth/queryupdate/` | +| **32 to 34** | Preauth Standalone Procedure | `/preauth/submit` & `on_submit` | Single stand-alone medical or surgical package booking | `fixtures/reference/provider/preauth/request/` | +| **35 to 37** | Preauth Cyclic Procedure | `/preauth/submit` & `on_submit` | Recurring cyclic treatments (e.g. hemodialysis, chemotherapy cycles) | `fixtures/collection/provider/preauth/` | +| **38 to 40** | Preauth Unspecified Procedure | `/preauth/submit` & `on_submit` | Unspecified surgical package (`SGU100`) with surgical notes attached | `fixtures/reference/provider/preauth/request/` | +| **41 to 43** | Enhancement: Length of Stay | `/preauth/submit` & `on_submit` | Increase in LOS (`x-hcx-use_case: Enhancement`), updated clinical justification | `fixtures/reference/provider/preauth/enhancement/` | +| **44 to 46** | Enhancement: Additional Procedures | `/preauth/submit` & `on_submit` | Additional secondary procedures or STG questionnaire inclusion | `fixtures/reference/provider/preauth/enhancement/` | +| **47 to 49** | Resubmission with STG | `/preauth/submit` & `on_submit` | Procedure modification/addition after rejection with STG questionnaire | `fixtures/reference/provider/preauth/request/` | +| **50 to 52** | Resubmission without STG | `/preauth/submit` & `on_submit` | Procedure modification/addition after rejection without STG questionnaire | `fixtures/reference/provider/preauth/request/` | +| **53 to 54** | Preauth Cancellation | `/task/submit` & `on_submit` | Cancellation `Task` (`PC01`/`PC02`) referencing original preauthorisation | `fixtures/reference/payer/task/cancelled/` | +| **55 to 57** | Claim Cyclic Procedure | `/claim/submit` & `on_submit` | Claim submission for completed cyclic treatment cycle | `fixtures/collection/provider/claim/` | +| **58 to 60** | Claim Live Discharge | `/claim/submit` & `on_submit` | Normal completed discharge to home (`DTH`). Final bills and summary | `fixtures/reference/provider/claim/request/` | +| **61 to 63** | Claim Query & Resolution | `/claim/submit` / `/communication/` | Payer raises query on claim (wf27); provider submits answer (wf141/151) | `fixtures/reference/provider/claim/queryupdate/` | +| **64 to 72** | Claim LAMA Scenarios | `/claim/submit` & `on_submit` | LAMA before surgery (`LM100` per diem), after surgery (package), during surgery (`LM100`) | `fixtures/reference/payer/claim/approved/` | +| **73 to 81** | Claim DAMA Scenarios | `/claim/submit` & `on_submit` | DAMA before surgery (`LM100`), after surgery (package), during surgery (`LM100`) | `fixtures/reference/payer/claim/approved/` | +| **82 to 90** | Claim Death Scenarios | `/claim/submit` & `on_submit` | Discharge to mortuary (`DTM`). Before, after, and during surgery | `fixtures/collection/provider/claim/` | +| **91 to 93** | Claim Erroneous Request | `/claim/submit` & `on_submit` | Erroneous submission corrected with remaining balance and mandatory docs | `fixtures/reference/provider/claim/request/` | +| **94 to 96** | Claim Reprocess / Dispute | `/task/submit` & `on_submit` | Reprocess `Task` (code 36) with appeal justification and mandatory docs | `fixtures/reference/provider/claim/reprocess/` | +| **97 to 100**| Payment Notice & Settlement | `/paymentnotice/request` & `on_request` | Payment initiation (wf30), ack (wf17/31), cleared update, and final ack | `fixtures/reference/payer/payment/notice/` | + +## Testing Against the Dummy Payer + +The sandbox hosts a payer that answers back, participant ID `1000003538@hcx`. It handles insurance plan, coverage eligibility, preauthorisation, claim, payment notice and communication. For the plan call use provider ID `32722` and policy `100217`. + +Two test hooks drive its decisions: +- `dummyhcxpayer/process/request` makes it approve, reject or query a preauthorisation or claim you have submitted, by correlation ID. +- `dummyhcxpayer/paymentNotice/init` makes it send you a payment notice. + +A query from the dummy payer arrives as a communication request, which you answer on `/v1/communication/on_request` before the final decision comes back on `on_submit`. + +--- + +## Workflow Codes Cross-Reference + +Endpoints alone do not identify a transaction. A new preauthorisation, a resubmission, an enhancement and a query response all travel on `/v1/preauth/submit` with the same bundle. The workflow code in the header is what tells them apart, and each code expects a particular status word. See [Workflow Codes](/docs/nhcx/v1/concepts/workflow-codes) for the complete state machines and code tables. diff --git a/site/docs/nhcx/v1/concepts/payer-flexibility.md b/site/docs/nhcx/v1/concepts/payer-flexibility.md new file mode 100644 index 000000000..ff52cfb1f --- /dev/null +++ b/site/docs/nhcx/v1/concepts/payer-flexibility.md @@ -0,0 +1,72 @@ +--- +title: Payer flexibility +sidebar_label: Payer flexibility +sidebar_position: 7 +description: How each payer configures queries, answers and case numbers +verification: unverified +source: nhcx-package/docs/01-Overview/07-Payer Flexibility.md +generated: true +--- + +# Payer flexibility + +NHCX gives each payer room to run a few parts of the exchange its own way. The endpoints, the envelope and the bundles stay the same for every payer. What a payer can choose is how it raises a query, how much detail its answers carry, and when it first sends its own case number. Build your integration to handle every option, keep a setting per payer, and one integration works with any payer on the network. Today PMJAY uses one set of options and private insurers use another. + +## In short + +- **Query mode.** A payer raises a query either on the claim thread, as a `ClaimResponse`, or through the communication API, as a `CommunicationRequest`. PMJAY uses the first, private insurers the second. Answer in the mode the query came in. +- **Answer detail.** Every payer uses the same core entries, workflow ids and status words. PMJAY adds a few fields on top. A reader built for the full set reads every payer. +- **Case number.** The payer's own case number arrives in `preAuthRef`. When it first arrives depends on the payer. File the case under it. +- **Task spelling.** The reprocess and cancel Tasks both carry `intimationNumber`, whatever the payer. + +## Query mode + +Hold a query mode per payer and route the answer by it. + +### On the claim thread + +PMJAY uses this mode. The query arrives as a `ClaimResponse` with `outcome` `partial`, on the case's own thread. Its workflow id is 24 for a pre-authorisation, 241 for an enhancement and 27 for a claim. + +The answer is the whole bundle again, on `/v1/preauth/submit` or `/v1/claim/submit`, under a new correlation id. Its workflow id is 19, 131 or 161. + +In this mode a claim query answered on 151, 19 or 16 is refused with `PAYR-1321`; 161 is the id PMJAY takes. The desk's reply travels on the bundle's `CQD` supporting information, so a resubmission that carries no reply is decided as if none was given. + +A `CommunicationRequest` in this mode is not a query. It is a notification: a turnaround-time alert, a grievance, a wallet or policy change, a request for extra information, or an arbitration intimation, named in `Task.reasonCode`. Acknowledge it with the same Task bundle, `Task.status` `completed`, within thirty seconds, and leave the case's status alone. + +### Through the communication API + +Private insurers use this mode. The query arrives as a `CommunicationRequest` task bundle on `/v1/communication/request`, on a new thread, carrying 24, 241 or 27 with `request.initiated`. A `CommunicationRequest` carrying `additionalinfo`, or no reason code at all, is the query itself. + +The answer is a `Communication` task bundle on `/v1/communication/on_request`, on the request's own correlation id, echoing the request's workflow id. + +## Answer detail + +Every payer answers with the same core set of workflow ids and status words. + +| Message | Workflow id | Status | +| :---- | :---- | :---- | +| Pre-authorisation or enhancement received | 20 | `response.partial` | +| Pre-authorisation approved, rejected | 21, 23 | `response.complete` | +| Enhancement approved, denied | 22, 231 | `response.complete` | +| Claim received | 25 | `response.partial` | +| Claim approved, rejected | 26, 291 | `response.complete` | +| Cancellation done | PC02 | `response.complete` | +| Arbitration acknowledged | 37 | `response.complete` | +| Payment notice | 30 | `request.initiated`, on a new thread | + +A `ClaimResponse` bundle from any payer carries the `ClaimResponse`, the `Patient`, both `Organization` entries and the `Coverage`, in that order. Item adjudications carry `submitted`, `eligible` and `benefit`; totals carry the same three. PMJAY adds `eligpercent`, `eligquant`, `tax` and `incentive`; a private insurer omits them and adds nothing of its own. A reader built for the full set reads every payer without a change. + +## When the case number arrives + +The payer's own number for the case arrives in `ClaimResponse.preAuthRef`. A private insurer sends it on every answer, the acknowledgement on 20 or 25 included. PMJAY sends it on the first answer that decides or queries a pre-authorisation, on 21, 23 or 24, and on the claim's acknowledgement on 25; its acknowledgement on 20 carries none. `ClaimResponse.identifier` stays the hospital's own number on every answer. The payer's desk files the case under its own number and every later action names it. Keep it on the record the moment it arrives. A desk asked about a case by the hospital's own number answers that no such case exists. + +## One spelling on the Task + +The cancel and reprocess Tasks both carry their second input as `intimationNumber`. A reprocess under any other spelling is refused with `PAYR-1008`. Reprocess goes on 36 and is acknowledged on 37, and the new verdict follows on the claim's own thread. + +## Next steps + +- Cancel, reprocess and shortfall, in the FHIR Reference: the Task bundles element by element +- Communication, in the FHIR Reference: the query and the notification on one endpoint pair +- Claim query and answer, in the FHIR Reference: the scheme's query inside the claim response +- Sample bundles, in the FHIR Reference: the collection every shape here is taken from diff --git a/site/docs/nhcx/v1/concepts/pmjay-on-nhcx.md b/site/docs/nhcx/v1/concepts/pmjay-on-nhcx.md new file mode 100644 index 000000000..eb2ea562d --- /dev/null +++ b/site/docs/nhcx/v1/concepts/pmjay-on-nhcx.md @@ -0,0 +1,85 @@ +--- +title: PMJAY on NHCX +sidebar_label: PMJAY on NHCX +sidebar_position: 8 +description: What the Ayushman Bharat scheme changes on the network +verification: unverified +source: nhcx-package/docs/01-Overview/08-PMJAY on NHCX.md +generated: true +--- + +# PMJAY on NHCX + +Ayushman Bharat Pradhan Mantri Jan Arogya Yojana, known as PMJAY, was launched on 23 September 2018. It is the largest health assurance scheme in the world, providing a health cover of Rs. 5 lakh per family per year for secondary and tertiary care hospitalisation to over 10.74 crore poor and vulnerable families, roughly 50 crore beneficiaries, forming the bottom 40 percent of the population. It is fully funded by government, with the cost of implementation shared between the Centre and the states. + +Claim adjudication under PMJAY runs through three integrated systems: the Beneficiary Identification System (BIS), the Transaction Management System (TMS), and the Hospital Empanelment Module (HEM). The key decisions sit in TMS, taken at preauthorisation by the Preauthorisation Processing Doctor (PPD) and at settlement by the Claim Processing Doctor (CPD). + +The previous chapters described how a claim moves between a Provider and a private insurer over NHCX. This chapter covers what changes when the Payer is PMJAY. + +## The problem with a TMS-only workflow + +PMJAY claims processing today depends on the TMS 2.0 Provider System, whether or not the hospital runs its own HMIS. That creates four difficulties. + +- **Duplication of data entry.** The same case is keyed into the hospital HMIS and again into TMS, increasing administrative workload and the risk of errors. +- **Lack of interoperability.** Beneficiary, clinical and claims data cannot move cleanly between systems. +- **Single-system dependency.** Relying exclusively on one provider system limits scalability and operational flexibility. +- **Restricted innovation.** System constraints leave little room for hospitals and technology partners to build around the workflow. + +## The change + +A hospital running an ABDM-enabled HMIS integrated with NHCX can operate PMJAY workflows entirely within its own system, with no mandatory portal usage. Claims move directly from the hospital system to the payer system over the exchange. + +- **No mandatory TMS dependency.** The PMJAY workflow lives inside the HMIS rather than beside it. +- **Single-source data capture.** PMJAY data is recorded once in the HMIS and reused for claims processing, removing the re-entry and reconciliation described above. +- **Choice of system.** Hospitals are no longer tied to one PMJAY processing system and can pick any ABDM-enabled HMIS. +- **Scale.** HMIS-based integration handles higher transaction volumes more reliably than a portal-based workflow. + +## What this means for an empanelled hospital + +**PMJAY becomes part of routine operations.** Cases are handled inside the hospital's normal workflow rather than as a separate portal-driven activity, and are no longer exposed to portal downtime, access constraints or concurrent user limits. + +**Structured data enables automation.** Preauthorisation and claim processing can be automated, cutting cost and turnaround, reducing manual error and improving data quality, which is the basic requirement for any AI model and for fraud control. + +**Audit and finance improve.** All PMJAY clinical and financial records sit within hospital systems, simplifying audits, internal reviews and compliance, and claims data flows natively into hospital billing and accounting. + +**Training simplifies.** Staff learn one system instead of managing separate roles and workflows across HMIS and TMS. + +## Where PMJAY differs from a private insurer integration + +Once NHCX integration is complete, an integrator can send claims to any private insurer. PMJAY is a national assurance programme, so it carries scheme-specific requirements on top. The endpoints themselves do not change. Four things do. + +**The InsurancePlan response carries the scheme configuration.** PMJAY uses the InsurancePlan FHIR bundle heavily. It is configured at hospital level and holds the available specialties, package costs, standard treatment guidelines, questionnaires and the mandatory documents required at preauthorisation and claim. This configuration drives most of what follows, so fetching and storing it correctly is a precondition rather than a convenience. + +**Biometric authentication is mandatory.** The scheme requires biometric verification of the beneficiary at registration, during treatment and at discharge. This is an additional API, outside the NHCX set, that a PMJAY integrator must implement. + +**Supporting information must be structured.** Sending scanned documents is not sufficient. Clinical information must travel in ABDM-defined structured Health Information Types. + +**Document queries do not use the Communication API.** When the PMJAY payer wants more documents or clarification on a preauthorisation or claim, it queries the case itself. The provider answers on the same preauthorisation or claim endpoint with the same bundle, distinguished only by the workflow code. The Communication API is still used, but for other things. Telling a hospital a case has breached its turnaround time, passing on a grievance, or announcing a change to the beneficiary's wallet or to a package rate. Also asking for extra information outside a formal query, and acknowledging an arbitration request. A hospital system must still be able to receive it. + +Set against the flows in the NHCX Use Cases chapter, the picture is: + +- **Get Insurance Plan, Get Policy, Coverage Eligibility Check, Claim Submission, Payment Notice and Status Check** behave the same as on any NHCX integration. +- **Preauthorisation** behaves the same, except that mandatory biometric authentication of the beneficiary must be completed before it is submitted. +- **Communication Request** is not used for document queries, which travel on the preauthorisation and claim endpoints instead. It is used for turnaround-time alerts, grievances, wallet and policy updates, and arbitration acknowledgements. A private insurer does the opposite: its query is the Communication Request itself. Payer flexibility, later in this section, sets the two query modes side by side. + +## The integrator journey + +The route to a PMJAY integration runs in five stages. + +1. **Get compliant for ABDM Milestone 1.** Request access to the sandbox APIs, integrate against them, complete functional testing and the security audit (WASA), give the HTC demo, and go live for ABDM M1. +2. **Register on the NHCX sandbox.** Register using the ABDM Client ID, generate a participant ID, create the public and private key pair, and work through the NHCX documentation until the API flows are properly understood. +3. **Build the integration.** Test the flows against the NHCX dummy payer, implement every use case API including biometric authentication and structured data exchange, and test all cases internally rather than only the happy path. +4. **Exit the sandbox.** Run the internal demo covering interoperability and FHIR bundle validation, give the PMJAY team demo, complete WASA and the HTC demo, and submit the NHCX sandbox exit form. + +5. **Go live by mapping.** After the participant is created and configured in production, the hospital raises a ticket. It carries the existing PMJAY hospital ID, the HEM ID used in TMS, and the new NHCX participant ID. NHA's operations team maps the two by hand. That mapping is the switch: preauthorisations and claims raised before it finish their life in TMS, and everything raised after it goes through the HMIS. For a while a hospital is running both, so this step is planned rather than flipped. + +Two practical notes. To begin the integration, the integrator shares the Participant ID, Client ID and Registry ID with the NHCX team for onboarding onto the PMJAY staging environment. The Registry ID is then used as the Provider ID on sandbox. On successful completion, the integrator receives production keys for NHCX, which also serve for processing private insurer claims. + +## About the source + +This chapter and the next are drawn from four documents: + +- The PMJAY Hospital Migration to HMIS via NHCX guide. +- The NHCX-PMJAY-HMIS Integration Overview. +- The Functional Requirement Document for NHCX-PMJAY-HMIS Integration, version 1.0, dated March 2026, prepared by the NHCX team at NHA. +- The NHCX Integration Handbook, version 1.0, which is the source for the workflow codes, the supporting info category and code combinations, and the gateway validation behaviour. Where the Handbook's gateway validation messages contradict the FRD, the next chapter follows the validation messages and says so. The FRD carries a disclaimer that it is work in progress and subject to revision, and the integrator journey above is marked tentative and not final. Nothing here has been verified against a running sandbox. diff --git a/site/docs/nhcx/v1/concepts/pmjay-scheme-rules.md b/site/docs/nhcx/v1/concepts/pmjay-scheme-rules.md new file mode 100644 index 000000000..61faa0ecc --- /dev/null +++ b/site/docs/nhcx/v1/concepts/pmjay-scheme-rules.md @@ -0,0 +1,111 @@ +--- +title: PMJAY Scheme Rules and HMIS Integration +sidebar_label: PMJAY Scheme Rules and HMIS Integration +sidebar_position: 10 +description: Package-based tariffs, LM100 LAMA/DAMA arithmetic and `los` bounding +verification: unverified +source: nhcx-package/docs/01-Overview/10-PMJAY Scheme Rules.md +generated: true +--- + +# PMJAY Scheme Rules and HMIS Integration + +The Pradhan Mantri Jan Arogya Yojana (PMJAY) operates under strict operational, clinical, and financial guidelines that diverge significantly from commercial, fee-for-service insurance exchanges. This chapter details the scheme-specific business rules, calculation models, and clinical workflows that a Hospital Management Information System (HMIS) must implement. + +--- + +## 1. Core Principles of PMJAY Adjudication + +1. **Strictly Package-Based**: PMJAY does not reimburse fee-for-service line items. All admissions are governed by Health Benefit Packages (HBP) with bundled tariffs covering registration, bed charges, nursing, consultations, procedures, medicines, consumables, and standard post-discharge follow-up. +2. **100% Cashless Mandate**: Empanelled healthcare providers cannot collect out-of-pocket co-payments from beneficiaries for covered procedures (`adjudication.copay` = ₹0). +3. **Pre-Authorization Gating**: Pre-authorization is mandatory for all secondary and tertiary surgical interventions. Final claims must reference the approved pre-authorisation number (`preAuthRef`). +4. **Mandatory Biometric Verification**: Live biometric capture (Fingerprint, Iris, or Face) is required at registration/admission, pre-authorisation, every cyclic treatment visit, and discharge. + +--- + +## 2. Discharge Types and Stages + +Under PMJAY, a hospital cannot record an open-ended "referral" or "transfer" discharge. Every patient episode must terminate in one of four standardized discharge types, qualified by the surgical timing stage: + +| Discharge Type Code | Display | Criteria & Adjudication Rule | +| :--- | :--- | :--- | +| `DTH` | Discharge to Home | Patient successfully completes inpatient care. Standard package adjudication applies. | +| `DTM` | Discharge to Mortuary | In-hospital mortality. Claim carries death date (`ONS`/`DTM`) and death summary questionnaire. | +| `LAMA` | Left Against Medical Advice | Patient absconds or departs against clinical counsel without formal documentation. | +| `DAMA` | Discharged Against Medical Advice | Patient or attendant executes an informed refusal undertaking. | + +### The Discharge Stage Qualification +Every claim records the clinical timing stage under `supportingInfo` category `DIS` ("Discharge status"): +- `Before Surgery` +- `During Surgery` +- `After Surgery` + +--- + +## 3. Package LM100 and LAMA/DAMA Billing Rules + +When a patient departs under `LAMA` or `DAMA`, the scheme strictly prohibits billing the full surgical package if the surgical intervention was not completed: + +```mermaid +flowchart TD + Discharge[LAMA or DAMA Discharge] --> StageCheck{Discharge Stage?} + StageCheck -->|Before Surgery| BillLM100[Nullify Surgical Package
Bill LM100 at Daily Per Diem Rate] + StageCheck -->|During Surgery| BillLM100 + StageCheck -->|After Surgery| BillPackage[Bill Full Approved Surgical Package
LM100 Prohibited] +``` + +### 1. Before or During Surgery +- **Nullification**: Submitting a LAMA/DAMA claim before or during surgery immediately **nullifies all prior approved surgical pre-authorisation packages**. +- **Item Code `LM100`**: The claim replaces all surgical line items with a single item: procedure code `LM100` (Conservative / Per Diem Inpatient Care). +- **Daily Quantity Multiplier & `los` Bound**: The quantity on `LM100` is set to the exact number of days the patient was admitted (`Discharge Date - Admission Date`). This quantity is strictly bounded by the `los` (Maximum Length of Stay) attribute declared in the scheme package master (`InsurancePlan`). Admitted days billed cannot exceed `los` without prior clinical justification; stays extending beyond standard procedure limits in ordinary admissions require an approved pre-authorisation enhancement request (workflow 13). +- **Stratification Tariffs**: Procedure `LM100` is stratified by bed tier in the PMJAY master: Routine Ward (₹1,800/day, `STRAT006a`), High Dependency Unit HDU (₹2,700/day, `STRAT006b`), ICU Without Ventilator (₹3,600/day, `STRAT006c`), and ICU With Ventilator (₹4,500/day, `STRAT006d`). +- **Error Safeguard**: Submitting a surgical package code alongside LAMA/DAMA before or during surgery triggers automated rejection with error `PAYR-1362`. +- **Pre-Auth Prohibition**: `LM100` is strictly a claim-time adjudication code. Submitting `LM100` in a pre-authorisation request triggers error `PAYR-1270`. + +### 2. After Surgery +- If surgery was successfully performed and the patient subsequently leaves against medical advice during post-operative recovery: + - The approved surgical package remains valid. + - `LM100` is **not** used. + - The discharge stage is recorded as `After Surgery`, and the hospital is reimbursed for the surgical package. + +--- + +## 4. In-Hospital Death Claims (`DTM`) + +If a patient expires during hospitalisation: +1. The discharge code is set to `DTM` (Discharge to Mortuary). +2. The claim retains the package appropriate to the clinical management provided up to the point of death. +3. The claim **must** include the date and time of death under `supportingInfo` category `ONS` with code `DTM`. Omitting the death timestamp causes rejection with error `PAYR-1096`. +4. The hospital must complete and attach the PMJAY Death Summary Questionnaire defined in the InsurancePlan. + +--- + +## 5. Cyclic Procedures (Dialysis, Chemotherapy) + +Cyclic treatments represent recurring therapy requiring multiple sessions under a single overarching pre-authorisation: +- **Plan Identification**: Packages flag cyclic eligibility with `cyclic_proc_yn = Y` and `no_of_cycles` in the `InsurancePlan`. +- **Pre-Auth Booking**: Pre-authorisation is requested and approved for the entire block of sessions (e.g., 10 cycles). +- **The Rolling 24-Hour Rule**: Two cycles of the same procedure cannot occur within a **rolling 24-hour window** (measured strictly from biometric timestamp to biometric timestamp, not calendar days). Submitting cycles within 24 hours triggers rejection with error `PAYR-1369`. +- **Biometric Enforcement**: Live biometric capture is mandatory at pre-auth, at **every individual treatment visit**, and at final discharge. +- **Payment Settlement**: The claim is submitted once after all sessions conclude. Payment is released exclusively for sessions backed by a verified biometric capture. (E.g., 10 sessions approved, 8 biometric captures recorded = 8 sessions paid). +- **Clinical Mapping**: Each cycle is recorded under `supportingInfo` category `CD` (Clinical document) with code `TD` (Treatment detail), carrying exact start and end timestamps matching the biometric verification log. + +--- + +## 6. Unspecified Surgical and Medical Procedures + +When a patient requires a clinically necessary surgical intervention not present in the PMJAY Health Benefit Package master: +1. **Strictly Planned**: Unspecified procedures are permitted **only for elective/planned admissions**; emergency cases cannot utilize unspecified package codes. +2. **Specialty Alignment**: Must be booked under the patient’s treating specialty. +3. **Coding Convention**: + - In live PMJAY plans, the procedure code is constructed as the **Specialty Prefix + `U100`** (e.g., `SGU100` for General Surgery, `SMU100` for Oral & Maxillofacial Surgery). + - Some earlier NHA documentation referenced `Specialty + 215` (e.g., `SG215`). Systems must echo the exact code returned in the hospital’s dynamic `InsurancePlan`. +4. **Free-Text Specification**: The procedure name, clinical description, and requested tariff are entered by the hospital staff rather than selected from fixed master lists. +5. **Wallet Validation**: The entered amount cannot exceed the beneficiary’s available wallet balance. HMIS systems must validate this balance server-side before submission. +6. **Standalone Requirement**: An unspecified procedure must be a solitary line item; it cannot be clubbed with standard packages, implants, or stratified ICU addons. + +--- + +## 7. Biometric Authentication and Aadhaar Exemption + +The captures these rules call for, at registration, preauthorisation, every cyclic visit and discharge, are made through ABDM's biometric APIs, not over NHCX. Biometric Authentication, in Building a Provider, gives the calls: fingerprint and iris on one host, face on another, the user token they return and its refresh, the `K-547` device error, and the Aadhaar exemption consent and questionnaire that stand in where a capture is not possible. diff --git a/site/docs/nhcx/v1/concepts/pmjay-use-cases.md b/site/docs/nhcx/v1/concepts/pmjay-use-cases.md new file mode 100644 index 000000000..5be493cb7 --- /dev/null +++ b/site/docs/nhcx/v1/concepts/pmjay-use-cases.md @@ -0,0 +1,309 @@ +--- +title: PMJAY use cases +sidebar_label: PMJAY use cases +sidebar_position: 9 +description: PMJAY-specific use cases D1 to D13 +verification: unverified +source: nhcx-package/docs/01-Overview/09-PMJAY Use Cases.md +generated: true +--- + +# PMJAY use cases + +The endpoints a PMJAY integration calls are the same ones listed in the NHCX Use Cases chapter. What changes is the behaviour around them: what must be fetched first, what must be proved before a request is accepted, how supporting information is packaged, and how a query is answered. The shared use cases apply unchanged, and so do Get Policy and Get Status. + +The exchanges below are the D-series. Where a use case is distinguished by a workflow code rather than by a separate endpoint, that code is given with it. The scheme rules that change how a submission is built, for unspecified, cyclic, medical, newborn and implant cases, are the next chapter. A PMJAY integration is as much about those rules as about the calls. + +```mermaid +flowchart TD + D1[D1 Fetch the insurance plan and keep it fresh] --> R[Patient registers] + R --> D2[D2 Biometric authentication] + D2 --> D3[D3 Eligibility: validation] + D3 --> D3b[D3 Eligibility: benefits and auth-requirements] + D3b --> D4[D4 Submit preauthorisation] + D4 --> Q{Payer answer} + Q -- query --> D7[D7 Answer the query] --> Q + Q -- approved --> TR[Treatment] + TR --> E{Case needs more?} + E -- yes --> D6[D6 Enhancement] --> Q + E -- no --> D2b[D2 Biometric at discharge] + D2b --> D9[D9 Submit claim with discharge details] + D9 --> Q2{Payer answer} + Q2 -- query --> D10[D10 Answer the query] --> Q2 + Q2 -- rejected --> D11[D11 Reprocess] + Q2 -- approved --> D13[D13 Payment notice and acknowledgement] + D13 -- paid short --> D12[D12 Claim the shortfall] + D4 -. withdraw .-> D8[D8 Cancel] + D4 -. revise .-> D5[D5 Resubmit] +``` + +## Scheme setup and identity + +### D1: fetch insurance plan + +**API Called:** `/v1/insuranceplan/request` +**Callback API:** `/v1/insuranceplan/on_request` +**Payload:** encrypted TaskBundle on the request, InsurancePlanBundle on the response + +The InsurancePlan is the structured representation of the policy under which a patient is covered. PMJAY is strictly package-based, with bundled costs for each service. Referencing the correct plan is what keeps the claim to admissible services, avoids rejections for non-compliance with scheme guidelines, and gives both sides an auditable record. + +The request is keyed on Provider ID, Policy Code and Participant ID. The response is scoped to that provider. It returns the specialties relevant to it, the covered services and their limits, and the mandatory documents for both preauthorisation and claim, at policy level and per benefit. It also carries the Standard Treatment Guidelines and clinical protocols, and the policy conditions, exclusions and renewal information. + +**How the plan is built.** Each specialty holds packages. Each package has a rate. Over and above the rate, the plan can attach add-ons that the payer allows for that package: an implant, a higher-cost bed category (called stratification), a high-end medicine or investigation. The plan also carries flags per package that change how a claim is built: whether it is an unspecified procedure, a cyclic one, or one that applies to a LAMA or DAMA discharge. The scheme rules section below explains each. + +**Size and storage.** The plan object sometimes exceeds 20 MB. The system must accept a payload that large and store it in a structured, queryable form linked to the policy record. + +**Freshness and versioning.** Refresh the plan regularly, and immediately whenever a policy is renewed or amended. The FRD says weekly; the scenario sheet says once in fifteen days. Version control on tariffs and packages is not optional: an outdated tariff version causes a rate mismatch and automatic claim rejection on suspicion of tampering. Keep audit logs of every fetch, refresh and version update, and of the version used in each preauth or claim. + +**Driving the forms.** The stored plan populates the preauth and claim forms with benefits and limits, and supplies the STG checklist, which must be rendered dynamically against the treatment plan selected. The questionnaire URL received in the plan is what gets sent back in the questionnaire response. + +### D2: biometric authentication of the beneficiary + +**API Called:** ABHA biometric auth init, then auth verify, with a refresh token endpoint +**Callback API:** none +**Note:** this is not an NHCX API. It was built specifically for the PMJAY payer. + +The scheme mandates biometric verification of the beneficiary at registration, during treatment and at discharge, to establish physical presence. + +**All three methods must be built.** Fingerprint, iris and face authentication are each mandatory to implement, because any of them may be the one that works for a given patient. A preauthorisation raised with a fingerprint can be followed by a claim raised with face authentication; the methods do not have to match. Fingerprint and iris follow an init-then-verify pair. Face authentication is a different flow. Initiate, show the patient a QR code to scan in the ABHA app, and poll until the capture is complete. Then verify with the Aadhaar number encrypted using the public key the portal supplies. + +On success the system receives a User Token, which must be passed as a header on every subsequent PMJAY claim event that requires proof of presence, including the coverage eligibility check and the preauthorisation submission. The payer validates this token before treating the request as legitimate. Discharge requires a fresh authentication, and that token is passed on the claim submission. + +**Token lifetime.** The User Token is valid for 30 minutes. Systems must refresh it automatically for the duration of a transaction cycle, and if it expires, start a fresh biometric authentication. + +```mermaid +sequenceDiagram + box Provider side + participant H as Hospital system + end + box ABDM + participant A as ABHA biometric service + end + box Payer side + participant Y as PMJAY payer + end + H->>A: auth init, fingerprint, iris or face + A-->>H: transaction id + H->>A: auth verify with the captured biometric + A-->>H: user token valid 30 minutes, plus refresh token + H->>Y: eligibility and preauthorisation, token in the header + Note over H: refresh before 30 minutes, else authenticate again + H->>A: fresh authentication at discharge + H->>Y: claim, discharge token in the header +``` + +**Applicability.** This applies only to beneficiaries whose ABHA number is linked to their PMJAY card. Beneficiaries without that linkage follow the existing PMJAY-approved KYC protocols. + +**Exemption.** Where biometric or Aadhaar authentication is not feasible, the provider obtains an Aadhaar exemption consent document signed by both the patient and a hospital representative. Store it digitally and link it to the beneficiary record. A preauthorisation or claim may then be raised on the consent form instead. The one exception is a cyclic procedure, where live biometrics are required at every step. Biometric authentication or a valid exemption is mandatory before a claim can be submitted. + +## Eligibility + +### D3: check coverage eligibility + +**API Called:** `/v1/coverageeligibility/check` +**Callback API:** `/v1/coverageeligibility/on_check` +**Payload:** encrypted CoverageEligibilityRequestBundle + +The check verifies a patient's eligibility and available benefits before registration or treatment. It is served with four purposes, and the purpose determines what comes back. + +- **Validation.** Confirms the specified coverages are in force, and returns the wallet balance. The benefit component carries one entry per wallet applicable to the beneficiary, with the allowed balance and the amount consumed. Called after registration. +- **Discovery.** Asks the insurer to report any coverages it knows of beyond those specified, giving the list of all active coverages for the beneficiary. +- **Benefits.** Returns the plan benefits, and optionally the benefits already consumed, for the listed or discovered coverages. Called before raising a preauthorisation or enhancement. +- **Auth requirements.** Returns the prior authorisation requirements for the given categories of service or billing codes, procedure by procedure, and the documents needed at each stage. This is where the documents and questionnaires mandatory for preauthorisation come from. Called on the preauthorisation page before submission. + +Validation, discovery and benefits require the Beneficiary ID, Coverage or Plan Code, Payer ID and Provider ID. Auth requirements and benefits additionally require the procedure or package codes. + +Register the patient only after coverage is validated, and alert both provider and patient where coverage is insufficient, including the case where a family's shared limit is exhausted. Call this check again, as a validation, every time an additional treatment is added, so the limit is confirmed before a preauthorisation goes out. + +## Preauthorisation + +All five preauthorisation exchanges share the same endpoints and the same bundle structure. The workflow code is what distinguishes them. Each follow-up, whether a query answer, an enhancement or a resubmission, is a new request carrying the original reference and a fresh correlation ID. + +**API Called:** `/v1/preauth/submit` +**Callback API:** `/v1/preauth/on_submit` +**Payload:** encrypted ClaimBundle, answered with a ClaimResponseBundle + +The documents and questionnaires required come from the coverage eligibility response with purpose auth-requirements. Procedure components must match the values returned by the InsurancePlan. The preauthorisation amount may not exceed the balance remaining on the beneficiary's coverage. Two dates are mandatory, each sent as a timing (date or period) or as a string value, adhering to NRCeS standards. + +| Field | Category | Code | Display | +| :---- | :---- | :---- | :---- | +| Registration date | `OTH` | `EDT` | EncounterDateTime | +| Admission date | `ONS` | `ADDD` | Admission date - Discharge date | + +See the note under D9 on where these codes come from and where the source documents disagree. + +A preauthorisation cannot be raised more than one day in advance, and D2 must be completed before submission. + +### D4: submit preauthorisation + +**Workflow ID:** 12 + +The first preauthorisation for a case. It is auto-approved only if it is the first preauth for that case and every requested procedure is eligible for auto-approval. Separately, where the policy is eligible for turnaround-time approval and no action is taken within the defined window, the case is approved automatically. Everything else is adjudicated manually by the payer. + +### D5: resubmit preauthorisation + +**Workflow ID:** 121 + +Raised once a base preauth already exists, for example to revise an approved or rejected case for a higher amount or a different package. A resubmission nullifies all previous instances, and the payer treats it as the new base request. + +### D6: raise enhancement + +**Workflow ID:** 13, with 131 for a response to an enhancement query + +Raised against an already approved preauth to extend a procedure or add new ones. Unlimited enhancements are allowed until discharge, within the limit, but each can only be sent after the previous request has closed. Check the plan's rules for the package before raising one. The bundle carries the enhancement workflow ID, the already approved treatments, and the treatments now sought. + +### D7: respond to preauthorisation query + +**Workflow ID:** 19 + +A query arrives in the item-wise adjudication field of the preauth response bundle. The provider reads it and answers with a preauth query response, not a resubmission. The bundle structure is unchanged. + +### D8: cancel preauthorisation + +**Workflow ID:** PC01 +**Payload:** Task bundle + +Cancels the whole preauthorisation. It can be raised at any point until the claim is raised, against an active preauth or one still pending decision at the payer end. The Task carries the code `cancel`, the case number as its input (the FRD calls this the intimation number, the scenario sheet the claim number), a reason, and any remarks in the disposition. + +Reasons the payer recognises: `treatmentplanchanged`, `patientrequest`, `financialconstraints`, `alternativetreatment`, `duplicateclaim`, `administrativeerror`, and `other` with a free-text explanation. + +## Claim + +The claim exchanges share endpoints and bundle structure in the same way. + +**API Called:** `/v1/claim/submit` +**Callback API:** `/v1/claim/on_submit` +**Payload:** encrypted ClaimBundle, answered with a ClaimResponseBundle + +The documents and questionnaires for the claim come from the InsurancePlan response. Coverage eligibility with purpose auth-requirements supplies only those needed at preauthorisation; the remainder are mandatory at claim. The claim amount may not exceed the preauthorisation's approved amount. A claim cannot be cancelled. + +### D9: submit claim + +**Workflow ID:** 15 + +**PMJAY has no separate discharge workflow.** Raising a claim implicitly asserts that the patient has been discharged, so discharge details form part of the claim request itself. Once the preauthorisation is approved and treatment is complete, the patient is discharged and the claim submitted, carrying a fresh D2 token. + +Four dates and the discharge status are mandatory. Each date is sent as a timing (date or period) or as a string value, adhering to NRCeS standards. + +| Field | Category | Code | Display | +| :---------------- | :-------------------------------- | :-------------------------------- | :------------------------------ | +| Registration date | `OTH` | `EDT` | EncounterDateTime | +| Admission date | `ONS` | `ADDD` | Admission date - Discharge date | +| Surgery date | `ONS`, or `SURD` in every sample | `PSP`, or `ADDD` in every sample | PatientSurgeryPerformed | +| Discharge date | `ONS`, or `DSCHD` in every sample | `DSDE`, or `ADDD` in every sample | Discharge Date | + +The discharge status itself goes under category `DIS`, with the code carrying the type of discharge. All four types from the hospital workflow are represented. There is no "referred to another hospital" type; a patient is discharged as one of these four before being admitted elsewhere. + +| Code | Display | Discharge type | +| :---- | :---- | :---- | +| `DTH` | DischargeToHome | Normal discharge | +| `DTM` | DischargetoMortuary | Death | +| `LAMA` | Discharge with LAMA | Left against medical advice, without telling the hospital | +| `DAMA` | Discharge with DAMA | Discharged against medical advice, having signed an undertaking | + +The value against the `DIS` entry is not a date. It is a string carrying the discharge stage: **Before Surgery**, **During Surgery** or **After Surgery**. It is sent for medical cases as well as surgical ones. Each discharge type has a matching questionnaire in the plan (Death, Life, LAMA, DAMA), found by title. + +A death is the one case that needs a fifth date. Where the discharge type is `DTM`, send the death date as an additional entry under category `ONS` with the same `DTM` code, alongside the four dates above. + +**LAMA and DAMA claims carry a special procedure code.** Under LAMA or DAMA, procedure code `LM100` may be the only code the payer accepts on the claim. Every item approved on the earlier preauthorisation is disqualified and only the stay is paid. The `LM100` line carries the number of days admitted as its quantity, and a LAMA discharge also sends the bed category with its duration. `LM100` is never valid on a preauthorisation. + +Which discharge stages trigger it is stated four ways across the sources: before surgery only, before or during, before or after, and after or during in the payer's own error message. Establish the rule with the payer before building; it decides whether an approved package is paid or voided. + +```mermaid +flowchart TD + A[Patient leaves] --> B{How?} + B -- went home --> DTH[DTH] + B -- died --> DTM[DTM, plus the death date] + B -- left without telling --> LAMA[LAMA] + B -- left, signed an undertaking --> DAMA[DAMA] + LAMA --> S{At what stage?} + DAMA --> S + S -- before surgery --> LM["LM100 only, quantity = days admitted, preauthorised items voided"] + S -- after surgery --> ST[Surgery items stand, no LM100] +``` + +**A note on the codes above.** These combinations are taken from the NHCX gateway validation messages, which reject a claim naming the exact category and code expected. The Functional Requirement Document gives a different set for three of these fields, listing the admission, surgery and discharge dates under categories `ADMD`, `SURD` and `DSCHD` with code `ADDD` throughout. Those three categories do not appear in the supporting info category value set. Confirm against the current NRCeS value sets before building. + +Claims are adjudicated manually, approved or rejected case by case. + +### D10: respond to claim query + +**Workflow ID:** 161. The payer refuses 151, 19 and 16 with `PAYR-1321`. + +As with D7, the provider answers a payer query with a claim query response using the same Claim Bundle structure. + +### D11: reprocess a rejected claim + +**API Called:** `/v1/task/submit` +**Callback API:** `/v1/task/on_submit` +**Workflow ID:** 36 +**Payload:** Task bundle, with a supporting document attached + +When a claim is rejected outright and the hospital disputes it, it asks for a re-evaluation. This is an appeal, not a resubmission: the claim itself is not sent again. + +The Task carries the code `reprocess` and the reason `claimrejected`. It names the case by its claim number, which under PMJAY is the preauthorisation number the hospital generated. No amount is sent, because the whole claim is in dispute. A supporting document is mandatory; without one there is no ground for the appeal. It can be raised as soon as the rejection arrives, with no dependency on any payment notice. + +The request goes to the Claim Review Committee, whose decision is final. A claim can be reprocessed once. The original claim number carries forward; no new case is created. + +### D12: claim a shortfall (erroneous claim) + +**API Called:** `/v1/task/submit` +**Callback API:** `/v1/task/on_submit` +**Workflow ID:** 36 +**Payload:** Task bundle, with a supporting document attached + +When a claim is approved and paid, but for less than was claimed, the hospital can ask for the difference. This uses the same Task as a reprocess with one change: the reason is `partialpayment`, and an amount is sent. + +The amount is capped at the shortfall. A claim raised for 10,000 and paid at 6,000 can ask for up to 4,000, with justification, and never more. The request can only be raised once the payment cycle is complete: after the payment notice with workflow 33 has arrived and the hospital has verified the money and sent its acknowledgement, code 17. As with a reprocess, it can be raised once, and a supporting document is mandatory. + +The two mechanisms do not chain. If a reprocess results in a partial approval, no shortfall claim can follow, because the Committee's decision is final. + +```mermaid +flowchart TD + A[Claim adjudicated] --> B{Outcome} + B -- rejected --> C["D11 Reprocess: Task, reason claimrejected, document attached, no amount"] + B -- paid in full --> D[Done] + B -- paid short --> E[Wait for payment notice 33] + E --> F[Verify the money, send acknowledgement 17] + F --> G["D12 Shortfall: Task, reason partialpayment, amount up to the difference"] + C --> H[Claim Review Committee decides, and that is final] + G --> H +``` + +## Payment + +### D13: acknowledge payment notice + +**API Called:** `/v1/paymentnotice/on_request` +**Callback API:** `/v1/paymentnotice/request` +**Workflow ID:** 17 + +Once a claim is approved and payment made, the payer sends a payment notice, which the provider system must be able to accept and acknowledge. Three notices may arrive in sequence: 30 when the payer initiates the transfer, 31 when the bank processes it, and 33 when it settles and the UTR number is available. The notice gives a consolidated status. **Cleared** where the amount has been initiated, **Paid** where it has been received, **Rejected** where it was initiated but failed on a server issue, **Adjusted** where a balance is being adjusted. Payment reconciliation gives the breakup for the case, including TDS and other deductions. Keep the UTR; it is the reference for any later dispute. + +## Structured data exchange + +This requirement applies to every preauthorisation and claim bundle, D4 through D10, and is what separates a PMJAY submission from an ordinary one. The Task bundles in D8, D11 and D12 carry their document as a plain attachment instead. + +Supporting clinical information travels through the `SupportingInfo` to `DocumentReference` resource. Inside `DocumentReference.content.attachment`, the `attachment.data` field carries a Base64-encoded FHIR Bundle holding the relevant structured resources, for example DiagnosticReport, DischargeSummary or WellnessRecord. This is the difference from an unstructured submission, where the same field would carry a Base64-encoded PDF or JPG. For structured submissions the content type is set to `application/json` or `application/fhir+json`. + +The category code decides which of the two applies. Structured data uses a supporting info category among DIA, HDS, CD and INF, with the value sent as a reference. Unstructured data uses a category among POI, POA, DOB, DEF, FIR and ATT, with the value sent as an attachment. Questionnaire responses are configured under supporting info with category INF, code AT, and a reference value. + +Each document is limited to 2 MB, against a whole-bundle maximum of 20 MB, and only one document can be linked per item, so multiple documents for a single item must be merged. + +## Workflow codes + +The full code list, provider-initiated and payer response, is in the Workflow Codes chapter. The codes are the same under PMJAY, and each D-series entry above carries the one that applies to it. + +Three points are specific to PMJAY. Because the scheme does not use the Communication API for document queries, the query codes 19 and 161 travel on the preauthorisation and claim endpoints. That is what allows D7 and D10 to reuse the original bundle structure unchanged. The Communication API is still used, with its own reason codes, for turnaround-time alerts, grievances, wallet and policy changes, and arbitration acknowledgements, so a hospital system must still host it. And codes 14 and 141 for discharge have no counterpart here, because PMJAY folds discharge into the claim rather than treating it as a submission of its own. + +## Error handling and validation + +Envelope errors, receipts, retries and the error endpoint are the same as on any NHCX integration and are covered in JWE, Status and Errors. Two things are specific here. Every callback must accept the answer in two forms, decided by the `type` field. A sealed bundle when the payer processed the request, or a protocol response when it could not be opened or failed validation. And the PMJAY payer's own error codes, the `PAYR-12xx` set for preauthorisation and `PAYR-13xx` for claims, name the exact field or rule that failed; surface them to the user as they are. + +## Before you build + +Three things on the portal shorten the first week. + +- **Sample bundles.** Twenty-two worked FHIR bundles, in eleven request-and-response pairs. They cover every eligibility purpose, preauthorisation with its query, enhancement and cancellation, claim with its query, and payment notice with its acknowledgement. One is an insurance plan response of 21 MB, which shows what the storage requirement means in practice. +- **Test cases.** A matrix from TC-ABHA-01 onward, each with preconditions, inputs and expected output. The scenario list beside it includes registration, wallet update, preauthorisation with implant, discharge in multiple modes, and the Claim Review Committee path. +- **The dummy payer.** Described in the NHCX Use Cases chapter, it answers the exchanges listed in the NHCX Use Cases chapter, which does not include the Task exchanges or biometrics. diff --git a/site/docs/nhcx/v1/concepts/workflow-codes.md b/site/docs/nhcx/v1/concepts/workflow-codes.md new file mode 100644 index 000000000..ebfb7a962 --- /dev/null +++ b/site/docs/nhcx/v1/concepts/workflow-codes.md @@ -0,0 +1,209 @@ +--- +title: Workflow Codes +sidebar_label: Workflow Codes +sidebar_position: 6 +description: The 74 workflow IDs and their message directions +verification: unverified +source: nhcx-package/docs/01-Overview/06-Workflow Codes.md +generated: true +--- + +# Workflow Codes + +Endpoints alone do not identify an NHCX transaction. A new preauthorisation, a resubmission, an enhancement and a query response all travel on `/v1/preauth/submit` carrying the same bundle. What separates them is the workflow code in the `x-hcx-workflow_id` header. Each code also expects a particular status word, given here beside it. The source is the official Workflow Status Sheet on the portal, updated 18 August 2026, which remains the authority as codes are added. + +The A-series registry and session calls carry no workflow code because they are infrastructure calls rather than claim transactions. + +## Workflow Code Prefix Families + +NHA organizes workflow codes into numeric mainline cashless codes and alphanumeric families: + +| Prefix | Family Name | Scope & Operational Coverage | +| :---: | :--- | :--- | +| **`R`** | **Reimbursement** | Mirrors the numeric cashless codes for the reimbursement route - the patient paid, and is claiming it back. | +| **`G`** | **Grievance** | Raising a grievance, its acknowledgement, and its failure path. | +| **`RP`** | **Return payment** | Money going back the other way. | +| **`N`** | **Notifications** | Push notifications addressed to payer, provider or beneficiary. | +| **`DC`** | **Discharge correction** | Correcting a discharge already submitted. | +| **`PC`** | **Preauth cancellation** | Withdrawing a pre-authorisation. Raised on /v1/task/submit with code `cancel`, not on the preauth endpoint. | + +--- + +## Mainline Cashless State Machines + +In the diagrams below, each arrow carries the workflow code of the message that moves the case. + +### Preauthorisation Lifecycle + +```mermaid +stateDiagram-v2 + [*] --> Requested: 12 + Requested --> Received: 20 + Received --> Approved: 21 + Received --> Rejected: 23 + Received --> Queried: 24 + Queried --> QueryAnswered: 19 + QueryAnswered --> Received + Rejected --> Resubmitted: 121 + Resubmitted --> Received: 251 + Approved --> EnhancementAsked: 13 + EnhancementAsked --> Approved: 22 + EnhancementAsked --> EnhancementDenied: 231 + EnhancementAsked --> EnhancementQueried: 241 + EnhancementQueried --> EnhancementAnswered: 131 + EnhancementAnswered --> Approved: 22 + EnhancementAnswered --> EnhancementDenied: 231 + Received --> CancelAsked: PC01 + Approved --> CancelAsked: PC01 + CancelAsked --> Cancelled: PC02 + Approved --> [*] +``` + +### Claim Lifecycle + +```mermaid +stateDiagram-v2 + [*] --> Submitted: 15 + Submitted --> Received: 25 + Received --> InProcess: 28 + InProcess --> Forwarded: 29 + Forwarded --> InProcess + InProcess --> Queried: 27 + Queried --> QueryAnswered: 151 + QueryAnswered --> InProcess + InProcess --> Approved: 26 + InProcess --> Denied: 291 + Denied --> ArbitrationAsked: 36 + ArbitrationAsked --> ArbitrationAcknowledged: 37 + ArbitrationAcknowledged --> ReprocessApproved: 252 + ArbitrationAcknowledged --> ReprocessRejected: 253 + ArbitrationAcknowledged --> ReprocessQueried: 254 + ReprocessQueried --> ArbitrationAcknowledged + Approved --> [*] +``` + +### Payment & Settlement Lifecycle + +```mermaid +stateDiagram-v2 + [*] --> Initiated: 30 + Initiated --> Processed: 31 + Processed --> Settled: 33, UTR available + Settled --> Acknowledged: 17, sent by the provider + Acknowledged --> [*] +``` + +--- + +## Master Catalog of All 74 Workflow Codes + +Complete index of all published codes: + +| Code | Meaning / Name | Sent By | Permitted Statuses | Stages / Outcomes | Reused | +| :--- | :--- | :--- | :--- | :--- | :---: | +| **`10`** | Patient Registered | Provider | `request.initiated` | Patient Registered | No | +| **`11`** | Patient Admitted | Provider | `request.initiated` | Patient Admitted | No | +| **`12`** | Preauth Request Initiated | Provider | `request.initiated` | Preauth Request Initiated | No | +| **`121`** | Preauth Request Resubmitted | Provider | `request.initiated` | PreAuth Reprocess(Resubmission) Initimation | No | +| **`PC01`** | Preauth Cancel Initiated | Provider | `request.initiated` | Preauthorization Cancellation | No | +| **`19`** | Preauth Query Response Submitted | Provider | `response.complete` | PreAuth Query Response Submitted | No | +| **`13`** | Enhancement Request Initiated | Provider | `request.initiated` | Enhancement Request Initiated | No | +| **`131`** | Enhancement Query Response Submitted | Provider | `response.partial`, `response.error`, `response.complete` | Enhancement Query Ack Success, Enhancement Query Ack Failed, Enhancement Query Response Submitted | Yes | +| **`14`** | Discharge Submitted | Provider | `request.initiated` | Discharge Submitted | No | +| **`141`** | Discharge Query Response Submitted | Provider | `response.complete` | Discharge Query Response Submitted | No | +| **`15`** | Claim Request Initiated | Provider | `request.initiated` | Claim Request Initiated | No | +| **`151`** | Claim Query Response Submitted | Provider | `response.complete` | Claim Query Response Submitted | No | +| **`17`** | Payment Received | Provider | `response.complete` | Payment Notice Recived | No | +| **`36`** | Claim Arbitration Request Submitted | Provider | `request.initiated` | Claim Arbitration Intimation | No | +| **`20`** | Preauth Request Received | Payer | `response.partial`, `response.error` | PreAuth Ack Success, PreAuth Ack Failed | Yes | +| **`21`** | Preauth Request Approved | Payer | `response.complete` | Preauth Request Approved | No | +| **`22`** | Enhancement Request Approved | Payer | `response.complete` | Enhancement Request Approved | No | +| **`23`** | Preauth Request Rejected | Payer | `response.complete` | PreAuth Request Rejected | No | +| **`24`** | Preauth Request Queried | Payer | `request.initiated` | PreAuth Request Queried | No | +| **`241`** | Enhancement Request Queried | Payer | `request.initiated` | Enhancement Query Raise | No | +| **`25`** | Claim Request Received | Payer | `response.partial`, `response.error` | Claim Doc Ack Success, Claim Doc Ack Failed | Yes | +| **`26`** | Claim Request Approved | Payer | `response.complete` | Claim Request Approved | No | +| **`27`** | Claim Request Queried | Payer | `request.initiated`, `response.partial/complete` | Claim Request Queried, Claim Request Queried | Yes | +| **`28`** | Claim Request In Process | Payer | `response.partial` | Claim Request in process | No | +| **`29`** | Claim Forwarded | Payer | `response.partial` | Claim Forwarded | No | +| **`251`** | Reprocess Request Received | Payer | `response.complete` | PreAuth Reprocess Ack | No | +| **`252`** | Reprocess Request Approved | Payer | `response.complete` | Reprocess Request Approved | No | +| **`253`** | Reprocess Request Rejected | Payer | `response.complete` | Reprocess Request Rejected | No | +| **`254`** | Reprocess Request Queried | Payer | `request.initiated` | Reprocess Request Queried | No | +| **`261`** | Discharge Request Approved | Payer | `response.partial` | Discharge Request Approved | No | +| **`262`** | Discharge Request Rejected | Payer | `response.complete` | Discharge Request Rejected | No | +| **`263`** | Discharge Request Queried | Payer | `request.initiated` | Discharge Request Queried | No | +| **`30`** | Payment Initiated | Payer | `request.initiated`, `response.partial`, `response.error` | Payment Notice Initmation, Payment Notice Ack Success, Payment Notice Ack Failed | Yes | +| **`31`** | Payment Processed | Payer | `request.initiated` | Payment Processed | No | +| **`33`** | Payment Settled | Payer | `request.initiated` | Payment Settled | No | +| **`45`** | Final Bill Initimation | | `request.initiated`, `response.partial`, `response.error` | Final Bill Initimation, Final Bill Ack Success, Final Bill Ack Failed | Yes | +| **`181`** | Final Bill Query Response | | `response.complete` | Final Bill Query Response | No | +| **`161`** | Claim Doc Query Response | | `response.complete` | Claim Doc Query Response | No | +| **`18`** | Preauth Query Ack Success | | `response.partial`, `response.error` | PreAuth Query Ack Success, PreAuth Query Ack Failed | Yes | +| **`231`** | Enhancement Deny | | `response.complete` | Enhancement Deny | No | +| **`46`** | Final Bill Approve | | `response.complete` | Final Bill Approve | No | +| **`47`** | Final Bill Query Raise | | `request.initiated`, `response.partial`, `response.error` | Final Bill Query Raise, Final Bill Query Ack Success, Final Bill Query Ack Failed | Yes | +| **`491`** | Final Bill Deny | | `response.complete` | Final Bill Deny | No | +| **`291`** | Claim Doc Deny | | `response.complete` | Claim Doc Deny | No | +| **`R122`** | Reimburstment Claim Reprocess Requested | | `request.initiated` | Reimburstment Claim Reprocess Requested | No | +| **`R15`** | Reimburstment Claim Submitted | | `request.initiated` | Reimburstment Claim Submitted | No | +| **`R151`** | Reimburstment Claim Query Response Submitted | | `response.complete` | Reimburstment Claim Query Response Submitted | No | +| **`R252`** | Reimburstment Claim Reprocess Request Approved | | `response.complete` | Reimburstment Claim Reprocess Request Approved | No | +| **`R253`** | Reimburstment Claim Reprocess Request Rejected | | `response.complete` | Reimburstment Claim Reprocess Request Rejected | No | +| **`R254`** | Reimburstment Claim Reprocess Request Queried | | `request.initiated` | Reimburstment Claim Reprocess Request Queried | No | +| **`R26`** | Reimburstment Claim Approved | | `response.complete` | Reimburstment Claim Approved | No | +| **`R27`** | Reimburstment Claim Queried | | `request.initiated` | Reimburstment Claim Queried | No | +| **`R28`** | Reimburstment Claim Evaluation In Process | | `response.partial` | Reimburstment Claim evaluation in process | No | +| **`R291`** | Reimburstment Claim Rejected | | `response.complete` | Reimburstment Claim Rejected | No | +| **`34`** | Wallet Upgrade Intimation | | `request.initiated` | Wallet Upgrade Intimation | No | +| **`38`** | Fraud Alert | | `request.initiated` | Fraud Alert | No | +| **`35`** | Wallet Upgrade Acknowledgement | | `response.complete` | Wallet Upgrade Acknowledgement | No | +| **`37`** | Claim Arbitration Acknowledgement | | `response.complete` | Claim Arbitration Acknowledgement | No | +| **`39`** | Fraud Alert Acknowledgement | | `response.complete` | Fraud Alert Acknowledgement | No | +| **`G11`** | Grievance Intimation | | `request.initiated` | Grievance Intimation | No | +| **`G12`** | Grievance Acknowledment | | `response.complete` | Grievance Acknowledment | No | +| **`G13`** | Grievance Intimation Failure | | `response.error` | Grievance Intimation Failure | No | +| **`41`** | Preauth Arbitration Intimation | | `request.initiated` | Preauth Arbitration Intimation | No | +| **`42`** | Preauth Arbitration Acknowledgement | | `response.complete` | Preauth Arbitration Acknowledgement | No | +| **`RP1`** | Return Payment Intimation | | `request.initiated` | Return Payment Intimation | No | +| **`RP2`** | Return Payment Acknowledgement | | `response.complete` | Return Payment Acknowledgement | No | +| **`RP3`** | Return Payment Failure | | `response.error` | Return Payment Failure | No | +| **`N01`** | Notifications Intended To Payer | | `request.initiated` | Notifications Intended to Payer | No | +| **`N02`** | Notifications Intended To Provider | | `request.initiated` | Notifications Intended to Provider | No | +| **`N03`** | Notifications Intended To Beneficiary | | `request.initiated` | Notifications Intended to Beneficiary | No | +| **`N04`** | Acknowledgement Of The Notificaion | | `response.complete` | Acknowledgement of the Notificaion | No | +| **`DC01`** | Discharge Correction Intimation | | `request.initiated` | Discharge Correction Intimation | No | +| **`DC02`** | Acknowledgement For Discharge Correction | | `response.complete` | Acknowledgement for Discharge Correction | No | +| **`PC02`** | Preauthorization Cancellation Accomplished | | `response.complete` | Preauthorization Cancellation Accomplished | No | + +--- + +## Reconciled Discrepancies and Authority Rules + +Seven codes are published differently in the PMJAY Handbook and the Workflow Status Sheet, resolved here by taking the Workflow Status Sheet as the definitive authority: + +| Code | PMJAY Handbook | Workflow Status Sheet | +| :--- | :--- | :--- | +| **`17`** | PAYMENT_RECEIVED, provider-side - "Payment received acknowledgment" | "Payment Notice Recived", response.complete | +| **`24`** | Payer-side response code, PREAUTH_REQUEST_QUERIED | "PreAuth Request Queried", header request.initiated | +| **`27`** | Payer-side response code, CLAIM_REQUEST_QUERIED | "Claim Request Queried", header request.initiated | +| **`30`** | Payer-side, PAYMENT_INITIATED | "Payment Notice Initmation", request.initiated | +| **`31 / 33`** | Payer-side response codes | header request.initiated | +| **`251`** | REPROCESS_REQUEST_RECEIVED | "PreAuth Reprocess Ack" | +| **`36`** | CLAIM_ARBITRATION_REQUEST_SUBMITTED, use case "Reprocess/Erroneous request" | "Claim Arbitration Intimation" | + +The same authority settles these conflicts across official NHA publications (Workflow Status Sheet vs PMJAY Handbook vs Value Sets): + +1. **251**: Reconciled as Preauthorisation Resubmission acknowledgement in the sheet; the PMJAY handbook uses it in its claim reprocess section. +2. **Cancellation (PC01 vs 122)**: The sheet and handbook code table prescribe `PC01` (request) and `PC02` (completion). The handbook prose mentions `122`, which clashes with `R122` (reimbursement claim reprocess). Integrators should strictly use `PC01` and `PC02` on `/v1/task/submit`. +3. **18**: Defined as Preauthorisation Query Acknowledgement in the sheet; the handbook repurposes it for claim reprocess. +4. **Reprocess (36 vs 18)**: Section 11 gives `18` for reprocess, while Section 12 gives `36` (Claim Arbitration). Integrators should use `36` with task code `reprocess` and reason `claimrejected`. +5. **Shortfall**: Rides on `36` as a Task with code `reprocess` and reason `partialpayment`, raised only after payment notice `33` has arrived and been acknowledged with `17`. +6. **25 and 291**: Named as Claim *Document* acknowledgement and denial in the sheet, and Claim request received and denied in the value sets. Both refer to the same transition. + +### Protocol Fault Flags + +The source sheet's audit flags mark certain code-and-status pairs as protocol errors rather than normal traffic: +- For `131`, `45`, `47`, and `30`, sending **either** `response.partial` or `response.error` is flagged as an invalid state transition. +- `18` sent with `response.error` is flagged as an invalid terminal state. +- Query `27` sent as `response.partial` or `response.complete` is invalid (must be `request.initiated`). diff --git a/site/docs/nhcx/v1/getting-started/README.md b/site/docs/nhcx/v1/getting-started/README.md deleted file mode 100644 index c597633c7..000000000 --- a/site/docs/nhcx/v1/getting-started/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Getting started - -Orientation for a developer new to NHCX: what it is, how to get sandbox -access or onboard, the glossary. Pages here are read first and in order, so -give each one a `sidebar_position`. - diff --git a/site/docs/nhcx/v1/getting-started/base-urls.md b/site/docs/nhcx/v1/getting-started/base-urls.md new file mode 100644 index 000000000..d0c9fd8d0 --- /dev/null +++ b/site/docs/nhcx/v1/getting-started/base-urls.md @@ -0,0 +1,69 @@ +--- +title: Base URLs +sidebar_label: Base URLs +sidebar_position: 2 +description: Every service's base in the sandbox and in production, from `baseurl.yaml` +verification: unverified +source: nhcx-package/docs/02-Getting Started/02-Base URLs.md +generated: true +covers: + - nhcx.sandbox.environments-and-base-urls +--- + +# Base URLs + +Every NHCX call is a base URL followed by a path. The paths are the same in the sandbox and in production. The bases are not, and they differ from one service to the next, so keep each one in configuration rather than in code. + +## In short + +- Each service has its own base. The exchange, the participant service and the ABDM gateway are three different bases, not one. +- A path in this documentation, such as `/v1/preauth/submit`, goes after the base of the service that serves it. +- Only some production bases are published. The rest arrive with your onboarding; Going Live has the order of the switch. + +## Every base, in both environments + +| Service | Sandbox | Production | +| :---- | :---- | :---- | +| ABDM session token | `https://dev.abdm.gov.in` | `https://apis.abdm.gov.in`. ABDM's published production gateway. Confirm it in your onboarding letter. | +| NHCX exchange | `https://apisbx.abdm.gov.in/hcx` | `https://apisprod.nha.gov.in/hcx` | +| Participant service | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice` | `https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice` | +| ABDM proxy | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/abdmproxy` | Not published. Confirm at onboarding. | +| PMJAY payer service, role lookup | `https://apisbx.abdm.gov.in` | Not published. Confirm at onboarding. | +| PMJAY payer service, act on a case | `https://apisbeta.nha.gov.in` | Not published. Confirm at onboarding. | +| Dummy payer | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/dummyhcxpayer` | A sandbox test hook only. | +| NHCX portal | `https://hcxsbx.abdm.gov.in` | Not published. | +| Face authentication page | `https://phrsbx.abdm.gov.in/face-auth` | Not published. | + +What each one serves: + +- **ABDM session token**: The session token every other call carries, at /api/hiecm/gateway/v3/sessions. +- **NHCX exchange**: Every use-case call under /v1, fingerprint and iris authentication under /abha. +- **Participant service**: Creating and updating a participant, the registry search, certificates and policies. +- **ABDM proxy**: Face authentication for PMJAY biometrics. +- **PMJAY payer service, role lookup**: The roles a PMJAY adjudicator user holds, at /pmjay/sbxhcx/nhcxpayerservice/v1/get/user-role. +- **PMJAY payer service, act on a case**: Acting on a PMJAY case, at /pmjay/hcx/nhcxpayerservice/wrapper/process/case. +- **Dummy payer**: The sandbox test hooks that make the dummy payer answer. +- **NHCX portal**: The portal, the live Swagger specifications it publishes, and notification subscribe. +- **Face authentication page**: The QR page a patient opens to complete face authentication, with ?txnId=<txnId>. + +The ABDM gateway also reads `X-CM-ID` on the session call: `sbx` in the sandbox, `abdm` in production. + +On the sandbox, a preauthorisation is therefore posted to `https://apisbx.abdm.gov.in/hcx/v1/preauth/submit`, and a participant is created at `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/v2/participant/create`. + +## Three things that are easy to get wrong + +**The use-case path is `/hcx/v1`, the participant path is `/pmjay/sbxhcx/participanthcxservice`.** They are different services on the same host and neither prefix works for the other. + +**Biometrics span two bases.** Fingerprint and iris sit under the exchange's `/abha/`; face authentication sits under the ABDM proxy's `/abha/`. A client that assumes one base path for all three will fail on face authentication alone. + +**The payer service spans two hosts.** The role lookup is on `apisbx.abdm.gov.in` and the action endpoint on `apisbeta.nha.gov.in`. + +## Production + +The exchange's production base is `https://apisprod.nha.gov.in/hcx`. The participant service's production address is published, and so is ABDM's production gateway. The NHCX Adapter assumes the pattern of swapping the sandbox hostname for the others, but that is an inference. Check every production base against your onboarding letter before you switch. + +## Next steps + +- Session Token: the first call, made against the ABDM gateway's base +- Environments and Addresses, in the Reference: every full address, the headers each service reads, and the firewall +- Going Live: when and how each base changes to production diff --git a/site/docs/nhcx/v1/getting-started/build-with-ai.mdx b/site/docs/nhcx/v1/getting-started/build-with-ai.mdx new file mode 100644 index 000000000..c91ad2304 --- /dev/null +++ b/site/docs/nhcx/v1/getting-started/build-with-ai.mdx @@ -0,0 +1,53 @@ +--- +title: Build with AI +sidebar_label: Build with AI +sidebar_position: 1.3 +description: "Give your coding agent the NHCX documentation and skills: over the Docs MCP server, as agent skills, or as Markdown it fetches." +verification: unverified +source: nhcx-package, system/build-ekadocs.mjs +generated: true +--- + +import McpInstall from '@site/src/components/docs/McpInstall'; +import SkillPicker from '@site/src/components/docs/SkillPicker'; + +# Build with AI + +Give your coding agent the NHCX documentation while it builds. Connect it to the Docs MCP server, install the NHCX agent skills, or have it fetch these pages as Markdown. + +## Connect the Docs MCP server + +The Docs MCP server searches the portal's catalogue. For NHCX it holds an entry for each concept, call, callback, error, flow and test case. It also holds the operations in the NHCX specifications. HIE-CM uses the same server, so one connection covers both. + + + +## Read these pages as Markdown + +- `/llms.txt` lists every page on this site. `/llms-full.txt` carries the text of every page in one file. +- Each NHCX API module has its own index at `/docs/nhcx/v1/api//llms.txt`. [API references](/docs/nhcx/v1/api) names the modules. +- Add `/index.md` to the address of any page to get that page as Markdown. + +## Agent skills + +There is one skill per NHCX use case, in episode order. Each builds its use case into a hospital information system or a standalone claims desk. +It checks what your system already has and builds only what is missing. The bundles it sends are held to the pinned samples in the NHCX package. Each skill installs and runs alone. + +| Skill | What it builds | [Use cases](/docs/nhcx/v1/concepts/nhcx-use-cases) | +| --- | --- | --- | +| `nhcx-coverage` | Policy search and coverage eligibility: discovery, validation and benefits | A2, B1, D3 | +| `nhcx-insurance` | The payer's package master: requested once per facility and policy, reused, and quoted from | B2, D1 | +| `nhcx-preauth` | Pre-authorisation, its query answers, enhancement, cancellation and predetermination | B3, B8 cancel, B9, D2, D4 to D8 | +| `nhcx-claim` | The discharge and the claim, the claim query answer, and the decision | B5, D9, D10 | +| `nhcx-payment` | Payment notices, each recorded once and acknowledged at once | B7, D13 | +| `nhcx-communication` | Payer queries and notifications: notifications acknowledged, queries answered | B4 | +| `nhcx-reprocess` | Reprocessing a decided claim, the balance of a short payment, and status enquiries | A5, B8 reprocess, D11, D12 | + + + +In Claude Code the portal's `nhcx` plugin carries all seven. Add the portal's marketplace as [Install the plugin](/docs/hiecm/v3/getting-started/build-with-ai#install-the-plugin) shows, then run `claude plugin install nhcx@abdm-portal`. + +## Next steps + +- [Get your sandbox credentials](/docs/nhcx/v1/getting-started/get-your-sandbox-credentials) +- [Quickstart](/docs/nhcx/v1/getting-started/quickstart) +- [The base framework](/docs/nhcx/v1/getting-started/the-base-framework) diff --git a/site/docs/nhcx/v1/getting-started/building-and-sending-a-jwe.md b/site/docs/nhcx/v1/getting-started/building-and-sending-a-jwe.md new file mode 100644 index 000000000..685fb7fa7 --- /dev/null +++ b/site/docs/nhcx/v1/getting-started/building-and-sending-a-jwe.md @@ -0,0 +1,142 @@ +--- +title: Building and sending a JWE +sidebar_label: Building and sending a JWE +sidebar_position: 8 +description: RSA-OAEP-256 + A256GCM compact serialisation +verification: unverified +source: nhcx-package/docs/02-Getting Started/08-Building and Sending a JWE.md +generated: true +--- + +# Building and sending a JWE + +A message on the exchange is a JSON Web Encryption token: a readable protected header and an encrypted body, serialised as five base64url parts joined by dots. The body is a FHIR bundle. This chapter builds one with an empty bundle, so that what you are testing is the envelope and the plumbing, not the FHIR. + +## The protected header + +Every field the exchange needs to route and log the message. All the `x-hcx-` names are fixed. + +```json +{ + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": "1000004446@hcx", + "x-hcx-recipient_code": "1000003538@hcx", + "x-hcx-api_call_id": "a1b2c3d4-e5f6-4890-abcd-ef1234567890", + "x-hcx-request_id": "f0e1d2c3-b4a5-4978-8fed-cba987654321", + "x-hcx-correlation_id": "11223344-5566-4788-99aa-bbccddeeff00", + "x-hcx-workflow_id": "12", + "x-hcx-timestamp": "2026-09-04T11:46:34+05:30", + "x-hcx-status": "request.initiated", + "x-hcx-ben-abha-id": "91123456781234" +} +``` + +- `alg` and `enc` are the encryption. The protocol page says `RSA-OAEP`; the handbook, the code samples and every Postman body on the portal say `RSA-OAEP-256`. Use `-256`. +- The three IDs are fresh UUIDs. `api_call_id` is new per call, `request_id` per request, `correlation_id` per conversation and reused on the answer. +- `workflow_id` says which step this is. `12` is a new preauthorisation. +- `timestamp` is ISO 8601. Which zone is contested: the handbook says Indian time and that UTC will fail validation, the FAQ says UTC with a trailing `Z`. The sample bundles use `+05:30`. Confirm before building; it is a validated field. +- `status` is always `request.initiated` on something you initiate. +- `ben-abha-id` is the beneficiary's ABHA number without hyphens. + +## The smallest possible bundle + +```json +{ + "resourceType": "Bundle", + "id": "smoke-test-001", + "type": "collection", + "timestamp": "2026-09-04T11:46:34+05:30", + "entry": [] +} +``` + +This is a valid FHIR Bundle with nothing in it. The exchange will accept it, because it only reads the header. The dummy payer will reject it, because there is no Claim inside. That rejection is what the next chapter catches. + +## Sealing it + +The recipe, from the message-security page. Base64url the header, generate a random content key, and encrypt that key with the recipient's public key using RSA-OAEP. Generate an IV, encrypt the bundle with AES-256-GCM using the header as additional authenticated data, and join the five parts. A JOSE library does all of it. + +```js +bundle = json.encode(fhirBundle) + +header = { + "alg": "RSA-OAEP-256", + "enc": "A256GCM", + "x-hcx-sender_code": sender, + "x-hcx-recipient_code": recipient, + "x-hcx-api_call_id": randomUUID(), + "x-hcx-request_id": randomUUID(), + "x-hcx-correlation_id": correlationId, + "x-hcx-workflow_id": workflowId, + "x-hcx-timestamp": currentISTTimestamp(), + "x-hcx-status": "request.initiated", + "x-hcx-ben-abha-id": abhaId +} + +jwe = jose.encrypt( + plaintext = bundle, + recipientKey = recipientPublicKey, // from the certificate fetched in the previous chapter + protectedHeader = header, + algorithm = "RSA-OAEP-256", + encryption = "A256GCM" +) + +body = { "payload": jwe } +``` + +:::warning +This is pseudo-code, not something to paste. Use your language's JOSE library: `jose` on Node, `jwcrypto` on Python, Nimbus on Java, `System.IdentityModel.Tokens.Jwt` or `jose-jwt` on .NET. +::: + +The result is one long string with four dots in it. That is the whole message. +Java users can take the portal's `JWEPayloadUtil` sample as-is; it does the same thing with Nimbus, `JWEAlgorithm.RSA_OAEP_256` and `EncryptionMethod.A256GCM`, passing the `x-hcx-` fields as custom header parameters. + +## Sending it + +The request body is a JSON object with one field. + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/hcx/v1/preauth/submit' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --header 'x-hcx-sender_code: 1000004446@hcx' \ + --header 'x-hcx-recipient_code: 1518@hcx' \ + --header 'x-hcx-api_call_id: ' \ + --header 'x-hcx-request_id: ' \ + --header 'x-hcx-correlation_id: ' \ + --header 'x-hcx-workflow_id: 12' \ + --header 'x-hcx-timestamp: ' \ + --header 'x-hcx-status: request.initiated' \ + --header 'x-hcx-ben-abha-id: 91711234567890' \ + --header 'x-hcx-use_case: New' \ + --data-raw '{ + "payload": "eyJhbGciOiJSU0EtT0FFUC0yNTYiLCJlbmMiOiJBMjU2R0NNIiwieC1oY3gtc2VuZGVyX2NvZGUiOi4uLn0.encrypted_key.iv.ciphertext.tag" + }' +``` + +[Pre-authorisation submit in the API reference](/docs/nhcx/v1/api/preauth/endpoints/preauth-v1-preauth-submit) + +## What comes straight back + +`202 Accepted`. The receipt below is the shape the sources define for a *recipient* acknowledging a delivery, which is what your own callback must return in the next chapter. Treat it as the pattern rather than a guaranteed gateway body, and inspect a real response: + +```json +{ + "timestamp": "04/09/2026 11:46:35:120", + "api_call_id": "a1b2c3d4-e5f6-4890-abcd-ef1234567890", + "correlation_id": "11223344-5566-4788-99aa-bbccddeeff00", + "result": { + "sender_code": "1000004446@hcx", + "recipient_code": "1000003538@hcx", + "entity_type": "preauth", + "protocol_status": "request.queued" + }, + "error": { "code": "", "message": "" } +} +``` + +This is not the decision. It says the envelope was valid and the message has been queued for the recipient. The decision, or in this case the rejection, comes later, on your callback. + +If instead you get `400`, the envelope failed validation. If you get `401`, go back to the token chapter. Anything else about the bundle itself will not show up here at all; the exchange never opens it. diff --git a/site/docs/nhcx/v1/getting-started/creating-and-updating-a-participant.md b/site/docs/nhcx/v1/getting-started/creating-and-updating-a-participant.md new file mode 100644 index 000000000..de17cd2f3 --- /dev/null +++ b/site/docs/nhcx/v1/getting-started/creating-and-updating-a-participant.md @@ -0,0 +1,189 @@ +--- +title: Creating and updating a participant +sidebar_label: Creating and updating a participant +sidebar_position: 5 +description: Registry onboarding and participant updates +verification: unverified +source: nhcx-package/docs/02-Getting Started/05-Creating and Updating a Participant.md +generated: true +--- + +# Creating and updating a participant + +A participant record is your identity on the exchange. It holds your participant code, your role, your certificate and your callback address. You create it once, then update it whenever the certificate or the address changes. + +The sandbox and production differ here. The sandbox is a single call each way. Production adds a one-time passcode to the registered mobile number at every step, so nobody can register a hospital they do not control. Both are shown. + +## Sandbox: create + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/participant/create' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --header 'source: internal' \ + --data-raw '{ + "linked_registry_codes": [ + "10001" + ], + "registryid": "", + "participant_name": "Test Hospital", + "scheme_code": "PMJAY", + "state": "Haryana", + "district": "Panchkula", + "roles": [ + "10001" + ], + "primaryEmail": "integration@hospital.example", + "phone": [ + "01123456789" + ], + "primaryMobile": "9876543210", + "signing_cert_path": "", + "encryption_cert": "", + "endpoint_url": "https://nhcx.hospital.example" + }' +``` + +[Participant create (v1) in the API reference](/docs/nhcx/v1/api/onboarding/endpoints/onboarding-participant-create) + +Field by field: + +| Field | What to put | +| :---- | :---- | +| `linked_registry_codes` | Which registry vouches for you. `10001` HFR, `10002` NIN, `10003` ROHINI, `10004` payer registry. | +| `registryid` | On the sandbox, your ABDM client ID. In production, the HFR ID for a hospital or the IRDAI ID for a payer. | +| `roles` | `10001` provider, `10002` payer, `10003` TPA. The full list is in the Overview. | +| `encryption_cert` | The base64 certificate from the previous chapter. | +| `signing_cert_path` | Optional. Leave empty. | + +The response carries your new address: + +```json +{ "participant_code": "1000004446@hcx" } +``` + +Keep it. It is `x-hcx-sender_code` on everything you send from now on. A hospital group creates one participant per facility, each with its own HFR ID, using the same credentials. + +## Sandbox: update + +The same shape, keyed on the participant code, used to change the certificate or the callback address: + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/participant/update' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --data-raw '{ + "participant_code": "", + "participant_name": "Test Hospital", + "scheme_code": "PMJAY", + "roles": [ + "10001" + ], + "primaryEmail": "integration@hospital.example", + "phone": [ + "01123456789" + ], + "primaryMobile": "9876543210", + "endpoint_url": "https://nhcx.hospital.example", + "signing_cert_path": "", + "encryption_cert": "" + }' +``` + +[Participant update (v1) in the API reference](/docs/nhcx/v1/api/registry/endpoints/registry-participant-update) + +`endpoint_url` is the base of your callback server, sometimes called the bridge URL. It can be set at creation as well as on update. The exchange appends the callback path to it: a preauthorisation decision arrives at `/v1/preauth/on_submit`. The rules for this address are in Receiving a Callback. + +## Production: four steps + +Base: `https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice`. + +**1. Create.** `POST v2/participant/create` + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/v2/participant/create' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --data-raw '{ + "registrytype": "10001", + "registryid": "XXXXX74586", + "role": [ + "10001" + ], + "endpointurl": "https://nhcx.demohospital.example.in", + "mobilenumber": "XXXX748348", + "email": "sample@gmail.com" + }' +``` + +[Participant create (v2) in the API reference](/docs/nhcx/v1/api/onboarding/endpoints/onboarding-v2-participant-create) + +The mobile number must match the one on your HFR record exactly, or for a payer the one NHA holds. The response gives `participantid` and a `transactionid`, and a passcode is sent to that mobile. The participant exists, in a pending state. + +**2. Confirm.** `GET validate?transactionId=&passcode=`. Note the method: the two confirmation calls are GETs, not POSTs. The participant becomes active. + +```bash +curl --location --request GET 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/validate?transactionId=&passcode=' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' +``` + +[Validate participant creation in the API reference](/docs/nhcx/v1/api/onboarding/endpoints/onboarding-validate) + +**3. Configure.** `POST v2/participant/update` + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/v2/participant/update' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --data-raw '{ + "participantcode": "XXXXX7583@hcx", + "encryptioncert": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t...", + "endpointurl": "https://nhcx.demotpa.example.in" + }' +``` + +[Participant certificate and bridge update (v2) in the API reference](/docs/nhcx/v1/api/registry/endpoints/registry-v2-participant-update) + +A second transaction ID and passcode arrive. + +**4. Confirm again.** `GET update/validate?transactionId=&passcode=`. The certificate and address go live. + +```bash +curl --location --request GET 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/update/validate?transactionId=&passcode=' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' +``` + +[Validate participant update in the API reference](/docs/nhcx/v1/api/onboarding/endpoints/onboarding-update-validate) + +Passcodes and transaction IDs are valid for 24 hours. If one is lost, repeat that step; a new pair is issued. + +## Replacing only the certificate + +In production there is a shorter path that skips the passcode: + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/v2/update/cert' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --data-raw '{ + "participantId": "XXXX@hcx", + "certificate": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0t..." + }' +``` + +[Update certificate (v2, no passcode) in the API reference](/docs/nhcx/v1/api/registry/endpoints/registry-v2-update-cert) + +Use it for the yearly rotation. + +## Checking it worked + +Fetch your own certificate back, using the Fetching a Recipient Certificate chapter's call with your own participant code. If what comes back matches what you registered, the record is live and other participants can seal messages for you. diff --git a/site/docs/nhcx/v1/getting-started/fetching-a-recipient-certificate.md b/site/docs/nhcx/v1/getting-started/fetching-a-recipient-certificate.md new file mode 100644 index 000000000..8648cf80d --- /dev/null +++ b/site/docs/nhcx/v1/getting-started/fetching-a-recipient-certificate.md @@ -0,0 +1,57 @@ +--- +title: Fetching a recipient certificate +sidebar_label: Fetching a recipient certificate +sidebar_position: 7 +description: Certificate discovery and caching discipline +verification: unverified +source: nhcx-package/docs/02-Getting Started/07-Fetching a Recipient Certificate.md +generated: true +--- + +# Fetching a recipient certificate + +Before you can seal a message for anyone, you need their public key. The participant service hands it out against a participant code. + +## The call + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/fetch/certs' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --data-raw '{ + "participantid": "1518@hcx" + }' +``` + +[Fetch certificate in the API reference](/docs/nhcx/v1/api/registry/endpoints/registry-fetch-certs) + +That participant code is the sandbox dummy payer. For the smoke test at the end of this section it is the recipient. + +## What comes back + +Key material in PEM text. None of the source documents gives the JSON envelope it arrives in, only the material itself, so inspect one response before writing the parser. Usually a full X.509 certificate: + +``` +-----BEGIN CERTIFICATE----- +MIID0zCCArugAwIBAgIUax... +-----END CERTIFICATE----- +``` + +Sometimes, for a participant who registered a bare key, an SPKI public key: + +``` +-----BEGIN PUBLIC KEY----- +MIIBIjANBgkqhkiG9w0BAQEF... +-----END PUBLIC KEY----- +``` + +Handle both. Try to load it as a certificate and take the public key out of it; if that fails, load it as a public key directly. The handbook's rule of thumb is that anything under about 400 bytes is a bare key. + +## Cache it + +Keys change rarely. Fetching one before every message is a round trip that buys nothing, and the portal's own code sample says to store certificates locally rather than call this endpoint repeatedly. Cache by participant code for 24 hours, and refresh early if a decryption on the other side starts failing, which is the sign that they rotated. + +## Whose certificate + +The participant code to fetch is the `processingid` from the policy lookup in the previous chapter, not the insurer's `payerid`. For the smoke test it is the dummy payer's code, `1000003538@hcx`. diff --git a/site/docs/nhcx/v1/getting-started/finding-participants-and-policies.md b/site/docs/nhcx/v1/getting-started/finding-participants-and-policies.md new file mode 100644 index 000000000..9741b2ef1 --- /dev/null +++ b/site/docs/nhcx/v1/getting-started/finding-participants-and-policies.md @@ -0,0 +1,172 @@ +--- +title: Finding participants and policies +sidebar_label: Finding participants and policies +sidebar_position: 6 +description: Search endpoints and policy resolution +verification: unverified +source: nhcx-package/docs/02-Getting Started/06-Finding Participants and Policies.md +generated: true +--- + +# Finding participants and policies + +Before a message can be sealed, two questions have to be answered: who is it going to, and which policy is it about. The participant service answers both. A provider asks them at every admission. A payer answers the second one in advance, by linking each policy to its holder when the policy is written. + +```mermaid +flowchart LR + A[List participants by role] --> B[Choose the insurer] + B --> C[Look up the patient's policies] + C --> D{processingid} + D --> E[Fetch that participant's certificate] + E --> F[Seal and send] +``` + +## Listing participants + +The registry can be asked for everyone holding a role. This is how a hospital system builds its list of payers, and how a payer finds hospitals. + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/fetch/participants/list' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --data-raw '{ + "role": "PAYER", + "fromdate": "01/04/2021", + "todate": "20/03/2026", + "entitytype": "Gov" + }' +``` + +[Fetch participants list in the API reference](/docs/nhcx/v1/api/registry/endpoints/registry-fetch-participants-list) + +- `role` is `PAYER`, `PROVIDER` or `TPA`. +- `fromdate` and `todate` bound the registration date, in `dd/MM/yyyy` only. +- `entitytype` is optional. `Gov` narrows to government schemes; leave it out for everyone. + +The response is a list of participant records, each with the participant code, name, roles and entity type. The list is not searchable by name on the server side. Fetch it, filter by name in your own code when a user is looking for a specific insurer, and classify government against private from the entity type. Cache it for the day; it changes rarely. + +There is no separate call to fetch one participant's details by code. The list is the lookup. Fetching a participant's certificate, covered in the next chapter, is the one per-participant call. + +## Looking up a patient's policies + +Given something that identifies the patient, the registry returns every policy linked to them. + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/participant/get/policies' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --data-raw '{ + "identifiertype": "AbhaNumber", + "identifiervalue": "12345678910111" + }' +``` + +[Get beneficiary policies in the API reference](/docs/nhcx/v1/api/registry/endpoints/registry-participant-get-policies) + +`identifiertype` is one of three, and they are not equal. Try them in this order and stop at the first that returns a policy: + +1. `AbhaNumber`, the ABHA number without hyphens. The strongest identifier. +2. `MemberId`, the member or policy number captured at admission. +3. `MobileNo`, the patient's registered mobile. The weakest, since a number can be shared or stale. + +Each policy in the answer carries the fields that every later message depends on. The shape, not a verbatim sample: + +```json +{ + "policies": [ + { + "payerid": "1518@hcx", + "processingid": "1000000109@hcx", + "memberid": "MD5SLS4X5", + "productid": "PMJAY/HP/S/G", + "productname": "PMJAY Himachal Pradesh" + } + ] +} +``` + +| Field | What it is for | +| :---- | :---- | +| `payerid` | The insurer's participant code. Goes inside the bundle as the insurer. | +| `processingid` | Who processes claims for this policy. **This is the recipient on the envelope and the certificate to fetch.** | +| `memberid` | Identifies the beneficiary in eligibility and claim bundles. | +| `productid` | The product or plan code, used to fetch the insurance plan and coverage detail. | +| `productname` | Human-readable; some systems use it as the effective policy code when a formal number is missing. | + +**Send to the processor.** When an insurer handles its own claims, `payerid` and `processingid` are the same code. When a TPA processes for it, `processingid` is the TPA and every request goes there. Pointing at `payerid` is the portal's seventh most common mistake; the request goes nowhere useful. If no `processingid` comes back, stop; nothing can be addressed. + +Cache the result against the patient. Their policies do not change between one screen and the next, and re-fetching on every step is wasted traffic. Provide a way to force a refresh when something has genuinely changed. + +## Linking a policy to a beneficiary + +This is the payer's half, and it is why the lookup above works at all. When a policy is written, the insurer links it to the holder's ABHA number, mobile and member ID, and names who will process claims for it. + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/participant/link/abha/policy' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --data-raw '{ + "requestid": "7f3f2a4e-0c6b-4b7a-9e2d-2c1f8a5b6d90", + "abhanumber": "12345678910111", + "mobilenumber": "9876543210", + "memberid": "MEM-2026-000123", + "payerid": "100234@sbx", + "policies": [ + { + "productid": "PRD-FLOATER-01", + "productname": "Family Floater Gold" + } + ], + "processingid": "100235@sbx" + }' +``` + +[Link ABHA number to policies in the API reference](/docs/nhcx/v1/api/registry/endpoints/registry-participant-link-abha-policy) + +- `requestid` is a fresh UUID. +- `payerid` is the insurer's own participant code. Every insurer has one, even when it works through a TPA. +- `processingid` is the TPA's participant code, or the insurer's own if it processes its own claims. +- `policies` lists each product the holder has, by product ID and name. + +Only the two participants named on the link, the `payerid` and the `processingid`, may change it later. The exchange takes the client ID from the caller's token and checks it against them. That also means the token used to link must come from the same credentials that created that participant; a mismatch is refused and has to be sorted out with NHA by email. + +## Removing a link + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/participant/delink/abha/policy' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --data-raw '{ + "requestid": "9a7c5e3d-1b2f-4c8a-b6d4-0e9f8a7b6c55", + "payerid": "100234@sbx", + "memberid": "MEM-2026-000123", + "policies": [ + { + "productid": "PRD-FLOATER-01", + "productname": "Family Floater Gold" + } + ], + "processingid": "100235@sbx" + }' +``` + +[De-link ABHA policies in the API reference](/docs/nhcx/v1/api/registry/endpoints/registry-participant-delink-abha-policy) + +Only products already on the link can be removed; naming one that is not there returns "There is no policies with requested details". + +The commonest reason to de-link is a change of TPA. There is no edit call: every affected policy is de-linked with the old `processingid` and linked again with the new one. Plan that as a batch job, not a manual task. + +## What a provider needs before sending anything + +From the two lookups above, four values, in this order: + +1. The insurer, chosen from the participant list. +2. The patient's policy with that insurer, from the policy lookup. +3. From it, the `processingid`, `memberid` and `productid`. +4. That participant's certificate, fetched in the next chapter against the `processingid`. + +Only then can a message be sealed and addressed. A patient can look correctly admitted as insured on screen while every NHCX call fails, because step 3 was never reached. diff --git a/site/docs/nhcx/v1/getting-started/get-your-sandbox-credentials.md b/site/docs/nhcx/v1/getting-started/get-your-sandbox-credentials.md new file mode 100644 index 000000000..020b153bc --- /dev/null +++ b/site/docs/nhcx/v1/getting-started/get-your-sandbox-credentials.md @@ -0,0 +1,111 @@ +--- +title: Get your sandbox credentials +sidebar_label: Get your sandbox credentials +sidebar_position: 1.1 +description: Register the organisation, get an ABDM client ID and secret, take NHCX sandbox roles, and meet the dummy payer +verification: unverified +source: nhcx-package/docs/02-Getting Started/12-Get Your Sandbox Credentials.md +generated: true +covers: + - nhcx.sandbox.prerequisites + - nhcx.sandbox.test-participants + - nhcx.sandbox.dummy-payer + - nhcx.sandbox.support-contacts +--- + +# Get your sandbox credentials + +Every National Health Claims Exchange (NHCX) call carries a session token, and every token starts with an [ABDM](/docs/nhcx/v1/getting-started/glossary#organisations-and-programmes) client ID and client secret. This chapter gets you those credentials, your NHCX sandbox roles, and a payer to test against. + +## In short + +- Register your organisation first: a hospital in the [Health Facility Registry (HFR)](/docs/nhcx/v1/getting-started/glossary#identity-and-registration), an insurer or [TPA](/docs/nhcx/v1/getting-started/glossary#organisations-and-programmes) with its [IRDAI](/docs/nhcx/v1/getting-started/glossary#organisations-and-programmes) registry id. +- Apply for ABDM sandbox credentials, then register the same client on the NHCX sandbox. +- Your software must support ABDM [Milestone 1](/docs/nhcx/v1/getting-started/glossary#identity-and-registration), [ABHA](/docs/nhcx/v1/getting-started/glossary#identity-and-registration) creation and verification. +- Test against the [dummy payer](/docs/nhcx/v1/getting-started/glossary#messages), participant code `1000003538@hcx`. +- The reviews have no fixed turnaround time, so start them first. + +## Prerequisites + +- Your organisation, and a mobile number for its registry record that you can receive messages on. + +## 1. Register the organisation + +| You are | Register in | Your registry id | +| :---- | :---- | :---- | +| A hospital or clinic | The Health Facility Registry (HFR), at https://facility.abdm.gov.in/ | The HFR ID | +| A payer or TPA | IRDAI, or the relevant authority | The id that authority issues | + +Keep the mobile number on the registry record current. Participant creation checks it and sends a passcode to it. + +## 2. Apply for ABDM sandbox credentials + +1. Apply at https://sandbox.abdm.gov.in/sandbox/v3/. +2. Select "Providers and Payer" and Milestone 1 as your intent. +3. Wait for review. On approval you receive a client ID and a client secret. + +The review is semi-manual. It filters out repeat requests from one organisation, organisations missing from every registry, technology providers without a valid website, and spam. Send one application only. + +Store the secret the way you store any production credential. Never commit it, and never write it to a log. + +## 3. Build Milestone 1 + +Your software must support ABDM Milestone 1 before it joins NHCX. It creates an ABHA number through Aadhaar or a driving licence. It verifies an ABHA number or ABHA address at patient registration. + +## 4. Register on the NHCX sandbox + +Register at https://sandbox.abdm.gov.in/sandbox/v3/sandbox-registration with your ABDM sandbox client ID and secret. When the form is submitted, NHCX sandbox roles are assigned to your client. + +Decide your role before you create your participant. A wrong role and registry pair leads to access errors, rejected requests or misrouted messages. + +| Role | Role code | Registry | Registry code | +| :---- | :---- | :---- | :---- | +| Provider | `10001` | HFR | `10001` | +| Payer | `10002` | Payer | `10004` | +| TPA | `10003` | Payer | `10004` | + +## 5. Meet the dummy payer + +A provider needs a payer to send requests to. The sandbox has one: the dummy payer, participant code `1000003538@hcx`. + +| Use case | What you do | +| :---- | :---- | +| Coverage eligibility | Send the check. It answers on its own. | +| Insurance plan | Send the request with provider id `32722` and policy number `100217` in the bundle. It answers on its own. | +| Preauthorisation or claim | Send the submit, then choose its answer with the [dummy payer action call](/docs/nhcx/v1/api/adjudicator/endpoints/adjudicator-dummy-payer-process-request): `Approve`, `Reject` or `Query`. | +| Payment notice | Start it with the [payment notice trigger](/docs/nhcx/v1/api/adjudicator/endpoints/adjudicator-dummy-payer-paymentnotice-init). | + +The provider id and policy number apply to the dummy payer only. Codes such as `100001@sbx` and `1000002090@hcx` in examples show the format. Before you address any other code, look it up in [the participant list](/docs/nhcx/v1/api/registry/endpoints/registry-fetch-participants-list). + +## What you see when it works + +- A [session token call](/docs/nhcx/v1/getting-started/session-token) with your client ID and secret returns an access token. +- The NHCX sandbox registration form is submitted, and roles are assigned to your client. +- [Fetching the certificate](/docs/nhcx/v1/getting-started/fetching-a-recipient-certificate) of `1000003538@hcx` returns a PEM certificate. + +## When it goes wrong + +| What you see | What to do | +| :---- | :---- | +| The sandbox application is still in review | Wait. A second application is filtered out as a repeat. Ask about a stalled request at the address below. | +| "No user role found/associated for sender code." | Your client has no NHCX role yet. Confirm the sandbox registration form went through, then write to support. | +| Participant creation fails the mobile number check | The number must match the HFR record, or the payer record. Update the registry record first. | +| Requests are rejected or misrouted after registration | Check the role and registry codes you registered with. | +| The dummy payer sends nothing after a preauthorisation or claim | It waits for the action call. Send it with the correlation ID of your submit. | + +## Where to get help + +| Topic | Write to | +| :---- | :---- | +| Fast Healthcare Interoperability Resources (FHIR) bundle validation at sandbox exit, and the internal and [Health Tech Committee (HTC)](/docs/nhcx/v1/getting-started/glossary#identity-and-registration) demos | `hcx.integration@nha.gov.in` | +| Building a FHIR bundle, and the [NRCeS](/docs/nhcx/v1/getting-started/glossary#organisations-and-programmes) specifications | `nrc-help@cdac.in` | +| ABDM Milestone 1 integration | `integration.support@nha.gov.in` | +| Facility registration in the HFR | `facility@nha.gov.in` | + +Put your participant code, the environment, the use case and the path in the message. Add the `x-hcx-correlation_id`, `x-hcx-api_call_id` and `x-hcx-timestamp` of the failing request. Quote the error exactly as returned. Replies have no fixed turnaround time. + +## Next steps + +- [Quickstart](/docs/nhcx/v1/getting-started/quickstart): your first three calls, with nothing but these credentials. +- [Base URLs](/docs/nhcx/v1/getting-started/base-urls): every address in the sandbox and in production. +- [Creating and Updating a Participant](/docs/nhcx/v1/getting-started/creating-and-updating-a-participant): your own participant code. diff --git a/site/docs/nhcx/v1/getting-started/glossary.md b/site/docs/nhcx/v1/getting-started/glossary.md new file mode 100644 index 000000000..517a937db --- /dev/null +++ b/site/docs/nhcx/v1/getting-started/glossary.md @@ -0,0 +1,97 @@ +--- +title: Glossary +sidebar_label: Glossary +sidebar_position: 90 +description: Definitive glossary of protocol, healthcare, and scheme terms +verification: unverified +source: nhcx-package/docs/01-Overview/11-Glossary.md +generated: true +--- + +# Glossary + +The terms this documentation uses, in the sense it uses them. Where NHA's documents use a term differently from ordinary English, the NHA sense is given. + +## Organisations and programmes + +- **ABDM.** Ayushman Bharat Digital Mission. The national digital health programme under which NHCX is built. +- **SNOMED CT, ICD, LOINC.** The clinical, diagnosis and laboratory terminologies FHIR bundles carry, alongside the NRCeS value sets for claim-specific codes. +- **NHA.** National Health Authority. Publishes the NHCX specifications, runs the exchange, and administers PMJAY. +- **NRCeS.** National Resource Centre for EHR Standards, at C-DAC Pune. Publishes the FHIR profiles and value sets NHCX bundles must follow. +- **IRDAI.** Insurance Regulatory and Development Authority of India. Consulted on the specifications; the registry insurers and TPAs are identified by. +- **PMJAY.** Pradhan Mantri Jan Arogya Yojana, the Ayushman Bharat health assurance scheme. On NHCX it is a payer with scheme-specific rules. +- **SHA.** State Health Agency. Administers PMJAY in a state; under the trust model, the payer for that state. +- **TPA.** Third-party administrator. Processes claims on an insurer's behalf; on the network it behaves as a payer and is the processor for the policies it handles. +- **ISNP.** Insurance self-network platform; an insurance marketplace, a participant role with aggregated or consented data access. +- **BSP, EUA.** Beneficiary service provider, end-user application. A patient's personal health record app registered as a participant to receive notifications. + +## PMJAY systems and roles + +- **TMS.** Transaction Management System. NHA's provider and payer applications for PMJAY claims; the system an HMIS integration replaces on the provider side. +- **BIS.** Beneficiary Identification System. PMJAY's beneficiary register. +- **HEM.** Hospital Empanelment Module. PMJAY's hospital register; the HEM ID is mapped to the NHCX participant ID at go-live. +- **PPD.** Preauthorisation Processing Doctor. The payer-side role that adjudicates preauthorisations. +- **CPD.** Claim Processing Doctor. The payer-side role that adjudicates claims. +- **CRC.** Claim Review Committee. Decides appeals; its decision is final. +- **HBP.** Health Benefit Package. PMJAY's package master, from which a hospital's insurance plan is drawn. +- **STG.** Standard Treatment Guideline. A clinical protocol attached to a package, delivered as a questionnaire the provider must answer. + +## Identity and registration + +- **ABHA.** Ayushman Bharat Health Account. The beneficiary's health ID; sent without hyphens. +- **HFR.** Health Facility Registry. A hospital's registry; its HFR ID is the hospital's registry ID on the exchange. +- **NIN, ROHINI.** Other registries a participant may be identified by. +- **Registry ID.** A participant's identity in the registry it belongs to: HFR ID for a hospital, IRDAI ID for an insurer or TPA, client ID for an app. +- **Participant ID, participant code.** A participant's address on the exchange, in the form `1518@hcx`. The part after the `@` names the exchange instance. +- **Client ID and secret.** The ABDM credentials used to obtain an access token; the same ones issued for Milestone 1. +- **Milestone 1, M1.** The ABDM integration level, ABHA creation and verification, that must be complete before NHCX. +- **Bridge URL, endpoint URL.** The base address of a participant's callback server, registered on its participant record. +- **Passcode.** The one-time code sent to a participant's registered mobile to confirm creation or configuration in production. +- **Processor, `processingid`.** The participant that processes claims for a policy: the insurer itself or its TPA. The recipient of every claim-side message. +- **Payer ID, `payerid`.** The insurer's own participant code, named inside the bundle as the insurer. +- **Member ID.** The beneficiary's identifier on the policy. +- **NPI, NIIP.** Identifier types for a provider's HFR ID and a payer's registry ID inside a bundle. +- **WASA.** The security audit completed before ABDM production access. +- **HTC demo.** The demonstration before NRCeS, IRDAI, TCS and NHA that closes sandbox certification. + +## Messages + +- **JWE.** JSON Web Encryption. The sealed-envelope format every message uses. +- **JWT.** JSON Web Token. The format of the access token and of the signature the exchange puts on calls to a participant. +- **Envelope, protected header.** The readable part of a message: the `x-hcx-` fields and the encryption settings. +- **Letter, payload.** The FHIR bundle inside the envelope, encrypted for the receiver. +- **Domain headers.** A few facts written on the envelope for the exchange's records, such as an amount. +- **Correlation ID.** The number that ties a request and its answers into one conversation. +- **API call ID, request ID.** Fresh identifiers for one call and one request. +- **Workflow code, workflow ID.** The number in the envelope that says which step of the claim a message is. +- **Status word.** The `x-hcx-status` value: `request.initiated`, `response.partial`, `response.complete`, `response.error`, and the exchange's own `request.queued`, `request.dispatched`, `request.stopped`. +- **Receipt.** The `202 Accepted` body returned on taking a message in. Not a decision. +- **Protocol response.** A refusal returned on the callback with `response.error` and error details, when a message could not be opened or failed validation. +- **Callback.** The endpoint a participant hosts to receive answers and payer-initiated messages. +- **Dummy payer.** The sandbox payer, participant `1000003538@hcx`, that answers the provider exchanges listed in the NHCX Use Cases chapter. + +## Claims + +- **Preauthorisation, preauth.** Approval to treat, sought before treatment. A `Claim` with `use = preauthorization`. +- **Enhancement.** Additional procedures or days sought against an approved preauthorisation. +- **Resubmission.** A revised preauthorisation that replaces an earlier one. +- **Query.** The payer asking for more before it decides. The case stays open. +- **Claim.** The request for payment after discharge. A `Claim` with `use = claim`. +- **Predetermination.** Asking what a payer would approve, without committing. +- **Adjudication.** The payer's decision on a preauthorisation or claim. +- **Reprocess.** An appeal against a rejection, raised as a Task. +- **Shortfall.** A request for the difference when a claim was paid short, raised as a Task after payment settles, under reason `partialpayment`. +- **Erroneous claim.** In the value set, a separate reason, `erroneousclaim`, for a reprocess caused by a mistaken submission by the provider. The FAQ uses the phrase for the shortfall case; the two senses coexist in the corpus. +- **Task.** The general-purpose request resource: plan fetch, cancel, reprocess, search, payment notice, acknowledgement, communication. +- **Communication.** A payer-initiated message outside the claim's own request-and-answer: a TAT alert, a grievance, a wallet or policy change, a request for information. +- **TAT.** Turnaround time. The window within which a payer is expected to act; under some policies, silence within it means approval. +- **Wallet.** The beneficiary's remaining cover under PMJAY, shared across the family. +- **Package.** A treatment with a fixed rate under a scheme; the unit a PMJAY claim is built from. +- **Stratification.** A higher bed category, such as ICU or HDU, allowed as an add-on over a package rate. +- **Implant.** A device allowed as an add-on over a package rate. +- **Unspecified procedure.** A treatment not in the package list, allowed under conditions with a free-text name and amount. +- **Cyclic procedure.** A treatment approved once and delivered over several visits, such as dialysis. +- **LAMA, DAMA.** Leave against medical advice, without informing the hospital; discharge against medical advice, with a signed undertaking. Two of the four discharge types, with `DTH` (home) and `DTM` (death). +- **LM100.** The single line item for a LAMA or DAMA stay before surgery, in place of the approved packages. +- **UTR.** Unique transaction reference. The bank's reference for a payment, carried on the payment reconciliation. +- **TDS.** Tax deducted at source, itemised on the payment reconciliation. diff --git a/site/docs/nhcx/v1/getting-started/glossary.mdx b/site/docs/nhcx/v1/getting-started/glossary.mdx deleted file mode 100644 index 7d60b867a..000000000 --- a/site/docs/nhcx/v1/getting-started/glossary.mdx +++ /dev/null @@ -1,24 +0,0 @@ ---- -title: Glossary -sidebar_label: Glossary -description: The ABDM terms NHCX shares. No NHCX-specific vocabulary is documented here yet. -verification: unverified -source: NHA's milestone documents and the NHCX document index -sidebar_position: 1 -sidebar_class_name: sidebar-icon sidebar-icon--book-a ---- - -import Shared from '@site/docs/_glossary/_shared.mdx'; - -# Glossary - -Every term the NHCX documentation links to. Each row keeps its own anchor. - -NHCX's own vocabulary, the claim objects and the workflow status codes, is not -documented here: no NHCX endpoint has been read yet, so there is nothing to -define that would not be a guess. [The introduction](/docs/nhcx/v1) records -which documents hold it. - -## Across ABDM - - diff --git a/site/docs/nhcx/v1/getting-started/nhcx-adapter.md b/site/docs/nhcx/v1/getting-started/nhcx-adapter.md new file mode 100644 index 000000000..0ae9d6d4a --- /dev/null +++ b/site/docs/nhcx/v1/getting-started/nhcx-adapter.md @@ -0,0 +1,246 @@ +--- +title: NHCX adapter (Optional) +sidebar_label: NHCX adapter (Optional) +sidebar_position: 10 +description: Turnkey protocol adapter implementation, optional +verification: unverified +source: nhcx-package/docs/02-Getting Started/10-NHCX Adapter.md +generated: true +--- + +# NHCX adapter (Optional) + +Everything in the nine chapters before this one is work you do once and then maintain for ever: + +- Minting a token and refreshing it. +- Fetching the recipient's certificate and caching it. +- Filling in nine envelope headers correctly, and sealing the bundle. +- Hosting a dozen or more callback paths, and answering each one with a receipt in the right shape inside thirty seconds. +- Noticing when the same message arrives twice. + +The NHCX Adapter does all of it for you. It is a single binary that sits between your hospital or payer system and the exchange. Your system speaks plain JSON and plain FHIR to it over your own network; it speaks the protocol to NHCX. Nothing else about your system has to change. + +Read this chapter after the rest of Getting Started rather than instead of it. The adapter hides the protocol, it does not abolish it, and when something goes wrong the error you get back is a protocol error. + +## What it does + +Three jobs, and they map onto the three hard parts of the protocol. + +**Send.** You post a FHIR bundle and the recipient's code. It completes the envelope headers, fetches the recipient's certificate, encrypts, posts to NHCX, and hands you back the exchange's answer on the same call. + +**Deliver.** NHCX posts a sealed message to it. It decrypts with your private key, posts the plain bundle to a URL of yours, and only then answers NHCX with the receipt the protocol requires. + +**Certificates.** It fetches and caches the certificates of everyone you talk to, and can generate and register your own. + +```mermaid +flowchart LR + HMIS[Your system] -->|plain FHIR| A[Adapter] + A -->|sealed| X((NHCX)) + X -->|sealed| A + A -->|plain FHIR| HMIS + A -.->|certificates, token| R[Participant registry] +``` + +## What it does not do + +Worth knowing before you plan around it. + +- **It does not queue or retry.** Both directions are synchronous. If your callback is down, NHCX is told, and NHCX redelivers up to five times before dropping the correlation ID. The only retry inside the adapter is a single token refresh after a `401`. +- **It does not build or validate bundles.** It checks that what you sent is valid JSON and nothing more. Everything in the FHIR Reference section is still yours to get right. +- **It has no business logic.** No adjudication, no policy modelling, no screens for claims work. The participant and policy calls are passed straight through. +- **It does not verify who sent an inbound message** beyond the fact that it decrypts with your key. + +## Onboarding + +### Before you start + +You need what Milestone 1 gave you: a participant code such as `1000003463@hcx`, a client ID and a client secret. If you want to receive callbacks, you also need a public HTTPS address that reaches the machine you will run this on. + +### Build it + +```bash +make build # produces ./nhcx-adapter +make check # what the project's own CI runs: vet plus tests with the race detector +``` + +It is a Go program with no C dependencies, so the binary is self-contained. Released archives exist for Linux, macOS, Windows and FreeBSD if you would rather not build. + +### Make a key and a certificate + +```bash +./nhcx-adapter config init # writes config.json; refuses to overwrite one +./nhcx-adapter cert generate # after setting participantId in the config +``` + +This writes a 2048-bit RSA private key to `private_key.pem` with owner-only permissions and a self-signed certificate to `certificate.pem`. The certificate's common name is your participant code, which is why the code has to be in the config first. It refuses to overwrite an existing pair, so add `--force` when you mean to replace one, which renames the old files rather than deleting them. It dates the certificate five minutes in the past so a registry with a slightly different clock still accepts it. + +### Register the certificate and your address + +Register `certificate.pem` as the participant's encryption certificate, and your public address as its endpoint, exactly as described in Creating and Updating a Participant. The adapter can do both itself from its startup repair menu, but only if the client ID you are using is the one that created the participant record. If it is not, the registry answers that you are not authorised to modify the details, and the fix is out of band. + +Register the address with `/in` on the end, or the host root. The adapter answers its health check under both. + +### Fill in the configuration + +```bash +./nhcx-adapter config edit +``` + +An arrow-key form over the whole file. It edits the JSON document in place, so environment-variable references and file references survive editing, and it validates as you type, including checking that your key file exists and parses. Arrow keys move and cycle values, Enter edits, Backspace resets a field to its default, Ctrl+S saves. + +Two conveniences make it safe to keep the file in version control. A value written as `${NAME}` is read from the environment, and a missing variable is a startup error naming every one that is missing. A value written as `@filename` is read from that file, relative to the config. That works for the private key. Elsewhere the string is used exactly as written, so an `@` in the API key or the console password is part of the password. So the key is normally `"@private_key.pem"` and the secret is normally `"${NHCX_CLIENT_SECRET}"`. + +Unknown keys are rejected outright, so a typo in a field name stops the adapter rather than being silently ignored. + +### Check it + +```bash +./nhcx-adapter check +``` + +Five checks, in order, with a line each: + +1. **Session token.** Your credentials mint a token at the sessions endpoint. +2. **Participant record.** Your code exists in the registry, with the name and endpoint it holds. +3. **Encryption certificate.** The certificate the registry holds for you matches the private key in your config. This is the check that catches the single most common cause of the other side being unable to read anything you send. +4. **Local listener.** The adapter's own port accepts connections. +5. **Registered endpoint.** This one is worth understanding. It starts the listener, then calls your registered public address from the outside and asks it to sign a random number. Only this adapter, running with this configuration, can produce the right answer. So it distinguishes three different failures: nothing is forwarding to the adapter at all, something is forwarding to a different adapter, and the address answers but not with a success. + +Only the token failure is fatal. A certificate mismatch opens a menu offering to generate a new pair and upload it, upload the certificate for the key you already have, or continue anyway. An endpoint failure offers to register the address from your config, or one you type. + +`nhcx-adapter serve` runs the same checks and then listens, so in normal use you never run `check` separately. + +### Prove it works + +```bash +./nhcx-adapter token # a fresh session token +./nhcx-adapter cert 1000004805@hcx # someone else's certificate +./nhcx-adapter send --path v1/coverageeligibility/check \ + --recipient 1000004805@hcx --file bundle.json +``` + +The command line send and the server share one code path, so a send that works means the server will work. + +## The configuration file + +The fields you will actually set. Everything has a working default except the four marked required. + +| Field | Meaning | +| :---- | :---- | +| `env` | `sandbox` or `production`. Chooses the gateway, registry and sessions addresses, and flips several security defaults | +| `listen` | Address and port to listen on. Defaults to loopback only | +| `publicUrl` | How NHCX reaches you from outside. Offered to the registry as your endpoint | +| `apiKey` | The key your own system must present. Required in production; off by default in sandbox | +| `participant.participantId` | **Required.** Your participant code | +| `participant.clientId` | **Required.** From onboarding | +| `participant.clientSecret` | **Required.** From onboarding | +| `participant.privateKey` | **Required.** The key matching your registered certificate, normally `@private_key.pem` | +| `callback.url` | Where decrypted messages are posted in your system | +| `callback.appendPath` | Whether the NHCX path is added to that URL. On by default | +| `callback.timeoutSeconds` | How long one delivery may take. Twenty by default, against the protocol's thirty-second limit | +| `callback.routes` | Per-path overrides, used exactly as written | +| `callback.also` | Extra destinations that all receive the same message | +| `auth.mode` | `sessions` or `get-session`. See the warning below | +| `ledger.storeBodies` | Set false to record headers and outcomes but keep no patient data on disk | +| `panel.password` | Enables the browser console. At least eight characters | + +A second block, `participants`, holds additional identities on the same adapter, each with its own code, credentials, key and callback. Inbound, the recipient code on the envelope picks which one receives. Outbound, the sender code picks which one sends. It is edited by hand; the form preserves it but does not edit it. + +### Two settings to get right before production + +**`auth.mode`.** The two ways of getting a token, described in Session Token, are both implemented, and the project's own README says the NHA documents disagree about which applies. There is no autodetection. Confirm with your onboarding contact, because the wrong choice fails at the first call with a token error. + +**The production addresses.** The sandbox addresses are verified. The production ones follow the documented pattern of swapping the sandbox hostnames, and the code says as much in a comment. Check all four against your onboarding letter and override them in the config if they differ. + +## Sending + +One route, and the NHCX path is the exchange. + +```bash +curl -s http://127.0.0.1:8090/out/v1/preauth/submit \ + -H "Authorization: Bearer $NHCX_ADAPTER_API_KEY" \ + -H 'Content-Type: application/json' \ + -d '{"recipient": "1000004805@hcx", "fhir": { "resourceType": "Bundle", "...": "..." }}' +``` + +Response: + +```json +{ "ok": true, + "path": "v1/preauth/submit", + "headers": { "x-hcx-correlation_id": "...", "x-hcx-api_call_id": "..." }, + "gateway_status": 202, + "response": { "...": "the exchange's receipt" }, + "correlation_id": "...", + "ledger_id": "7UMV0007" } +``` + +Keep the correlation ID. It is how you will recognise the answer when it arrives. + +**Sending a response** rather than a request means posting to the matching `on_` path. The status word defaults correctly and the message type is set for you. The one thing the adapter cannot infer is which request you are answering, so a response should carry the original correlation ID. As a convenience, a response sent without one is threaded onto the most recent inbound request of the same kind from that participant, but do not rely on that when you can pass it. + +If a failure happens the answer says so plainly, with the exchange's own status and body underneath, and a code that tells you whether retrying is worthwhile. + +## Receiving + +NHCX posts to `/in/` plus the path, or to `/v1/` plus the path, so a registry entry pointing at your host root works. These routes are not protected by your API key, because NHCX is the caller. + +The adapter decrypts and posts this to your callback: + +```json +{ "meta": { "type": "in", "payloadType": "fhir", "path": "v1/preauth/on_submit", + "redelivery": false, "participant": "1000003463@hcx" }, + "jwe_headers": { "x-hcx-sender_code": "...", "x-hcx-correlation_id": "...", "x-hcx-status": "..." }, + "fhir": { "resourceType": "Bundle", "...": "..." } } +``` + +Useful facts about that delivery, all of which affect how you write the receiving end. + +- **Your answer is what NHCX is told.** The adapter waits for your 2xx and only then sends the receipt. A non-2xx from you becomes a failure to NHCX, which retries. +- **Your callback must be idempotent.** The retry means the same message can arrive several times. The call identifier stays the same across those attempts, and a repeat is flagged both in the body and in a header, so you can recognise one. +- **A protocol message arrives on the same routes** with no sealed payload, marked as a protocol message rather than a bundle. That is how a refusal or a delivery failure reaches you. +- **A message addressed to a code you do not hold is refused** with an error naming every code this adapter does hold, which is usually enough to spot the misconfiguration. + +A callback address is not optional: the adapter refuses to start without one. What the ledger gives you instead is a way to poll for what has already arrived, including the whole thread for one correlation ID. That is useful when your receiving end is down and you are catching up. + +## Watching what happens + +Every message in both directions is written to a file ledger, one file per message plus a daily index. No database. Identifiers sort chronologically as plain strings, so `7UMV0007` came before `7UMV0008`. + +```bash +nhcx-adapter ledger follow # live, one coloured line per message +nhcx-adapter ledger list --since 24h --entity preauth --status rejected +nhcx-adapter ledger show 7UMV0007 +nhcx-adapter ledger thread # the whole conversation +nhcx-adapter ledger stats +``` + +The live view reads the files directly, so it works from another terminal, another shell, or a machine with the directory mounted, and it needs nothing running locally. Each line carries the identifier, the direction, the path, the counterparty, the outcome, the other side's status code and how long it took. + +A thread view is the thing to reach for when a case has gone quiet. It states plainly whether you are waiting for them or they are waiting for you. + +Setting `ledger.retentionDays` prunes old days hourly. Note that the field defaults to keeping everything if you leave it out of a hand-written config, which is not what the sample file implies. + +There is also a browser console, off unless you set a password, with a live view, the ledger, a send form and a participant lookup. + +## Running it + +One port carries everything. Timeouts are set conservatively: thirty seconds on requests, twenty on a callback delivery against the protocol's thirty-second budget, thirty on calls out to the exchange. + +Put it behind a reverse proxy for TLS, forwarding your public path to the adapter's port, and set `publicUrl` to match. If you expose the console, proxy it on the same path, because its session cookie is scoped to that path, and turn response buffering off so the live view streams. + +It refreshes every session token a minute before expiry in the background, prunes the ledger hourly, and drains for thirty seconds on shutdown. Bodies and tokens are never written to the log. + +## Before you expose it + +Three things to settle, because the defaults are tuned for a sandbox on a laptop. + +**The compatibility routes under `/internal/` have no authentication at all.** Among them are routes that list recent traffic and return a full decrypted bundle for any record. Others proxy to the participant service using your session token. On an adapter bound only to loopback this does not matter. On one bound to all interfaces it is patient data and a credentialed proxy, readable by anyone who can reach the port. Bind to loopback, or keep the port off any network you do not control. + +**In sandbox the API key is not demanded by default.** Anything that can reach the port can send messages as you. Setting `requireApiKey` to true turns the check on regardless of environment, and production turns it on anyway. + +**Readiness reflects the first identity only.** If you host several participants, a broken credential on a second one still reports ready. + +## What this chapter does not replace + +The adapter removes the protocol work. It does not remove the need to understand what you are sending. Which bundle, which workflow code, which supporting information, which status word, and what the payer's answer means are all still yours, and they are the subject of the rest of this documentation. diff --git a/site/docs/nhcx/v1/getting-started/quickstart.md b/site/docs/nhcx/v1/getting-started/quickstart.md new file mode 100644 index 000000000..4d95c6d99 --- /dev/null +++ b/site/docs/nhcx/v1/getting-started/quickstart.md @@ -0,0 +1,107 @@ +--- +title: Quickstart +sidebar_label: Quickstart +sidebar_position: 1.2 +description: "Three calls with only your credentials: a session token, the dummy payer's registry record, and its certificate" +verification: unverified +source: nhcx-package/docs/02-Getting Started/13-Quickstart.md +generated: true +--- + +# Quickstart + +Make your first three National Health Claims Exchange (NHCX) calls with nothing but your sandbox credentials. You get a session token, look up the dummy payer in the participant registry, and fetch the certificate you would seal its messages with. + +## In short + +- Three calls, in order: session token, participant search, fetch certificate. +- None of them changes anything and none has a callback, so you need no server yet. +- The two registry calls carry the token in `bearer_auth`, with `Bearer` and a space in front. +- The counterparty is the sandbox [dummy payer](/docs/nhcx/v1/getting-started/glossary#messages), `1000003538@hcx`. + +## Prerequisites + +- An [ABDM](/docs/nhcx/v1/getting-started/glossary#organisations-and-programmes) sandbox client ID and client secret, with NHCX sandbox roles assigned. [Get your sandbox credentials](/docs/nhcx/v1/getting-started/get-your-sandbox-credentials) if you do not have them. +- A terminal with `curl`, and a way to generate a universally unique identifier (UUID). +- A clock synchronised with NTP, because the session call carries the current time. + +## 1. Get a session token + +```bash +curl --location --request POST 'https://dev.abdm.gov.in/api/hiecm/gateway/v3/sessions' \ + --header 'Content-Type: application/json' \ + --header 'REQUEST-ID: ' \ + --header 'TIMESTAMP: ' \ + --header 'X-CM-ID: sbx' \ + --data-raw '{ + "clientId": "", + "clientSecret": "", + "grantType": "client_credentials" + }' +``` + +[Session token in the API reference](/docs/nhcx/v1/api/session/endpoints/session-session-token) + +- `` and ``: your ABDM sandbox client ID and client secret. +- `` in `REQUEST-ID`: a fresh UUID you generate for this call. Generate a new one on every call. +- `` in `TIMESTAMP`: the current UTC time with milliseconds and a trailing `Z`, such as `2026-09-04T06:15:51.975Z`. + +You receive HTTP `200` with a non-empty `accessToken` and an integer `expiresIn`. The token lasts `expiresIn` seconds from the moment it arrives. Keep it for the next two steps. + +## 2. Look up the dummy payer + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/participant/search' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --data-raw '{ + "participant_code": "1518@hcx" + }' +``` + +[Participant search in the API reference](/docs/nhcx/v1/api/registry/endpoints/registry-participant-search) + +- The sample body carries `1518@hcx`. Replace it with the code of the participant you are looking up. For the sandbox dummy payer, that is `1000003538@hcx`. +- ``: the `accessToken` from step 1. + +You receive HTTP `200` with a `participants` array. Its entry carries the code you sent, its roles and its status. A participant is ready to receive messages when its status is `Active`, and its `endpoint_url` and `encryption_cert` are filled. + +## 3. Fetch its certificate + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice/fetch/certs' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --data-raw '{ + "participantid": "1518@hcx" + }' +``` + +[Fetch certificate in the API reference](/docs/nhcx/v1/api/registry/endpoints/registry-fetch-certs) + +- The sample body carries `1518@hcx` in `participantid`. Replace it with the code you looked up in step 2, `1000003538@hcx` for the dummy payer. +- ``: the same `accessToken` from step 1, in the same header. + +You receive HTTP `200` with PEM text in `encryption_cert`. Some participants register a bare SubjectPublicKeyInfo (SPKI) public key rather than a full X.509 certificate. Import the value as an X.509 certificate first, and fall back to SPKI if that fails. + +## What you have now + +A token that every NHCX call accepts, a counterparty you know is on the network, and the key that seals its messages. Those are items 1, 4 and 5 of [the base framework](/docs/nhcx/v1/getting-started/the-base-framework). + +## When it goes wrong + +| What you see | Cause | What to do | +| :---- | :---- | :---- | +| The session call is refused | `grantType` missing, `REQUEST-ID` reused, or `TIMESTAMP` from a drifting clock | Fix all three and call again | +| `401` on step 2 or 3 | The token expired, or went out without the `Bearer ` prefix | Get a fresh token and retry once | +| `400` or an empty result on step 2 | The body used `participantid` | This call takes `participant_code` | +| `400` or no certificate on step 3 | The body used `participant_code` | This call takes `participantid` | +| No entry for the code | The code is wrong or not registered | Pick it again from [the participant list](/docs/nhcx/v1/api/registry/endpoints/registry-fetch-participants-list) | + +## Next steps + +- [Your Certificate](/docs/nhcx/v1/getting-started/your-certificate): make your own key pair, the counterpart of the one step 3 fetched. +- [Creating and Updating a Participant](/docs/nhcx/v1/getting-started/creating-and-updating-a-participant): register your certificate and callback address. +- [Building and Sending a JWE](/docs/nhcx/v1/getting-started/building-and-sending-a-jwe): seal a message with the certificate from step 3. diff --git a/site/docs/nhcx/v1/getting-started/receiving-a-callback.md b/site/docs/nhcx/v1/getting-started/receiving-a-callback.md new file mode 100644 index 000000000..6dc43abe1 --- /dev/null +++ b/site/docs/nhcx/v1/getting-started/receiving-a-callback.md @@ -0,0 +1,168 @@ +--- +title: Receiving a callback +sidebar_label: Receiving a callback +sidebar_position: 9 +description: Asynchronous callback listener and 202 receipt handling +verification: unverified +source: nhcx-package/docs/02-Getting Started/09-Receiving a Callback.md +generated: true +covers: + - nhcx.sandbox.callback-url-requirements +--- + +# Receiving a callback + +Every answer on the exchange arrives at your server, not in the response to your call. This chapter builds the endpoint that receives it, and closes the loop opened in the previous one. + +## What to host + +Under the `endpoint_url` you registered, the exchange will POST to a path per use case. For a provider that starts with: + +``` +/v1/coverageeligibility/on_check +/v1/insuranceplan/on_request +/v1/preauth/on_submit +/v1/claim/on_submit +/v1/predetermination/on_submit +/v1/search/on_submit +/v1/communication/request +/v1/paymentnotice/request +/v1/task/on_submit +/v1/on_status +/v1/error +``` + +A payer hosts the mirror set, the `submit` and `check` sides. Both host `/v1/error`; it is where the exchange reports a message it could not deliver after five attempts, and without it you never find out. + +Build one handler and route by path. The body shape and the steps are the same for all of them except `/v1/error`, which is described below. + +## Rules for the address + +- A domain name, over HTTPS with TLS 1.2 or newer. Not an IP address, not a port number. +- Hosted in India. +- Reachable from the exchange's outbound addresses: allow `3.109.99.210`, `13.126.152.0` and `13.200.129.223` through the firewall. +- Answering within 30 seconds. Anything slower is treated as a failed delivery and retried. + +## What arrives + +A POST with a JSON body of two fields: + +```json +{ "type": "JWEPayload", "payload": "eyJhbGciOiJSU0EtT0FFUC0yNTYi...." } +``` + +`type` is `JWEPayload` when there is a sealed bundle to open. It is `ProtocolResponse` when the recipient refused the message; then the body carries the `x-hcx-` fields in the clear, `x-hcx-status` set to `response.error`, and the reason in `x-hcx-error_details`: + +```json +{ + "type": "ProtocolResponse", + "x-hcx-sender_code": "1000003538@hcx", + "x-hcx-recipient_code": "1000004446@hcx", + "x-hcx-api_call_id": "…", + "x-hcx-correlation_id": "11223344-5566-4788-99aa-bbccddeeff00", + "x-hcx-workflow_id": "12", + "x-hcx-timestamp": "…", + "x-hcx-status": "response.error", + "x-hcx-error_details": { "code": "…", "message": "…", "trace": "…" }, + "x-hcx-entity-type": "preauth" +} +``` + +`/v1/error` is the exception to the two shapes above. It carries no `payload` and no `x-hcx-` fields. What arrives is a plain JSON report of the request the exchange gave up on, with the rejection details. Its field names are not published, so do not parse it against a fixed schema. Store it whole, and answer it with `202` and the receipt like every other delivery. Fill in whatever identifiers the report happens to carry, and leave the rest of the receipt empty. Do not answer `/v1/error` with a `4xx` because the body is not a shape you recognise. Every delivery the exchange makes to you, on any of the paths listed above, is answered `202`. + +The exchange signs its calls to you with a JWT: RS256 over its own private key, carrying the claims `jti`, `iss`, `sub` (the same value as `iss`), `iat` and `exp`. Validate the signature against the NHCX public key before trusting anything in the body. + +**This is the one instruction in this documentation you cannot follow from it.** The API Security page gives the algorithm and the claims above, but no published source gives the NHCX public key or an address to fetch it from, and none names the header the token arrives in. Every integration built from these documents alone has therefore shipped with signature checking disabled, because the alternative, rejecting everything, makes the endpoint useless. + +Do not leave that as an accident. Build the check, put the key in configuration, and treat a missing key as a deliberate, logged, temporary state rather than a silent default. Ask for the key during onboarding, at the same time you register your endpoint, and turn the check on the day you get it. Until then your callback address is an unauthenticated endpoint that accepts patient data. Keep it behind whatever else you have: an allow-list of the exchange's addresses, mutual TLS at your edge, a shared secret in a header the exchange agrees to send. + +## Answer first, read second + +The 30-second clock starts when the request lands. Do the minimum, send the receipt, and process afterwards. + +The receipt is the same shape you received in the previous chapter, with the roles reversed: + +```json +{ + "timestamp": "04/09/2026 11:46:41:305", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "1000003538@hcx", + "recipient_code": "1000004446@hcx", + "entity_type": "preauth", + "protocol_status": "request.queued" + }, + "error": { "code": "", "message": "" } +} +``` + +HTTP status `202`. Not `200`, not an empty body. For a `JWEPayload` the header fields come from the decrypted protected header; for a `ProtocolResponse` they are already in the clear. + +## Opening it + +The mirror of sealing. Read the body, decide which of the two shapes it is, and for a `JWEPayload` unwrap the compact string with your own private key, the one behind the certificate on your participant record. The protected header comes out of the token in the clear; the bundle is the decrypted plaintext. + +```text +body = json.decode(httpRequest.body) + +if body.type == "ProtocolResponse": + header = fields of body whose name starts with "x-hcx-" + bundle = none +else: + token = jose.decrypt( + compact = body.payload, + privateKey = ourPrivateKey, // PKCS8, the pair of the registered certificate + algorithm = "RSA-OAEP-256", + encryption = "A256GCM" + ) + header = token.protectedHeader + bundle = json.decode(token.plaintext) + +respond 202 with the receipt above +handle(header, bundle) +``` + +:::warning +This is pseudo-code, not something to paste. Use the same JOSE library you sealed with; decrypting is the reverse call on the same object. +::: + +`openssl genpkey` wrote the private key in PKCS8 form, which is what every JOSE library loads directly. If decryption fails, the message was sealed with a certificate that is not the one on your participant record; go back to the update call and check what is registered. + +## Then, in order + +1. **Match the conversation.** `x-hcx-correlation_id` pairs this answer with the request you sent. Look it up. If you do not recognise it, log it and stop; do not act on it. +2. **Read the status.** `response.complete` is a final answer, `response.partial` an interim one, `response.error` a refusal. +3. **Read the workflow code.** It says what kind of answer this is: `21` a preauthorisation approved, `24` a query raised, and so on. The full table is in the Overview. +4. **Store the raw message** before doing anything with it. Disputes are settled on what was actually received. +5. **Act on the bundle**, if there is one. A `ClaimResponse` for a preauthorisation, a `CoverageEligibilityResponse` for an eligibility check, and so on. + +Make the handler idempotent. The exchange retries on a missed receipt, so the same message can arrive twice; the `x-hcx-api_call_id` tells you it is the same one. + +## Closing the loop + +Send the empty bundle from the previous chapter to the dummy payer, then trigger its answer: + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/dummyhcxpayer/process/request' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --data-raw '{ + "action": "Approve", + "method": "Preauth", + "correlationId": "" + }' +``` + +[Dummy payer, act on a request in the API reference](/docs/nhcx/v1/api/adjudicator/endpoints/adjudicator-dummy-payer-process-request) + +`action` is `Approve`, `Reject` or `Query`; `method` is `Preauth` or `Claim`. Your `/v1/preauth/on_submit` then receives the answer, either a sealed `ClaimResponse` or a `ProtocolResponse` carrying the refusal, with the correlation ID you sent. A `Query` action makes the dummy payer raise a communication request instead, which you answer on `/v1/communication/on_request` before the decision arrives. + +Whichever comes back, that message proves the whole framework. Your token works, your participant record is live, the exchange can reach your address, the dummy payer could open your message, and you could read its reply. Nothing that follows changes any of it, only what goes in the bundle. + +## Where next + +- A **provider** goes to the B-series in the Overview's NHCX Use Cases chapter, starting with Check Coverage Eligibility, and to the sample bundles on the portal for a real Claim to put inside. +- A **payer** goes to the C-series, and hosts the `submit` and `check` endpoints this chapter described for the other side. +- Both should read JWE, Status and Errors in the Overview before writing a second use case; it is where the status words and the retry rules live. diff --git a/site/docs/nhcx/v1/getting-started/session-token.md b/site/docs/nhcx/v1/getting-started/session-token.md new file mode 100644 index 000000000..57f8c3c46 --- /dev/null +++ b/site/docs/nhcx/v1/getting-started/session-token.md @@ -0,0 +1,191 @@ +--- +title: Session token +sidebar_label: Session token +sidebar_position: 3 +description: Minting and refreshing ABDM gateway session JWTs +verification: unverified +source: nhcx-package/docs/02-Getting Started/03-Session Token.md +generated: true +--- + +# Session token + +Every call carries a bearer token. The token does not come from NHCX. It comes from the ABDM gateway, with the client ID and secret you were given for Milestone 1. + +## Getting one + +```bash +curl --location --request POST 'https://dev.abdm.gov.in/api/hiecm/gateway/v3/sessions' \ + --header 'Content-Type: application/json' \ + --header 'REQUEST-ID: ' \ + --header 'TIMESTAMP: ' \ + --header 'X-CM-ID: sbx' \ + --data-raw '{ + "clientId": "", + "clientSecret": "", + "grantType": "client_credentials" + }' +``` + +[Session token in the API reference](/docs/nhcx/v1/api/session/endpoints/session-session-token) + +Three headers matter here, and none of them is optional. + +- `REQUEST-ID` is a fresh UUID that you generate for every call. Sending the same one twice is the mistake to avoid; generate it, do not copy it from an example. +- `TIMESTAMP` is the current time in UTC, ISO 8601 with milliseconds and a trailing `Z`, as in `2026-09-04T06:15:51.975Z`. A clock that has drifted will be refused, so take the time from the system rather than constructing it by hand. How to produce it in each language is at the end of this chapter. +- `X-CM-ID` names the environment. It is `sbx` on the sandbox. The mirror and the adapter both use lowercase. + +`grantType` is `client_credentials`. The older form of this call omitted it, which is why an otherwise correct request copied from an old sample can be rejected. + +The response: + +```json +{ + "accessToken": "eyJhbGciOiJSUzI1NiIs...", + "expiresIn": 300, + "refreshTokenIn": 300, + "refreshToken": "eyJhbGciOiJSUzI1NiIs...", + "tokenType": "bearer" +} +``` + +## Using it + +On every NHCX call, the token goes in a header called `bearer_auth`, with the word `Bearer` and a space in front. The sources are not unanimous: the authentication page and the FAQ both write the example as `Authorization`, and the notification endpoint uses `Authorization`. The safe course, and what the adapter does, is to send both headers with the same value. + +``` +bearer_auth: Bearer eyJhbGciOiJSUzI1NiIs... +``` + +Leaving out the `Bearer` prefix is the portal's own example of how to get a `401`. + +## Keeping it fresh + +The token is short-lived. The portal's documents put its life at 300 seconds in the authentication note, 1200 in the handbook and 6000 in the notification guide, so do not rely on any of them. Build it like this: + +- Keep the token and the time you got it. +- Before each call, if it is older than a few minutes, get a new one first. +- If any call answers `401`, get a new token and retry that call once. Do not retry with the same token; it will fail the same way. +- Never write the token or the secret to a log. + +One token serves every call: the participant service, the use-case endpoints, and the status check. + +## What can go wrong + +| Symptom | Cause | +| :---- | :---- | +| `401` on the sessions call itself | Wrong client ID or secret, or Milestone 1 not complete | +| An error on the sessions call naming a header | `REQUEST-ID` reused or absent, `TIMESTAMP` stale or in the wrong format, or `X-CM-ID` missing | +| An error on the sessions call naming the body | `grantType` omitted, which the v3 address requires | +| `401 Sender is not authorized to execute the operation` on an NHCX call | Token expired | +| `401` immediately after getting a fresh token | `Bearer` prefix missing | + +## Generating the timestamp + +Two ISO 8601 shapes appear on NHCX, and they are not interchangeable. + +- The ABDM gateway headers, `TIMESTAMP` on the sessions call, take UTC with milliseconds and a trailing `Z`: `2026-09-04T06:15:51.975Z`. +- The exchange header `x-hcx-timestamp` and `Bundle.timestamp` take Indian Standard Time as an offset, without milliseconds: `2026-09-04T11:46:34+05:30`. The two examples are the same instant. + +Take the time from the system clock, keep the clock synchronised with NTP, and let a date library do the formatting. Each snippet below produces `utc` for the gateway and `ist` for the exchange. + +### JavaScript and TypeScript + +```js +const now = new Date(); +const utc = now.toISOString(); // 2026-09-04T06:15:51.975Z +const ist = new Date(now.getTime() + 330 * 60 * 1000) + .toISOString().slice(0, 19) + "+05:30"; // 2026-09-04T11:46:34+05:30 +``` + +### Python + +```python +from datetime import datetime, timezone, timedelta + +utc = datetime.now(timezone.utc).isoformat(timespec="milliseconds").replace("+00:00", "Z") +ist = datetime.now(timezone(timedelta(hours=5, minutes=30))).isoformat(timespec="seconds") +``` + +### Java and Kotlin + +```java +import java.time.*; +import java.time.format.DateTimeFormatter; + +String utc = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX") + .withZone(ZoneOffset.UTC).format(Instant.now()); +String ist = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssXXX") + .format(OffsetDateTime.now(ZoneOffset.ofHoursMinutes(5, 30))); +``` + +### C# and ASP.NET + +```csharp +var now = DateTimeOffset.UtcNow; +string utc = now.ToString("yyyy-MM-dd'T'HH:mm:ss.fff'Z'"); +string ist = now.ToOffset(TimeSpan.FromMinutes(330)).ToString("yyyy-MM-dd'T'HH:mm:sszzz"); +``` + +### PHP + +```php +$utc = (new DateTime('now', new DateTimeZone('UTC')))->format('Y-m-d\TH:i:s.v\Z'); +$ist = (new DateTime('now', new DateTimeZone('Asia/Kolkata')))->format('Y-m-d\TH:i:sP'); +``` + +### Go + +```go +now := time.Now() +utc := now.UTC().Format("2006-01-02T15:04:05.000Z") +ist := now.In(time.FixedZone("IST", 330*60)).Format("2006-01-02T15:04:05-07:00") +``` + +### C++ + +C++20 `` and ``: + +```cpp +#include +#include +using namespace std::chrono; + +auto now = floor(system_clock::now()); +std::string utc = std::format("{:%FT%T}Z", now); // 2026-09-04T06:15:51.975Z +auto ist = floor(now) + hours(5) + minutes(30); +std::string istStr = std::format("{:%FT%T}+05:30", ist); // 2026-09-04T11:46:34+05:30 +``` + +Before C++20, `gmtime` with `strftime("%FT%T")` gives the seconds; append the milliseconds from `gettimeofday` and the `Z` by hand. + +### Ruby + +```ruby +utc = Time.now.utc.strftime('%Y-%m-%dT%H:%M:%S.%LZ') +ist = Time.now.getlocal('+05:30').strftime('%Y-%m-%dT%H:%M:%S%:z') +``` + +### Swift + +```swift +let f = ISO8601DateFormatter() +f.formatOptions = [.withInternetDateTime, .withFractionalSeconds] +let utc = f.string(from: Date()) +f.formatOptions = [.withInternetDateTime] +f.timeZone = TimeZone(secondsFromGMT: 19800) +let ist = f.string(from: Date()) +``` + +### Shell + +GNU `date`, as on Linux: + +```bash +utc=$(date -u +%Y-%m-%dT%H:%M:%S.%3NZ) +ist=$(TZ=Asia/Kolkata date +%Y-%m-%dT%H:%M:%S%:z) +``` + +macOS `date` has no `%N`; use `gdate` from coreutils, or generate the value in the application rather than the shell. + +Whichever language, the check is the same: the gateway value ends in `Z` and has three digits after the seconds; the exchange value ends in `+05:30` and has none. diff --git a/site/docs/nhcx/v1/getting-started/status-and-search.md b/site/docs/nhcx/v1/getting-started/status-and-search.md new file mode 100644 index 000000000..b8db6a3c4 --- /dev/null +++ b/site/docs/nhcx/v1/getting-started/status-and-search.md @@ -0,0 +1,174 @@ +--- +title: Status and search +sidebar_label: Status and search +sidebar_position: 11 +description: Status checking (`/v1/status`) and search queries (`/v1/search/submit`) +verification: unverified +source: nhcx-package/docs/02-Getting Started/11-Status and Search.md +generated: true +--- + +# Status and search + +Two exchanges that are not about a claim's progress but about finding out what +happened to one. Both sides build them, both are on the sandbox exit +checklists, and neither carries clinical content. Status asks the exchange +where a message went. Search asks a payer for cases matching criteria. + +They belong here rather than in the provider or payer sections because they are +shared: the A-series, built once, used by both. + +## Status + +A sender asks the exchange what became of a message it already sent. It is a +protocol operation, not a FHIR one. + +| | | +| :---- | :---- | +| Call | `POST /v1/status` | +| Callback | `POST /v1/on_status` | +| Payload | **An empty string.** No bundle, no Task, no resource of any kind | + +Everything travels in the protected header. That is the whole design, and it is +why a status check costs nothing to answer. + +### The request header + +| Field | Value | +| :---- | :---- | +| `x-hcx-status` | `request.initiated` | +| `x-hcx-correlation_id` | **The `api_call_id` of the message whose status you are asking about** | +| `x-hcx-api_call_id` | A fresh UUID, as always | +| `x-hcx-sender_code`, `x-hcx-recipient_code` | You, and the exchange | +| `x-hcx-ben-abha-id` | Mandatory | +| `x-hcx-workflow_id` | Optional | +| `x-hcx-use_case` | Optional. `New`, `Enhancement` or `Resubmit` on the status sheet | + +The correlation rule is the exception that proves the rule set out in Envelope +Fields. Everywhere else a correlation ID threads a conversation. Here it points +at another message's call ID, because that is the only way to name the message +you are asking about. Keep your own `api_call_id` values; without them you +cannot ask this question at all. + +### The answer + +Arrives on `/v1/on_status`, again with an empty payload. + +| Field | What it tells you | +| :---- | :---- | +| `x-hcx-status` | `request.dispatched` where the message reached the recipient. The other exchange-side values are `request.queued` and `request.stopped` | +| `x-hcx-error_details` | Present where the original failed, with `code`, `message` and `trace` | +| `x-hcx-correlation_id` | The correlation of your status request | + +`request.stopped` is the one to act on. It means redelivery was exhausted and +the correlation has been retired, so the original request is dead and a retry +needs a fresh correlation ID. + +### When to call it + +Not on a timer. The exchange delivers answers to your callback, and polling for +something that will arrive on its own is wasted traffic on both sides. Call it +when a case has gone quiet for longer than the payer's expected turnaround, and +call it from a support screen rather than from the claims desk. + +The Provider UI Guide makes the point the other way round: do not offer a +refresh or chase control unless you have implemented this exchange behind it, +because a control that does nothing is worse than no control. + +### A note on the path + +The Technical Specifications table names the pair `/hcx/status` and +`/NHCX/on_status`. The sandbox Postman collection uses +`https://apisbx.abdm.gov.in/hcx/v1/status` and `/hcx/v1/on_status`. Build +against the Postman form, which is what the sandbox serves, and keep the path +configurable. + +The status service's live specification is at +`https://hcxsbx.abdm.gov.in/statushcxservice/swagger-ui-custom.html`. +Environments and Addresses lists it with the others. + +## Search + +Two different exchanges share the word. A provider may search, but only its +own cases, and the sources do not settle which endpoint that search goes to. + +| | Own-case search | Cross-payer search | +| :---- | :---- | :---- | +| Endpoints | `/preauth/search`, `/claim/search`, `/paymentnotice/search`, each with its `on_search` | `/v1/search/submit`, `/v1/search/on_submit` | +| Who calls it | The participant whose messages these were | NHA, or a regulator such as IRDAI | +| Scope | Requests that originated from the caller | Any claim, at every payer | +| Also serves | Status lookups on those resources | | + +The access-control policy is explicit that providers may make search and status +requests for requests that originated from them, and that payers may do the +same for their own payment notices. A provider's search over its own cases is +`/claim/search` under that policy. A regulator's search is forwarded by the +exchange to every payer, each answering under the regulator's policies. + +The Technical Specifications route `/search/submit` from NHA through NHCX to +the payer: a cross-payer search for NHA or a regulator. But the provider +sandbox exit checklist, item 10 "Claim Search", names `/v1/search/submit`, and +the payer exit checklist expects that search to arrive from a provider. No +source confirms which of the two endpoints the sandbox accepts from a provider. +Treat it as open: confirm with NHA before the demo, and keep the endpoint +configurable. Access Control and Roles sets out the same rule. + +The search service's live specification is at +`https://hcxsbx.abdm.gov.in/searchhcxservice/swagger-ui-custom.html`. + +### The request bundle + +A `Task` in a collection bundle. + +| Element | Value | +| :---- | :---- | +| `Task.status` | `requested` | +| `Task.basedOn` | The request reference being searched for | +| `Task.code` | See the warning below | +| `Task.input[]` | One or more criteria, each with a type from the input value set and a `valueString` | + +Input types, from +`https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code`: + +| Input | What it narrows by | +| :---- | :---- | +| `ClaimNumber` | The case number | +| `IntimationNumber` | The intimation number | +| `PolicyNumber` | The member's policy | +| `ProductNumber` | The benefit product | +| `PayerId`, `ProviderId` | The two participants | +| `FromDate`, `ToDate` | The window | +| `FinanceYear` | Policy or financial year | +| `ServiceCode` | A benefit or service code | + +### The answer + +A `Task` bundle whose `output` references the matching `ClaimResponse` +resources in the same bundle, resolved exactly as a reprocess or cancel answer +is. Parse those with the `ClaimResponse` parser you already have. + +**A search may be answered across several callbacks.** `response.partial` is +valid on `/v1/search/on_submit`, and only the last carries `response.complete`. +Accumulate against the correlation ID rather than treating the first answer as +the whole result set. + +### The Task code is stated three ways + +The value set defines `search` as the code for searching claim responses. The +Search sheet of the same workbook gives `status` on the request and `poll` on +the callback. Nothing has been observed, so none can be confirmed. + +Agree the code with the payer in writing before you build this, and record what +you agreed. It is the one field that decides whether the message reaches the +right queue. + +## What neither exchange gives you + +Under PMJAY, where a case actually stands is not readable over NHCX. A case +sits at `request.initiated` until somebody acts on it in the scheme's own +system, and a `Task` coded `status` is refused. The role lookup on the payer +service is what answers that question instead; PMJAY Adjudication APIs in +Building a Provider has it. + +So a provider system needs both: the status exchange for "did my message +arrive", and, for PMJAY, the role lookup for "who is holding this case now". diff --git a/site/docs/nhcx/v1/getting-started/the-base-framework.md b/site/docs/nhcx/v1/getting-started/the-base-framework.md new file mode 100644 index 000000000..66e61c9ac --- /dev/null +++ b/site/docs/nhcx/v1/getting-started/the-base-framework.md @@ -0,0 +1,87 @@ +--- +title: The base framework +sidebar_label: The base framework +sidebar_position: 1 +description: Six-step base client architecture +verification: unverified +source: nhcx-package/docs/02-Getting Started/01-The Base Framework.md +generated: true +--- + +# The base framework + +Every participant on NHCX, whether it sends claims or answers them, needs the same seven things working before a single use case can be built. This section builds them in order, and ends with a live round trip: a message out to the sandbox, and the reply back on your own server. + +None of it is specific to a hospital or an insurer. A provider goes on from here to the B-series use cases; a payer to the C-series. The framework underneath is identical. + +## What you will have at the end + +1. A way to get and refresh an access token. +2. Your own encryption key and certificate. +3. A participant record on the sandbox with your certificate and callback address on it. +4. A way to find the participant a message goes to, and the policy it concerns. +5. A way to fetch any other participant's certificate. +6. Code that turns a FHIR bundle into a sealed message and sends it. +7. A callback endpoint that accepts a message, acknowledges it, opens it and reads it. + +Put together, that is the whole loop: + +```mermaid +sequenceDiagram + box You + participant Y as Your system + end + box ABDM and NHCX + participant G as ABDM gateway + participant P as Participant service + participant X as NHCX + end + box Payer side + participant D as Dummy payer + end + Y->>G: 1. client ID and secret + G-->>Y: access token + Note over Y: 2. make a key pair and certificate + Y->>P: 3. create participant, register certificate and callback URL + P-->>Y: participant code + Y->>P: 4. list payers, look up the policy + P-->>Y: processingid, memberid, productid + Y->>P: 5. fetch the dummy payer's certificate + P-->>Y: certificate + Note over Y: 6. seal a bundle as JWE + Y->>X: 7. POST payload + X-->>Y: 202 receipt + X->>D: forwards + D->>X: reply + X->>Y: 8. callback on your URL + Y-->>X: 202 receipt +``` + +## Before you start + +- **An identity in a registry.** A hospital needs its Health Facility Registry (HFR) ID. An insurer or TPA needs its IRDAI registry ID. +- **ABDM sandbox credentials.** A client ID and secret from the ABDM sandbox, with Milestone 1 completed. NHCX uses these same credentials; there is no separate login. +- **A public HTTPS server in India** with a domain name, for the callback. The exchange will not call an IP address or a port number. +- **openssl** on the machine that will hold the private key. +- **A JOSE library** in your language. The portal's own samples use Nimbus for Java. The examples here use `jwcrypto` and `cryptography` for Python, because they are short; any library that does RSA-OAEP-256 with A256GCM will do. + +## Addresses used in this section + +All sandbox. + +| What | Where | +| :---- | :---- | +| Session token | `https://dev.abdm.gov.in/api/hiecm/gateway/v3/sessions` | +| Participant service | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice` | +| Use-case calls | `https://apisbx.abdm.gov.in/hcx/v1` | +| Dummy payer | participant `1000003538@hcx` | + +Every call to the participant service and the use-case endpoints carries the same three headers: + +``` +Accept: application/json +Content-Type: application/json +bearer_auth: Bearer +``` + +Note the header name. It is `bearer_auth`, not `Authorization`, on NHCX's own endpoints. The biometric endpoints used later under PMJAY use `Authorization` instead. diff --git a/site/docs/nhcx/v1/getting-started/your-certificate.md b/site/docs/nhcx/v1/getting-started/your-certificate.md new file mode 100644 index 000000000..58000aaa2 --- /dev/null +++ b/site/docs/nhcx/v1/getting-started/your-certificate.md @@ -0,0 +1,54 @@ +--- +title: Your certificate +sidebar_label: Your certificate +sidebar_position: 4 +description: RSA-2048 key pair generation and self-signed certificate assembly +verification: unverified +source: nhcx-package/docs/02-Getting Started/04-Your Certificate.md +generated: true +--- + +# Your certificate + +Every message on the exchange is sealed for the receiver. For anyone to send you anything, you need a key pair: a private half you keep, and a public half, wrapped in a certificate, that you publish through your participant record. + +## Making the key pair + +Three commands, on a machine you control. + +```bash +# 1. A 2048-bit RSA private key +openssl genpkey -algorithm RSA -out private.key -pkeyopt rsa_keygen_bits:2048 + +# 2. A signing request. It will ask for country, state, organisation and so on. +openssl req -new -key private.key -out request.csr + +# 3. A self-signed X.509 certificate, valid for a year +openssl x509 -req -in request.csr -signkey private.key -out certificate.crt -days 365 +``` + +`private.key` is the secret. It opens every letter addressed to you. It never leaves your server and it is never sent to NHCX. + +`certificate.crt` is public. It is what other participants use to seal messages for you. + +## Encoding it for registration + +The participant service takes the certificate as a single base64 string, not as a file. + +```bash +base64 -w 0 certificate.crt > certificate.b64 # Linux +base64 -i certificate.crt -o certificate.b64 # macOS +``` + +The contents of `certificate.b64` go into the `encryption_cert` field in the next chapter. It will start with `LS0tLS1CRUdJTi`, which is `-----BEGIN` in base64. + +## Keeping it + +- Store `private.key` where your callback service can read it and nothing else can. +- Note the expiry. A year from now the certificate lapses and every sender's encryption for you fails. +- NHA recommends replacing the key once a year. Replacing it is a certificate update on the participant record, covered next; there is no passcode step for a certificate-only change. +- If the private key may have leaked, generate a new pair, update the record, and tell NHA. + +## A note on what you will see from others + +When you fetch another participant's certificate later, you may get back a full X.509 certificate or, for some participants, a bare public key in SPKI form. Your code should try the certificate first and fall back to the key. The portal's Java sample loads the certificate with `CertificateFactory` and takes `getPublicKey()` from it; the Python equivalent is in Building and Sending a JWE. diff --git a/site/docs/nhcx/v1/go-live/_category_.json b/site/docs/nhcx/v1/go-live/_category_.json new file mode 100644 index 000000000..0de9710c1 --- /dev/null +++ b/site/docs/nhcx/v1/go-live/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Go live", + "position": 6 +} diff --git a/site/docs/nhcx/v1/go-live/index.md b/site/docs/nhcx/v1/go-live/index.md new file mode 100644 index 000000000..1eeab9f7d --- /dev/null +++ b/site/docs/nhcx/v1/go-live/index.md @@ -0,0 +1,99 @@ +--- +title: Going live +sidebar_label: Going live +sidebar_position: 1 +description: Sandbox exit, production credentials, registering in production, switching addresses, the network path, the PMJAY cutover and the pilot +verification: unverified +source: nhcx-package/docs/07-Go Live/01-Going Live.md +generated: true +covers: + - nhcx.sandbox.going-live + - nhcx.sandbox.sandbox-exit +--- + +# Going live + +Going live is a certification followed by a switch. The sandbox proves the integration against the exchange and its dummy payer. NHA then certifies it, production credentials are issued, and the participant is registered again in production before the first real case travels. This chapter puts the steps in order and names the chapter that covers each one. + +## In short + +- Finish the sandbox exit list for your side, get your FHIR bundles validated, and give the demos. +- Production credentials come from NHA for a hospital, and through the NHA or IRDAI portal for a payer or TPA. +- Register the participant again in production, through the passcode flow, with your production certificate and callback address. +- Point every base URL at production. Only some production addresses are published; the rest come with your onboarding. +- Pilot on a few real cases before switching the whole organisation. + +## 1. Leave the sandbox + +Run every test case on the exit list for your side: the Provider Checklist for a hospital, the Payer Checklist for an insurer, scheme or TPA. Cancel and reprocess, status and search are on both lists. A payer is also checked on the four validations every response must pass, on every use case. + +Then: + +- Email sample FHIR bundles to `hcx.integration@nha.gov.in` for NRCeS validation. +- Give the internal demo to the NHA team, then the HTC demo before NRCeS, IRDAI, TCS and NHA. +- Under PMJAY, add the PMJAY team demo, complete the WASA security audit, and submit the NHCX sandbox exit form. + +## 2. Get production credentials + +For a hospital, NHA confirms the certification and adds the provider role to the production client ID. + +A payer or TPA enrols through the NHA or IRDAI portal. The portal registers it after scrutiny and asks the ABDM gateway team to issue credentials with the payer or TPA role. + +Under PMJAY, the integrator receives production keys for NHCX on successful completion, and the same keys serve for private insurer claims. + +## 3. Register in production + +The production participant service is `https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice`. Registration there takes four steps, and each confirmation needs a passcode sent to the registered mobile number: + +1. **Create** the participant, with the mobile number exactly as your HFR record holds it, or for a payer as NHA holds it. +2. **Confirm** with the transaction ID and passcode. The participant becomes active. +3. **Update** it with your production certificate and callback address. A second transaction ID and passcode arrive. +4. **Confirm again.** The certificate and address go live. + +Passcodes and transaction IDs are valid for 24 hours; if one is lost, repeat that step. In production the registry ID is the HFR ID for a hospital and the IRDAI ID without leading zeros for a payer, and sending the wrong one is a common production failure. Creating and Updating a Participant has every call. + +Fetch your own certificate back from the production registry, and check that it matches your private key, before anything is sent. + +## 4. Switch the addresses + +Every base URL changes. Base URLs, in Getting Started, lists them for both environments. The exchange's production base is `https://apisprod.nha.gov.in/hcx`, and the participant service's production address is published too. Keep every base in configuration, and check each one against your onboarding letter. + +If you run the NHCX Adapter, set `env` to `production`, confirm `auth.mode` with your onboarding contact, and expect the API key to be required. Its production addresses follow the pattern of swapping the sandbox hostnames, which is an inference, so override any that differ from your letter. + +## 5. Open the network path + +The exchange calls your callback from three addresses. Allow all three inbound: + +``` +3.109.99.210 +13.126.152.0 +13.200.129.223 +``` + +The callback address must be a domain name over HTTPS, with TLS 1.2 or newer, hosted in India. It must not be an IP address, and it must not carry a port number. + +## 6. Under PMJAY, plan the cutover + +After the participant is created and configured in production, the hospital raises a ticket carrying its existing PMJAY hospital ID, the HEM ID used in TMS, and the new NHCX participant ID. NHA's operations team maps the two by hand, and that mapping is the switch. Preauthorisations and claims raised before it finish their life in TMS; everything raised after it goes through the HMIS. For a while both run at once, so brief the desk and plan the day. + +## 7. Pilot, then switch + +NHA recommends a small pilot on a few real cases, and staff training, before switching fully. + +## Before you switch + +- Sandbox exit list complete, bundles validated by NRCeS, and the demos given. +- Production credentials issued with the right role. +- Production participant active, with the certificate and callback address registered and confirmed, and your own certificate fetched back and checked. +- Every base URL pointed at production and held in configuration. +- The three exchange addresses allowed inbound, and the callback on HTTPS with TLS 1.2 or newer, hosted in India. +- For a payer, every policy linked with the correct processor, and the plan master versioned and published for every empanelled hospital. +- Under PMJAY, the mapping ticket raised, and the desk briefed that in-flight TMS cases finish in TMS. +- A pilot planned. + +## Next steps + +- Provider Checklist and Payer Checklist: the sandbox exit lists +- Creating and Updating a Participant: the production registration calls +- Base URLs: every address in both environments +- PMJAY on NHCX: the scheme's integrator journey from Milestone 1 to the mapping ticket diff --git a/site/docs/nhcx/v1/go-live/security-audit.md b/site/docs/nhcx/v1/go-live/security-audit.md new file mode 100644 index 000000000..5a58634cf --- /dev/null +++ b/site/docs/nhcx/v1/go-live/security-audit.md @@ -0,0 +1,65 @@ +--- +title: Security audit +sidebar_label: Security audit +sidebar_position: 2 +description: The security tests for your role, the WASA audit, STQC or CERT-In review, and the certificates production asks for +verification: unverified +source: nhcx-package/docs/07-Go Live/02-Security Audit.md +generated: true +--- + +# Security audit + +Every National Health Claims Exchange (NHCX) participant passes the functional and security tests for its role before it leaves the sandbox. Production onboarding then asks for the certificates those tests produce. This chapter covers the security half and where it sits in the order. + +## In short + +- Security tests are part of sandbox certification for every participant, beside the functional use cases. +- A provider completes the [Web Application Security Assessment (WASA)](/docs/nhcx/v1/getting-started/glossary#identity-and-registration) for [ABDM](/docs/nhcx/v1/getting-started/glossary#organisations-and-programmes) Milestone 1. NHCX production runs on that same production client. +- Sandbox certification can require additional security testing, such as an STQC or CERT-In review. +- Production onboarding reviews your functional and security testing certificates before credentials are issued. + +## Prerequisites + +- Your integration runs every use case on the exit list for your side: the [Provider Checklist](/docs/nhcx/v1/roles/provider/provider-checklist) or the [Payer Checklist](/docs/nhcx/v1/roles/payer/payer-checklist). + +## What applies to you + +| Review | When it applies | What it gives you | +| :---- | :---- | :---- | +| Functional and security tests for your role | Every participant, before sandbox sign-off | The test results you submit for review | +| WASA security audit | ABDM Milestone 1 production access, which NHCX production builds on. Under [PMJAY](/docs/nhcx/v1/getting-started/glossary#organisations-and-programmes) it is also on the sandbox exit list | Clearance for ABDM production access | +| STQC or CERT-In review | When NHCX policy requires it | An additional security clearance | + +## 1. Pass the security tests for your role + +Run the security tests and flows that apply to your role alongside the functional use cases. Submit your test results for review. Include how your application uses and interacts with the exchange APIs. + +## 2. Complete the WASA audit + +Milestone 1 production credentials follow Milestone 1 functional testing, the WASA security audit and the [Health Tech Committee (HTC)](/docs/nhcx/v1/getting-started/glossary#identity-and-registration) demo. For a hospital, the provider role is then assigned to that Milestone 1 production client ID. The same client ID gives you NHCX production access, so the audit comes before NHCX production. + +Under PMJAY, the sandbox exit adds the PMJAY team demo, the WASA audit and the NHCX sandbox exit form. [PMJAY on NHCX](/docs/nhcx/v1/concepts/pmjay-on-nhcx) has the scheme's full order. + +## 3. Plan for STQC or CERT-In review + +Sandbox certification can require additional security testing, such as an STQC or CERT-In review. Plan for it until your onboarding confirms whether it applies. Request your demos and bundle review by email to `hcx.integration@nha.gov.in`. + +## 4. Keep the certificates for production onboarding + +On approval, the sandbox issues a completion certificate, valid for a configured period. When you apply for production, a final approval reviews it. You share the functional and security testing certificates issued in the sandbox, and production credentials follow. + +## What you see when it works + +- You hold the email confirming your successful integration on the NHCX sandbox. +- You hold the security testing certificates that apply to you, ready to share at production onboarding. + +## Confirm at onboarding + +- **Whether STQC or CERT-In review applies to you.** Plan for it until you are told otherwise. +- **The validity period of your sandbox completion certificate.** Apply for production within it. + +## Next steps + +- [Going Live](/docs/nhcx/v1/go-live): the production credentials, registration and switch that follow. +- [Governance and Audit](/docs/nhcx/v1/reference/governance-and-audit): the security obligations that continue in production, and the full onboarding question list. diff --git a/site/docs/nhcx/v1/index.md b/site/docs/nhcx/v1/index.md index 056acc1cb..971be3729 100644 --- a/site/docs/nhcx/v1/index.md +++ b/site/docs/nhcx/v1/index.md @@ -1,113 +1,91 @@ --- -title: NHCX -sidebar_label: NHCX -description: What NHCX is, who is on it, and the index of the NHCX documentation set. -verification: unverified -source: NHCX__NHCX-Website_DocumentDetails.md +title: Introduction +sidebar_label: Introduction sidebar_position: 1 -sidebar_class_name: sidebar-icon sidebar-icon--compass +description: What NHCX is, objectives, participants, machine-readable specifications +verification: unverified +source: nhcx-package/docs/01-Overview/01-Introduction.md +generated: true --- -# NHCX +# Introduction + +## What it is -The Ayushman Bharat Digital Mission ([ABDM](/docs/nhcx/v1/getting-started/glossary#abdm)) is India's national -health data network, run by the National Health Authority ([NHA](/docs/nhcx/v1/getting-started/glossary#nha)). -It is three gateways, not one, and this section documents the third of them. +The National Health Claims Exchange is a single road between hospitals and insurers. A hospital asks whether a patient is covered, asks permission to treat, sends the bill, and gets paid. Today each of those steps runs differently for every insurer. On the exchange they run the same way for all of them. -[NHCX](/docs/nhcx/v1/getting-started/glossary#nhcx) is the National Health Claims Exchange, the third [ABDM](/docs/nhcx/v1/getting-started/glossary#abdm) gateway, carrying insurance claims and their responses between providers and payers. After this page you will know who is on NHCX and which of [NHA](/docs/nhcx/v1/getting-started/glossary#nha)'s own documents to open next. +It carries the whole journey: checking cover before admission, getting treatment approved, submitting the claim at discharge, being paid, and arguing when the answer is wrong. Every step is a message out and an answer back later, so nothing is left hanging and there is a record of both halves. -## What is not here +Hospitals, insurers, patients, regulators and observers all connect to it the same way. -No endpoint on this gateway has been documented here yet. No endpoint reference, no sequence diagrams, no error tables, no test cases. +NHCX is developed under the Ayushman Bharat Digital Mission (ABDM) by the National Health Authority (NHA), in consultation with the Insurance Regulatory and Development Authority of India (IRDAI). The idea is to introduce a platform of exchange to Providers and Payers so that both can transfer digitised health records and other pertinent information directly, in a machine readable format, to their counterpart. -The [HIE-CM](/docs/nhcx/v1/getting-started/glossary#hie-cm) and [UHI](/docs/nhcx/v1/getting-started/glossary#uhi) gateways are documented at [milestones](/docs/hiecm/v3/milestones) and [UHI](/docs/uhi/v1). NHCX sits outside both, on its own sandbox, with its own onboarding, participant registry and document set. +## What NHCX aims to achieve -NHCX does appear in the sandbox database. An NHCX application is recorded against your organisation, and the column list for it is the [`nhcx_exit` table](/docs/hiecm/v3/reference/data-dictionary#nhcx_exit). +NHA states five objectives for the exchange. -## HIE-CM or NHCX +- **Wider cover.** Bring new kinds of claim onto the network, including outpatient (OPD) visits and pharmacy bills, so insurance is not only about hospital stays. +- **Faster money.** Shorten the time between treatment and payment, and make cashless treatment workable even in small hospitals. +- **Room to innovate.** Give insurers the structured data they need to automate decisions and to spot fraud. +- **One way of doing things.** A single, rule-based process that both sides trust, instead of every insurer running its own. +- **A better patient experience.** Fewer forms, fewer delays, fewer surprises at discharge. -Claims are not health records. If your product shares or fetches a patient's clinical record, you are on HIE-CM. If it submits or adjudicates an insurance claim, you are on NHCX. A hospital system can end up on both. The two integrations share no API surface. +Underneath all five sits one requirement. A hospital's software and an insurer's software are built by different people on different technology, and a message has to mean exactly the same thing at both ends. That is why everything on the exchange is written in one agreed format, with agreed words for diagnoses, procedures and test results. How Claims Move on NHCX introduces that format, and Bundles and Conventions in the FHIR Reference sets out its rules. -The documentation set shows the shape of a claim without describing it. A claim is a [FHIR](/docs/nhcx/v1/getting-started/glossary#fhir) bundle. It travels with a protected header that carries a workflow status code. A request cycle is closed by sending a protocol response back. Those are rows 11, 12 and 15 below. +## NHCX operating framework -## Who is on it +A stock exchange works because a buyer and a seller each connect to the exchange rather than to each other. NHCX works the same way. A hospital connects once, an insurer connects once, and from then on either can reach the other without having built anything specific to them. -| Participant | What it does | -| --- | --- | -| Provider | A hospital or clinic. Row 9 below covers the use cases a provider has to implement. | -| Payer | An insurer, or a third party administrator acting for one. Row 10 below is the matching list for a payer. | -| NHCX | The exchange in the middle. Routes between registered participants. | +## What NHCX is made of -Both providers and payers onboard as participants, in sandbox first and then in production. The production onboarding document carries the role and registry enums and the validations applied to them. +It helps to think of NHCX as three rulebooks and one referee. -## What is published +- **The protocol** says how a message travels: how it is addressed, sealed, acknowledged and answered. It is deliberately like email: a message goes to the exchange, the exchange passes it on, and the reply comes back the same way. +- **The data specifications** say what goes inside a message. Claims, policies, payments and the rest are written as FHIR records, using profiles published by NRCeS, so that both sides read the same thing. +- **The operational guidelines** say who may join, how they are checked, what they may do, and how they can be removed. +- **NHA is the referee.** It publishes the rules, runs the exchange, and works with NRCeS and IRDAI to change them. -The NHCX documentation set has 32 numbered rows, each giving a purpose, a document name and a location. It is an index, not a specification. No row carries a request shape, a response shape or an endpoint. Two rows have no document name in the source, and one row is blank apart from its location. Those gaps are marked below. +The portal also publishes a live Swagger specification for each of the exchange's services, and Environments and Addresses in the Reference section lists them. -There is one location per group of documents, not a URL per file. +Five principles run through all of it. The rules are **open**, published under a permissive licence so anyone can build against them. They are **evolvable**, so a scheme can add what it needs without breaking everyone else. They are **minimal**, so they are easy to understand and do not hold back innovation. They protect **privacy and security**, with sealed contents and tamper-proof records. And they are **unbundled**, so a participant can adopt one part without adopting all of it. -| Location | What is there | -| --- | --- | -| [hcxsbx.abdm.gov.in/#/documents](https://hcxsbx.abdm.gov.in/#/documents) | Onboarding, use cases, payload references, error handling, Postman collections and FAQs. Rows 1 to 22. | -| [hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications](https://hcxsbx.abdm.gov.in/#/technical-specifications/api-specifications) | Swagger for the use case APIs and the participant service. Row 23. | -| [hcxsbx.abdm.gov.in/#/hmisdocuments](https://hcxsbx.abdm.gov.in/#/hmisdocuments) | The Supporting Documents section of that page holds the PMJAY and [HMIS](/docs/hiecm/v3/getting-started/glossary#hmis) material. Rows 24 to 32. | +## Who is on the network -## The document index +Most of this documentation talks about two parties, the hospital and the insurer. The network recognises more. -Row numbers match the published index, so you can match a line here to a line there. +- **Providers.** Hospitals and clinics, identified by their Health Facility Registry entry. +- **Payers.** Insurance companies, and the government agencies that pay for schemes. +- **TPAs.** Third-party administrators who process claims on an insurer's behalf. On the network a TPA behaves like a payer. +- **Regulators.** IRDAI and bodies like it, who can search claims across every payer. +- **Scheme sponsors.** The owner of a programme, for example NHA for Ayushman Bharat, with payer-level access. +- **Researchers and insurance marketplaces.** Given aggregated or consented data only. +- **Patient apps.** Personal health record apps that receive notifications on a beneficiary's behalf. +- **Other exchanges.** NHCX is designed so that more than one instance can exist and relay to each other. -### Onboarding, use cases and specifications +```mermaid +flowchart LR + H1[Hospital] --- X((NHCX)) + H2[Clinic] --- X + A[Patient app] --- X + X --- P1[Insurer] + X --- P2[Government scheme] + X --- T[TPA] + X --- R[Regulator] + X --- N[Another exchange] +``` -| # | Document | What it covers | -| --- | --- | --- | -| 1 | NHCX Usecases | High level introduction to the NHCX use cases. | -| 2 | Standards for NHCX | Standards followed in NHCX, and an introduction to FHIR. | -| 3 | Name not given in the source | How to generate a token using the ABDM API for the NHCX APIs. | -| 4 | Onboarding providers and payers in Sandbox | How to onboard participants in sandbox. | -| 5 | Onboarding providers and payers in Production | How to onboard participants in production. Includes the role and registry enums, and the validations imposed. | -| 6 | AWS(Sandbox)NHCX-OnBoarding APIs Postman Collection | Postman collection for participant onboarding in sandbox. A zip file. | -| 7 | AWS(PROD)_NHCX-OnBoarding APIs Postman Collection | Postman collection for participant onboarding in production. A zip file. | -| 8 | Policy Linking and De-Linking Process | Policy linking and de-linking validations, and API implementation detail, for payer and TPA. | -| 9 | NHCX Provider Side Use Cases, Sandbox Exit Process | Which use cases a provider must cover: which API, at whose end, which bundle, which status, and the callback logic. | -| 10 | NHCX Payer Side Use Cases, Sandbox Exit Process | The same list for a payer. | -| 11 | NHCX Requests and Responses for UseCases | Which value sets to use when building FHIR bundles, which bundle to use, and which values are mandatory. One tab per use case. A spreadsheet. | -| 12 | Workflow Status Sheets (with Codes) | The workflow codes to send in the protected header. A spreadsheet, updated when codes change. | -| 13 | NHCX Code Snippets references for payload preparation | Reference code snippets for preparing use case payloads. | -| 14 | Implementation Guide for Adoption of FHIR in ABDM and NHCX | The FHIR implementation guide for both. | -| 15 | API Response Handling to avoid Failures | How to handle error scenarios, and how to send the protocol response that closes the request cycle. | -| 16 | AWS(Sandbox)-PARTICIPANT SERVICE_APIs Postman Collection | Postman collection for the participant service APIs in sandbox. A zip file. | -| 17 | AWS(Sandbox)-NHCX USECASE Postman Collection | Postman collection for the use case APIs in sandbox. A zip file. | -| 18 | Standard Error Codes | Every error code and scenario, by use case, for the bridge and for NHCX. A spreadsheet. | -| 19 | NHCX Dummy Payer Implementation | Implementation guide for the dummy payer. | -| 20 | Steps to generate encryption Certificate | How to generate the encryption certificate, a public and private key pair. | -| 21 | FAQs | Frequently asked questions. | -| 22 | Common Mistakes while implementing through NHCX | Mistakes seen at the integrator end, and how they are resolved. | -| 23 | Technical Specification, API Specifications | Swagger for the use cases and for the participant service. The source adds a warning: for use case payloads, work from rows 11 and 13 rather than the swagger. The swagger is the relevant source for the participant service APIs. | +Each role comes with a fixed list of what it may send and receive. A hospital can ask about eligibility and submit claims; it cannot search another hospital's claims. A regulator can search; it cannot submit. -### PMJAY and HMIS supporting documents +## What changes in practice -PMJAY is the Ayushman Bharat Pradhan Mantri Jan Arogya Yojana scheme. These rows sit under Supporting Documents on the HMIS documents page. +Four things are different once a hospital is on the exchange, and the rest of this documentation is about making them work. -| # | Document | What it covers | -| --- | --- | --- | -| 24 | NHCX PMJAY Integration Handbook | The integration handbook for an HMIS. | -| 25 | Insurance Plan IG | Implementation guide for the insurance plan bundle. | -| 26 | NHCX_APIs to be called based on scenario | A roadmap for an HMIS: which NHCX APIs to call in which scenario. | -| 27 | NHCX-PMJAY-HMIS Integration Overview | Overview of the integration. | -| 28 | NHCX-PMJAY-HMIS Integration Guide | The integration guide. | -| 29 | Name not given in the source | Sample FHIR. | -| 30 | Biometric Authentication APIs Postman Collection | Postman collection for the biometric authentication APIs. | -| 31 | NHCX-PMJAY-HMIS Test Cases | Test cases for the integration. | -| 32 | Row blank in the source | The source row carries a location and nothing else. | +**Records go across as records.** A hospital's software already holds the diagnosis, the test results and the treatment as data. Today most of it is printed or turned into a picture before it is sent, and the insurer's software cannot read a picture. On the exchange it goes across as data and stays readable. -## What is missing here +**That makes automatic decisions possible.** An insurer can only decide a claim by machine if it can read the values. A blood test sent as ten separate results can be checked automatically; the same test sent as a scan cannot. -Everything past the index. This page carries the title and purpose of each document, not the endpoints, payloads, status codes or error codes inside them. No NHCX call is served against a sandbox. +**One place to type things.** The hospital's own system becomes the single place the information is entered, rather than being re-keyed into an insurer's portal afterwards. Most rejections on technical grounds come from that second typing. -## Next +**Any hospital can reach any insurer.** A small hospital that could never afford to integrate with thirty insurers separately can integrate once. -- New to NHCX? Start at row 4 above, the sandbox onboarding document. -- [Choose your gateway](/docs/hiecm/v3) -- [HIE-CM](/docs/hiecm/v3/) -- [UHI services](/docs/uhi/v1) -- [Support](/docs/support), for anything about these pages rather than about NHCX itself +How Claims Move on NHCX follows a claim from admission to payment, in the ordinary language of the people who do it, before any of this becomes technical. diff --git a/site/docs/nhcx/v1/reference/README.md b/site/docs/nhcx/v1/reference/README.md index 68dec0ae7..99f26ec11 100644 --- a/site/docs/nhcx/v1/reference/README.md +++ b/site/docs/nhcx/v1/reference/README.md @@ -1,7 +1,4 @@ # Reference -Material that is true across every module of NHCX. `authentication.md`, -`callbacks.md` and `error-codes.md` are generated from the OpenAPI specs on -every build; hand-written pages (like a data dictionary) live alongside them -with a `sidebar_position`. - +The package's reference chapters, and the FHIR bundles under `fhir/`. `authentication.md`, +`callbacks.md` and `error-codes.md` are the site's, generated from the specifications. diff --git a/site/docs/nhcx/v1/reference/access-control-and-roles.md b/site/docs/nhcx/v1/reference/access-control-and-roles.md new file mode 100644 index 000000000..d43c329f5 --- /dev/null +++ b/site/docs/nhcx/v1/reference/access-control-and-roles.md @@ -0,0 +1,154 @@ +--- +title: Access control and roles +sidebar_label: Access control and roles +sidebar_position: 14 +description: Role permissions, search rights, consent headers, and registry attributes (`payment_details`) +verification: unverified +source: nhcx-package/docs/06-Reference/04-Access Control and Roles.md +generated: true +--- + +# Access control and roles + +Most of this documentation talks about two parties. The network recognises +nine, and each one has a fixed list of what it may send and what it may +receive. That list is an access-control policy, enforced by the exchange +against the roles on your participant record, and it decides what your +integration is allowed to do before any of your own code runs. + +## The roles + +The exchange extends the HL7 organisation-role value set and namespaces it for +claims. + +| Role on the network | Code | Who it is | +| :---- | :---- | :---- | +| `provider` | 10001 | Health service provider. A hospital or clinic | +| `payer` | 10002 | Insurance service provider | +| `agency.tpa` | 10003 | Third-party administrator acting for a payer. In this version it behaves as a payer for data exchange | +| `agency.regulator` | 10004 | IRDAI, IIB and bodies like them | +| `research` | 10005 | Research groups | +| `member.isnp` | 10006 | Insurance self-network platforms. Marketplaces facilitating insurance adoption | +| `agency.sponsor` | 10007 | Scheme owners, for example NHA for Ayushman Bharat | +| `HIE/HIO.NHCX` | 10008 | Another exchange instance | +| End-user application | 10009 | A beneficiary's personal health record app | + +The FAQ notes that only four role codes are live in practice on the sandbox and +in production: provider, payer, TPA and the end-user application. The rest are +specified rather than deployed. + +## What each role may do + +| Role | Eligibility | Preauthorisation | Claim | Payment | Search and status | +| :---- | :---- | :---- | :---- | :---- | :---- | +| `provider` | Send request, receive response | Send request, receive response | Send request, receive response | Receive notice, send acknowledgement | Its own preauthorisations and claims | +| `payer`, `agency.tpa` | Receive request, send response | Receive request, send response | Receive request, send response | Send notice, receive acknowledgement | Its own payment notices | +| `agency.regulator` | | | Search claims | | Across every payer | +| `research` | Receive request, send response | | | | Aggregate or anonymised only | +| `member.isnp` | Receive request, send response | | | | Aggregate or anonymised, plus individual claims on beneficiary consent | +| `agency.sponsor` | Equivalent to payer throughout | | | | | +| `HIE/HIO.NHCX` | Relays as the use case needs, and can never read the payload | | | | | + +Five things in that table change how a system is built. + +**A provider can search, and only its own.** The policy is explicit: providers +may make search and status requests "for multiple requests that originated from +them". That is why the provider sandbox exit checklist includes claim search. +Which endpoint that search goes to is not settled by the sources, and the next +section sets out why. + +**A regulator's search fans out.** The exchange forwards a regulator's search to +every payer, each of which returns claims data under the regulator's policies. +Nobody else on the network can cause one request to reach every payer. + +**Research and marketplace access is aggregate by default.** Anything a +`research` participant receives is aggregated or anonymised. The key +aggregations are named as still to be defined, so treat this role as specified +rather than usable. + +**A marketplace needs consent, carried on the envelope.** `member.isnp` may see +an individual beneficiary's preauthorisations and claims only with that +beneficiary's consent, obtained through existing consent-management +infrastructure, and "ISNPs are expected to submit the acquired consent as part +of the domain header". That is the one place in the corpus where a domain +header is load-bearing rather than informational. Envelope Fields has the +naming convention. + +**Another exchange never sees the payload.** A relaying instance routes on the +envelope alone, which is the whole point of sealing the letter separately. + +## Two kinds of search + +The sources describe two search exchanges with different endpoints and +different callers. + +| | Own-case search | Cross-payer search | +| :---- | :---- | :---- | +| Endpoints | `/preauth/search`, `/claim/search`, `/paymentnotice/search`, each with `on_search` | `/v1/search/submit` and `/v1/search/on_submit` | +| Who calls it | The participant that originated the messages | NHA, or a regulator such as IRDAI | +| Flow | provider to NHCX to payer, and back | NHA to NHCX to payer, and back | +| Scope | Requests that originated from the caller | Any claim, across every payer | +| Also serves | Status lookups on those resources | | + +A provider's search over its own cases, the search the access-control policy +allows, is `/claim/search`, the endpoint the Open Protocol page gives for it. The Technical Specifications route +`/search/submit` from NHA through NHCX to the payer, and the requests-and-responses +workbook gives NHA or IRDAI searching by case number as its example. That is +the cross-payer search. + +The provider sandbox exit checklist points the other way. Its item 10, "Claim +Search", names `/v1/search/submit`, for "the providers/regulatory bodies", and +the payer exit checklist expects that search to arrive from a provider. No +source confirms which of the two endpoints the sandbox accepts from a provider. +Treat it as open: confirm with NHA before the demo, and keep the endpoint +configurable. + +The Open Protocol page lists `/claim/search` as reachable by +`provider | regulator | auditor`, which introduces an auditor role that appears +in no other source and in no role table. Treat it as an unmodelled participant +type rather than something to build for. + +## Roles are set on the participant record + +The role is not a claim you make per message. It is the `roles` field on your +participant record, set at creation, and the exchange checks every call against +it. Three practical consequences. + +- **A participant may hold more than one role.** The field is an array. +- **The registry must match the role.** A provider is vouched for by the Health + Facility Registry, a payer or TPA by the payer registry. The FAQ warns that + incorrect role and registry mapping causes "API access issues, request + rejection, or improper routing", and it is one of the harder faults to + diagnose because the failure looks like a routing problem. +- **One entity, many participant IDs.** A hospital group holds one participant + ID per Health Facility Registry ID, all created under the same credentials. + +## What the registry holds about you + +The participant registry is the source of truth for who may do what. Its +attributes, with their obligations: + +| Attribute | Type | Obligation | Notes | +| :---- | :---- | :---- | :---- | +| `participant_code` | String | Mandatory | Generated by the exchange. Unique across installations, namespaced as `code@instance` | +| `registry_code` | String | Optional | The HFR or payer registry code, used to validate and link the participant against the role | +| `participant_name` | String | Mandatory | Unique within the instance | +| `roles` | String | Mandatory | Used for access control | +| `address` | JSON | Optional | Physical address including geolocation | +| `email` | String | Optional | Up to 3 | +| `phone` | String | Optional | Landline, up to 3 | +| `mobile` | String | Mandatory | At least 1, up to 3 | +| `status` | String | Mandatory | `Created` (not yet verified), `Active`, `Inactive`, `Blocked` | +| `signing_cert_path` | String | Optional | URI or path to the JWT signing certificate | +| `encryption_cert` | String | Mandatory | URI or path to the encryption certificate | +| `endpoint_url` | String | Mandatory | The default callback address | +| `payment_details` | JSON | Optional | A UPI ID, or an account number with an IFSC code | + +`payment_details` is the only place on the network where a participant's bank +details sit, and it is what `PAYR-1020`, "unable to process payment as no valid +bank details found for the provider", refers to. It is optional at +registration and not optional if you expect to be paid. + +Only `Active` may send or receive. The registry offers create, update, delete +and search, with modification controlled by the exchange operator as part of +onboarding rather than exposed to participants. diff --git a/site/docs/nhcx/v1/reference/envelope-fields.md b/site/docs/nhcx/v1/reference/envelope-fields.md new file mode 100644 index 000000000..127d5147c --- /dev/null +++ b/site/docs/nhcx/v1/reference/envelope-fields.md @@ -0,0 +1,234 @@ +--- +title: Envelope fields +sidebar_label: Envelope fields +sidebar_position: 13 +description: Full JWE header table, obligations, and correlation rules +verification: unverified +source: nhcx-package/docs/06-Reference/03-Envelope Fields.md +generated: true +--- + +# Envelope fields + +Every field on the JWE protected header, with its obligation, its type and the +rule that governs it. JWE, Status and Errors in the Overview explains what the +envelope is and why it is separate from the letter. This chapter is the table +you check a field against while you are building one. + +The authority here is the Technical Specifications page on the portal, which +carries the current header table, together with the ten sheets of the NHCX +Requests and Responses workbook, which state the obligation of each field per +exchange. Where the older Open Protocol page differs it is noted, because it is +still published and still read. + +## The fields + +| Field | Type | Obligation | What it carries | +| :---- | :---- | :---- | :---- | +| `alg` | String | Mandatory | Key wrapping. `RSA-OAEP-256` | +| `enc` | String | Mandatory | Content encryption. `A256GCM` | +| `x-hcx-sender_code` | String | Mandatory | Your participant code | +| `x-hcx-recipient_code` | String | Mandatory | The recipient's. For a provider, the processor code from the policy lookup | +| `x-hcx-api_call_id` | UUID | Mandatory | Fresh on every message, including responses | +| `x-hcx-request_id` | UUID | **Optional** | One per originating request. The Open Protocol page marks it Mandatory; the Technical Specifications page marks it Optional | +| `x-hcx-correlation_id` | UUID | Mandatory | The thread. See the rule below | +| `x-hcx-workflow_id` | String | **Optional** | Which step, or which case. See the two readings below | +| `x-hcx-timestamp` | datetime | Mandatory | See the format note below | +| `x-hcx-status` | String | Mandatory | Where this message stands. Values below | +| `x-hcx-ben-abha-id` | String | **Mandatory** | The beneficiary's ABHA number. Mandatory on every exchange, including those with no beneficiary in the payload | +| `x-hcx-use_case` | String | Optional | Values differ by exchange, see below | +| `x-hcx-error_details` | JSON object | Optional | `code`, `message`, `trace`. Mandatory on a protocol response | +| `x-hcx-debug_details` | JSON object | Optional | The same shape, for debugging | +| `x-hcx-debug_flag` | Enum | Optional | `Error`, `Info` or `Debug`. A server may ignore it | + +**The `x-hcx-use_case` values are not one enum.** The workbook states them on +three sheets and they are not the same on all three. + +| Sheet | Permitted values | +| :---- | :---- | +| Preauth | `New`, `Enhancement`, `Resubmit` | +| Status | `New`, `Enhancement`, `Resubmit` | +| Claim | `New`, `Resubmit` | + +A claim cannot be enhanced, which is why `Enhancement` is absent from that row. +Both workbooks agree, sheet for sheet. + +**`x-hcx-debug_flag` is typed two ways.** The Technical Specifications page +gives the enum as `Error`, `Info` or `Debug`. The NHCX Requests and Responses +workbook types it as Enum with the single value `INFO`, on its response +headers, and every header table in the FHIR Reference and every sample in the +API collection that carries the field sends `INFO`. The field is optional and a +server may ignore it. Where you send it, send `INFO`, as the samples do. No +source says whether a server checks the case of the value. + +Three of those obligations are not stated anywhere else in this documentation +and are worth reading twice. `x-hcx-request_id` is optional. `x-hcx-workflow_id` +is optional. `x-hcx-ben-abha-id` is mandatory. + +## The correlation ID rule, in full + +The rule is stated in two halves in two places, which has been read as a +contradiction. It is not one. The workbook has twenty-five correlation rows: +twenty-four state one half or the other, and they fit together, and the +twenty-fifth gives the status enquiry its own rule. + +| On a | Set `correlation_id` to | Rows stating it | +| :---- | :---- | :---- | +| Request | This message's own `api_call_id` | 8 | +| Response | The `correlation_id` of the request being answered | 16 | +| Status enquiry | The `api_call_id` of the message whose status you are asking about | 1 | + +So the initiator seeds the thread from its own call ID, and every responder +echoes what it received. The Open Protocol page says the same thing in prose: +the correlation ID "may be chosen as the message_id of the original sender's +system. For return messages responders are expected to populate with the one in +the request." + +The sandbox exit checklists describe the initiator's half; the protocol pages +describe the responder's. Build both and threading works. + +Two further rules, and both bite on retries. + +- `api_call_id` and `correlation_id` must be **different values** on a + response. The exit checklists check this on every answering use case. +- A correlation ID that has failed is **retired**. The next attempt needs a + fresh one. Reusing it earns `NHCX-1006`, duplicate request, or goes nowhere. + +## The workflow code means two different things + +This is the field most likely to be misunderstood, because the sources define +it twice and the definitions are not the same. + +**As a step code.** The Workflow Status Sheet assigns a number to each step of +a claim: 12 a new preauthorisation, 21 approved, 24 queried, and so on. This is +the reading the Workflow Codes chapter documents and the one the reference +payer validates. + +**As a case thread.** The Open Protocol page defines it as the "unique id of +workflow that may span over a series of message exchanges, e.g. an eligibility +check, a preauth and then claims submission for a patient may be linked with +such an id". The Technical Specifications page keeps both readings in one +sentence: "Workflow id depicts the current process/state of the case. It may +span over a series of message exchanges for a given transaction." + +The field is **Optional** on all twenty-five rows of the workbook, across all +ten sheets, including CoverageEligibility and Insurance Plan. So the exchanges +for which the Workflow Status Sheet assigns no code are exchanges on which the +header may simply be omitted. There is nothing to negotiate. + +In practice: send the step code where the sheet gives one, because that is what +the payer keys on. Send nothing where it does not. Agree the case-thread +reading with a payer only if one asks for it. + +## Status words + +The Technical Specifications page defines all seven. + +| Value | Sent by | Meaning | +| :---- | :---- | :---- | +| `request.initiated` | The initiator | Starting the request cycle | +| `request.queued` | The exchange | Queued at NHCX, waiting to be processed | +| `request.dispatched` | The exchange | Successfully reached the recipient's system | +| `request.stopped` | The exchange | Stopped completely after failed attempts to reach the recipient | +| `response.partial` | The responder | A partial response, or an acknowledgement of the request | +| `response.complete` | The responder | The final response, closing the cycle | +| `response.error` | The responder | The request was rejected, or an error was met | + +`request.stopped` is the one nothing else explains. It is what the exchange +records when redelivery has been exhausted, and it is the state behind a +retired correlation ID. + +**The Open Protocol page carries a different set entirely**: `request.initiate`, +`request.retry`, `response.success`, `response.fail`, +`response.sender_not_supported`, `response.unhandled`, +`response.request_retry`. None of those seven appears in the workflow sheet, in +any sample, or in the gateway's own validation messages. It is a superseded +draft. Do not build against it, and be ready to meet it in older material. + +## Timestamp + +Contested in format and in zone, and the chapter on JWE, Status and Errors sets +out the disagreement. Two facts settle part of it. + +- **The workbook types the field as a Unix timestamp** and gives `1706308383` + as its example on every sheet. The handbook and the FAQ use ISO 8601. Every + sample bundle uses ISO 8601 with `+05:30`. +- **There is one numeric tolerance.** The reference payer refuses a message + whose timestamp is more than **24 hours** behind the current time, with + `PAYR-1005`. That is the only bound any source states. + +Send ISO 8601 with `+05:30`, because that is what the samples carry. Accept a +Unix epoch on the way in. Note that the ABDM sessions call is a different +matter: its `TIMESTAMP` header is UTC with a trailing `Z` and milliseconds, and +a drifted clock is refused. + +## Domain headers + +The Overview says a few facts may be written on the outside of the envelope for +the exchange's records. There is a naming convention for them and there are +named examples, which is more than this documentation has said before. + +**The convention**, from both the Open Protocol and Technical Specifications +pages: + +``` +x-hcx-- +``` + +where `use_case_name` is under sixteen characters and ideally matches the API +path segment, and `parameter_name` is under thirty-two characters. Both pages +print the prefix as `x-NHCX-`. Send `x-hcx-`, for the reason given under The +header prefix below. + +**The named examples.** The Notification Integration document carries four in +its `domain_values` table, which is what the exchange passes to a beneficiary's +app so it can render a message without opening anything: + +| Header | What it carries | +| :---- | :---- | +| `x-hcx-amount_submitted` | The amount submitted by the provider | +| `x-hcx-benefit-category_type` | The benefit category, meaning the specialty | +| `x-hcx-benefit_code` | An array of the benefits or services submitted | +| `x-hcx-action` | The event type, such as `preauth_response` | + +The eObjects page adds a `Usage` domain header on the Claim Request and Claim +Response, carrying `preauthorization` or `claim`. + +And the access-control policy makes one of them load-bearing: an insurance +marketplace must "submit the acquired consent as part of the domain header" +before it may be given individual claim data. Access Control and Roles has the +rest. + +Send none of these to a payer that has not asked for one. But they are named, +they have a convention, and the earlier statement in this documentation that no +source names any of them was wrong. + +## The header prefix + +The Open Protocol page writes every field as `x-NHCX-`. The Technical +Specifications page, the workbook, the FAQ, the Postman collections and every +sample write `x-hcx-`. Send `x-hcx-`. + +## What the receipt carries + +Not a protected header, but the shape every participant must return within +thirty seconds of a delivery. + +```json +{ + "timestamp": "04/09/2026 11:46:41:305", + "api_call_id": "", + "correlation_id": "", + "result": { + "sender_code": "…", + "recipient_code": "…", + "entity_type": "preauth", + "protocol_status": "request.queued" + }, + "error": { "code": "", "message": "" } +} +``` + +HTTP `202`. Not `200`, not an empty body. `entity_type` is derived from the +path: the second-to-last segment, or the last where that is `v1`, with `on_` +stripped. diff --git a/site/docs/nhcx/v1/reference/environments-and-addresses.md b/site/docs/nhcx/v1/reference/environments-and-addresses.md new file mode 100644 index 000000000..a7723f6ae --- /dev/null +++ b/site/docs/nhcx/v1/reference/environments-and-addresses.md @@ -0,0 +1,170 @@ +--- +title: Environments and addresses +sidebar_label: Environments and addresses +sidebar_position: 16 +description: Sandbox/production URLs, firewall IPs, token headers, and 12 live Swagger specifications +verification: unverified +source: nhcx-package/docs/06-Reference/06-Environments and Addresses.md +generated: true +--- + +# Environments and addresses + +Every address this documentation uses, together with the live specifications +the portal publishes. Addresses are scattered through the chapters that need +them; this is where you check one. + +## Base URLs + +The base of every service, in both environments. Base URLs, in Getting +Started, explains how a path is appended to them and what is easy to get wrong. + +| Service | Sandbox | Production | +| :---- | :---- | :---- | +| ABDM session token | `https://dev.abdm.gov.in` | `https://apis.abdm.gov.in`. ABDM's published production gateway. Confirm it in your onboarding letter. | +| NHCX exchange | `https://apisbx.abdm.gov.in/hcx` | `https://apisprod.nha.gov.in/hcx` | +| Participant service | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice` | `https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice` | +| ABDM proxy | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/abdmproxy` | Not published. Confirm at onboarding. | +| PMJAY payer service, role lookup | `https://apisbx.abdm.gov.in` | Not published. Confirm at onboarding. | +| PMJAY payer service, act on a case | `https://apisbeta.nha.gov.in` | Not published. Confirm at onboarding. | +| Dummy payer | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/dummyhcxpayer` | A sandbox test hook only. | +| NHCX portal | `https://hcxsbx.abdm.gov.in` | Not published. | +| Face authentication page | `https://phrsbx.abdm.gov.in/face-auth` | Not published. | + +What each one serves: + +- **ABDM session token**: The session token every other call carries, at /api/hiecm/gateway/v3/sessions. +- **NHCX exchange**: Every use-case call under /v1, fingerprint and iris authentication under /abha. +- **Participant service**: Creating and updating a participant, the registry search, certificates and policies. +- **ABDM proxy**: Face authentication for PMJAY biometrics. +- **PMJAY payer service, role lookup**: The roles a PMJAY adjudicator user holds, at /pmjay/sbxhcx/nhcxpayerservice/v1/get/user-role. +- **PMJAY payer service, act on a case**: Acting on a PMJAY case, at /pmjay/hcx/nhcxpayerservice/wrapper/process/case. +- **Dummy payer**: The sandbox test hooks that make the dummy payer answer. +- **NHCX portal**: The portal, the live Swagger specifications it publishes, and notification subscribe. +- **Face authentication page**: The QR page a patient opens to complete face authentication, with ?txnId=<txnId>. + +The ABDM gateway also reads `X-CM-ID` on the session call: `sbx` in the sandbox, `abdm` in production. + +## Full sandbox addresses + +| What | Address | +| :---- | :---- | +| Session token | `https://dev.abdm.gov.in/api/hiecm/gateway/v3/sessions` | +| Use-case calls | `https://apisbx.abdm.gov.in/hcx/v1` | +| Dummy payer test hook | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/dummyhcxpayer/process/request` | +| Dummy payer payment hook | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/dummyhcxpayer/paymentNotice/init` | +| Biometric, fingerprint and iris | `https://apisbx.abdm.gov.in/hcx/abha/biometric/auth/{init,verify}` | +| Biometric, token refresh | `https://apisbx.abdm.gov.in/hcx/abha/biometric/auth/refresh/token` | +| Biometric, face | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/abdmproxy/abha/biometric/` | +| Face auth QR page | `https://phrsbx.abdm.gov.in/face-auth?txnId=` | +| PMJAY payer service, role lookup | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/nhcxpayerservice/v1/get/user-role` | +| PMJAY payer service, act on a case | `https://apisbeta.nha.gov.in/pmjay/hcx/nhcxpayerservice/wrapper/process/case` | +| Notification subscribe | `https://hcxsbx.abdm.gov.in/v1/notification/subscribe` | +| The portal itself | `https://hcxsbx.abdm.gov.in` | + +The production addresses NHA has not published follow, elsewhere, the pattern +of swapping the sandbox hostname, and the NHCX Adapter's own source says as +much in a comment, but that is an inference. Check every one against your +onboarding letter and make every one configurable. Going Live has the order +the switch happens in. + +## Headers, by service + +Which header carries the token is not uniform, and this is a common first-day +failure. + +| Service | Token header | Other required headers | +| :---- | :---- | :---- | +| ABDM sessions | none | `REQUEST-ID`, `TIMESTAMP`, `X-CM-ID` | +| Participant service | `bearer_auth: Bearer ` | `Accept`, `Content-Type`, sometimes `X-CM-ID` | +| Use-case endpoints | `bearer_auth: Bearer ` | `Accept`, `Content-Type` | +| Biometric endpoints | `Authorization: Bearer ` | `process`, `payerid` | +| PMJAY payer service | `bearer_auth: Bearer ` | `Accept`, `Content-Type` | +| Notification service | `Authorization: Bearer ` | `Content-Type` | + +The sources are not unanimous about `bearer_auth` against `Authorization` on +the exchange's own endpoints: the authentication note and the FAQ both write +the example as `Authorization`. Sending both headers with the same value is +what the adapter does and it costs nothing. + +`Accept: application/json` is the portal's sixth most common mistake when +omitted. + +## Firewall + +The exchange calls your callback from three addresses. All three must be +allowed inbound. + +``` +3.109.99.210 +13.126.152.0 +13.200.129.223 +``` + +Your callback address itself must be a domain name over HTTPS with TLS 1.2 or +newer, hosted in India, not an IP address and not carrying a port number. + +## Live API specifications + +The portal publishes a Swagger document per service. These are the +authoritative API surface and they cover three exchanges for which no sample +bundle exists anywhere, so they are the only concrete description of those +available. + +| Service | Specification | +| :---- | :---- | +| Coverage eligibility | `https://hcxsbx.abdm.gov.in/coverageeligibilityhcxservice/swagger-ui-custom.html` | +| Preauthorisation | `https://hcxsbx.abdm.gov.in/preauthhcxservice/swagger-ui-custom.html` | +| Claim | `https://hcxsbx.abdm.gov.in/claimhcxservice/swagger-ui-custom.html` | +| Request additional attachments | `https://hcxsbx.abdm.gov.in/communicationhcxservice/swagger-ui-custom.html` | +| Payment | `https://hcxsbx.abdm.gov.in/servicehcxpayment/swagger-ui-custom.html` | +| Status check | `https://hcxsbx.abdm.gov.in/statushcxservice/swagger-ui-custom.html` | +| Reprocess, the Task service | `https://hcxsbx.abdm.gov.in/taskhcxservice/swagger-ui-custom.html` | +| Search | `https://hcxsbx.abdm.gov.in/searchhcxservice/swagger-ui-custom.html` | +| Insurance plan | `https://hcxsbx.abdm.gov.in/insuranceplanhcxservice/swagger-ui/index.html` | +| Communication | `https://hcxsbx.abdm.gov.in/communicationhcxservice/swagger-ui/index.html` | +| Participant | `https://hcxsbx.abdm.gov.in/participanthcxservice/swagger-ui/index.html` | +| Notifications | `https://hcxsbx.abdm.gov.in/subscriptionhcxservice/swagger-ui/index.html` | + +The service names are worth noting on their own. Reprocess is served by +`taskhcxservice`, notifications by `subscriptionhcxservice`, payment by +`servicehcxpayment`. A name in a log will not always match the exchange you +think you are calling. + +## The endpoint set + +Every path in the V1 cashless use case, with its direction. + +| Exchange | Action | Callback | Direction | +| :---- | :---- | :---- | :---- | +| Coverage eligibility | `/v1/coverageeligibility/check` | `/v1/coverageeligibility/on_check` | provider to payer | +| Insurance plan | `/v1/insuranceplan/request` | `/v1/insuranceplan/on_request` | provider to payer | +| Preauthorisation | `/v1/preauth/submit` | `/v1/preauth/on_submit` | provider to payer | +| Predetermination | `/v1/predetermination/submit` | `/v1/predetermination/on_submit` | provider to payer | +| Claim | `/v1/claim/submit` | `/v1/claim/on_submit` | provider to payer | +| Communication | `/v1/communication/request` | `/v1/communication/on_request` | payer to provider | +| Payment notice | `/v1/paymentnotice/request` | `/v1/paymentnotice/on_request` | payer to provider | +| Task: reprocess, cancel | `/v1/task/submit` | `/v1/task/on_submit` | provider to payer | +| Cross-payer search | `/v1/search/submit` | `/v1/search/on_submit` | NHA or regulator to payer | +| Own-case search | `/preauth/search`, `/claim/search`, `/paymentnotice/search` | the matching `on_search` | originator to payer | +| Status | `/v1/status` | `/v1/on_status` | either party to the exchange | +| Error report | | `/v1/error` | exchange to every participant | +| Notifications | `/v1/notification/subscribe` | `/v1/notification/on_subscribe` | patient app to exchange | + +Predetermination is listed on the Technical Specifications page among the APIs +"designed and deployed in the sandbox environment", which is more than the FHIR +Reference chapter on it can say. No payer in the corpus is recorded as having +implemented it. + +The status pair is named two ways. The Technical Specifications table gives +`/hcx/status` and `/NHCX/on_status`; the Postman collection uses +`/hcx/v1/status` and `/hcx/v1/on_status`. Build against the Postman form, which +is what the sandbox serves, and keep the path configurable. + +## A defect in the published table + +The FAQ's own base-URL table gives the payment notice address as +`https://apisbx.abdm.gov.inhcx/v1/paymentnotice/on_request`, with the slash +after the hostname missing. Anyone copying it will get a DNS failure rather +than an API error, which is a confusing first symptom. The address is +`https://apisbx.abdm.gov.in/hcx/v1/paymentnotice/on_request`. diff --git a/site/docs/nhcx/v1/reference/error-code-guide.md b/site/docs/nhcx/v1/reference/error-code-guide.md new file mode 100644 index 000000000..0f925901f --- /dev/null +++ b/site/docs/nhcx/v1/reference/error-code-guide.md @@ -0,0 +1,517 @@ +--- +title: Error codes +sidebar_label: Reading error codes +sidebar_position: 11 +description: Directory of 309 error codes, the three code spaces, and collisions +verification: unverified +source: nhcx-package/docs/06-Reference/01-Error Codes.md +generated: true +--- + +# Error codes + +Every error code NHCX and the reference payer can send, in one place. The +workflow codes are in the Overview's Workflow Codes chapter and the FHIR value +sets in Codes and Value Sets; this chapter is only about failure. + +Three hundred and nine distinct codes exist across the seven sheets of the +Standard Error Codes workbook, last updated 11 August 2026. They are not one +list. They are three, and the first thing to get right is which one you are +reading. + +## The code spaces + +| Space | Prefix | Count | Who sends it | Where it arrives | +| :---- | :---- | :---- | :---- | :---- | +| Gateway | `NHCX-` | 19 | The exchange | Synchronously on your own call, or on `/v1/error` | +| Standard payer | `PAYR-1001 to PAYR-1020` | 20 | A payer implementing the published standard | Inside the sealed response | +| Reference payer | `PAYR-1001 to PAYR-1520` | 290 | The PMJAY reference implementation | Inside the sealed response | +| Observed live | `ERR-PYR-` | 1 | The PMJAY reference implementation, on none of its published sheets | Inside the sealed response | + +The fourth row is not a sheet. It is the one code the reference payer sent on +the sandbox run that none of the seven sheets lists; What the live payer sent +that the sheets do not say, below, covers it. + +**The two `PAYR-` spaces collide.** All twenty codes in the `PAYR-1001` to +`PAYR-1020` range are on both the standard sheet and the reference payer's +Bridge Error sheet, and eighteen of them carry a different meaning on each. The +two that agree are `PAYR-1001` and `PAYR-1002`, a decryption and an encryption +failure on both sheets in different words. The reference payer's own sheet +marks three of its readings, `PAYR-1003`, `PAYR-1006` and `PAYR-1007`, as +deprecated. + +| Code | Standard sheet says | Reference payer says | +| :---- | :---- | :---- | +| `PAYR-1003` | Error while connecting to NHCX; the system will resend later | Invalid workflow requested (marked deprecated on the Bridge Error sheet) | +| `PAYR-1004` | Provider is not registered with the payer for the requested policy | Received FHIR bundle is malformed | +| `PAYR-1005` | Beneficiary is not a covered member for the requested policy | Maximum time limit exceeded in receiving the request | +| `PAYR-1006` | Policy does not exist | Invalid name in request (marked deprecated on the Bridge Error sheet) | +| `PAYR-1007` | Requested policy is expired | Invalid gender in request (marked deprecated on the Bridge Error sheet) | +| `PAYR-1008` | Eligible coverage amount is insufficient | Invalid FHIR bundle received | +| `PAYR-1009` | Requested items are not valid or not covered | No identifier found for patient component | +| `PAYR-1010` | Preauthorisation is required but was not obtained | No type found for patient component identifier | +| `PAYR-1011` | The prior approved package does not support enhancement | No identifier found for claim component | +| `PAYR-1012` | Claim amount is more than the preauthorisation approved amount | No type found for claim component identifier | +| `PAYR-1013` | No prior approval for the requested procedures or packages | No identifier found for organization component for provider | +| `PAYR-1014` | Date of birth is after the date of service | No type found for organization component identifier for provider | +| `PAYR-1015` | Date of service is after the date of death | No identifier found for organization component for payer | +| `PAYR-1016` | Duplicate claim submitted based on service codes and dates | No type found for organization component identifier for payer | +| `PAYR-1017` | Amount calculations are not correct | No task code received | +| `PAYR-1018` | Time limit for submission expired | No task reason code received | +| `PAYR-1019` | Requested additional information was not received in time | Invalid sequence received in supporting info element | +| `PAYR-1020` | No valid bank details found for the provider | Invalid category received in supporting info element | + +A system that maps its error handling from the standard sheet and then meets +the reference payer will mis-read eighteen codes in that band, and for most of +them the two readings point at opposite remedies: a business refusal the desk +must act on, against a structural fault only an engineer can fix. The live +sandbox run recorded in PMJAY Sandbox Run met the reference payer's readings +throughout. + +Decide which payer you are talking to before you look a code up. If you +support both, key your table on the pair of payer and code, never on the code +alone. + +## Reading a code by its band + +The reference payer's codes are banded by the stage that rejected the message, +and the band is more useful than the code when you are triaging. + +| Band | Codes | What rejected it | What it means for you | +| :---- | :---- | :---- | :---- | +| `NHCX-1xxx` | 19 | The exchange, on the envelope | The message never reached the payer | +| `PAYR-10xx` | 98 | Transport and bundle structure | An element, id, sequence or type is missing. Not a value problem | +| `PAYR-11xx` | 23 | Coverage eligibility | The policy, the beneficiary or the hospital configuration | +| `PAYR-12xx` | 73 | Preauthorisation | Codes, amounts, dates, sequencing and scheme rules | +| `PAYR-13xx` | 70 | Claim | The same, against the approved preauthorisation | +| `PAYR-14xx` | 26 | Insurance plan, and the scheme's outer rules | Empanelment, policy association, plan configuration | + +Two consequences follow, both confirmed live. + +**The bands are applied in order.** The bundle is validated before the scheme's +rules are applied, so a `PAYR-12xx` or `PAYR-13xx` refusal is the first sign +that the bundle itself is structurally sound. Reaching `PAYR-1238` is progress. + +**The `PAYR-10xx` band is structural, not semantic.** When you meet one, check +ids, sequences and types before you go looking at values. `PAYR-1027`, "invalid +item id", is not about the package code at all; it means the `Claim.item` has +no FHIR element `id`. + +## Gateway codes +| Code | Message | +| :---- | :---- | +| `NHCX-401` | User Unauthorized | +| `NHCX-1001` | Receiver system is not reachable. | +| `NHCX-1002` | Sender not registered in NHCX. Please register in NHCX portal and try again. | +| `NHCX-1003` | Receiver not registered in NHCX. Please try again with valid receiver details. | +| `NHCX-1004` | No receiver registered in NHCX for the requested scheme. Please try again with valid receiver details for the scheme. | +| `NHCX-1005` | Invalid request header. Please try again with valid headers. | +| `NHCX-1006` | Duplicate request. Request with same correlation id already exist in the system. | +| `NHCX-1007` | Something went wrong while processing the request. Please check the request structure and values and try again. | +| `NHCX-1008` | Something went wrong while processing the request. Please try again after sometime. | +| `NHCX-1009` | Something went wrong while processing the request. Please check log for more details. | +| `NHCX-1010` | No Data with given Correlation id for call back request, please check status for more details | +| `NHCX-1011` | Invalid Status, please check x-hcx-status value from the protected header | +| `NHCX-1012` | No records found with the requested api caller id. Please try again with a valid api caller id. | +| `NHCX-1013` | Invalid or blank request found. | +| `NHCX-1014` | Unable to send protocol response to sender. | +| `NHCX-1015` | Invalid response received from receiver. | +| `NHCX-1016` | Invalid Api Action, please check the request action for this correlationId before trying again | +| `NHCX-1017` | Invalid response received from receiver | +| `NHCX-1018` | Invalid ABHA number received. ABHA number should be sent in the format XX-XXXX-XXXX-XXXX | + +`NHCX-1010` is the one to understand before you build a payer. The exchange +redelivers a submission you have not answered, drops it after a few attempts +and retires the correlation ID, so a verdict decided minutes later has nowhere +to land. Acknowledge every submission at once with an interim response and send +the decision later on the same thread. + +`NHCX-1006`, duplicate correlation ID, is what a retry earns if you reuse a +correlation ID after a failure. Mint a fresh one. + +## Standard payer codes + +The twenty codes a payer implementing the published standard sends. These are +business refusals and belong on the claims desk, shown in the payer's own +words. +| Code | Message | +| :---- | :---- | +| `PAYR-1001` | Error while decrypting request. Please reprocess the request encrypting with valid certificate of the payer. | +| `PAYR-1002` | Error while encrypting request. Please update encryption certificate in NHCX. | +| `PAYR-1003` | Error while connecting to NHCX. System will try to resend the message to NHCX after some time. | +| `PAYR-1004` | Provider is not registered with the payer for requested policy. | +| `PAYR-1005` | Beneficiary is not a covered member for requested policy. Please enroll beneficiary for the policy and try again. | +| `PAYR-1006` | Policy does not exist. Please try with a valid policy. | +| `PAYR-1007` | Requested policy is expired. Please try with a valid policy. | +| `PAYR-1008` | Eligible coverage amount of the beneficiary for the requested policy is insufficient to process the request. | +| `PAYR-1009` | Requested items are not valid or not covered. Please try again with valid or covered items. | +| `PAYR-1010` | Preauthorization is required to process the request but was not obtained. | +| `PAYR-1011` | Enhancement request can not be processed as the prior approved package/procedure does not support enhancement. | +| `PAYR-1012` | Claim amount requested is more than the preauthorization approved amount. | +| `PAYR-1013` | No prior approval for the requested procedures/packages obtained. | +| `PAYR-1014` | Date of birth of the beneficiary can not be after date of service. | +| `PAYR-1015` | Date of service cannot be after date of death. | +| `PAYR-1016` | Duplicate claim submitted based on service codes and dates. | +| `PAYR-1017` | Amount calculations are not correct. Please verify calculated amount. | +| `PAYR-1018` | Time limit for submission expired. | +| `PAYR-1019` | Requested additional information was not received or was not received within time limit | +| `PAYR-1020` | Unable to process payment as no valid bank details found for the provider. | + +## Reference payer: structure and transport, `PAYR-10xx` + +Ninety-eight codes. Almost all of them say that an element the payer addresses +by id, sequence or type is missing its handle. None of them is a code lookup. +| Code | Message | +| :---- | :---- | +| `PAYR-1001` | Error occurred while decrypting payload for receiver code <receiver_code> with correlation id <sender_correlation_id>. | +| `PAYR-1002` | Error occurred while encrypting payload for receiver code <receiver_code> with correlation id <sender_correlation_id>. | +| `PAYR-1003` | Invalid workflow requested. Hence request will not be processed further. | +| `PAYR-1004` | Received FHIR bundle is malformed. Please correct the bundle and try again. <Error details> | +| `PAYR-1005` | Maximum time limit exceeded in receiving the request. Please try again. | +| `PAYR-1006` | Invalid name in request. Hence request will not be processed further. | +| `PAYR-1007` | Invalid gender in request. Hence request will not be processed further. | +| `PAYR-1008` | Invalid FHIR bundle received. Hence request will not be processed further. | +| `PAYR-1009` | No identifier found for patient component. Hence request will not be processed further. https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html | +| `PAYR-1010` | No type found for patient component identifier. Hence request will not be processed further. https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html | +| `PAYR-1011` | No identifier found for claim component. Hence request will not be processed further. | +| `PAYR-1012` | No type found for claim component identifier. Hence request will not be processed further. | +| `PAYR-1013` | No identifier found for organization component for provider. Hence request will not be processed further. | +| `PAYR-1014` | No type found for organization component identifier for provider. Hence request will not be processed further. | +| `PAYR-1015` | No identifier found for organization component for payer. Hence request will not be processed further. | +| `PAYR-1016` | No type found for organization component identifier for payer. Hence request will not be processed further. | +| `PAYR-1017` | No task code received. Hence request will not be processed further. | +| `PAYR-1018` | No task reason code received. Hence request will not be processed further. | +| `PAYR-1019` | Invalid sequence received in supporting info element. Hence request will not be processed further. | +| `PAYR-1020` | Invalid category received in supporting info element for sequence %s. Hence request will not be processed further. | +| `PAYR-1021` | Invalid code received in supporting info element for sequence %s. Hence request will not be processed further. | +| `PAYR-1023` | Invalid procedure category received for procedure component. Hence request will not be processed further. | +| `PAYR-1024` | Invalid procedure status received for procedure component. Hence request will not be processed further. | +| `PAYR-1025` | Invalid procedure sequence received for procedure component. Hence request will not be processed further. | +| `PAYR-1026` | No procedure component found for reference in claim component. Hence request will not be processed further. | +| `PAYR-1027` | Invalid item id found for item in claim component. Hence request will not be processed further. | +| `PAYR-1028` | Invalid item sequence received for item in claim component. Hence request will not be processed further. | +| `PAYR-1029` | Invalid bundle id received for FHIR bundle. Hence request will not be processed further. | +| `PAYR-1030` | Invalid questionnaire id received in FHIR bundle for questionnaire component. Hence request will not be processed further. | +| `PAYR-1031` | Invalid url received for bundle entry in FHIR bundle. Hence request will not be processed further. Please reach out to technical team. | +| `PAYR-1032` | Invalid purpose received for coverage eligibility request. Hence request will not be processed further. Please try again with valid purpose details. | +| `PAYR-1033` | No items received for coverage eligibility purpose. Since items are mandatory for the requested purpose, hence request will not be processed further. Please try again with valid item details. | +| `PAYR-1034` | Invalid procedure code received. Please try again with valid procedure details. | +| `PAYR-1035` | Invalid policy code received. Please try again with valid policy details. | +| `PAYR-1036` | Invalid attachment received in supporting info with sequence number %s. Please try again with valid attachment details as attachment value is expected. If issue is not resolved, please reach out to technical team. | +| `PAYR-1037` | No identifier found for communication component. Hence request will not be processed further. | +| `PAYR-1038` | No type found for communication component identifier. Hence request will not be processed further. | +| `PAYR-1039` | No payload found for communication component. Hence request will not be processed further. | +| `PAYR-1040` | No component found for given reference. Hence request will not be processed further. | +| `PAYR-1041` | No identifier found for procedure component. Hence request will not be processed further. | +| `PAYR-1042` | No type found for procedure component identifier. Hence request will not be processed further. | +| `PAYR-1043` | Date received in the request does not adhere to the NRCES date datatype format. Hence request will not be processed further. Please refere to the date format in NRCES portal. | +| `PAYR-1044` | Date and time received in the request does not adhere to the NRCES date datatype format. Hence request will not be processed further. Please refere to the date time format in NRCES portal. | +| `PAYR-1045` | Invalid quantity received for item. Hence request will not be processed further. | +| `PAYR-1046` | No value or timing details received for supporting info for sequence %s. Hence request will not be processed further. Please reach out to technical team. | +| `PAYR-1047` | Invalid reference received in supporting info with sequence number %s. Please try again with valid resource as reference value. | +| `PAYR-1048` | No reference resource received for supporting info with sequence number %s. Please try again with valid resource for reference value. | +| `PAYR-1049` | Invalid FHIR bundle received. Hence request will not be processed further. please reach out to technical team. | +| `PAYR-1050` | No type found for practitioner component identifier. Hence request will not be processed further. | +| `PAYR-1051` | No section found for composition component. Hence request will not be processed further. | +| `PAYR-1052` | No references found in composition section. Hence request will not be processed further. | +| `PAYR-1053` | Invalid reference found in child sections of composition section. Hence request will not be processed further. | +| `PAYR-1054` | No section content found for composition component. Hence request will not be processed further. | +| `PAYR-1055` | Invalid subject type found for composition component. This should be of type Patient. Hence request will not be processed further. Please try again with valid subject type for the composition. | +| `PAYR-1056` | Invalid contact organization found for subject in composition component. This should be of type Organization. Hence request will not be processed further. Please try again with valid data. | +| `PAYR-1057` | Invalid general practioner type found for subject in composition component. This should be of type Organization/Practitioner/PractitionerRole. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html | +| `PAYR-1058` | Invalid managing organization type found for subject in composition component. This should be of type Organization. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html | +| `PAYR-1059` | Invalid encounter type found for composition/observation component. This should be of type Encounter. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-DiagnosticReportRecord.html | +| `PAYR-1060` | No subject found for encounter in composition component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html | +| `PAYR-1061` | Invalid subject type found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html | +| `PAYR-1062` | No episode of care found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html | +| `PAYR-1063` | Invalid episode of care type found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html | +| `PAYR-1064` | No based on found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html | +| `PAYR-1065` | Invalid based on type found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html | +| `PAYR-1066` | No appointment found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html | +| `PAYR-1067` | Invalid appointment type found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html | +| `PAYR-1068` | No reason reference found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html | +| `PAYR-1069` | Invalid reason reference type found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html | +| `PAYR-1070` | No author found for composition component. Hence request will not be processed further. | +| `PAYR-1071` | Invalid author type found for composition component. This should be of type Practitioner / PractitionerRole / Organization / Patient / Device / RelatedPerson. Hence request will not be processed further. Please try again with valid author type for the composition. | +| `PAYR-1072` | No procedure reference received for procedure element in claim resource. Hence request will not be processed further. | +| `PAYR-1073` | No based on found for observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Observation.html | +| `PAYR-1074` | Invalid based on type found for observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Observation.html | +| `PAYR-1075` | No part of found for observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Observation.html | +| `PAYR-1076` | Invalid part of type found for observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Observation.html | +| `PAYR-1077` | No subject found for observation component. Hence request will not be processed further. | +| `PAYR-1078` | Invalid subject type found for observation component. This should be of type Patient. Hence request will not be processed further. Please try again with valid subject type for the observation. | +| `PAYR-1079` | No care team details received. Hence request will not be processed further. Please add the care team details and try again. | +| `PAYR-1080` | Invalid HPR details received for practioner resource with url %s. Hence request will not be processed further. Please try again with valid HPR id. | +| `PAYR-1081` | Invalid service date received for item with sequence %s in claim resource. Hence request will not be processed further. Please try again with valid item service date. | +| `PAYR-1082` | Invalid title received for composition for supporting info with sequence %s in claim resource. Hence request will not be processed further. Please try again with valid composition title. | +| `PAYR-1083` | No HPR details found for the practitioner for resource %s. Hence request will not be processed further. Please send the details in the identifier for Practitioner resource with category code as HPIN. | +| `PAYR-1084` | No questionnaire response resource found for url %s. Hence request will not be processed further. Please add the resources for all the references given in the FHIR bundle and try again. | +| `PAYR-1085` | Invalid questionnaire response resource type found in the FHIR bundle for url %s. Hence request will not be processed further. | +| `PAYR-1086` | No procedure resource found for url %s. Hence request will not be processed further. Please add the resources for all the references given in the FHIR bundle and try again. | +| `PAYR-1087` | Invalid procedure resource type found in the FHIR bundle for url %s. Hence request will not be processed further. Procedure resource type is expected. | +| `PAYR-1088` | Invalid composition details. | +| `PAYR-1089` | No billing items found. Hence request will not be processed further. Please try again with valid billing items. | +| `PAYR-1090` | No identifier found for coverage component. Hence request will not be processed further. | +| `PAYR-1091` | No type found for coverage component identifier. Hence request will not be processed further. | +| `PAYR-1092` | Something went wrong while processing request, kindly intiate new request | +| `PAYR-1093` | No subject found for encounter in composition component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html | +| `PAYR-1094` | Invalid subject type found for encounter in composition/observation component. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Encounter.html | +| `PAYR-1095` | Invalid discharge information received for claim request. Hence request will not be processed further. Please send the discharge information in supporting info in claim resource, with category as DIS (refer - https://www.nrces.in/ndhm/fhir/r4/ValueSet-ndhm-supportinginfo-category.html), and codes in LAMA/DAMA/DTH/DTM (refer - https://www.nrces.in/ndhm/fhir/r4/ValueSet-ndhm-supportinginfo-code.html). | +| `PAYR-1096` | Invalid death date received for claim request. Hence request will not be processed further. Please send the death date information in supporting info in claim resource, with category as ONS (refer - https://www.nrces.in/ndhm/fhir/r4/ValueSet-ndhm-supportinginfo-category.html), and code as DTM (refer - https://www.nrces.in/ndhm/fhir/r4/ValueSet-ndhm-supportinginfo-code.html). | +| `PAYR-1097` | No payload found in the request. Please ensure that the request that is being sent, contains encrypted payload within the mandatory payload properties. | +| `PAYR-1098` | Value type received as %s for category - OTH and code - EDT for item with sequence %s in supporting info in claim resource. In supporting info list, item with category - OTH and code - EDT combination is used to get the registration date. So the registration date should be sent as timing (date or period) or as a string value, adhering to the NRCES standards, with the category - OTH and code - EDT. | +| `PAYR-1099` | Value type received as %s for category - ONS and code - DSDE for item with sequence %s in supporting info in claim resource. In supporting info list, item with category - ONS and code - DSDE combination is used to get the discharge date. So the discharge date should be sent as timing (date or period) or as a string value, adhering to the NRCES standards, with the category - ONS and code - DSDE. | + +## Reference payer: coverage eligibility, `PAYR-11xx` +| Code | Message | +| :---- | :---- | +| `PAYR-1101` | Invalid purpose received as (%s) for beneficiary id (%s) from hospital id (%s). Hence no result will be returned. Please try again with a valid purpose. | +| `PAYR-1102` | Invalid search parameter requested. Please try again with a valid id. | +| `PAYR-1103` | Invalid careplan id received. Please try again with valid careplan id. | +| `PAYR-1104` | Multiple records found for the beneficiary. Hence request will not be processed further. | +| `PAYR-1105` | Hospital configuration not found. Please contact support team. | +| `PAYR-1106` | No details found for the requested procedures in the system. | +| `PAYR-1107` | No billable item received. Please try again with valid item data. | +| `PAYR-1108` | No details found for the requested stratification in the system. | +| `PAYR-1109` | No details found for the requested investigations in the system. | +| `PAYR-1110` | No details found for the requested implants in the system. | +| `PAYR-1111` | Rule failure. | +| `PAYR-1112` | Invalid payer id received. Please try again ith valid payer details | +| `PAYR-1113` | Invalid item code received as %s. Please try again with valid data | +| `PAYR-1114` | Invalid speciality code received as %s for item %s. Please try again with valid data. Speciality code is available as the code of the category for specific cost of plan in isurance plan | +| `PAYR-1115` | Invalid procedure quantity received as %s for item %s. Please try again with valid data. Item quantity should be greater than 1 | +| `PAYR-1116` | Hospital is not authorized to raise any case under policy %s. Hence request will not be processed further. Please connect with the support team to get the required authorization | +| `PAYR-1117` | No policy details found for %s. Hence request will not be processed further | +| `PAYR-1118` | No details found for requested items. Hence request will not be processed further | +| `PAYR-1119` | No payer details received for payer id %s from HCX. Please try again with valid payer details. | +| `PAYR-1120` | Duplicate reference id found as %s. Please try again with valid reference details. | +| `PAYR-1121` | No policy details found for %s for beneficiary %s. Hence request will not be processed further. | +| `PAYR-1122` | No policy details found for beneficiary %s. Hence request will not be processed further. | +| `PAYR-1123` | Beneficiary is not a covered member for requested payer. Please enroll beneficiary for applicable policy of requested payer and try again. | + +`PAYR-1114` is the one PMJAY Sandbox Run cites without defining: the +specialty on `item.category` must be the code of the category the package +master files the package under, not a generic value. + +## Reference payer: preauthorisation, `PAYR-12xx` +| Code | Message | +| :---- | :---- | +| `PAYR-1201` | Invalid claimed amount received for case number %s. Please try again with a valid claim amount. Claimed amount should be greater than INR 0 and less than equals to balance wallet amount of the beneficiary. | +| `PAYR-1202` | Invalid speciality code received as %s for item %s for case number %s. Please try again with valid data. Speciality code is available as the code of the category for specific cost of plan in isurance plan. | +| `PAYR-1203` | Invalid speciality description received as %s for procedure %s for case number %s. Please try again with valid data. Speciality description is available as the display of the category for specific cost of plan in isurance plan. | +| `PAYR-1204` | Invalid procedure code received as %s for case number %s. Please try again with valid data. Procedure code is available as the code of the type for benefit component, of specific cost, of plan in isurance plan. | +| `PAYR-1205` | Invalid procedure description received as %s for procedure %s for case number %s. Please try again with valid data. Procedure description is available as the display of the type for benefit component, of specific cost, of plan in isurance plan. | +| `PAYR-1206` | Invalid procedure type received as %s for procedure %s for case number %s. Please try again with valid data. | +| `PAYR-1207` | Invalid procedure factor received as %s for procedure %s for case number %s. Please try again with valid data. | +| `PAYR-1208` | Invalid procedure quantity received as %s for item %s for case number %s. Please try again with valid data. Item quantity should be greater than 1. | +| `PAYR-1209` | Invalid net amount received as INR %s for item %s for case number %s. Please try again with valid data. Item net amount should be greater than INR 0. | +| `PAYR-1210` | Invalid procedure status received as %s for procedure %s for case number %s. Please try again with valid data. | +| `PAYR-1211` | Requested beneficary details and careplan details does not match any criteria for processing the case at this hospital. Please try again with valid data. | +| `PAYR-1212` | No previous preauthorization approved record found for the enhancement request for case number %s. Hence request will not be processed further. Please initiate a new preauthorization. | +| `PAYR-1213` | Existing case in progress found for case number %s. Hence enhancement request will not be accepted. Please try after the adjudication is completed for the current case. | +| `PAYR-1214` | No previous preauthorization approved record found for the resubmission request for case number %s. Hence request will not be processed further. Please initiate a new preauthorization. | +| `PAYR-1215` | Existing case in progress found for case number %s. Hence resubmission request will not be accepted. Please try after the adjudication is completed for the current case. | +| `PAYR-1216` | Existing case in progress found for case number %s. Hence new preauthorization request will not be accepted. | +| `PAYR-1217` | Previous preauthorization approved record found for the new preauthorization request for case number %s. Hence request will not be processed further. Please initiate enhancement/resubmission. | +| `PAYR-1218` | No queried preauthorization record found for the query update request for case number %s. Hence request will not be processed further. | +| `PAYR-1219` | Case number %s is not queried. Hence query updation request will not be processed further. | +| `PAYR-1220` | Invalid investigation description received as %s for investigation code %s for case number %s. Please try again with valid data. | +| `PAYR-1221` | Invalid investigation code received as %s for case number %s. Please try again with valid data. | +| `PAYR-1222` | Invalid investigation status received as %s for investigation %s for case number %s. Please try again with valid data. | +| `PAYR-1223` | Invalid investigation attachment received for investigation %s for case number %s. Please try again with valid data. | +| `PAYR-1224` | Invalid implant description received as %s for implant code %s for case number %s. Please try again with valid data. | +| `PAYR-1225` | Invalid implant code received as %s for case number %s. Please try again with valid data. | +| `PAYR-1226` | Invalid implant status received as %s for investigation %s for case number %s. Please try again with valid data. | +| `PAYR-1227` | Invalid implant attachment received for investigation %s for case number %s. Please try again with valid data. | +| `PAYR-1228` | Invalid implant quantity received as %s for implant %s for case number %s. Please try again with valid data. | +| `PAYR-1229` | Invalid implant net amount received as INR %s for implant %s for case number %s. Please try again with valid data. | +| `PAYR-1230` | Invalid implant unit price received as INR %s for implant %s for case number %s. Please try again with valid data. | +| `PAYR-1231` | Claim has already been raised for case number %s. Hence preauthorization request will not be accepted. | +| `PAYR-1232` | No investigation found for case number %s. Investigation details are mandatory for private hospitals. | +| `PAYR-1233` | Patient liability is not aplicable for the hospital and beneficiary do not have enough wallet balance with deficit amount INR %s for the requested preauthorization for case number %s. | +| `PAYR-1234` | No preauthorization record found for case number %s. Hence the request will not be processed. | +| `PAYR-1235` | Insufficient wallet balance. Hence the request will not be processed. | +| `PAYR-1236` | Invalid claim type (in-patient/out-patient) received. Hence the request will not be processed. | +| `PAYR-1237` | Beneficiary is having an active preauthorization request at %s. Hence the request will not be processed. Kindly inform %s to cancel the active preauthorization request or raise a claim to proceed with current preauthorization. | +| `PAYR-1238` | Beneficiary is having an active preauthorization request at this hospital with reference number %s. Hence the request will not be processed. Kindly cancel the active preauthorization request or raise a claim to proceed with current preauthorization. | +| `PAYR-1239` | Hospital configuration not found. Please contact support team. | +| `PAYR-1240` | No details found for the requested procedures in the system. | +| `PAYR-1241` | Invalid registration date received for case number %s. Hence the request will not be processed. | +| `PAYR-1242` | Invalid registration date format received for case number %s. Hence the request will not be processed. | +| `PAYR-1243` | Invalid admission date received for case number %s. Hence the request will not be processed. | +| `PAYR-1244` | Invalid admission date format received for case number %s. Hence the request will not be processed. | +| `PAYR-1245` | Rule failure. | +| `PAYR-1246` | Invalid payer id received as %s. Please try again with valid payer id. | +| `PAYR-1247` | Payer details for payer id %s is not received from HCX for the request. Hence the request will not be processed. | +| `PAYR-1248` | Invalid item code received as %s for item sequence %s case number %s. Please try again with valid data. | +| `PAYR-1249` | Invalid item sequence received as %s for case number %s. Please try again with valid data. | +| `PAYR-1250` | Requested policy %s is not listed. Please try again with valid policy code. | +| `PAYR-1251` | No billable treatment plan received for case number %s. Please try again with valid treatment plan data. | +| `PAYR-1252` | Case number %s is not in active preauthorization state with the current status of the case with the payer system is %s. Hence the preauthorization can not be cancelled. Only the cases with current status as preauthorization submitted or preauthorization approved can be cancelled. | +| `PAYR-1253` | Case number %s is already cancelled. Hence the preauthorization can not be cancelled again. Only the cases with current status as preauthorization submitted or preauthorization approved can be cancelled. | +| `PAYR-1254` | Response for STG Questionnaire id %s is mandatory for procedure code %s. Hence the preauthorization request will not be processed as the questionnaire response is not received for procedure code. | +| `PAYR-1255` | Case number %s is already cancelled. Hence no preauthorization request will be accepted for this case number. New preauthorization request needs to be raised with new case/reference number to proceed further. | +| `PAYR-1256` | Response for Authentication Consent Questionnaire is missing for case number %s. This must be sent if the biometric authentication for patient is not available. For new preauthorization request, either biometric authentication for patient or response for Authentication Consent questionnaire must be sent. Please check/update the insurance plan for the policy for the details of the questionnaire. Please adhere to the response of the coverage eligibility for auth-requirements purpose to check the mandatory documents to be attached with the request | +| `PAYR-1257` | Payment is initiated for case number %s. Hence the preauthorization can not be cancelled again. Only the cases with current status as preauthorization submitted or preauthorization approved can be cancelled | +| `PAYR-1258` | Payment is accomplished/cleared for case number %s. Hence the preauthorization can not be cancelled again. Only the cases with current status as preauthorization submitted or preauthorization approved can be cancelled | +| `PAYR-1259` | DOB is missing for new born for the case number (%s) with correlation id as (%s) at (%s) | +| `PAYR-1260` | DOB cannot be a future date for the case number (%s) with correlation id as (%s) at (%s) | +| `PAYR-1261` | Invalid new born details for the case number (%s) with correlation id as (%s) at (%s) | +| `PAYR-1262` | Gender is mandatory for the new born beneficiary | +| `PAYR-1263` | Documents are mandatory for the new born beneficiary | +| `PAYR-1264` | Documents are mandatory for the new born beneficiary | +| `PAYR-1265` | Documents are mandatory for the new born beneficiary | +| `PAYR-1266` | Documents are mandatory for the new born beneficiary | +| `PAYR-1267` | Beneficiary is having an active preauthorization request for new born case at this hospital with reference number %s. Hence the request will not be processed. Kindly cancel the active preauthorization request or raise a claim to proceed with current preauthorization | +| `PAYR-1268` | Beneficiary is having an active preauthorization request for new born case at %s. Hence the request will not be processed. Kindly inform %s to cancel the active preauthorization request or raise a claim to proceed with current preauthorization | +| `PAYR-1269` | Date of birth received for new born beneficiary exceeds 6 years before the current date. New born cases can be raised only for the beneficiary whose date of birth is within 6 years of current date | +| `PAYR-1270` | Item LM100 is not applicable for preauthorization request. This item is expected/mandated only during claim submission if the patient is discharged after/during surgery under LAMA/DAMA category for PMJAY cases. | +| `PAYR-1271` | No value received for link id %s for Authentication Consent Questionnaire for preauthorization request. This must be sent if the biometric authentication for patient is not available. For new preauthorization request, either biometric authentication for patient or response for Authentication Consent questionnaire must be sent. Please check/update the insurance plan for the policy for the details of the questionnaire. Please adhere to the response of the coverage eligibility for auth-requirements purpose to check the mandatory documents to be attached with the request. | +| `PAYR-1272` | Invalid biometric user token received. Please try again with valid valid biometric details of the beneficiary. For any issues with biometric, please try with Authentication Consent Questionnaire, details for which has been received in response for coverage eligibliity auth-requirements. | +| `PAYR-1273` | No questionnaire found for the received selection. Please validate the questionnaire url from insurance plan/coverage auth-requirements response. | + +## Reference payer: claim, `PAYR-13xx` +| Code | Message | +| :---- | :---- | +| `PAYR-1301` | Claim has already been raised for case number %s. Hence new claim request will not be accepted. | +| `PAYR-1302` | No preauthorization approved record found for case number %s. Hence new claim request will not be accepted. | +| `PAYR-1303` | No active claim record found for case number %s. Hence query updation request will not be accepted. | +| `PAYR-1304` | No claim queried record found for case number %s. Hence query updation request will not be accepted. | +| `PAYR-1305` | Invalid usecase requested for case number %s. Please try again with valid usecase. | +| `PAYR-1306` | No item found in preauthorization request for procedure %s with item sequence %s for case number %s. Please try again with valid items. | +| `PAYR-1307` | Invalid quantity requested for procedure %s with item sequence %s for case number %s. Please try again with valid quantity. | +| `PAYR-1308` | No item found in active claim request for procedure %s with item sequence %s for case number %s. Please try again with valid items. | +| `PAYR-1309` | No item found in preauthorization request for implant %s with item sequence %s for case number %s. Please try again with valid items. | +| `PAYR-1310` | Invalid quantity requested for implant %s with item sequence %s for case number %s. Please try again with valid quantity. | +| `PAYR-1311` | No item found in active claim request for implant %s with item sequence %s for case number %s. Please try again with valid items. | +| `PAYR-1312` | No item found in preauthorization request for investigation %s with item sequence %s for case number %s. Please try again with valid items. | +| `PAYR-1313` | Invalid quantity requested for investigation %s with item sequence %s for case number %s. Please try again with valid quantity. | +| `PAYR-1314` | No item found in active claim request for investigation %s with item sequence %s for case number %s. Please try again with valid items. | +| `PAYR-1315` | Rejected item found for preauthorization for procedure %s with item sequence %s for case number %s. Please try again with valid items. | +| `PAYR-1316` | Rejected item found for preauthorization for investigation %s with item sequence %s for case number %s. Please try again with valid items. | +| `PAYR-1317` | Rejected item found for preauthorization for implant %s with item sequence %s for case number %s. Please try again with valid items. | +| `PAYR-1318` | No requested treatment plan found for case number %s. Please try again with valid items. | +| `PAYR-1319` | No requested investigation plan found for case number %s. Please try again with valid items. | +| `PAYR-1320` | No details found for the requested investigations in the system. Hence request will not be processed. | +| `PAYR-1321` | Error occurred while processing the request due to invalid workflow id as (%s) | +| `PAYR-1322` | No active case found for the given case number. | +| `PAYR-1323` | Insufficient wallet balance. Hence the request will not be processed. | +| `PAYR-1324` | Invalid discharge stage received for case number %s. Hence the request will not be processed. | +| `PAYR-1325` | Invalid admission date received for case number %s. Hence the request will not be processed. | +| `PAYR-1326` | Invalid discharge date received for case number %s. Hence the request will not be processed. | +| `PAYR-1327` | Invalid admission date format received for case number %s. Hence the request will not be processed. | +| `PAYR-1328` | Invalid discharge date format received for case number %s. Hence the request will not be processed. | +| `PAYR-1329` | Invalid registration date received for case number %s. Hence the request will not be processed. | +| `PAYR-1330` | Invalid registration date format received for case number %s. Hence the request will not be processed. | +| `PAYR-1331` | Receiver not registered in NHCX. Please try again with valid receiver details. | +| `PAYR-1332` | Invalid CRC request. | +| `PAYR-1333` | Invalid claim type (in-patient/out-patient) received. Hence the request will not be processed. | +| `PAYR-1334` | Hospital configuration not found. Please contact support team. | +| `PAYR-1335` | Invalid implant quantity received as %s for implant %s for case number %s. Please try again with valid data. | +| `PAYR-1336` | Invalid implant unit price received as INR %s for implant %s for case number %s. Please try again with valid data. | +| `PAYR-1337` | Invalid implant net amount received as INR %s for implant %s for case number %s. Please try again with valid data. | +| `PAYR-1338` | Invalid implant attachment received for investigation %s for case number %s. Please try again with valid data. | +| `PAYR-1339` | Invalid implant status received as %s for investigation %s for case number %s. Please try again with valid data. | +| `PAYR-1340` | Invalid investigation status received as %s for investigation %s for case number %s. Please try again with valid data. | +| `PAYR-1341` | Invalid investigation attachment received for investigation %s for case number %s. Please try again with valid data. | +| `PAYR-1342` | Existing case in progress found for case number %s. Hence new reimbursement request will not be accepted. | +| `PAYR-1343` | Previous reimbursement approved record found for the new reimbursement request for case number %s. Hence request will not be processed further. | +| `PAYR-1344` | No details found for the requested procedures in the system. | +| `PAYR-1345` | Invalid procedure status received as %s for procedure %s for case number %s. Please try again with valid data. | +| `PAYR-1346` | Invalid procedure description received as %s for procedure %s for case number %s. Please try again with valid data. | +| `PAYR-1347` | Invalid procedure type received as %s for procedure %s for case number %s. Please try again with valid data. | +| `PAYR-1348` | Invalid procedure factor received as %s for procedure %s for case number %s. Please try again with valid data. | +| `PAYR-1349` | Invalid procedure quantity received as %s for procedure %s for case number %s. Please try again with valid data. | +| `PAYR-1350` | Invalid procedure net amount received as INR %s for procedure %s for case number %s. Please try again with valid data. | +| `PAYR-1351` | Invalid speciality code received as %s for procedure %s for case number %s. Please try again with valid data. | +| `PAYR-1352` | Requested beneficary details and careplan details does not match any criteria for processing the case at this hospital. Please try again with valid data. | +| `PAYR-1353` | Invalid careplan id received. Please try again with valid careplan id. | +| `PAYR-1354` | Rule failure. | +| `PAYR-1355` | No details found for the requested implants in the system. Hence request will not be processed. | +| `PAYR-1356` | Patient liability is not aplicable for the hospital and beneficiary do not have enough wallet balance with deficit amount INR %s for the requested preauthorization for case number %s. | +| `PAYR-1357` | Admission date cannot be after the discharge date. Hence request will not be processed. Please correct the data and try again. | +| `PAYR-1358` | Registration of the patient is allowed maximum upto %s days after admission. Hence request will not be processed. Please correct the data and try again. | +| `PAYR-1359` | No billable treatment plan received for case number %s. Please try again with valid treatment plan data. | +| `PAYR-1360` | Invalid item code received as %s for item sequence %s case number %s. Please try again with valid data. | +| `PAYR-1361` | Invalid item sequence received as %s for case number %s. Please try again with valid data. | +| `PAYR-1362` | No procedure with code LM100 received with 'Requested' status for case number %s. Please try again with valid data. For PMJAY claims, if case comes under LAMA/DAMA scenario with beneficiary being discharged before surgery or during surgery, procedure with code LM100 is mandatory. Only this procedure code will be accepted for LAMA/DAMA case, and all other previous preauthorization approved items will get disqualified for the claim submission | +| `PAYR-1363` | Response for Authentication Consent Questionnaire is missing for case number %s. This must be sent if the biometric authentication for patient is not available during discharge. For new claim request, either biometric authentication for patient during discharge, or response for Authentication Consent questionnaire must be sent. Please check/update the insurance plan for the policy for the details of the questionnaire. | +| `PAYR-1364` | No value received for link id %s for Authentication Consent Questionnaire for claim request. This must be sent if the biometric authentication for patient is not available during discharge. For new claim request, either biometric authentication for patient during discharge, or response for Authentication Consent questionnaire must be sent. Please check/update the insurance plan for the policy for the details of the questionnaire. | +| `PAYR-1365` | Response for STG Questionnaire id %s is mandatory for procedure code %s. Hence the preauthorization request will not be processed as the questionnaire response is not received for procedure code. | +| `PAYR-1366` | Invalid biometric user token received. Please try again with valid biometric details of the beneficiary. For any issues with biometric, please try with Authentication Consent Questionnaire for discharge, details for which has been received in insurance plan. | +| `PAYR-1367` | No biometric records found for the beneficiary for %s. Please ensure correctness of biometric authentication date for the day for cyclic procedure %s. | +| `PAYR-1368` | %s units of cycle information received for procedure code %s with item sequence %s. Cycle information should be sent for all the requested/processed cycles. | +| `PAYR-1369` | Biometric authentication cannot be performed more than once on the same date. Multiple biometric authentication information has been provided for same date for cyclic procedure %s. Hence case will not be processed. Please check and update biometric authentication execution dates and try again. | +| `PAYR-1370` | Received invalid start date as %s for supporting details with item sequence %s. Please try again with valid start date. | + +## Reference payer: plan and scheme rules, `PAYR-14xx` and above +| Code | Message | +| :---- | :---- | +| `PAYR-1401` | <policy_code> policy not allowed for the hospital. Please reach out to technical support team. | +| `PAYR-1402` | Requested policy <policy_code> found not be associated with any payer for insurance plan request. Hence request will not be processed. | +| `PAYR-1403` | Requested renewal <renewal_code> found not be associated with requested policy <policy_code> for insurance plan request. Hence request will not be processed. | +| `PAYR-1404` | No treatment provided for policy <policy_code> under any speciality. Please reach out to technical support team. | +| `PAYR-1405` | No enrolled hospital found for HFR id <hfr_id> or sender id <sender_code>. Please reach out to technical support team. | +| `PAYR-1406` | Existing request with correlation id %s is in progress with the payer. Hence this request will not be accepted until the execution for previous request is complete. Please wait for 15 - 60 minutes to allow the execution of previous requests. For further assistance, please reach out to technical support team. | +| `PAYR-1501` | Value type received as %s for category - ONS and code - PSP for item with sequence %s in supporting info in claim resource. In supporting info list, item with category - ONS and code - PSP combination is used to get the surgery date. So the surgery date should be sent as timing (date or period) or as a string value, adhering to the NRCES standards, with the category - ONS and code - PSP. | +| `PAYR-1502` | Value type received as %s for category - ONS and code - ADDD for item with sequence %s in supporting info in claim resource. In supporting info list, item with category - ONS and code - ADDD combination is used to get the admission date. So the admission date should be sent as timing (date or period) or as a string value, adhering to the NRCES standards, with the category - ONS and code - ADDD. | +| `PAYR-1503` | Value type received as %s for category - ONS and code - DTM for item with sequence %s in supporting info in claim resource. In supporting info list, item with category - ONS and code - DTM combination is used to get the death date. So the death date should be sent as timing (date or period) or as a string value, adhering to the NRCES standards, with the category - ONS and code - DTM. | +| `PAYR-1504` | Value type received as %s for category - NMI and code - CQD for item with sequence %s in supporting info in claim resource. In supporting info list, item with category - NMI and code - CQD combination is used to get the overall case remarks for query response. So the case remarks for query response should be sent as a string value, adhering to the NRCES standards, with the category - NMI and code - CQD. | +| `PAYR-1505` | Category received as %s and code received as %s for item with sequence %s in supporting info in claim resource, where the reference value redirects to Questionnaire Response resource in the FHIR bundle. To include a policy/case level Questionnaire Response, in supporting info list there should be an entry with category - INF and code - ODN , and the value as reference. This reference value should refer to a resource of Questionnaire Response in the FHIR bundle. To include response for any STG questionnaire, in supporting info list there should be an entry with category - STG, and the value as reference | +| `PAYR-1506` | Invalid gender received for new born patient. Please try agian with valid gender data as it is mandatory for PMJAY in new born case. Please refer to the valid gender values at https://hl7.org/fhir/R4/valueset-administrative-gender.html | +| `PAYR-1507` | Invalid date of birth received for new born patient. Please try agian with valid date of birth as it is mandatory for PMJAY in new born case. | +| `PAYR-1508` | Invalid resource received for new born patient for url %s. Please try agian with valid Patient resource for the link reference as linked Patient resource is mandatory for PMJAY in new born case | +| `PAYR-1509` | Invalid attachment received for new born patient. Please try agian with valid attachment as attachment is mandatory for PMJAY in new born case | +| `PAYR-1510` | Invalid parameter code received. Please check and try again with a valid parameter code | +| `PAYR-1511` | Invalid parameter value received. Please check and try again with a valid parameter value | +| `PAYR-1512` | Invalid resource received for patient for url %s. Please try agian with valid Patient resource for the reference | +| `PAYR-1513` | Invalid diagnosis received in DiagnosisComponent. In DiagnosisComponent, diagnosis should be sent as CodeableConcept. Please try agian with valid data | +| `PAYR-1514` | Value type received as %s for category - DIS for item with sequence %s in supporting info in claim resource. In supporting info list, item with category - DIS is used to get the discharge related information. So the discharge information should be sent as string value, with value representing discharge stage (After Surgery / Before Surgery / During Surgery), with the category - DIS and code - DTH/LAMA/DAMA/DTM | +| `PAYR-1515` | Invalid name received for organization resource with url %s. Name is mandatory for organization resource. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html | +| `PAYR-1516` | No event found for api-caller-id %s and correlation id %s for sender code %s. Hence error response willnot be accepted. | +| `PAYR-1517` | Invalid error structure received for NHCX error. Protocol response structure is expected, but received JWEPayloadResponse. | +| `PAYR-1518` | No input parameters received for task resource. Input parameters are expected for task resource, but not received. Please try again with valid data. | +| `PAYR-1519` | No type found for task input parameters. Hence request will not be processed further. Please refer to https://www.nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html | +| `PAYR-1520` | Invalid resource received for communication for url %s. Please try agian with valid Communication resource for the reference. | + +## What the live payer sent that the sheets do not say + +The SHA HP sandbox run recorded in PMJAY Sandbox Run met three codes whose +live message is not the one in the tables above. The tables keep the sheet's +message; the live one is here. + +| Code | The sheet says | The sandbox sent | What it meant | +| :---- | :---- | :---- | :---- | +| `PAYR-1245` | Rule failure. | Only one conservative procedure can be booked for a case | An enhancement added a second `Conservative` package | +| `PAYR-1322` | No active case found for the given case number. | Active instance found for case number | A second request on a case while the first was still queued | +| `ERR-PYR-CLM-007` | On no sheet | No prior preauthorization or claim record found for case number | The claim went out under a number of its own, not the preauthorisation's | + +`PAYR-1322` is the one to watch: the sheet and the live message point opposite +ways. Act on the live reading and wait for the open request to be decided. +`PAYR-1245` is one of three codes the sheet gives only as "Rule failure", with +`PAYR-1111` and `PAYR-1354`, and the live message names the rule. None of the +live messages is published; confirm them with the payer before you key logic +on them. + +## Denial codes are a separate thing again + +A refusal stops a message. A denial decides a case. The denial families, +`ClaimError-1` to `ClaimError-28` and `PreauthError-1` to `PreauthError-15` +with no 14 defined, arrive inside an adjudicated `ClaimResponse` and are the +adjudicator's reason, not a fault in what you sent. They belong on the appeal +screen. Codes and Value Sets in the FHIR Reference lists them. + +## Which desk gets which + +| Family | Who acts | +| :---- | :---- | +| `NHCX-` | The integration team. The message did not arrive | +| `PAYR-10xx` | The integration team. Structural | +| `ERR-PYR-CLM-007` | The integration team. The claim was sent under the wrong case number | +| `PAYR-11xx` to `PAYR-14xx` | Read the message. Some name a field, some name a policy fact. The band alone does not decide | +| Standard `PAYR-1001` to `PAYR-1020` | The claims desk, in the payer's own words | +| `ClaimError-`, `PreauthError-` | The claims desk, on the appeal screen | + +Show the payer's sentence verbatim in every case. The reference payer's +messages already name the field, the code or the case number, and a system that +rewrites them into a generic failure throws away the only diagnosis available. diff --git a/site/docs/nhcx/v1/reference/fhir/_category_.json b/site/docs/nhcx/v1/reference/fhir/_category_.json new file mode 100644 index 000000000..2107dc6b3 --- /dev/null +++ b/site/docs/nhcx/v1/reference/fhir/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "FHIR bundles", + "position": 30 +} diff --git a/site/docs/nhcx/v1/reference/fhir/cancel-reprocess-and-shortfall.md b/site/docs/nhcx/v1/reference/fhir/cancel-reprocess-and-shortfall.md new file mode 100644 index 000000000..2e0a01395 --- /dev/null +++ b/site/docs/nhcx/v1/reference/fhir/cancel-reprocess-and-shortfall.md @@ -0,0 +1,594 @@ +--- +title: Cancel, reprocess and shortfall +sidebar_label: Cancel, reprocess and shortfall +sidebar_position: 15 +description: Task-based cancel (`cancel`), reprocess (`reprocess`), balance release (`release`) and `nullify` +verification: unverified +source: nhcx-package/docs/05-FHIR Reference/15-Cancel, Reprocess and Shortfall.md +generated: true +--- + +# Cancel, reprocess and shortfall + +The post-decision exchanges. All are `Task` bundles on `/v1/task/submit`, answered on `/v1/task/on_submit`, and `Task.code` with its reason is the only thing that tells them apart. + +## Cancel + +Sent on `/v1/task/submit`, workflow PC01. + +### The bundle + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `Task` | [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html) | +| 2 | `Organization (prov)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 3 | `Organization (pay)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | + +### Elements + +#### 1. Task + +NRCeS profile: [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html). + +| Element | Example | +| :-- | :-- | +| `status` | `requested` | +| `intent` | `order` | +| `code.coding[]` | `cancel` in `http://terminology.hl7.org/CodeSystem/financialtaskcode` | +| `authoredOn` | `2026-09-10T23:52:03+05:30` | +| `requester` | reference `https://nhcx.abdm.gov.in/provider` | +| `owner` | reference `https://nhcx.abdm.gov.in/payer` | +| `description` | `Treatment plan changed; withdrawn.` | +| `reasonCode.coding[]` | `treatmentplanchanged` Treatment plan changed during hospitalization in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-reason-code` | +| `input[]` | valueString `NM-26-0SE00002I` | +| `input[].type.coding[]` | `claimNumber` ClaimNumber in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code` | +| | `intimationNumber` Intimation Number in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code` | + +#### 2. Organization (prov) + +NRCeS profile: [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system `https://nhcx.abdm.gov.in`, value `IN1910000151` | +| `identifier[].type.coding[]` | `NPI` National provider identifier in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `type[].coding[]` | `prov` Healthcare Provider in `http://terminology.hl7.org/CodeSystem/organization-type` | +| `name` | `KyroCare Multispeciality Hospital` | + +#### 3. Organization (pay) + +NRCeS profile: [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system `https://nhcx.abdm.gov.in`, value `1000004805` | +| `identifier[].type.coding[]` | `NIIP` National Insurance Payor Identifier (Payor) in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `type[].coding[]` | `pay` Payer in `http://terminology.hl7.org/CodeSystem/organization-type` | +| `name` | `Sandbox Payer` | + +## Reprocess + +Sent on `/v1/task/submit`, workflow 36. + +### The bundle + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `Task` | [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html) | +| 2 | `Organization (prov)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 3 | `Organization (pay)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | + +### Elements + +#### 1. Task + +NRCeS profile: [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html). + +| Element | Example | +| :-- | :-- | +| `status` | `requested` | +| `intent` | `order` | +| `code.coding[]` | `reprocess` in `http://terminology.hl7.org/CodeSystem/financialtaskcode` | +| `authoredOn` | `2026-09-10T23:53:27+05:30` | +| `requester` | reference `https://nhcx.abdm.gov.in/provider` | +| `owner` | reference `https://nhcx.abdm.gov.in/payer` | +| `description` | `Package rate revised; please reassess the approved amount.` | +| `reasonCode.coding[]` | `claimrejected` Reprocess request due to claim rejected by payer in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-reason-code` | +| `basedOn[]` | display `Claim NM-26-0SE00002L` | +| `basedOn[].identifier` | system `https://nhcx.abdm.gov.in`, value `NM-26-0SE00002L` | +| `basedOn[].identifier.type.coding[]` | `CLN` Claim number in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| `input[]` | valueString `NM-26-0SE00002L` | +| `input[].type.coding[]` | `claimNumber` ClaimNumber in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code` | +| | `intimationNumber` Intimation Number in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code` | +| `for.identifier` | value `MRAV1985001` | +| `for.identifier.type.coding[]` | `MB` Member Number in `http://terminology.hl7.org/CodeSystem/v2-0203` | + +#### 2. Organization (prov) + +NRCeS profile: [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system `https://nhcx.abdm.gov.in`, value `IN1910000151` | +| `identifier[].type.coding[]` | `NPI` National provider identifier in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `type[].coding[]` | `prov` Healthcare Provider in `http://terminology.hl7.org/CodeSystem/organization-type` | +| `name` | `KyroCare Multispeciality Hospital` | + +#### 3. Organization (pay) + +NRCeS profile: [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system `https://nhcx.abdm.gov.in`, value `1000004805` | +| `identifier[].type.coding[]` | `NIIP` National Insurance Payor Identifier (Payor) in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `type[].coding[]` | `pay` Payer in `http://terminology.hl7.org/CodeSystem/organization-type` | +| `name` | `Sandbox Payer` | + +## Release + +Sent on `/v1/task/submit`. + +### The bundle + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `Task` | [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html) | +| 2 | `Organization (prov)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 3 | `Organization (pay)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | + +### Elements + +#### 1. Task + +NRCeS profile: [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html). + +| Element | Example | +| :-- | :-- | +| `status` | `requested` | +| `intent` | `order` | +| `code.coding[]` | `release` in `http://terminology.hl7.org/CodeSystem/financialtaskcode` | +| `description` | `Release the balance amount for claim EO26AA2700001` | +| `authoredOn` | `2026-03-05T11:20:00+05:30` | +| `requester` | reference `https://nhcx.abdm.gov.in/provider` | +| `owner` | reference `https://nhcx.abdm.gov.in/payer` | +| `reasonCode.coding[]` | `partialpayment` Reprocess request due to partial payment by payer in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-reason-code` | +| `basedOn[]` | display `Claim EO26AA2700001` | +| `basedOn[].identifier` | system `https://nhcx.abdm.gov.in`, value `EO26AA2700001` | +| `basedOn[].identifier.type.coding[]` | `CLN` Claim number in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| `input[]` | valueString `EO26AA2700001` | +| `input[].type.coding[]` | `claimNumber` ClaimNumber in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code` | +| | `amount` Amount in `https://nhcx.abdm.gov.in/task-input-type` | +| `input[].valueMoney` | value `1650`, currency `INR` | + +#### 2. Organization (prov) + +NRCeS profile: [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system `https://nhcx.abdm.gov.in`, value `IN1910000151` | +| `identifier[].type.coding[]` | `NPI` National provider identifier in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `type[].coding[]` | `prov` Healthcare Provider in `http://terminology.hl7.org/CodeSystem/organization-type` | +| `name` | `Facility Name` | + +#### 3. Organization (pay) + +NRCeS profile: [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system `https://nhcx.abdm.gov.in`, value `1518` | +| `identifier[].type.coding[]` | `NIIP` National Insurance Payor Identifier (Payor) in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `type[].coding[]` | `pay` Payer in `http://terminology.hl7.org/CodeSystem/organization-type` | +| `name` | `Insurance Company` | + +## Cancellation done + +Sent on `/v1/task/on_submit`, workflow PC02. + +### The bundle + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `Task` | none declared; NRCeS [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html) | +| 2 | `ClaimResponse` | none declared; NRCeS [ClaimResponse](https://nrces.in/ndhm/fhir/r4/StructureDefinition-ClaimResponse.html) | +| 3 | `Patient` | none declared; NRCeS [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html) | +| 4 | `Organization (pay)` | none declared; NRCeS [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 5 | `Organization (prov)` | none declared; NRCeS [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 6 | `Coverage` | none declared; NRCeS [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html) | + +### Elements + +#### 1. Task + +NRCeS profile: [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html). + +| Element | Example | +| :-- | :-- | +| `status` | `completed` | +| `intent` | `order` | +| `code.coding[]` | `approve` Activate/approve the focal resource in `http://hl7.org/fhir/CodeSystem/task-code` | +| `description` | `Pre-authorisation withdrawn by 1000003463@hcx: Treatment plan changed; withdraw…` | +| `authoredOn` | `2026-09-10T23:52:05+05:30` | +| `requester` | reference `` | +| `owner` | reference `` | +| `output[].type.coding[]` | `include` Include in `http://terminology.hl7.org/CodeSystem/financialtaskinputtype` | +| `output[].valueReference` | reference `` | + +#### 2. ClaimResponse + +NRCeS profile: [ClaimResponse](https://nrces.in/ndhm/fhir/r4/StructureDefinition-ClaimResponse.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system ``, value `NM-26-0SE00002I` | +| `identifier[].type.coding[]` | `CLN` Claim number in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| `status` | `active` | +| `type.coding[]` | `737481003` Inpatient care management (procedure) in `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-claim-type` | +| `use` | `preauthorization` | +| `patient` | reference `` | +| `created` | `2026-09-10T23:52:05+05:30` | +| `insurer` | reference `` | +| `requestor` | reference `` | +| `outcome` | `complete` | +| `disposition` | `Pre-authorisation withdrawn by 1000003463@hcx: Treatment plan changed; withdraw…` | +| `payeeType.coding[]` | `provider` Provider in `http://terminology.hl7.org/CodeSystem/payeetype` | +| `adjudication[].category.coding[]` | `status` Status | +| `adjudication[].reason.coding[]` | `cancelled` Cancelled | +| `total[].category.coding[]` | `benefit` Benefit Amount in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| | `submitted` Submitted Amount in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| `total[].amount` | value `150000` | + +The `Patient`, `Organization`, `Coverage` entries are shaped as in the chapters that introduce them. + +## Reprocess acknowledged + +Sent on `/v1/task/on_submit`, workflow 37. + +### The bundle + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `Task` | none declared; NRCeS [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html) | +| 2 | `ClaimResponse` | none declared; NRCeS [ClaimResponse](https://nrces.in/ndhm/fhir/r4/StructureDefinition-ClaimResponse.html) | +| 3 | `Patient` | none declared; NRCeS [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html) | +| 4 | `Organization (pay)` | none declared; NRCeS [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 5 | `Organization (prov)` | none declared; NRCeS [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 6 | `Coverage` | none declared; NRCeS [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html) | + +### Elements + +#### 1. Task + +NRCeS profile: [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html). + +| Element | Example | +| :-- | :-- | +| `status` | `accepted` | +| `intent` | `order` | +| `code.coding[]` | `approve` Activate/approve the focal resource in `http://hl7.org/fhir/CodeSystem/task-code` | +| `description` | `Claim reopened for reprocessing (round 1) at the request of 1000003463@hcx: Pac…` | +| `authoredOn` | `2026-09-10T23:53:28+05:30` | +| `requester` | reference `` | +| `owner` | reference `` | +| `output[].type.coding[]` | `include` Include in `http://terminology.hl7.org/CodeSystem/financialtaskinputtype` | +| `output[].valueReference` | reference `` | + +#### 2. ClaimResponse + +NRCeS profile: [ClaimResponse](https://nrces.in/ndhm/fhir/r4/StructureDefinition-ClaimResponse.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system ``, value `NM-26-0SE00002L` | +| `identifier[].type.coding[]` | `CLN` Claim number in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| `status` | `active` | +| `type.coding[]` | `737481003` Inpatient care management (procedure) in `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-claim-type` | +| `use` | `claim` | +| `patient` | reference `` | +| `created` | `2026-09-10T23:53:28+05:30` | +| `insurer` | reference `` | +| `requestor` | reference `` | +| `outcome` | `queued` | +| `disposition` | `Claim reopened for reprocessing (round 1) at the request of 1000003463@hcx: Pac…` | +| `payeeType.coding[]` | `provider` Provider in `http://terminology.hl7.org/CodeSystem/payeetype` | +| `adjudication[].category.coding[]` | `status` Status | +| `adjudication[].reason.coding[]` | `submitted` Submitted | +| `total[].category.coding[]` | `benefit` Benefit Amount in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| | `submitted` Submitted Amount in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| `total[].amount` | value `0` | +| | value `150000` | + +The `Patient`, `Organization`, `Coverage` entries are shaped as in the chapters that introduce them. + +## Rules + +### 1. Cancel + +`Task.code` `cancel`, a reason from `ndhm-reason-code` (`treatmentplanchanged`, `patientrequest`, `financialconstraints`, `alternativetreatment`, `duplicateclaim`, `administrativeerror`, `other`), and the inputs `claimNumber` and `intimationNumber`. + +### 2. Reprocess + +`Task.code` `reprocess`, reason `claimrejected` for a rejected claim or `partialpayment` for one paid short, `basedOn` naming the claim by its `CLN` identifier, `for` the member, and the inputs `claimNumber` and `intimationNumber`, spelled so. + +### 3. Release + +`Task.code` `release`, reason `partialpayment`, with the claim number and the amount sought as a `valueMoney` input. + +### 4. Nullify + +The Reprocess sheet of the requests-and-responses workbook gives `Task.code` on `/v1/task/submit` as `reprocess`, `cancel`, `release` or `nullify`, as the use case needs, each with a `ClaimNumber` input carrying the claim number and `Task.status` `requested`; the answer is a `Task` whose output is the `ClaimResponse`. The provider sandbox exit checklist names the same four codes. The value sets describe `nullify` as closing a claim the provider submitted. No sample bundle, reason code or workflow code is published for it. + +### 5. Suspend + +`suspend` appears only as a code. The value sets list it, glossed "suspend the preauthorization or claim that was submitted by provider", beside the task output `claimsuspended`. No exchange carries it: no request shape, answer or workflow code is published. + +### 6. The answer + +A `Task` whose `output` of type `include` references a `ClaimResponse` in the same bundle. Read the result from that `ClaimResponse`'s adjudication reason, not from `outcome` and not from `Task.code`. A cancellation is `completed` with reason `cancelled`; a reprocess is `accepted` with the `ClaimResponse` `queued`, and the new verdict follows on the claim's own thread. + +### 7. Switch on system and code together + +The Task code systems differ between request and response. + +### 8. A cancelled case still reports money + +Zero the figure yourself once the reason reads `cancelled`. + +## PMJAY + +The generic bundle above is what every payer takes, IRDAI-regulated insurers and TPAs included. PMJAY takes it with the changes and requirements below. + +### What changes in the bundle + +#### Cancel + +The PMJAY bundle has the same resources, elements and systems as the generic one. + +#### Reprocess + +##### Elements PMJAY adds + +| Element | Example | +| :-- | :-- | +| `Task.input[].valueAttachment` | contentType `application/pdf`, title `Medical Superintendent Declaration Form (During Admission)` | + +##### Systems PMJAY binds differently + +| Element | Generic | PMJAY | +| :-- | :-- | :-- | +| `Task.for.identifier.type.coding[]` | `http://terminology.hl7.org/CodeSystem/v2-0203` | `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | + +### What PMJAY specifies + +- A shortfall is the reprocess `Task` with reason `partialpayment` and an amount capped at the difference. +- The reprocess carries the supporting document as a `document` input with a `valueAttachment`, and names the member by the `PMJAY` identifier. +- The reprocess is acknowledged on 37; the new verdict then arrives on the claim's own thread. + +### What PMJAY requires + +- Cancel is allowed until the claim is raised, and refused once payment has been initiated (`PAYR-1257`). +- Reprocess once, the moment the rejection arrives, with a supporting document. The Claim Review Committee is final. +- Shortfall only after payment notice 33 has arrived and been acknowledged on 17, once, and never after a reprocess. +- A `Task` coded `status` is not taken (`PAYR-1018`, `PAYR-1008`). Read where a case stands from the payer service instead. + +## Use cases, APIs and data elements + +### B8 Reprocess or cancel (provider) + +One endpoint, several jobs, told apart by the Task's code and reason: reprocess with claimrejected, shortfall with partialpayment, cancel. A reprocess goes on 36 and is acknowledged on 37; a cancel goes on PC01 and is done on PC02. Both carry the input intimationNumber. A supporting document is mandatory on a reprocess. + +| | | +| :-- | :-- | +| **API** | `/v1/task/submit` [`apis/13-other/v1-task-submit.bru`](/docs/nhcx/v1/api/other/endpoints/other-v1-task-submit) | +| **Callback** | `/v1/task/on_submit` [`apis/13-other/v1-task-on-submit.bru`](/docs/nhcx/v1/api/other/endpoints/other-v1-task-on-submit) | +| **Workflow** | PC01 cancel, 36 reprocess or shortfall | +| **Carries JWE** | yes | +| **Focal resource** | `Task` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `x-hcx-sender_code` | `1000004446@hcx` | +| `x-hcx-recipient_code` | `1518@hcx` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-request_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{$guid}}` | +| `x-hcx-workflow_id` | `PC01` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `request.initiated` | +| `x-hcx-ben-abha-id` | `91711234567890` | + +**Workflow codes** + +| Code | Name | Authored by | `x-hcx-status` | Means | +| :-- | :-- | :-- | :-- | :-- | +| `PC01` | Preauth Cancel Initiated | provider | `request.initiated` | Cancel an existing preauth | +| `36` | Claim Arbitration Request Submitted | provider | `request.initiated` | Reprocess/Erroneous request, with input intimationNumber; acknowledged on 37 | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `taskCode` | Action Code | Task | `code` | `1..1` | `Task.code.coding[0].code` | `reprocess` | | +| `taskReason` | Appeal Reason Code | Task | `code` | `1..1` | `Task.reasonCode.coding[0].code` | `claimrejected` | | +| `originalCaseNumber` | Original Case Number | Task Input | `string` | `1..1` | `Task.input[0].valueString` | `CL0000000001` | | +| `appealDocument` | Dispute Justification Document | Task Input | `base64Binary` | `1..1` | `Task.input[category=document].valueAttachment.data` | `JVBERi0xLjQK...` | | + +NRCeS profiles: [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html). + +### D8 Cancel pre-authorisation (pmjay) + +A Task with code cancel, the case number as input and one of seven reasons: treatmentplanchanged, patientrequest, financialconstraints, alternativetreatment, duplicateclaim, administrativeerror, other. Allowed at any point until the claim is raised. + +| | | +| :-- | :-- | +| **API** | `/v1/task/submit` [`apis/13-other/v1-task-submit.bru`](/docs/nhcx/v1/api/other/endpoints/other-v1-task-submit) | +| **Callback** | `/v1/task/on_submit` [`apis/13-other/v1-task-on-submit.bru`](/docs/nhcx/v1/api/other/endpoints/other-v1-task-on-submit) | +| **Workflow** | PC01 | +| **Carries JWE** | yes | +| **Focal resource** | `Task` | +| **Simulator console** | `/builder?family=preauth&usecase=cancel` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `x-hcx-sender_code` | `1000004446@hcx` | +| `x-hcx-recipient_code` | `1518@hcx` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-request_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{$guid}}` | +| `x-hcx-workflow_id` | `PC01` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `request.initiated` | +| `x-hcx-ben-abha-id` | `91711234567890` | + +**Workflow codes** + +| Code | Name | Authored by | `x-hcx-status` | Means | +| :-- | :-- | :-- | :-- | :-- | +| `PC01` | Preauth Cancel Initiated | provider | `request.initiated` | Cancel an existing preauth | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `taskCode` | Action Code | Task | `code` | `1..1` | `Task.code.coding[0].code` | `cancel` | | +| `caseNumber` | Pre-auth Case Number | Task Input | `string` | `1..1` | `Task.input[0].valueString` | `VB26AA2600001` | | + +NRCeS profiles: [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html). + +### D11 Reprocess a rejected claim (pmjay) + +An appeal, not a resubmission: a Task with code reprocess and reason claimrejected, a supporting document attached, no amount. Raise it the moment the rejection arrives. Once only; the Claim Review Committee is final. + +| | | +| :-- | :-- | +| **API** | `/v1/task/submit` [`apis/13-other/v1-task-submit.bru`](/docs/nhcx/v1/api/other/endpoints/other-v1-task-submit) | +| **Callback** | `/v1/task/on_submit` [`apis/13-other/v1-task-on-submit.bru`](/docs/nhcx/v1/api/other/endpoints/other-v1-task-on-submit) | +| **Workflow** | 36 | +| **Carries JWE** | yes | +| **Focal resource** | `Task` | +| **Simulator console** | `/builder?family=claim&usecase=reprocess` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `x-hcx-sender_code` | `1000004446@hcx` | +| `x-hcx-recipient_code` | `1518@hcx` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-request_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{$guid}}` | +| `x-hcx-workflow_id` | `36` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `request.initiated` | +| `x-hcx-ben-abha-id` | `91711234567890` | + +**Workflow codes** + +| Code | Name | Authored by | `x-hcx-status` | Means | +| :-- | :-- | :-- | :-- | :-- | +| `36` | Claim Arbitration Request Submitted | provider | `request.initiated` | Reprocess/Erroneous request, with input intimationNumber; acknowledged on 37 | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `taskCode` | Task Code | Task | `code` | `1..1` | `Task.code.coding[0].code` | `reprocess` | | +| `taskReason` | Dispute Reason | Task | `code` | `1..1` | `Task.reasonCode.coding[0].code` | `claimrejected` | | +| `claimNumber` | Rejected Claim ID | Task Input | `string` | `1..1` | `Task.input[0].valueString` | `CL26AA2600001` | | + +NRCeS profiles: [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html). + +### D12 Claim a shortfall (pmjay) + +The same Task with reason partialpayment and an amount capped at the difference, allowed only after payment notice 33 has arrived and been acknowledged with 17. Once only, and never after a reprocess. + +| | | +| :-- | :-- | +| **API** | `/v1/task/submit` [`apis/13-other/v1-task-submit.bru`](/docs/nhcx/v1/api/other/endpoints/other-v1-task-submit) | +| **Callback** | `/v1/task/on_submit` [`apis/13-other/v1-task-on-submit.bru`](/docs/nhcx/v1/api/other/endpoints/other-v1-task-on-submit) | +| **Workflow** | 36 | +| **Carries JWE** | yes | +| **Focal resource** | `Task` | +| **Simulator console** | `/builder?family=claim&usecase=shortfall` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `x-hcx-sender_code` | `1000004446@hcx` | +| `x-hcx-recipient_code` | `1518@hcx` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-request_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{$guid}}` | +| `x-hcx-workflow_id` | `36` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `request.initiated` | +| `x-hcx-ben-abha-id` | `91711234567890` | + +**Workflow codes** + +| Code | Name | Authored by | `x-hcx-status` | Means | +| :-- | :-- | :-- | :-- | :-- | +| `36` | Claim Arbitration Request Submitted | provider | `request.initiated` | Reprocess/Erroneous request, with input intimationNumber; acknowledged on 37 | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `taskCode` | Task Code | Task | `code` | `1..1` | `Task.code.coding[0].code` | `reprocess` | | +| `taskReason` | Reason Code | Task | `code` | `1..1` | `Task.reasonCode.coding[0].code` | `partialpayment` | | +| `claimNumber` | Partially Paid Claim ID | Task Input | `string` | `1..1` | `Task.input[0].valueString` | `CL26AA2600001` | | + +NRCeS profiles: [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html). + +### C10 Respond to a Task (payer) + +The answer to a reprocess, shortfall or cancel. A cancellation done is PC02 and carries the case's ClaimResponse in its output; a reprocess on 36 is acknowledged on 37 as arbitration. Both payers answer this way. + +| | | +| :-- | :-- | +| **API** | `/v1/task/on_submit` [`apis/13-other/v1-task-on-submit.bru`](/docs/nhcx/v1/api/other/endpoints/other-v1-task-on-submit) | +| **Callback** | `/v1/task/submit` [`apis/13-other/v1-task-submit.bru`](/docs/nhcx/v1/api/other/endpoints/other-v1-task-submit) | +| **Workflow** | 251 acknowledged, 252 approved, 253 rejected, 254 queried, PC02 cancelled, 37 arbitration acknowledged | +| **Carries JWE** | yes | +| **Focal resource** | `Task` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `x-hcx-sender_code` | `1518@hcx` | +| `x-hcx-recipient_code` | `1000004446@hcx` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-request_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{$guid}}` | +| `x-hcx-workflow_id` | `252` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `response.complete` | +| `x-hcx-ben-abha-id` | `91711234567890` | + +**Workflow codes** + +| Code | Name | Authored by | `x-hcx-status` | Means | +| :-- | :-- | :-- | :-- | :-- | +| `251` | Reprocess Request Received | payer | `response.complete` | Reprocess request received | +| `252` | Reprocess Request Approved | payer | `response.complete` | Reprocess request approved | +| `253` | Reprocess Request Rejected | payer | `response.complete` | Reprocess request rejected | +| `254` | Reprocess Request Queried | payer | `request.initiated` | Reprocess request queried | +| `PC02` | Preauthorization Cancellation Accomplished | status sheet only | `response.complete` | | +| `37` | Claim Arbitration Acknowledgement | status sheet only | `response.complete` | | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `taskStatus` | Task Status | Task | `code` | `1..1` | `Task.status` | `completed` | | +| `outputDecision` | Decision Reference | Task Output | `reference` | `0..1` | `Task.output[0].valueReference.reference` | `ClaimResponse/cr-reprocess-approved` | | + +NRCeS profiles: [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html). diff --git a/site/docs/nhcx/v1/reference/fhir/claim-query-and-answer.md b/site/docs/nhcx/v1/reference/fhir/claim-query-and-answer.md new file mode 100644 index 000000000..66af70757 --- /dev/null +++ b/site/docs/nhcx/v1/reference/fhir/claim-query-and-answer.md @@ -0,0 +1,445 @@ +--- +title: Claim query and answer +sidebar_label: Claim query and answer +sidebar_position: 14 +description: Claim query updates (wf 27 / 151) +verification: unverified +source: nhcx-package/docs/05-FHIR Reference/14-Claim Query and Answer.md +generated: true +--- + +# Claim query and answer + +The payer asking for something before it adjudicates a claim. A private insurer asks through a communication; PMJAY asks in the claim response and takes the whole claim back as the answer. + +## The query + +Sent on `/v1/communication/request`, workflow 27. + +### The bundle + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `Task` | [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html) | +| 2 | `CommunicationRequest` | [CommunicationRequest](https://nrces.in/ndhm/fhir/r4/StructureDefinition-CommunicationRequest.html) | +| 3 | `Claim` | [Claim](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Claim.html) | +| 4 | `Patient` | [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html) | +| 5 | `Organization (ins)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 6 | `Organization (prov)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 7 | `Practitioner` | [Practitioner](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Practitioner.html) | +| 8 | `Coverage` | [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html) | + +### Elements + +#### 1. Task + +NRCeS profile: [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html). + +| Element | Example | +| :-- | :-- | +| `status` | `requested` | +| `intent` | `order` | +| `reasonCode.coding[]` | `additionalinfo` Additional Information Request in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-reason-code` | +| `code.coding[]` | `poll` in `http://terminology.hl7.org/CodeSystem/financialtaskcode` | +| `description` | `Share the final bill breakup and the discharge summary.` | +| `authoredOn` | `2026-09-10T23:52:39+05:30` | +| `requester` | reference `urn:uuid:39cd4b51-bddd-5cc1-a65a-6fa4a2a83cb5`, display `Organization` | +| `owner` | reference `urn:uuid:84d112ec-041c-57f8-986c-6619ccd8245e`, display `Organization` | +| `input[].type.coding[]` | `include` in `http://terminology.hl7.org/CodeSystem/financialtaskinputtype` | +| `input[].valueReference` | reference `urn:uuid:e6c95fe2-3bd5-5c9f-bf78-47959029cfe2`, display `CommunicationRequest` | + +#### 2. CommunicationRequest + +NRCeS profile: [CommunicationRequest](https://nrces.in/ndhm/fhir/r4/StructureDefinition-CommunicationRequest.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | value `NM-26-0SE00002K` | +| `basedOn[]` | reference `urn:uuid:5c997608-ee6c-5496-9fdb-f8415e3eb8d5`, display `Claim-claim` | +| `status` | `active` | +| `category[].coding[]` | `alert` in `http://terminology.hl7.org/CodeSystem/communication-category` | +| `priority` | `routine` | +| `payload[]` | contentString `Share the final bill breakup and the discharge summary.` | +| `authoredOn` | `2026-09-10T23:52:39+05:30` | +| `requester` | reference `urn:uuid:39cd4b51-bddd-5cc1-a65a-6fa4a2a83cb5`, display `Organization` | +| `recipient[]` | reference `urn:uuid:84d112ec-041c-57f8-986c-6619ccd8245e`, display `Organization` | +| `sender` | reference `urn:uuid:39cd4b51-bddd-5cc1-a65a-6fa4a2a83cb5`, display `Organization` | +| `reasonCode[]` | text `Share the final bill breakup and the discharge summary.` | +| `reasonCode[].coding[]` | `additionalinfo` Additional Information Request in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-reason-code` | + +The `Claim`, `Patient`, `Organization`, `Practitioner`, `Coverage` entries are shaped as in the chapters that introduce them. + +## The answer + +Sent on `/v1/communication/on_request`, workflow 27, echoed. + +### The bundle + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `Task` | [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html) | +| 2 | `Communication` | [Communication](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Communication.html) | +| 3 | `CommunicationRequest` | [CommunicationRequest](https://nrces.in/ndhm/fhir/r4/StructureDefinition-CommunicationRequest.html) | +| 4 | `Claim` | [Claim](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Claim.html) | +| 5 | `Patient` | [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html) | +| 6 | `Organization (prov)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 7 | `Organization (pay)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 8 | `Practitioner` | [Practitioner](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Practitioner.html) | +| 9 | `Coverage` | [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html) | + +### Elements + +#### 1. Task + +NRCeS profile: [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html). + +| Element | Example | +| :-- | :-- | +| `status` | `completed` | +| `intent` | `order` | +| `code.coding[]` | `deliver` in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-codes` | +| `authoredOn` | `2026-09-10T23:52:45+05:30` | +| `requester` | reference `https://nhcx.abdm.gov.in/provider`, display `Organization` | +| `owner` | reference `https://nhcx.abdm.gov.in/payer`, display `Organization` | +| `input[].type.coding[]` | `include` in `http://terminology.hl7.org/CodeSystem/financialtaskinputtype` | +| `input[].valueReference` | reference `urn:uuid:6840ec3f-7126-4bfc-8a56-c2a2e9576d8d`, display `Communication` | +| `reasonCode.coding[]` | `additionalinfo` Additional Information Request in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-reason-code` | + +#### 2. Communication + +NRCeS profile: [Communication](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Communication.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | value `NM-26-0SE00002K` | +| `basedOn[]` | reference `urn:uuid:e6c95fe2-3bd5-5c9f-bf78-47959029cfe2`, display `CommunicationRequest` | +| `inResponseTo[]` | reference `urn:uuid:e6c95fe2-3bd5-5c9f-bf78-47959029cfe2`, display `CommunicationRequest` | +| `about[]` | reference `https://nhcx.abdm.gov.in/claim/request`, display `Claim urn:uuid:5c997608-ee6c-5496-9fdb-f8415e3eb8d5` | +| `status` | `completed` | +| `category[].coding[]` | `notification` in `http://terminology.hl7.org/CodeSystem/communication-category` | +| `priority` | `routine` | +| `recipient[]` | reference `https://nhcx.abdm.gov.in/payer`, display `Organization` | +| `sender` | reference `https://nhcx.abdm.gov.in/provider`, display `Organization` | +| `payload[]` | contentString `Final bill and discharge summary attached.` | +| `payload[].contentAttachment` | contentType `application/pdf`, title `Proof of Identity (Aadhaar / Passport / Voter ID)`, creation `2026-09-10T23:52:21+05:30` | +| | contentType `application/pdf`, title `Medical Certificate / Doctor Referral`, creation `2026-09-10T23:52:21+05:30` | +| | contentType `application/pdf`, title `Radiology / X-Ray / CT / MRI Scan Reports`, creation `2026-09-10T23:52:21+05:30` | +| | and 6 more | +| `payload[].extension[]` | url ``, valueString `POI` | +| | url ``, valueString `CER` | +| | url ``, valueString `RAD` | +| | and 6 more | + +The `CommunicationRequest`, `Claim`, `Patient`, `Organization`, `Practitioner`, `Coverage` entries are shaped as in the chapters that introduce them. + +## Rules + +### 1. The generic query + +A `Task` coded `poll`, reason `additionalinfo`, with an `include` input referencing a `CommunicationRequest` whose `basedOn` names the claim. Sent on `/v1/communication/request` under 27. + +### 2. The generic answer + +A `Task` coded `deliver` in `ndhm-task-codes`, `completed`, with an `include` input referencing a `Communication` whose `basedOn` names the request and whose `payload` carries the message and the documents. Posted on `/v1/communication/on_request`, echoing the correlation id and workflow id. + +### 3. Keep attachments on their codes + +When rebuilding a bundle to answer a query, key each attachment to its document code as you assemble it, and check the pairing before you send. + +## PMJAY + +The generic bundle above is what every payer takes, IRDAI-regulated insurers and TPAs included. PMJAY takes it with the changes and requirements below. + +### What changes in the bundle + +#### The query + +PMJAY uses a different bundle for this step, headed by `ClaimResponse` rather than `Task`. + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `ClaimResponse` | none declared; NRCeS [ClaimResponse](https://nrces.in/ndhm/fhir/r4/StructureDefinition-ClaimResponse.html) | +| 2 | `Patient` | none declared; NRCeS [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html) | +| 3 | `Organization (pay)` | none declared; NRCeS [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 4 | `Organization (prov)` | none declared; NRCeS [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 5 | `Coverage` | none declared; NRCeS [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html) | + +###### 1. ClaimResponse + +NRCeS profile: [ClaimResponse](https://nrces.in/ndhm/fhir/r4/StructureDefinition-ClaimResponse.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system `https://hcx.pmjay.gov.in/v1/preauthorization`, value `NM-26-0SF00002T` | +| `identifier[].type.coding[]` | `CLN` Claim number in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| `status` | `active` | +| `use` | `claim` | +| `patient` | reference `https://payer.nha.gov.in/claim/v1/claim/on_submit/claimresponse/patient/PMJAY00…` | +| `created` | `2026-09-11T00:04:37+05:30` | +| `insurer` | reference `https://payer.nha.gov.in/claim/v1/claim/on_submit/claimresponse/organization/pa…` | +| `requestor` | reference `https://payer.nha.gov.in/claim/v1/claim/on_submit/claimresponse/organization/pr…` | +| `outcome` | `partial` | +| `disposition` | `query` | +| `payeeType.coding[]` | `provider` Provider in `http://terminology.hl7.org/CodeSystem/payeetype` | +| `item[]` | id `Item/Item/1`, itemSequence `1` | +| `item[].adjudication[].category.coding[]` | `submitted` Submitted Amount in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| | `eligible` Eligible Amount in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| | `reason` Reason for Adjudication in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| | and 3 more | +| `item[].adjudication[].amount` | value `1800` | +| | value `2070` | +| `item[].adjudication[].reason.coding[]` | display ` : null` | +| | `Queried` Queried | +| `item[].adjudication[]` | value `100` | +| | value `0` | +| `adjudication[].category.coding[]` | `status` Status | +| `adjudication[].reason.coding[]` | `queried` Queried | +| `total[].category.coding[]` | `benefit` Benefit Amount in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| | `submitted` Submitted Amount in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| | `tax` Tax in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| | and 2 more | +| `total[].amount` | value `0` | +| | value `1800` | +| | value `2070` | +| `total[]` | id `PMJAY0000X/PMJAY-T` | + +The `Patient`, `Organization`, `Coverage` entries are shaped as in the chapters that introduce them. + +#### The answer + +PMJAY uses a different bundle for this step, headed by `Claim` rather than `Task`. + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `Claim` | [Claim](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Claim.html) | +| 2 | `Patient` | [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html) | +| 3 | `Organization (prov)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 4 | `Organization (pay)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 5 | `Coverage` | [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html) | +| 6 | `Practitioner` | [Practitioner](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Practitioner.html) | +| 7 | `Procedure` | [Procedure](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Procedure.html) | +| 8 | `QuestionnaireResponse` | `QuestionnaireResponse`, which NRCeS does not publish; base FHIR [QuestionnaireResponse](https://hl7.org/fhir/R4/questionnaireresponse.html) | +| 9 | `QuestionnaireResponse` | `QuestionnaireResponse`, which NRCeS does not publish; base FHIR [QuestionnaireResponse](https://hl7.org/fhir/R4/questionnaireresponse.html) | +| 10 | `QuestionnaireResponse` | `QuestionnaireResponse`, which NRCeS does not publish; base FHIR [QuestionnaireResponse](https://hl7.org/fhir/R4/questionnaireresponse.html) | +| 11 | `QuestionnaireResponse` | `QuestionnaireResponse`, which NRCeS does not publish; base FHIR [QuestionnaireResponse](https://hl7.org/fhir/R4/questionnaireresponse.html) | +| 12 | `QuestionnaireResponse` | `QuestionnaireResponse`, which NRCeS does not publish; base FHIR [QuestionnaireResponse](https://hl7.org/fhir/R4/questionnaireresponse.html) | +| 13 | `QuestionnaireResponse` | `QuestionnaireResponse`, which NRCeS does not publish; base FHIR [QuestionnaireResponse](https://hl7.org/fhir/R4/questionnaireresponse.html) | + +###### 1. Claim + +NRCeS profile: [Claim](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Claim.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system `https://nhcx.abdm.gov.in`, value `NM-26-0SF00002T` | +| `identifier[].type.coding[]` | `CLN` Claim number in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| `status` | `active` | +| `type.coding[]` | `737481003` Inpatient care management (procedure) in `http://snomed.info/sct` | +| `use` | `claim` | +| `patient` | reference `https://nhcx.abdm.gov.in/patient` | +| `billablePeriod` | start `2026-09-10T00:00:00+05:30`, end `2026-09-10T00:00:00+05:30` | +| `created` | `2026-09-11T00:04:45+05:30` | +| `insurer` | reference `https://nhcx.abdm.gov.in/payer` | +| `provider` | reference `https://nhcx.abdm.gov.in/provider` | +| `priority.coding[]` | `normal` Normal in `http://terminology.hl7.org/CodeSystem/processpriority` | +| `careTeam[]` | sequence `1` | +| `careTeam[].provider` | reference `https://nhcx.abdm.gov.in/practitioner` | +| `careTeam[].role.coding[]` | `primary` Primary provider in `http://terminology.hl7.org/CodeSystem/claimcareteamrole` | +| `careTeam[].qualification.coding[]` | `394802001` General medicine in `http://snomed.info/sct` | +| `supportingInfo[]` | id `SupportingInformation/1`, sequence `1` | +| | id `SupportingInformation/2`, sequence `2` | +| | id `SupportingInformation/3`, sequence `3` | +| | and 24 more | +| `supportingInfo[].category.coding[]` | `INV` Document Type - Investigation in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| | `HDS` Hospital discharge summary in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| | `ONS` Period, start or end dates of aspects of the Condition. (e.g. admission, discha… in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| | and 4 more | +| `supportingInfo[].code.coding[]` | `ODN` Death Certificate in `https://nhcx.abdm.gov.in/document-code` | +| | `ODN` Clinical Note/Death Summary in `https://nhcx.abdm.gov.in/document-code` | +| | `ODN` Mortality audit report in `https://nhcx.abdm.gov.in/document-code` | +| | and 17 more | +| `supportingInfo[].valueAttachment` | contentType `application/pdf`, title `Death Certificate` | +| | contentType `application/pdf`, title `Clinical Note/Death Summary` | +| | contentType `application/pdf`, title `Mortality audit report` | +| | and 10 more | +| `supportingInfo[].valueReference` | reference `https://nhcx.abdm.gov.in/questionnaireresponse/1`, display `Death` | +| | reference `https://nhcx.abdm.gov.in/questionnaireresponse/2`, display `Discharge Against Medical Advice (DAMA)` | +| | reference `https://nhcx.abdm.gov.in/questionnaireresponse/3`, display `Discharge Consent` | +| | and 3 more | +| `diagnosis[]` | sequence `1` | +| `diagnosis[].diagnosisCodeableConcept.coding[]` | `E11.9` Type 2 diabetes mellitus without complications in `http://hl7.org/fhir/sid/icd-10` | +| `diagnosis[].type[].coding[]` | `admitting` Admitting Diagnosis in `http://terminology.hl7.org/CodeSystem/ex-diagnosistype` | +| `diagnosis[].onAdmission.coding[]` | `yes` Yes in `http://terminology.hl7.org/CodeSystem/ex-diagnosis-on-admission` | +| `procedure[]` | id `Procedure/1`, sequence `1`, date `2026-09-10T00:00:00+05:30` | +| `procedure[].type[].coding[]` | `conservative` Conservative in `https://nhcx.abdm.gov.in/procedure-type` | +| `procedure[].procedureReference` | reference `https://nhcx.abdm.gov.in/procedure/1`, display `Pleural Effusion (Pleural Effusion)` | +| `insurance[]` | sequence `1`, focal `true`, preAuthRef `2026091110000795` | +| `insurance[].coverage` | reference `https://nhcx.abdm.gov.in/coverage` | +| `item[]` | id `Item/1`, sequence `1`, factor `1`, careTeamSequence `1`, diagnosisSequence `1`, procedureSequence `1`, informationSequence `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`, `9`, `10`, `11`, `12`, `13`, `14`, `15`, `16`, `17`, `18`, `19`, `20`, `21`, `22`, `23`, `24`, `25`, `26`, `27` | +| `item[].productOrService.coding[]` | `MG0111A` Pleural Effusion (Pleural Effusion) in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-procedure-code` | +| `item[].servicedPeriod` | start `2026-09-10`, end `2026-09-10` | +| `item[].quantity` | value `1` | +| `item[].unitPrice` | value `1800`, currency `INR` | +| `item[].net` | value `1800`, currency `INR` | +| `item[].category.coding[]` | `MG` General Medicine in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-benefit-category` | +| `item[].modifier[].coding[]` | `STRAT006a` Routine Ward | +| `item[].programCode[].coding[]` | `AB-PMJAY` Ayushman Bharat Pradhan Mantri Jan Arogya Yojana (AB-PMJAY) in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-program-code` | +| `total` | value `1800`, currency `INR` | + +###### 8. QuestionnaireResponse + +| Element | Example | +| :-- | :-- | +| `questionnaire` | `https://payer.gov.in/policy/questionnaire/100025` | +| `status` | `completed` | +| `subject` | reference `https://nhcx.abdm.gov.in/patient` | +| `authored` | `2026-09-11T00:04:45+05:30` | +| `item[]` | linkId `100011`, text `Death Stage` | +| | linkId `100098`, text `Death Date` | +| | linkId `100099`, text `Death Certificate` | +| | and 2 more | +| `item[].answer[]` | valueString `Before Surgery/Treatment` | +| | valueDateTime `2026-09-10T18:34:00+05:30` | +| `item[].answer[].valueAttachment` | contentType `application/pdf`, title `Death Certificate` | +| | contentType `application/pdf`, title `Clinical Note/Death Summary` | +| | contentType `application/pdf`, title `Mortality audit report` | + +###### 9. QuestionnaireResponse + +| Element | Example | +| :-- | :-- | +| `questionnaire` | `https://payer.gov.in/policy/questionnaire/100137` | +| `status` | `completed` | +| `subject` | reference `https://nhcx.abdm.gov.in/patient` | +| `authored` | `2026-09-11T00:04:45+05:30` | +| `item[]` | linkId `103020`, text `DAMA Stage` | +| | linkId `101403`, text `In Treatment Photo with Doctor/PMAM` | +| | linkId `100012`, text `Discharge Date` | +| | and 3 more | +| `item[].answer[]` | valueString `Before Surgery/Treatment` | +| | valueDateTime `2026-09-10T18:34:00+05:30` | +| `item[].answer[].valueAttachment` | contentType `application/pdf`, title `In Treatment Photo with Doctor/PMAM` | +| | contentType `application/pdf`, title `Upload Mangalkamana Patra` | +| | contentType `application/pdf`, title `Feedback Form` | + +###### 10. QuestionnaireResponse + +| Element | Example | +| :-- | :-- | +| `questionnaire` | `https://payer.gov.in/policy/questionnaire/100466` | +| `status` | `completed` | +| `subject` | reference `https://nhcx.abdm.gov.in/patient` | +| `authored` | `2026-09-11T00:04:45+05:30` | +| `item[]` | linkId `135477`, text `Medical Superintendent Declaration Form (During Discharge)` | +| `item[].answer[].valueAttachment` | contentType `application/pdf`, title `Medical Superintendent Declaration Form (During Discharge)` | + +###### 11. QuestionnaireResponse + +| Element | Example | +| :-- | :-- | +| `questionnaire` | `https://payer.gov.in/policy/questionnaire/100005` | +| `status` | `completed` | +| `subject` | reference `https://nhcx.abdm.gov.in/patient` | +| `authored` | `2026-09-11T00:04:45+05:30` | +| `item[]` | linkId `100097`, text `Post Treatment Photo with Doctor/PMAM` | +| | linkId `100096`, text `Discharge Summary` | +| | linkId `101799`, text `Discharge Stage` | +| | and 4 more | +| `item[].answer[].valueAttachment` | contentType `application/pdf`, title `Post Treatment Photo with Doctor/PMAM` | +| | contentType `application/pdf`, title `Discharge Summary` | +| | contentType `application/pdf`, title `Feedback Form` | +| `item[].answer[]` | valueString `After Surgery/Treatment` | +| | valueDateTime `2026-09-10T18:34:00+05:30` | +| | valueString `Yes` | + +###### 12. QuestionnaireResponse + +| Element | Example | +| :-- | :-- | +| `questionnaire` | `https://payer.gov.in/policy/questionnaire/100022` | +| `status` | `completed` | +| `subject` | reference `https://nhcx.abdm.gov.in/patient` | +| `authored` | `2026-09-11T00:04:45+05:30` | +| `item[]` | linkId `100088`, text `Hospital Bill` | +| | linkId `15201`, text `Justification Letter` | +| | linkId `103013`, text `Bill Date` | +| | and 4 more | +| `item[].answer[].valueAttachment` | contentType `application/pdf`, title `Hospital Bill` | +| | contentType `application/pdf`, title `Justification Letter` | +| | contentType `application/pdf`, title `Any other document` | +| `item[].answer[]` | valueDateTime `2026-09-10T18:34:00+05:30` | +| | valueString `Recorded.` | + +###### 13. QuestionnaireResponse + +| Element | Example | +| :-- | :-- | +| `questionnaire` | `https://payer.gov.in/policy/questionnaire/100136` | +| `status` | `completed` | +| `subject` | reference `https://nhcx.abdm.gov.in/patient` | +| `authored` | `2026-09-11T00:04:45+05:30` | +| `item[]` | linkId `100115`, text `LAMA Stage` | +| | linkId `101403`, text `In Treatment Photo with Doctor/PMAM` | +| | linkId `100101`, text `Surgery/Treatment Date` | +| | and 2 more | +| `item[].answer[]` | valueString `Before Surgery/Treatment` | +| | valueDateTime `2026-09-10T18:34:00+05:30` | +| | valueString `Yes` | +| `item[].answer[].valueAttachment` | contentType `application/pdf`, title `In Treatment Photo with Doctor/PMAM` | + +The `Patient`, `Organization`, `Coverage`, `Practitioner`, `Procedure` entries are shaped as in the chapters that introduce them. + +### What PMJAY specifies + +- The query is a `ClaimResponse` with `outcome` `partial` and reason `queried` on 27, the question as free text in the item adjudication. +- The answer is a fresh submit of the whole claim, on the same claim number, under 161. + +### What PMJAY requires + +- Answer on 161. A claim query answered on 151, 19 or 16 is refused with `PAYR-1321`. +- The full bundle, rebuilt from your stored submission, never a delta. + +## Use cases, APIs and data elements + +### D10 Answer a claim query (pmjay) + +As D7, on the claim endpoint: the query is a ClaimResponse on 27, the answer a fresh submit on 161. The sandbox refuses 151, 19 and 16 with PAYR-1321. The final adjudication then arrives with outcome complete and, often, a deductible adjudication naming why the eligible amount is less than the claimed one. + +| | | +| :-- | :-- | +| **API** | `/v1/claim/submit` [`apis/05-claim/v1-claim-submit.bru`](/docs/nhcx/v1/api/claim/endpoints/claim-v1-claim-submit) | +| **Callback** | `/v1/claim/on_submit` [`apis/05-claim/v1-claim-on-submit.bru`](/docs/nhcx/v1/api/claim/endpoints/claim-v1-claim-on-submit) | +| **Workflow** | 161 | +| **Carries JWE** | yes | +| **Focal resource** | `Claim` | +| **Simulator console** | `/builder?family=claim&usecase=query-answer` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `x-hcx-sender_code` | `1000004446@hcx` | +| `x-hcx-recipient_code` | `1518@hcx` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-request_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{$guid}}` | +| `x-hcx-workflow_id` | `161` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `request.initiated` | +| `x-hcx-ben-abha-id` | `91711234567890` | +| `x-hcx-use_case` | `New` | + +**Workflow codes** + +| Code | Name | Authored by | `x-hcx-status` | Means | +| :-- | :-- | :-- | :-- | :-- | +| `161` | Claim Doc Query Response | status sheet only | `response.complete` | | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `claimNumber` | Claim Number | Case | `string` | `1..1` | `Claim.identifier[0].value` | `CL26AA2600001` | | +| `workflowId` | Workflow Code | Header | `string` | `1..1` | `Header.x-hcx-workflow_id` | `161` | | + +NRCeS profiles: [Claim](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Claim.html). diff --git a/site/docs/nhcx/v1/reference/fhir/claim-request.md b/site/docs/nhcx/v1/reference/fhir/claim-request.md new file mode 100644 index 000000000..001b386fa --- /dev/null +++ b/site/docs/nhcx/v1/reference/fhir/claim-request.md @@ -0,0 +1,367 @@ +--- +title: Claim request +sidebar_label: Claim request +sidebar_position: 12 +description: Final claim bundle, `billablePeriod`, discharge evidence, and invoice attachments +verification: unverified +source: nhcx-package/docs/05-FHIR Reference/12-Claim Request.md +generated: true +--- + +# Claim request + +The request for payment once treatment is done. The same `Claim` as the preauthorisation with `use` set to `claim`, carrying the finalised dates, bill and documents. + +Sent on `/v1/claim/submit`, answered on `/v1/claim/on_submit`, workflow 15. + +## The bundle + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `Claim` | [Claim](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Claim.html) | +| 2 | `Patient` | [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html) | +| 3 | `Organization (prov)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 4 | `Organization (pay)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 5 | `Coverage` | [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html) | +| 6 | `Practitioner` | [Practitioner](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Practitioner.html) | +| 7 | `Procedure` | [Procedure](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Procedure.html) | + +## Elements + +### 1. Claim + +NRCeS profile: [Claim](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Claim.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system `https://nhcx.abdm.gov.in`, value `NM-26-0SE00002L` | +| `identifier[].type.coding[]` | `CLN` Claim number in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| `status` | `active` | +| `type.coding[]` | `737481003` Inpatient care management (procedure) in `http://snomed.info/sct` | +| `use` | `claim` | +| `patient` | reference `https://nhcx.abdm.gov.in/patient` | +| `billablePeriod` | start `2026-09-10T00:00:00+05:30`, end `2026-09-10T00:00:00+05:30` | +| `created` | `2026-09-10T23:53:21+05:30` | +| `insurer` | reference `https://nhcx.abdm.gov.in/payer` | +| `provider` | reference `https://nhcx.abdm.gov.in/provider` | +| `priority.coding[]` | `normal` Normal in `http://terminology.hl7.org/CodeSystem/processpriority` | +| `careTeam[]` | sequence `1` | +| `careTeam[].provider` | reference `https://nhcx.abdm.gov.in/practitioner` | +| `careTeam[].role.coding[]` | `primary` Primary provider in `http://terminology.hl7.org/CodeSystem/claimcareteamrole` | +| `careTeam[].qualification.coding[]` | `394802001` General medicine in `http://snomed.info/sct` | +| `supportingInfo[]` | id `SupportingInformation/1`, sequence `1` | +| | id `SupportingInformation/2`, sequence `2` | +| | id `SupportingInformation/3`, sequence `3` | +| | and 7 more | +| `supportingInfo[].category.coding[]` | `INV` Document Type - Investigation in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| | `HDS` Hospital discharge summary in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| | `ONS` Period, start or end dates of aspects of the Condition. (e.g. admission, discha… in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| | and 2 more | +| `supportingInfo[].code.coding[]` | `MB` Medical & Pharmacy Bills Itemized in `https://nhcx.abdm.gov.in/document-code` | +| | `IMP` Medical Implant Invoice & Barcode Sticker in `https://nhcx.abdm.gov.in/document-code` | +| | `FCF` Filled NHCX Claim Form (Signed) in `https://nhcx.abdm.gov.in/document-code` | +| | and 7 more | +| `supportingInfo[].valueAttachment` | contentType `application/pdf`, title `Medical & Pharmacy Bills Itemized` | +| | contentType `application/pdf`, title `Medical Implant Invoice & Barcode Sticker` | +| | contentType `application/pdf`, title `Filled NHCX Claim Form (Signed)` | +| | and 2 more | +| `diagnosis[]` | sequence `1` | +| `diagnosis[].diagnosisCodeableConcept.coding[]` | `E11.9` Type 2 diabetes mellitus without complications in `http://hl7.org/fhir/sid/icd-10` | +| `diagnosis[].type[].coding[]` | `admitting` Admitting Diagnosis in `http://terminology.hl7.org/CodeSystem/ex-diagnosistype` | +| `diagnosis[].onAdmission.coding[]` | `yes` Yes in `http://terminology.hl7.org/CodeSystem/ex-diagnosis-on-admission` | +| `procedure[]` | id `Procedure/1`, sequence `1`, date `2026-09-10T00:00:00+05:30` | +| `procedure[].type[].coding[]` | `surgical` Surgical in `https://nhcx.abdm.gov.in/procedure-type` | +| `procedure[].procedureReference` | reference `https://nhcx.abdm.gov.in/procedure/1`, display `Total Knee Replacement (Unilateral)` | +| `insurance[]` | sequence `1`, focal `true`, preAuthRef `CL/26/0SE000107` | +| `insurance[].coverage` | reference `https://nhcx.abdm.gov.in/coverage` | +| `item[]` | id `Item/1`, sequence `1`, factor `1`, careTeamSequence `1`, diagnosisSequence `1`, procedureSequence `1`, informationSequence `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`, `9`, `10` | +| `item[].productOrService.coding[]` | `PROC-KNEE-01` Total Knee Replacement (Unilateral) in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-procedure-code` | +| `item[].servicedPeriod` | start `2026-09-10`, end `2026-09-10` | +| `item[].quantity` | value `1` | +| `item[].unitPrice` | value `150000`, currency `INR` | +| `item[].net` | value `150000`, currency `INR` | +| `item[].category.coding[]` | `Surgical` Surgical in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-benefit-category` | +| `total` | value `150000`, currency `INR` | + +### 2. Patient + +NRCeS profile: [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | value `MRAV1985001` | +| | value `91-1234-1234-1234` | +| `identifier[].type.coding[]` | `PMJAY` Pradhan Mantri Jan Aarogya Yojana (PMJAY) ID in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| | `ABHA` Ayushman Bharat Health Account (ABHA) ID in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| | `MB` Member Number in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `name[]` | text `` | +| `telecom[]` | system `phone`, value `9876543210` | +| `gender` | `male` | +| `birthDate` | `1985-06-15` | + +### 3. Organization (prov) + +NRCeS profile: [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system `https://nhcx.abdm.gov.in`, value `IN1910000151` | +| `identifier[].type.coding[]` | `NPI` National provider identifier in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `type[].coding[]` | `prov` Healthcare Provider in `http://terminology.hl7.org/CodeSystem/organization-type` | +| `name` | `KyroCare Multispeciality Hospital` | + +### 4. Organization (pay) + +NRCeS profile: [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system `https://nhcx.abdm.gov.in`, value `1000004805` | +| `identifier[].type.coding[]` | `NIIP` National Insurance Payor Identifier (Payor) in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `type[].coding[]` | `pay` Payer in `http://terminology.hl7.org/CodeSystem/organization-type` | +| `name` | `Sandbox Payer` | + +### 5. Coverage + +NRCeS profile: [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | value `POL7UMU001` | +| `identifier[].type.coding[]` | `NH` National Health Plan Identifier in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `status` | `active` | +| `type.coding[]` | `HIP` health insurance plan policy in `http://terminology.hl7.org/CodeSystem/v3-ActCode` | +| `subscriber` | reference `https://nhcx.abdm.gov.in/patient` | +| `subscriberId` | `MRAV1985001` | +| `beneficiary` | reference `https://nhcx.abdm.gov.in/patient` | +| `relationship.coding[]` | `self` in `http://terminology.hl7.org/CodeSystem/subscriber-relationship` | +| `payor[]` | reference `https://nhcx.abdm.gov.in/payer` | + +### 6. Practitioner + +NRCeS profile: [Practitioner](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Practitioner.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system `https://nhcx.abdm.gov.in`, value `71-8422-5818-7201` | +| | system `https://hpr.abdm.gov.in`, value `71-8422-5818-7201` | +| `identifier[].type.coding[]` | `HPID` Healthcare Professional ID (HPID) in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| | `HPIN` Health Practitioner ID issued by NDHM in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| `name[]` | text `Dr. Ananya Rao` | +| `qualification[].code.coding[]` | `MD` Doctor of Medicine in `http://terminology.hl7.org/CodeSystem/v2-0360` | + +### 7. Procedure + +NRCeS profile: [Procedure](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Procedure.html). + +| Element | Example | +| :-- | :-- | +| `status` | `completed` | +| `code` | text `Total Knee Replacement (Unilateral)` | +| `code.coding[]` | `71388002` Procedure (procedure) in `http://snomed.info/sct` | +| `subject` | reference `https://nhcx.abdm.gov.in/patient` | +| `performedDateTime` | `2026-09-10T00:00:00+05:30` | + +## Rules + +### 1. What a claim adds + +The final bill under `MB` and the discharge summary under `HDS`, with the implant invoice, the operation notes and the signed claim form where the plan asks for them. + +### 2. The stay + +`billablePeriod` carries the admission and the discharge. + +### 3. Sequences may have gaps + +Map supporting information by `sequence` and resolve `item.informationSequence` through the map. + +### 4. The amount + +May not exceed what the preauthorisation approved. + +### 5. Cyclic treatment + +One supporting-info entry per cycle, with `timingPeriod`, listed in the item's `informationSequence`, its record referenced from `valueReference`. + +### 6. Newborn + +The parent stays the primary `Patient`; the child is a second `Patient` linked with `link.type` `refer`, with gender and birth date, and a proof of birth under category `DOB`, code `BCF` or `DCB`. + +## PMJAY + +The generic bundle above is what every payer takes, IRDAI-regulated insurers and TPAs included. PMJAY takes it with the changes and requirements below. + +### What changes in the bundle + +#### Resources + +- PMJAY adds 4 `QuestionnaireResponse`. + +##### QuestionnaireResponse + +| Element | Example | +| :-- | :-- | +| `questionnaire` | `https://payer.gov.in/policy/questionnaire/100025` | +| `status` | `completed` | +| `subject` | reference `https://nhcx.abdm.gov.in/patient` | +| `authored` | `2026-09-11T00:25:00+05:30` | +| `item[]` | linkId `100011`, text `Death Stage` | +| | linkId `100098`, text `Death Date` | +| | linkId `100099`, text `Death Certificate` | +| | and 2 more | +| `item[].answer[]` | valueString `Before Surgery/Treatment` | +| | valueDateTime `2026-09-10T18:54:00+05:30` | +| `item[].answer[].valueAttachment` | contentType `application/pdf`, title `Death Certificate` | +| | contentType `application/pdf`, title `Clinical Note/Death Summary` | +| | contentType `application/pdf`, title `Mortality audit report` | + +#### Elements PMJAY adds + +| Element | Example | +| :-- | :-- | +| `Claim.supportingInfo[].valueReference` | reference `https://nhcx.abdm.gov.in/questionnaireresponse/1`, display `Death` | +| | reference `https://nhcx.abdm.gov.in/questionnaireresponse/2`, display `Discharge Consent` | +| | reference `https://nhcx.abdm.gov.in/questionnaireresponse/3`, display `Discharge Information` | +| | and 1 more | +| `Claim.item[].modifier[].coding[]` | `STRAT006a` Routine Ward | +| `Claim.item[].programCode[].coding[]` | `AB-PMJAY` Ayushman Bharat Pradhan Mantri Jan Arogya Yojana (AB-PMJAY) in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-program-code` | + +### What PMJAY specifies + +- Dates ride as supporting information: the stay under category `ONS`, code `ADDD`, the encounter under `OTH`, code `EDT`, and the surgery under code `PSP`, each as a `valueString` in `+05:30`. +- Discharge types `DTH`, `DTM`, `LAMA` and `DAMA` under category `DIS`, with the stage, before, during or after surgery, as the `valueString`. +- LAMA or DAMA before or during surgery voids the approved packages: one item `LM100`, quantity the days admitted, capped by the package's `los`. After surgery the package stays billable. +- A death records its date under category `ONS`, code `DTM`. +- The discharge consent and the other policy questionnaires ride as `QuestionnaireResponse` resources, each referenced from a `supportingInfo` entry. + +### What PMJAY requires + +- Send the claim under the preauthorisation's own number. Refused with `ERR-PYR-CLM-007` otherwise. +- The discharge status under `DIS` and the admission and discharge dates. The claim is refused without them. +- Bill the package alone, at the whole amount. Room rent, consultations and investigations are not items. +- A fresh biometric token at discharge, or the plan's Discharge Consent questionnaire answered. Refused with `PAYR-1363` otherwise. +- `LM100` as the single procedure on LAMA or DAMA before or during surgery (`PAYR-1362`), and the death date under `ONS` / `DTM` (`PAYR-1096`). +- Each cycle's `timingPeriod` matches the biometric capture for that cycle. + +## Use cases, APIs and data elements + +### B5 Submit claim (provider) + +Reimbursement after discharge. The amount may not exceed what the pre-authorisation approved. The acknowledgement on 25 brings the payer's case number. PMJAY takes a claim query answer on 161 only; 151, 19 and 16 are refused with PAYR-1321. + +| | | +| :-- | :-- | +| **API** | `/v1/claim/submit` [`apis/05-claim/v1-claim-submit.bru`](/docs/nhcx/v1/api/claim/endpoints/claim-v1-claim-submit) | +| **Callback** | `/v1/claim/on_submit` [`apis/05-claim/v1-claim-on-submit.bru`](/docs/nhcx/v1/api/claim/endpoints/claim-v1-claim-on-submit) | +| **Workflow** | 15 claim, 161 query answer under PMJAY, 14 provisional discharge where a payer supports one | +| **Carries JWE** | yes | +| **Focal resource** | `Claim` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `x-hcx-sender_code` | `1000004446@hcx` | +| `x-hcx-recipient_code` | `1518@hcx` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-request_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{$guid}}` | +| `x-hcx-workflow_id` | `15` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `request.initiated` | +| `x-hcx-ben-abha-id` | `91711234567890` | +| `x-hcx-use_case` | `New` | + +**Workflow codes** + +| Code | Name | Authored by | `x-hcx-status` | Means | +| :-- | :-- | :-- | :-- | :-- | +| `15` | Claim Request Initiated | provider | `request.initiated` | Final claim submission | +| `161` | Claim Doc Query Response | status sheet only | `response.complete` | | +| `14` | Discharge Submitted | provider | `request.initiated` | Discharge summary submitted | +| `151` | Claim Query Response Submitted | provider | `response.complete` | Response to claim query, as published; the PMJAY sandbox refuses it with PAYR-1321 and takes 161 (Claim Doc Query Response) | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `claimNumber` | Final Claim Number | Case | `string` | `1..1` | `Claim.identifier[0].value` | `CL0000000001` | also at `Bundle.id` | +| `use` | Claim Use | Case | `code` | `1..1` | `Claim.use` | `claim` | | +| `preAuthRef` | Approved Pre-auth Reference | Case | `string` | `1..1` | `Claim.insurance[0].preAuthRef[0]` | `APPR-2026-HP-00891` | | +| `patientName` | Patient Full Name | Beneficiary | `string` | `1..1` | `Patient.name[0].text` | `Ramesh Chandra Sharma` | | +| `memberId` | Scheme / Insurer Member ID | Beneficiary | `string` | `1..1` | `Patient.identifier[type=PMJAY].value` | `PMJAY-HP-2024-998811` | also at `Coverage.subscriberId` | +| `abhaNumber` | ABHA Number | Beneficiary | `string` | `0..1` | `Patient.identifier[type=ABHA].value` | `91234567890123` | | +| `gender` | Gender | Beneficiary | `code` | `1..1` | `Patient.gender` | `male` | code system `http://hl7.org/fhir/administrative-gender` | +| `birthDate` | Date of Birth | Beneficiary | `date` | `1..1` | `Patient.birthDate` | `1982-06-15` | | +| `patientPhone` | Mobile Phone | Beneficiary | `string` | `0..1` | `Patient.telecom[system=phone].value` | `9876543210` | | +| `policyNumber` | Policy Number | Coverage | `string` | `1..1` | `Coverage.identifier[0].value` | `PMJAY/HP/S/G` | | +| `facilityId` | Hospital Facility ID (HFR/NPI) | Provider | `string` | `1..1` | `Organization[type=prov].identifier[system=https://facility.abdm.gov.in].value` | `IN1910000151` | | +| `providerName` | Hospital Name | Provider | `string` | `1..1` | `Organization[type=prov].name` | `Apex Multispeciality Hospital` | | +| `payerId` | Payer Identifier (NIIP) | Payer | `string` | `1..1` | `Organization[type=pay].identifier[system=https://irdai.gov.in].value` | `1000003538` | | +| `payerName` | Payer Name | Payer | `string` | `1..1` | `Organization[type=pay].name` | `National Health Authority - PMJAY` | | +| `practitionerId` | Practitioner ID (HPID/HPIN) | Practitioner | `string` | `1..1` | `Practitioner.identifier[system=https://hpr.abdm.gov.in].value` | `21-8899-4455-6677` | | +| `practitionerName` | Doctor Name | Practitioner | `string` | `1..1` | `Practitioner.name[0].text` | `Dr. Arvind Kumar` | | +| `admissionDate` | Admission Date | Stay | `dateTime` | `1..1` | `Claim.billablePeriod.start` | `2026-02-26T10:00:00+05:30` | | +| `dischargeDate` | Discharge Date | Stay | `dateTime` | `1..1` | `Claim.billablePeriod.end` | `2026-03-02T14:30:00+05:30` | | +| `careSetting` | Care Setting | Stay | `code` | `1..1` | `Claim.type.coding[0].code` | `institutional` | code system `http://terminology.hl7.org/CodeSystem/claim-type` | +| `primaryDiagnosisCode` | Primary Diagnosis (ICD-10) | Clinical | `string` | `1..1` | `Claim.diagnosis[0].diagnosisCodeableConcept.coding[0].code` | `A97.0` | code system `http://hl7.org/fhir/sid/icd-10` | +| `procedureCode` | Package / Procedure Code | Clinical | `string` | `1..1` | `Claim.procedure[0].procedureCodeableConcept.coding[0].code` | `MG004A` | | +| `finalBilledAmount` | Total Claim Amount | Billing | `decimal` | `1..1` | `Claim.total.value` | `15500.00` | | + +NRCeS profiles: [Claim](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Claim.html), [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html), [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html), [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html), [Practitioner](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Practitioner.html). + +### D9 Submit claim (pmjay) + +There is no discharge submission: the claim asserts the discharge and carries its details. Four dates, the discharge type under category DIS with the stage as its value, a fresh biometric token, and LM100 as the single procedure in place of the approved items on a LAMA or DAMA discharge before or during surgery. The amount may not exceed what was approved. + +| | | +| :-- | :-- | +| **API** | `/v1/claim/submit` [`apis/05-claim/v1-claim-submit.bru`](/docs/nhcx/v1/api/claim/endpoints/claim-v1-claim-submit) | +| **Callback** | `/v1/claim/on_submit` [`apis/05-claim/v1-claim-on-submit.bru`](/docs/nhcx/v1/api/claim/endpoints/claim-v1-claim-on-submit) | +| **Workflow** | 15 | +| **Carries JWE** | yes | +| **Focal resource** | `Claim` | +| **Simulator console** | `/builder?family=claim&usecase=submit` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `x-hcx-sender_code` | `1000004446@hcx` | +| `x-hcx-recipient_code` | `1518@hcx` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-request_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{$guid}}` | +| `x-hcx-workflow_id` | `15` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `request.initiated` | +| `x-hcx-ben-abha-id` | `91711234567890` | +| `x-hcx-use_case` | `New` | + +**Workflow codes** + +| Code | Name | Authored by | `x-hcx-status` | Means | +| :-- | :-- | :-- | :-- | :-- | +| `15` | Claim Request Initiated | provider | `request.initiated` | Final claim submission | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `claimNumber` | PMJAY Claim Number | Case | `string` | `1..1` | `Claim.identifier[0].value` | `CL26AA2600001` | | +| `dischargeSummary` | Hospital Discharge Summary (HDS) | Documents | `base64Binary` | `1..1` | `Claim.supportingInfo[category=HDS].valueAttachment.data` | `JVBERi0xLjQK...` | | +| `patientName` | Patient Full Name | Beneficiary | `string` | `1..1` | `Patient.name[0].text` | `Ramesh Chandra Sharma` | | +| `memberId` | Scheme / Insurer Member ID | Beneficiary | `string` | `1..1` | `Patient.identifier[type=PMJAY].value` | `PMJAY-HP-2024-998811` | also at `Coverage.subscriberId` | +| `abhaNumber` | ABHA Number | Beneficiary | `string` | `0..1` | `Patient.identifier[type=ABHA].value` | `91234567890123` | | +| `gender` | Gender | Beneficiary | `code` | `1..1` | `Patient.gender` | `male` | code system `http://hl7.org/fhir/administrative-gender` | +| `birthDate` | Date of Birth | Beneficiary | `date` | `1..1` | `Patient.birthDate` | `1982-06-15` | | +| `patientPhone` | Mobile Phone | Beneficiary | `string` | `0..1` | `Patient.telecom[system=phone].value` | `9876543210` | | +| `facilityId` | Hospital Facility ID (HFR/NPI) | Provider | `string` | `1..1` | `Organization[type=prov].identifier[system=https://facility.abdm.gov.in].value` | `IN1910000151` | | +| `providerName` | Hospital Name | Provider | `string` | `1..1` | `Organization[type=prov].name` | `Apex Multispeciality Hospital` | | +| `payerId` | Payer Identifier (NIIP) | Payer | `string` | `1..1` | `Organization[type=pay].identifier[system=https://irdai.gov.in].value` | `1000003538` | | +| `payerName` | Payer Name | Payer | `string` | `1..1` | `Organization[type=pay].name` | `National Health Authority - PMJAY` | | +| `practitionerId` | Practitioner ID (HPID/HPIN) | Practitioner | `string` | `1..1` | `Practitioner.identifier[system=https://hpr.abdm.gov.in].value` | `21-8899-4455-6677` | | +| `practitionerName` | Doctor Name | Practitioner | `string` | `1..1` | `Practitioner.name[0].text` | `Dr. Arvind Kumar` | | + +NRCeS profiles: [Claim](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Claim.html), [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html), [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html), [Practitioner](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Practitioner.html). diff --git a/site/docs/nhcx/v1/reference/fhir/claim-response.md b/site/docs/nhcx/v1/reference/fhir/claim-response.md new file mode 100644 index 000000000..77373ed06 --- /dev/null +++ b/site/docs/nhcx/v1/reference/fhir/claim-response.md @@ -0,0 +1,210 @@ +--- +title: Claim response +sidebar_label: Claim response +sidebar_position: 13 +description: Claim decisions, item adjudications, and verified rejection bundles (wf 291) +verification: unverified +source: nhcx-package/docs/05-FHIR Reference/13-Claim Response.md +generated: true +--- + +# Claim response + +The payer's adjudication of a submitted claim, on `/v1/claim/on_submit`. The same bundle carries an acknowledgement, an approval, a query and a rejection. + +Sent on `/v1/claim/on_submit`. + +## The bundle + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `ClaimResponse` | none declared; NRCeS [ClaimResponse](https://nrces.in/ndhm/fhir/r4/StructureDefinition-ClaimResponse.html) | +| 2 | `Patient` | none declared; NRCeS [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html) | +| 3 | `Organization (pay)` | none declared; NRCeS [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 4 | `Organization (prov)` | none declared; NRCeS [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 5 | `Coverage` | none declared; NRCeS [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html) | + +## Elements + +### 1. ClaimResponse + +NRCeS profile: [ClaimResponse](https://nrces.in/ndhm/fhir/r4/StructureDefinition-ClaimResponse.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system ``, value `NM-26-0SE00002L` | +| `identifier[].type.coding[]` | `CLN` Claim number in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| `status` | `active` | +| `use` | `claim` | +| `patient` | reference `` | +| `created` | `2026-09-10T23:53:32+05:30` | +| `insurer` | reference `` | +| `requestor` | reference `` | +| `outcome` | `complete` | +| `disposition` | `Reprocessed and approved.` | +| `payeeType.coding[]` | `provider` Provider in `http://terminology.hl7.org/CodeSystem/payeetype` | +| `item[]` | id `Item/LI-558aa12a`, itemSequence `1` | +| `item[].adjudication[].category.coding[]` | `submitted` Submitted Amount in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| | `eligible` Eligible Amount in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| | `reason` Reason for Adjudication in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| | and 1 more | +| `item[].adjudication[].amount` | value `150000` | +| `item[].adjudication[].reason.coding[]` | display `Reprocessed and approved.` | +| | `Approved` Approved | +| `adjudication[].category.coding[]` | `status` Status | +| `adjudication[].reason.coding[]` | `approved` Approved | +| `total[].category.coding[]` | `benefit` Benefit Amount in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| | `submitted` Submitted Amount in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| | `eligible` Eligible Amount | +| `total[].amount` | value `150000` | +| `total[]` | id `MRAV1985001/SANDBOX-DEFAULT-01` | + +### 2. Patient + +NRCeS profile: [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system ``, value `MRAV1985001` | +| `identifier[].type.coding[]` | `MB` Member Number in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `name[]` | family `Kumar`, given `Ravi`, text `Ravi Kumar` | +| `gender` | `male` | +| `birthDate` | `1985-06-15` | + +### 3. Organization (pay) + +NRCeS profile: [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html). + +| Element | Example | +| :-- | :-- | +| `active` | `true` | +| `identifier[]` | system `https://facility.abdm.gov.in`, value `1000004805` | +| `identifier[].type.coding[]` | `NIIP` National Insurance Payor Identifier (Payor) in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `type[].coding[]` | `pay` Payer in `http://terminology.hl7.org/CodeSystem/organization-type` | +| `name` | `Sandbox Payer` | + +### 4. Organization (prov) + +NRCeS profile: [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html). + +| Element | Example | +| :-- | :-- | +| `active` | `true` | +| `identifier[]` | system `https://facility.abdm.gov.in`, value `IN1910000151` | +| `identifier[].type.coding[]` | `NPI` National provider identifier in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `type[].coding[]` | `prov` Healthcare Provider in `http://terminology.hl7.org/CodeSystem/organization-type` | +| `name` | `KyroCare Multispeciality Hospital` | + +### 5. Coverage + +NRCeS profile: [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system ``, value `SANDBOX-DEFAULT-01` | +| `identifier[].type.coding[]` | `NH` National Health Plan Identifier in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `status` | `active` | +| `type.coding[]` | `HIP` health insurance plan policy in `http://terminology.hl7.org/CodeSystem/v3-ActCode` | +| `beneficiary` | reference `` | +| `period` | start `2026-01-01T00:00:00+05:30`, end `2026-12-31T00:00:00+05:30` | +| `payor[]` | reference `` | +| `class[]` | id `POL7UMU002`, value `SANDBOX-DEFAULT-01` | +| `class[].type.coding[]` | `XV` Health Plan Identifier in `http://terminology.hl7.org/CodeSystem/v2-0203` | + +## The answers + +The same bundle, told apart by the workflow code, `outcome` and the claim-level adjudication reason. + +| Variant | Workflow | outcome | reason | +| :-- | :-- | :-- | :-- | +| Acknowledged | `25` | `queued` | `submitted` Submitted | +| Approved | `26` | `complete` | `approved` Approved | +| Queried | `27` | `partial` | `queried` Queried | +| Rejected | `291` | `error` | `rejected` Rejected | + +## Rules + +### 1. partial is two things + +An acknowledgement and a query are both `partial`. Read the claim-level reason, then `disposition`, then the totals. + +### 2. Deductions + +Item-level `deductible` adjudications carry the amount and the reason. Sum them before reporting an approved figure. + +### 3. Joining + +Join the response to the claim by `identifier.value`. + +### 4. Settlement is separate + +An approval closes adjudication, not the money. The claim closes on the payment notice. + +### 5. Submitted amounts + +Do not reconcile your submitted amount against the payer's `submitted` total; it comes from the payer's own record. + +## PMJAY + +The generic bundle above is what every payer takes, IRDAI-regulated insurers and TPAs included. PMJAY takes it with the changes and requirements below. + +### What changes in the bundle + +PMJAY sends this exchange in the generic shape. + +### What PMJAY specifies + +- `total[]` adds a `tax` line beside `benefit` and `submitted`. +- The adjudication reason carries the desk's audit trail, with mixed date formats. Display it; never parse a timestamp from it. +- A benefit of 0 on a query means undetermined, not refused. + +## Use cases, APIs and data elements + +### C7 Respond to claim (payer) + +The adjudicated claim, item by item, with any deduction and its reason. The acknowledgement on 25 travels as response.partial with the payer's case number. Under PMJAY a query is this ClaimResponse on 27, answered by a fresh submit on 161. + +| | | +| :-- | :-- | +| **API** | `/v1/claim/on_submit` [`apis/05-claim/v1-claim-on-submit.bru`](/docs/nhcx/v1/api/claim/endpoints/claim-v1-claim-on-submit) | +| **Callback** | `/v1/claim/submit` [`apis/05-claim/v1-claim-submit.bru`](/docs/nhcx/v1/api/claim/endpoints/claim-v1-claim-submit) | +| **Workflow** | 25 received, 26 approved, 27 queried, 28 in process, 29 forwarded, 291 denied | +| **Carries JWE** | yes | +| **Focal resource** | `ClaimResponse` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `x-hcx-sender_code` | `1518@hcx` | +| `x-hcx-recipient_code` | `1000004446@hcx` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-request_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{$guid}}` | +| `x-hcx-workflow_id` | `26` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `response.complete` | +| `x-hcx-ben-abha-id` | `91711234567890` | +| `x-hcx-debug_flag` | `INFO` | + +**Workflow codes** + +| Code | Name | Authored by | `x-hcx-status` | Means | +| :-- | :-- | :-- | :-- | :-- | +| `25` | Claim Request Received | payer | `response.partial`, `response.error` | Final claim received by payer | +| `26` | Claim Request Approved | payer | `response.complete` | Final claim approved | +| `27` | Claim Request Queried | payer | `request.initiated`, `response.partial/complete` | Final claim queried - payer needs additional documents; under PMJAY answer with 161 | +| `28` | Claim Request In Process | payer | `response.partial` | Final claim is being processed by payer | +| `29` | Claim Forwarded | payer | `response.partial` | Claim forwarded to another processing entity | +| `291` | Claim Doc Deny | status sheet only | `response.complete` | | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `outcome` | Claim Outcome | Adjudication | `code` | `1..1` | `ClaimResponse.outcome` | `complete` | | +| `approvedBenefit` | Approved Claim Amount | Financials | `decimal` | `1..1` | `ClaimResponse.total[category=benefit].amount.value` | `15500.00` | | +| `copayAmount` | Beneficiary Co-payment | Financials | `decimal` | `0..1` | `ClaimResponse.total[category=copay].amount.value` | `0.00` | | +| `deductionReason` | Deduction Justification | Adjudication | `string` | `0..1` | `ClaimResponse.item[].adjudication[category=deduction].reason.coding[0].display` | `Non-medical consumables deducted` | | + +NRCeS profiles: [ClaimResponse](https://nrces.in/ndhm/fhir/r4/StructureDefinition-ClaimResponse.html). diff --git a/site/docs/nhcx/v1/reference/fhir/codes-and-value-sets.md b/site/docs/nhcx/v1/reference/fhir/codes-and-value-sets.md new file mode 100644 index 000000000..0e5804c52 --- /dev/null +++ b/site/docs/nhcx/v1/reference/fhir/codes-and-value-sets.md @@ -0,0 +1,856 @@ +--- +title: Codes and value sets +sidebar_label: Codes and value sets +sidebar_position: 19 +description: All code systems, bindings, and known NHA discrepancies +verification: unverified +source: nhcx-package/docs/05-FHIR Reference/19-Codes and Value Sets.md +generated: true +--- + +# Codes and value sets + +Every code the bundles carry, grouped by the system it is bound to, then the value sets the specifications define beyond them. The workflow codes are in the Overview's Workflow Codes chapter and are not repeated here. + +## Codes in the bundles + +### `http://hl7.org/fhir/CodeSystem/task-code` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `approve` | Activate/approve the focal resource | `Task.code.coding` | both | + +### `http://hl7.org/fhir/resource-types` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `ClaimResponse` | | `Task.output.type.coding` | generic | + +### `http://hl7.org/fhir/sid/icd-10` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `A97` | Dengue | `Claim.diagnosis.diagnosisCodeableConcept.coding` | generic | +| `E11.9` | Type 2 diabetes mellitus without complications | `Claim.diagnosis.diagnosisCodeableConcept.coding` | both | +| `I46.9` | Cardiac arrest, unspecified | `Claim.diagnosis.diagnosisCodeableConcept.coding` | generic | + +### `http://hl7.org/fhir/ValueSet/payment-type` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `Payment` | Payment | `PaymentReconciliation.detail.type.coding` | both | +| `RF` | RF | `PaymentReconciliation.detail.type.coding` | PMJAY | +| `TDS` | TDS | `PaymentReconciliation.detail.type.coding` | both | + +### `http://hl7.org/fhir/ValueSet/procedure-category` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `LM100` | LAMA DAMA Procedure (LAMA DAMA Procedure) | `InsurancePlan.plan.specificCost.benefit.type.coding` | PMJAY | +| `MG004A` | Dengue fever (Dengue fever) | `InsurancePlan.plan.specificCost.benefit.type.coding` | PMJAY | +| `MG005A` | Chikungunya fever (Chikungunya fever) | `InsurancePlan.plan.specificCost.benefit.type.coding` | PMJAY | +| `MG014A` | Liver abscess (Liver abscess) | `InsurancePlan.plan.specificCost.benefit.type.coding` | PMJAY | +| `MG072C` | Acute Haemodialysis (Acute Haemodialysis) | `InsurancePlan.plan.specificCost.benefit.type.coding` | PMJAY | +| `MO071R` | PemetrexedPemetrexed 500mg/m2 D1 every 21 days (CT for CA Lung) | `InsurancePlan.plan.specificCost.benefit.type.coding` | PMJAY | +| `SB043F` | Hand (Single Stage Amputation) | `InsurancePlan.plan.specificCost.benefit.type.coding` | PMJAY | +| `SBU100` | Unspecified Surgical Package (Unspecified Surgical Package) | `InsurancePlan.plan.specificCost.benefit.type.coding` | PMJAY | +| `SE004A` | Lid Tear Repair (Lid Tear Repair) | `InsurancePlan.plan.specificCost.benefit.type.coding` | PMJAY | +| `SE005A` | Lid Abscess Drainage (Lid Abscess Drainage) | `InsurancePlan.plan.specificCost.benefit.type.coding` | PMJAY | +| `SEU100` | Unspecified Surgical Package (Unspecified Surgical Package ) | `InsurancePlan.plan.specificCost.benefit.type.coding` | PMJAY | +| `SGU100` | Unspecified Surgical Package (Unspecified Surgical Package ) | `InsurancePlan.plan.specificCost.benefit.type.coding` | PMJAY | +| `SL026A` | Tracheostomy (Tracheostomy / Tracheotomy) | `InsurancePlan.plan.specificCost.benefit.type.coding` | PMJAY | +| `SL026B` | Tracheotomy (Tracheostomy / Tracheotomy) | `InsurancePlan.plan.specificCost.benefit.type.coding` | PMJAY | +| `ST009B` | Nerve and/or tendon injury. A. Wound exploration and closure. B. Nerve graft. C… | `InsurancePlan.plan.specificCost.benefit.type.coding` | PMJAY | + +### `http://snomed.info/sct` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `105461009` | Organ donor | `InsurancePlan.coverage.type.coding`, `InsurancePlan.coverage.benefit.type.coding` | generic | +| `223366009` | Healthcare professional (occupation) | `Claim.careTeam.role.coding`, `PractitionerRole.code.coding` | generic | +| `224663004` | Single room (environment) | `InsurancePlan.plan.specificCost.category.coding`, `InsurancePlan.plan.specificCost.benefit.type.coding` | generic | +| `24099007` | Oxygen (substance) | `InsurancePlan.coverage.benefit.type.coding` | generic | +| `307988006` | Medical technician | `PractitionerRole.code.coding` | both | +| `309904001` | Intensive care unit | `Claim.item.productOrService.coding`, `InsurancePlan.coverage.benefit.type.coding` | generic | +| `394658006` | Clinical specialty (qualifier value) | `Claim.careTeam.qualification.coding` | generic | +| `394802001` | General medicine | `Claim.careTeam.qualification.coding` | both | +| `409972000` | Pre-hospital care | `InsurancePlan.coverage.type.coding`, `InsurancePlan.coverage.benefit.type.coding` | generic | +| `414005` | Percutaneous Transluminal Coronary Angioplasty (PTCA) | `InsurancePlan.coverage.benefit.type.coding`, `InsurancePlan.plan.specificCost.benefit.type.coding` | generic | +| `418285008` | Angioplasty of blood vessel | `Claim.procedure.procedureCodeableConcept.coding`, `Claim.item.productOrService.coding` | generic | +| `427189009` | Paediatric Pneumonia, PICU Management | `InsurancePlan.coverage.benefit.type.coding`, `InsurancePlan.plan.specificCost.benefit.type.coding` | generic | +| `49122002` | Ambulance, device (physical object) | `InsurancePlan.coverage.type.coding`, `InsurancePlan.coverage.benefit.type.coding` | generic | +| `60689008` | Home care of patient | `InsurancePlan.plan.specificCost.category.coding`, `InsurancePlan.plan.specificCost.benefit.type.coding` | generic | +| `710967003` | Management of health status after discharge from hospital (procedure) | `InsurancePlan.coverage.type.coding`, `InsurancePlan.coverage.benefit.type.coding` | generic | +| `71388002` | Procedure (procedure) | `Procedure.code.coding` | both | +| `737481003` | Inpatient care management (procedure) | `Claim.type.coding`, `CoverageEligibilityResponse.insurance.item.productOrService.coding` | both | +| `737850002` | Day care case management (procedure) | `InsurancePlan.coverage.type.coding`, `InsurancePlan.coverage.benefit.type.coding` | generic | +| `77343006` | Angiography | `Claim.procedure.procedureCodeableConcept.coding`, `Claim.item.productOrService.coding` | generic | +| `86077009` | Operation for glaucoma | `InsurancePlan.extension.extension.valueCodeableConcept.coding` | generic | +| `87612001` | Blood | `InsurancePlan.coverage.benefit.type.coding` | generic | +| `89100005` | Final diagnosis (discharge) (contextual qualifier) (qualifier value) | `Claim.diagnosis.type.coding` | generic | + +### `http://snomed.info/sct0` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `305056002` | Admission procedure | `CoverageEligibilityResponse.insurance.item.productOrService.coding` | PMJAY | + +### `http://terminology.hl7.org/CodeSystem/adjudication` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `benefit` | Benefit Amount | `ClaimResponse.item.adjudication.category.coding`, `ClaimResponse.total.category.coding` | generic | +| `copay` | CoPay | `ClaimResponse.item.adjudication.category.coding` | generic | +| `eligible` | Eligible Amount | `ClaimResponse.item.adjudication.category.coding`, `ClaimResponse.total.category.coding` | generic | +| `submitted` | Submitted Amount | `ClaimResponse.item.adjudication.category.coding`, `ClaimResponse.total.category.coding` | generic | + +### `http://terminology.hl7.org/CodeSystem/benefit-type` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `benefit` | Benefit | `CoverageEligibilityResponse.insurance.item.benefit.type.coding` | both | + +### `http://terminology.hl7.org/CodeSystem/claimcareteamrole` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `primary` | Primary provider | `Claim.careTeam.role.coding` | both | + +### `http://terminology.hl7.org/CodeSystem/communication-category` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `alert` | | `CommunicationRequest.category.coding` | generic | +| `information` | Information | `Task.reasonCode.coding` | PMJAY | +| `notification` | Notification | `Communication.category.coding`, `CommunicationRequest.category.coding` | both | + +### `http://terminology.hl7.org/CodeSystem/coverage-class` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `plan` | Plan | `Coverage.class.type.coding` | generic | + +### `http://terminology.hl7.org/CodeSystem/ex-benefitcategory` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `30` | Health Benefit Plan Coverage | `CoverageEligibilityResponse.insurance.item.benefit.type.coding` | PMJAY | + +### `http://terminology.hl7.org/CodeSystem/ex-diagnosis-on-admission` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `yes` | Yes | `Claim.diagnosis.onAdmission.coding` | both | + +### `http://terminology.hl7.org/CodeSystem/ex-diagnosistype` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `admitting` | Admitting Diagnosis | `Claim.diagnosis.type.coding` | both | + +### `http://terminology.hl7.org/CodeSystem/financialtaskcode` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `cancel` | | `Task.code.coding` | both | +| `poll` | Poll | `Task.code.coding` | both | +| `release` | | `Task.code.coding` | generic | +| `reprocess` | | `Task.code.coding` | both | +| `status` | | `Task.code.coding` | both | + +### `http://terminology.hl7.org/CodeSystem/financialtaskinputtype` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `include` | Include | `Task.input.type.coding`, `Task.output.type.coding` | both | +| `status` | Status code | `Task.input.type.coding` | both | + +### `http://terminology.hl7.org/CodeSystem/organization-type` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `ins` | Insurance Company | `Organization.type.coding` | generic | +| `pay` | Payer | `Organization.type.coding` | both | +| `prov` | Healthcare Provider | `Organization.type.coding` | both | + +### `http://terminology.hl7.org/CodeSystem/payeetype` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `provider` | Provider | `ClaimResponse.payeeType.coding` | both | + +### `http://terminology.hl7.org/CodeSystem/paymentstatus` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `cleared` | Cleared | `PaymentNotice.paymentStatus.coding` | generic | +| `paid` | Paid | `PaymentNotice.paymentStatus.coding` | PMJAY | + +### `http://terminology.hl7.org/CodeSystem/processpriority` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `normal` | Normal | `CoverageEligibilityRequest.priority.coding`, `Claim.priority.coding` | both | + +### `http://terminology.hl7.org/CodeSystem/subscriber-relationship` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `self` | Self | `Coverage.relationship.coding` | both | + +### `http://terminology.hl7.org/CodeSystem/v2-0203` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `JHN` | Jurisdictional health number | `Patient.identifier.type.coding` | PMJAY | +| `MB` | Member Number | `Patient.identifier.type.coding`, `Task.for.identifier.type.coding` | both | +| `MD` | Medical License number | `Practitioner.identifier.type.coding` | generic | +| `NH` | National Health Plan Identifier | `Coverage.identifier.type.coding`, `InsurancePlan.identifier.type.coding` | both | +| `NIIP` | National Insurance Payor Identifier (Payor) | `Organization.identifier.type.coding` | both | +| `NPI` | National provider identifier | `Organization.identifier.type.coding` | both | +| `PI` | Patient internal identifier | `Patient.identifier.type.coding` | PMJAY | +| `PRN` | Provider number | `Organization.identifier.type.coding` | generic | +| `XV` | Health Plan Identifier | `Coverage.class.type.coding`, `InsurancePlan.identifier.type.coding` | both | + +### `http://terminology.hl7.org/CodeSystem/v2-0360` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `MD` | Doctor of Medicine | `Practitioner.qualification.code.coding` | both | + +### `http://terminology.hl7.org/CodeSystem/v3-ActCode` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `HIP` | health insurance plan policy | `Coverage.type.coding` | both | + +### `http://www.cms.gov/Medicare/Coding/ICD10` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `02703ZZ` | Percutaneous Transluminal Coronary Angioplasty (PTCA) | `InsurancePlan.coverage.benefit.type.coding`, `InsurancePlan.plan.specificCost.benefit.type.coding` | generic | +| `08RJ3JZ` | Cataract Surgery with Foldable IOL | `InsurancePlan.coverage.benefit.type.coding`, `InsurancePlan.plan.specificCost.benefit.type.coding` | generic | +| `0DTJ4ZZ` | Acute Appendectomy (Laparoscopic) | `InsurancePlan.coverage.benefit.type.coding`, `InsurancePlan.plan.specificCost.benefit.type.coding` | generic | +| `0SRC0JZ` | Total Knee Replacement (Unilateral) | `CoverageEligibilityResponse.insurance.item.productOrService.coding`, `InsurancePlan.coverage.benefit.type.coding` | generic | +| `5A09357` | Paediatric Pneumonia, PICU Management | `InsurancePlan.coverage.benefit.type.coding`, `InsurancePlan.plan.specificCost.benefit.type.coding` | generic | + +### `https://hl7.org/fhir/R4/codesystem-benefit-type.html` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `Procedure` | Procedure | `CoverageEligibilityResponse.insurance.item.benefit.type.coding` | PMJAY | + +### `https://hl7.org/fhir/R4/v2/0360/2.7/index.html` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `BSC NURSING` | BSC NURSING | `Practitioner.qualification.code.coding` | PMJAY | + +### `https://hl7.org/fhir/R4/valueset-adjudication.html` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `benefit` | Benefit Amount | `ClaimResponse.total.category.coding` | both | +| `eligible` | Eligible Amount | `ClaimResponse.item.adjudication.category.coding` | both | +| `eligpercent` | Eligible % | `ClaimResponse.item.adjudication.category.coding` | PMJAY | +| `eligquant` | Eligible Quantity | `ClaimResponse.item.adjudication.category.coding` | PMJAY | +| `incentive` | Hospital Incentive | `ClaimResponse.total.category.coding` | PMJAY | +| `reason` | Reason for Adjudication | `ClaimResponse.item.adjudication.category.coding` | both | +| `status` | Item adjudication status | `ClaimResponse.item.adjudication.category.coding` | both | +| `submitted` | Submitted Amount | `ClaimResponse.total.category.coding`, `ClaimResponse.item.adjudication.category.coding` | both | +| `tax` | Tax | `ClaimResponse.total.category.coding` | PMJAY | + +### `https://https://nrces.in/ndhm/fhir/r4/ValueSet-ndhm-identifier-type-code.html` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `PLAC` | Placer Identifier | `PaymentReconciliation.detail.identifier.type.coding` | both | + +### `https://nhcx.abdm.gov.in/category-code` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `MG` | General Medicine | `CoverageEligibilityRequest.item.category.coding` | both | +| `Surgical` | Surgical | `CoverageEligibilityRequest.item.category.coding` | generic | + +### `https://nhcx.abdm.gov.in/communication-reason` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `additionalinfo` | Additional information request | `Task.reasonCode.coding` | generic | +| `tatquery` | Turnaround time query | `Task.reasonCode.coding` | generic | + +### `https://nhcx.abdm.gov.in/document-code` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `CER` | Medical Certificate / Doctor Referral | `Claim.supportingInfo.code.coding` | generic | +| `DOC001` | Clinical notes and admission notes | `Claim.supportingInfo.code.coding` | generic | +| `DOC002` | Diagnostic imaging report | `Claim.supportingInfo.code.coding` | generic | +| `DOC003` | Investigations performed | `Claim.supportingInfo.code.coding` | generic | +| `DOC004` | Planned line of management | `Claim.supportingInfo.code.coding` | generic | +| `DOC101` | Internal case papers | `Claim.supportingInfo.code.coding` | generic | +| `DOC102` | Treatment details | `Claim.supportingInfo.code.coding` | generic | +| `DOC103` | All investigation reports | `Claim.supportingInfo.code.coding` | generic | +| `DOC104` | Discharge summary | `Claim.supportingInfo.code.coding` | generic | +| `EST` | Detailed Pre-Auth Cost Estimate | `Claim.supportingInfo.code.coding` | generic | +| `FCF` | Filled NHCX Claim Form (Signed) | `Claim.supportingInfo.code.coding` | generic | +| `HDS` | Hospital Discharge Summary | `Claim.supportingInfo.code.coding` | both | +| `IMP` | Medical Implant Invoice & Barcode Sticker | `Claim.supportingInfo.code.coding` | generic | +| `MAND0006` | Detailed discharge summary | `Claim.supportingInfo.code.coding` | generic | +| `MAND0062` | Detailed ICPs | `Claim.supportingInfo.code.coding` | generic | +| `MAND0063` | Treatment details | `Claim.supportingInfo.code.coding` | generic | +| `MAND0064` | All investigations reports | `Claim.supportingInfo.code.coding` | generic | +| `MAND0408` | Clinical notes detailing history and Admission notes showing vitals and examina… | `Claim.supportingInfo.code.coding` | both | +| `MAND0409` | Any investigations done | `Claim.supportingInfo.code.coding` | both | +| `MAND0455` | CXR PA view or CECT chest abdomen and pelvis | `Claim.supportingInfo.code.coding` | both | +| `MAND0570` | Planned line of management | `Claim.supportingInfo.code.coding` | both | +| `MB` | Medical & Pharmacy Bills Itemized | `Claim.supportingInfo.code.coding` | generic | +| `ODN` | Death Certificate | `Claim.supportingInfo.code.coding` | PMJAY | +| `OTR` | Operation Theatre Notes & Surgical Summary | `Claim.supportingInfo.code.coding` | generic | +| `POI` | Proof of Identity (Aadhaar / Passport / Voter ID) | `Claim.supportingInfo.code.coding` | generic | +| `RAD` | Radiology / X-Ray / CT / MRI Scan Reports | `Claim.supportingInfo.code.coding` | generic | + +### `https://nhcx.abdm.gov.in/procedure-type` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `conservative` | Conservative | `Claim.procedure.type.coding` | both | +| `medical` | Medical | `Claim.procedure.type.coding` | PMJAY | +| `STRAT001` | HDU | `CoverageEligibilityRequest.item.modifier.coding`, `Claim.item.modifier.coding` | generic | +| `surgical` | Surgical | `Claim.procedure.type.coding` | generic | + +### `https://nhcx.abdm.gov.in/product-code` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `MG004C` | Dengue shock syndrome (Dengue fever) | `CoverageEligibilityRequest.item.productOrService.coding` | generic | +| `MG0111A` | Pleural Effusion (Pleural Effusion) | `CoverageEligibilityRequest.item.productOrService.coding` | PMJAY | +| `MG072C` | Acute Haemodialysis (Acute Haemodialysis) | `CoverageEligibilityRequest.item.productOrService.coding` | PMJAY | +| `PROC-KNEE-01` | Total Knee Replacement (Unilateral) | `CoverageEligibilityRequest.item.productOrService.coding` | generic | + +### `https://nhcx.abdm.gov.in/task-input-type` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `amount` | Amount | `Task.input.type.coding` | generic | + +### `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-benefit-category` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `MG` | General Medicine | `Claim.item.category.coding`, `CoverageEligibilityRequest.item.category.coding` | both | +| `Surgical` | Surgical | `Claim.item.category.coding` | generic | + +### `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-claim-exclusion` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `Excl01` | Pre-Existing Diseases | `InsurancePlan.extension.extension.valueCodeableConcept.coding` | generic | +| `Excl02` | Specified disease/procedure waiting period | `InsurancePlan.extension.extension.valueCodeableConcept.coding` | generic | +| `Excl03` | 30-day waiting period | `InsurancePlan.extension.extension.valueCodeableConcept.coding` | generic | +| `Excl08` | Cosmetic or plastic Surgery | `InsurancePlan.extension.extension.valueCodeableConcept.coding` | generic | + +### `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `ABHA` | Ayushman Bharat Health Account (ABHA) ID | `Patient.identifier.type.coding` | both | +| `ADN` | Adhaar number | `Patient.identifier.type.coding` | both | +| `ClaimNumber` | Claim Number | `Task.input.type.coding` | generic | +| `CLN` | Claim number | `Claim.identifier.type.coding`, `Task.basedOn.identifier.type.coding` | both | +| `HPID` | Healthcare Professional ID (HPID) | `Practitioner.identifier.type.coding` | both | +| `HPIN` | Health Practitioner ID issued by NDHM | `Practitioner.identifier.type.coding` | both | +| `PMJAY` | Pradhan Mantri Jan Aarogya Yojana (PMJAY) ID | `Patient.identifier.type.coding`, `Task.for.identifier.type.coding` | both | +| `ROHINI` | Registry of Hospitals in Network of Insurance (ROHINI) ID | `Organization.identifier.type.coding` | generic | +| `UTR` | Unique Transaction Reference | `PaymentReconciliation.paymentIdentifier.type.coding` | both | + +### `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-insuranceplan-type` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `01` | Hospitalisation Indemnity Policy | `InsurancePlan.type.coding` | generic | +| `07` | Universal Health Policy | `InsurancePlan.type.coding` | PMJAY | + +### `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-plan-type` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `01` | Individual | `InsurancePlan.plan.type.coding` | generic | +| `03` | Group | `InsurancePlan.plan.type.coding` | PMJAY | +| `Procedure` | Selected treatment or service or product is a type of procedure or package | `InsurancePlan.plan.specificCost.benefit.cost.type.coding` | generic | + +### `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-procedure-code` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `MG001A` | Sample package | `CoverageEligibilityRequest.item.productOrService.coding`, `CoverageEligibilityResponse.insurance.item.productOrService.coding` | generic | +| `MG004B` | Dengue hemorrhagic fever | `Claim.item.productOrService.coding` | generic | +| `MG0111A` | Pleural Effusion | `Claim.item.productOrService.coding` | both | +| `MG072C` | Acute Haemodialysis (Acute Haemodialysis) | `Claim.item.productOrService.coding` | PMJAY | +| `PROC-APP-02` | Acute Appendectomy (Laparoscopic) | `Claim.item.productOrService.coding` | generic | +| `PROC-KNEE-01` | Total Knee Replacement (Unilateral) | `Claim.item.productOrService.coding` | generic | + +### `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-program-code` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `AB-PMJAY` | Ayushman Bharat Pradhan Mantri Jan Arogya Yojana (AB-PMJAY) | `Claim.item.programCode.coding` | both | + +### `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-reason-code` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `additionalinfo` | Additional Information Request | `Task.reasonCode.coding`, `CommunicationRequest.reasonCode.coding` | generic | +| `administrativeerror` | Administrative error | `Task.reasonCode.coding` | PMJAY | +| `claimrejected` | Reprocess request due to claim rejected by payer | `Task.reasonCode.coding` | both | +| `partialpayment` | Reprocess request due to partial payment by payer | `Task.reasonCode.coding` | generic | +| `treatmentplanchanged` | Treatment plan changed during hospitalization. | `Task.reasonCode.coding` | generic | + +### `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `CD` | Clinical document | `InsurancePlan.coverage.benefit.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.valueCodeableConcept.coding` | both | +| `CER` | Medical Certficate | `InsurancePlan.coverage.benefit.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.valueCodeableConcept.coding` | generic | +| `DIA` | Diagnostic report | `InsurancePlan.coverage.benefit.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.valueCodeableConcept.coding` | both | +| `DIS` | Discharge status and discharge to location detail | `Claim.supportingInfo.category.coding` | both | +| `FCF` | Filled claim form | `InsurancePlan.coverage.benefit.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.valueCodeableConcept.coding` | generic | +| `HDS` | Hospital discharge summary | `Claim.supportingInfo.category.coding`, `InsurancePlan.coverage.benefit.extension.extension.valueCodeableConcept.coding` | both | +| `IMP` | Document Type - Implant | `InsurancePlan.coverage.benefit.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.valueCodeableConcept.coding` | generic | +| `INF` | Information | `Claim.supportingInfo.category.coding`, `InsurancePlan.coverage.benefit.extension.extension.valueCodeableConcept.coding` | both | +| `INV` | Document Type - Investigation | `Claim.supportingInfo.category.coding` | both | +| `MB` | Medical bill | `InsurancePlan.coverage.benefit.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.valueCodeableConcept.coding` | generic | +| `NMI` | Claim query detail | `Claim.supportingInfo.category.coding` | both | +| `ONS` | Period, start or end dates of aspects of the Condition. (e.g. admission, discha… | `Claim.supportingInfo.category.coding` | both | +| `OTH` | Other | `Claim.supportingInfo.category.coding` | both | +| `POI` | Proof of identity | `InsurancePlan.coverage.benefit.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.valueCodeableConcept.coding` | both | +| `STG` | Total Knee Replacement (Unilateral), Standard Treatment Guidelines | `CoverageEligibilityResponse.insurance.item.authorizationSupporting.coding`, `InsurancePlan.coverage.benefit.extension.extension.valueCodeableConcept.coding` | both | + +### `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-code` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `ADDD` | Admission date -Discharge date | `Claim.supportingInfo.code.coding` | both | +| `CQD` | Claim query detail | `Claim.supportingInfo.code.coding` | both | +| `DSDE` | Discharge start-discharge end time | `Claim.supportingInfo.code.coding` | both | +| `DTH` | DischargeToHome (Discharge disposition status) | `Claim.supportingInfo.code.coding` | both | +| `DTM` | DischargetoMortuary | `Claim.supportingInfo.code.coding` | PMJAY | +| `EDT` | EncounterDateTime | `Claim.supportingInfo.code.coding` | both | +| `ODN` | Other document | `Claim.supportingInfo.code.coding` | both | +| `PSP` | PatientSurgeryPerformed(startdatetime-enddatetime) | `Claim.supportingInfo.code.coding` | both | + +### `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-codes` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `deliver` | deliver | `Task.code.coding` | both | +| `search` | Search | `Task.code.coding` | generic | + +### `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `claimNumber` | ClaimNumber | `Task.input.type.coding`, `Task.output.type.coding` | both | +| `document` | Document | `Task.input.type.coding` | both | +| `intimationNumber` | Intimation Number | `Task.input.type.coding` | both | +| `policyNumber` | | `Task.input.type.coding` | both | +| `providerId` | | `Task.input.type.coding` | both | + +### `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-output-type` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `status` | Status | `Task.output.type.coding` | both | + +### `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-output-value` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `paymentack` | Payment is acknowledged | `Task.output.valueCodeableConcept.coding` | both | +| `taskak` | Requested task is acknowledged | `Task.output.valueCodeableConcept.coding` | generic | + +### `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-benefitcategory` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `MG` | General Medicine | `InsurancePlan.coverage.type.coding`, `InsurancePlan.plan.specificCost.category.coding` | PMJAY | +| `MO` | Medical Oncology | `InsurancePlan.coverage.type.coding`, `InsurancePlan.plan.specificCost.category.coding` | PMJAY | +| `SB` | Orthopaedics | `InsurancePlan.coverage.type.coding`, `InsurancePlan.plan.specificCost.category.coding` | PMJAY | +| `SC` | Surgical Oncology | `InsurancePlan.coverage.type.coding` | PMJAY | +| `SE` | Opthalmology | `InsurancePlan.coverage.type.coding`, `InsurancePlan.plan.specificCost.category.coding` | PMJAY | +| `SG` | General Surgery | `InsurancePlan.coverage.type.coding`, `InsurancePlan.plan.specificCost.category.coding` | PMJAY | +| `SU` | Urology | `InsurancePlan.coverage.type.coding` | PMJAY | + +### `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-claim-type` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `737481003` | Inpatient care management (procedure) | `ClaimResponse.type.coding` | both | +| `737492002` | Outpatient care management (procedure) | `ClaimResponse.type.coding` | PMJAY | + +### `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-productorservice` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `LM100` | LAMA DAMA Procedure (LAMA DAMA Procedure) | `InsurancePlan.coverage.benefit.type.coding` | PMJAY | +| `MG004A` | Dengue fever (Dengue fever) | `InsurancePlan.coverage.benefit.type.coding` | PMJAY | +| `MG005A` | Chikungunya fever (Chikungunya fever) | `InsurancePlan.coverage.benefit.type.coding` | PMJAY | +| `MG014A` | Liver abscess (Liver abscess) | `InsurancePlan.coverage.benefit.type.coding` | PMJAY | +| `MG072C` | Acute Haemodialysis (Acute Haemodialysis) | `InsurancePlan.coverage.benefit.type.coding` | PMJAY | +| `MO071R` | PemetrexedPemetrexed 500mg/m2 D1 every 21 days (CT for CA Lung) | `InsurancePlan.coverage.benefit.type.coding` | PMJAY | +| `SB043F` | Hand (Single Stage Amputation) | `InsurancePlan.coverage.benefit.type.coding` | PMJAY | +| `SBU100` | Unspecified Surgical Package (Unspecified Surgical Package) | `InsurancePlan.coverage.benefit.type.coding` | PMJAY | +| `SC006A` | Open-Transthoracic esophagectomy: 2F / 3F (Transthoracic esophagectomy: 2F / 3F) | `InsurancePlan.coverage.benefit.type.coding` | PMJAY | +| `SCU100` | Unspecified Surgical Package (Unspecified Surgical Package) | `InsurancePlan.coverage.benefit.type.coding` | PMJAY | +| `SE004A` | Lid Tear Repair (Lid Tear Repair) | `InsurancePlan.coverage.benefit.type.coding` | PMJAY | +| `SE005A` | Lid Abscess Drainage (Lid Abscess Drainage) | `InsurancePlan.coverage.benefit.type.coding` | PMJAY | +| `SEU100` | Unspecified Surgical Package (Unspecified Surgical Package ) | `InsurancePlan.coverage.benefit.type.coding` | PMJAY | +| `SGU100` | Unspecified Surgical Package (Unspecified Surgical Package ) | `InsurancePlan.coverage.benefit.type.coding` | PMJAY | +| `SL026A` | Tracheostomy (Tracheostomy / Tracheotomy) | `InsurancePlan.coverage.benefit.type.coding` | PMJAY | +| `SL026B` | Tracheotomy (Tracheostomy / Tracheotomy) | `InsurancePlan.coverage.benefit.type.coding` | PMJAY | +| `SL032B` | Translabyrinthine approach (Advanced lateral skull base surgery) | `InsurancePlan.coverage.benefit.type.coding` | PMJAY | +| `ST009B` | Nerve and/or tendon injury. A. Wound exploration and closure. B. Nerve graft. C… | `InsurancePlan.coverage.benefit.type.coding` | PMJAY | +| `STRAT003a` | Local Anesthesia | `InsurancePlan.plan.specificCost.benefit.cost.qualifiers.coding` | PMJAY | +| `STRAT003b` | General Anesthesia | `InsurancePlan.plan.specificCost.benefit.cost.qualifiers.coding` | PMJAY | +| `STRAT006a` | Routine Ward | `InsurancePlan.plan.specificCost.benefit.cost.qualifiers.coding` | PMJAY | +| `STRAT006b` | HDU | `InsurancePlan.plan.specificCost.benefit.cost.qualifiers.coding` | PMJAY | +| `STRAT006c` | ICU - Without Ventilator | `InsurancePlan.plan.specificCost.benefit.cost.qualifiers.coding` | PMJAY | +| `STRAT006d` | ICU - With Ventilator | `InsurancePlan.plan.specificCost.benefit.cost.qualifiers.coding` | PMJAY | +| `SU037A` | Acute management of upper urinary tract trauma – conservative ( (1-5 days)plus … | `InsurancePlan.coverage.benefit.type.coding` | PMJAY | + +### `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `ADN` | Aadhaar Number | `InsurancePlan.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0003` | Clinical notes | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0006` | Detailed discharge summary | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0008` | Detailed Procedure / Operative Notes | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0030` | Procedure / Operative Notes | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0062` | Detailed ICPs | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0063` | Treatment details | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0064` | All investigations reports | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0067` | CBC | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0074` | LFT | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0099` | BAR CODE OF THE DRUGS | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0100` | REPORTS OF THE TESTS (PATHOLOGY, RADIOLOGY, MICROBIOLOGY, HEMATOLOGY, BIOCHEMIS… | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0101` | DISCHARGE SUMMARY OF INPATIENT DEPARTMENT / DISCHARGE SUMMARY OF DAY CARE DEPAR… | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0102` | CHARTS OF CHEMOTHERAPY REGIMEN | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0103` | TRANFUSION SLIPS | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0112` | Post Procedure clinical photgraph | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0151` | Post Procedure Photographs of surgical site | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0152` | HPE report | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0159` | Still image of the the procedure with pt. ID and date | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0161` | operative notes | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0162` | Discharge notes | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0163` | microbiology report | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0164` | Still image of the patient undergoing the procedure with date stamp | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0189` | Histopathology report | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0226` | Post Procedure Photograph of affected part | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0300` | Detailed operatives notes | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0309` | Intra operative still photograph | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0326` | Reports of all investigations done and consultation paper of treating doctor me… | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0327` | Detailed discharge summary; | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0339` | Clinical notes with planned line of treatment | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0368` | Procedure / Operative Notes, Detailed Discharge Summary | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0384` | MLC/ FIR if traumatic | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0408` | Clinical notes detailing history and Admission notes showing vitals and examina… | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0409` | any investigations done | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0447` | RFT | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0457` | RBS | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0459` | CECT Thorax, abdomen and Pelvis | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0564` | histopathology (non small cell - adenocarcinoma or adenosquamous carcinoma) | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0582` | clinical photograph of affected part | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0588` | clinical photograph | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0592` | X Ray of affected limb | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0604` | clinical notes justifying the indication | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0621` | FNAC/ BIOPSY | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0622` | CECT | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0647` | FIR/MLC in case of accident | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0648` | Patient details | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0649` | doctors notes | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0650` | photo | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0730` | USG/CT Abdomen | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0822` | Clinical notes with planned line of treatment justifying indication | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0831` | Audiogram report justfying surgery | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0832` | CT- TEMPORAL BONE of affected side /X-RAY BOTH MASTOIDS | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0946` | Clinical notes detailing the injury and need of surgery | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND0952` | MLC/ FIR +/- Nerve conduction velocity (NCV) + /- MRI + /- MRA + /- EMG (Electr… | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `MAND1045` | Clinical notes with planned line of treatment (including indication for need of… | `InsurancePlan.coverage.benefit.extension.extension.extension.valueCodeableConcept.coding`, `InsurancePlan.plan.specificCost.benefit.extension.extension.extension.valueCodeableConcept.coding` | PMJAY | +| `ODN` | Other document | `InsurancePlan.extension.extension.valueCodeableConcept.coding` | PMJAY | + +### `https://payer.pmjay.nha.gov.in` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `A97.0` | Dengue without warning signs | `CoverageEligibilityRequest.item.diagnosis.diagnosisCodeableConcept.coding` | PMJAY | +| `MG004A` | Dengue fever | `CoverageEligibilityRequest.item.productOrService.coding` | PMJAY | + +### `https://terminology.hl7.org/6.5.0/CodeSystem-subscriber-relationship.html` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `child` | Child | `Coverage.relationship.coding` | PMJAY | + +### `https://www.nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-plan-type` + +| Code | Display | Where | Used by | +| :-- | :-- | :-- | :-- | +| `Procedure` | Selected treatment or service or proudct is a type of procedure or package | `InsurancePlan.plan.specificCost.benefit.cost.type.coding` | PMJAY | +| `Stratification` | Selected treatment or service or proudct is a type of stratification | `InsurancePlan.plan.specificCost.benefit.cost.type.coding` | PMJAY | + +## Value sets + +The codes the specifications define beyond those the bundles carry. + +### Supporting-info categories + +System `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category`. + +| Code | Meaning | Notes | +| :-- | :-- | :-- | +| `ONS` | Period, start or end dates | date-time string | +| `OTH` | Other | date-time string | +| `INV` | Investigation | reference | +| `ATT` | Attachment | attachment | +| `HDS` | Hospital discharge summary | reference | +| `DGN` | Diagnosis | reference | +| `LAB` | Lab test | reference | +| `AOB` | Onset of current symptoms | value | +| `MB` | Medical bill | attachment | +| `DIA` | Diagnostic report | reference | +| `CD` | Clinical document | reference | +| `INF` | Information | reference | +| `DIS` | Discharge status | string | +| `NMI` | Query remarks | string | +| `POI` | Proof of identity | attachment | +| `POA` | Proof of address | attachment | +| `DOB` | Proof of birth | attachment | +| `DEF` | Declaration | attachment | +| `FIR` | First information report | attachment | +| `EMP` | Proof of employment | attachment | +| `STG` | Standard treatment guideline questionnaire | reference | +| `ADMD` | Admission date | date-time string | +| `SURD` | Surgery date | date-time string | +| `DSCHD` | Discharge date | date-time string | + +### Supporting-info codes + +System `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code`. + +| Code | Meaning | Notes | +| :-- | :-- | :-- | +| `EDT` | EncounterDateTime | | +| `ADDD` | Admission date - Discharge date | | +| `PSP` | PatientSurgeryPerformed | | +| `DSDE` | Discharge Date | | +| `DTH` | DischargeToHome | | +| `DTM` | DischargetoMortuary | Also the death date under `ONS` | +| `LAMA` | Discharge with LAMA | | +| `DAMA` | Discharge with DAMA | | +| `DIS` | Discharge Summary | | +| `AT` | Questionnaire answers | Under `INF` | +| `ODN` | Policy-level questionnaire | Under `INF` | +| `CQD` | Case remarks for a query answer | Under `NMI` | +| `BCF` | Birth certificate | | +| `DCB` | Discharge card for birth of a child | | +| `MAND…` | Mandatory documents | Defined by the plan; the auth-requirements answer returns the ones a package needs | + +### Identifier types + +| Code | Meaning | Notes | +| :-- | :-- | :-- | +| `PMJAY` | Scheme member id | NRCeS | +| `ABHA` | ABHA number, no hyphens | NRCeS | +| `CLN` | Claim number | NRCeS | +| `UTR` | Bank transaction reference | NRCeS | +| `HPID` | Healthcare professional id | NRCeS | +| `HPIN` | Health practitioner id | NRCeS | +| `NPI` | Provider's HFR ID | HL7 v2-0203 | +| `NIIP` | Payer's registry ID | HL7 v2-0203 | +| `NH` | Plan identifier | HL7 v2-0203 | +| `JHN` | Jurisdictional health number | HL7 v2-0203 | +| `MD` | Medical registration number | HL7 v2-0203 | +| `MR` | Medical record number | HL7 v2-0203 | + +### Adjudication + +| Code | Meaning | Notes | +| :-- | :-- | :-- | +| `submitted` | Amount asked | category | +| `eligible` | Amount allowed | category | +| `benefit` | Amount payable | category | +| `copay` | Co-payment | category | +| `eligpercent` | Percentage allowed | category | +| `eligquant` | Quantity allowed | category | +| `reason` | Free-text reason | category | +| `status` | Decision | category | +| `deductible` | Deduction with its reason | category | +| `tax` | Tax | total | +| `incentive` | Hospital incentive | total | +| `approved` | Approved | claim-level reason | +| `queried` | Queried | claim-level reason | +| `cancelled` | Cancelled or rejected | claim-level reason | +| `rejected` | Rejected | claim-level reason | + +### Task codes + +| Code | Meaning | Notes | +| :-- | :-- | :-- | +| `poll` | Poll | financialtaskcode | +| `cancel` | Cancel | financialtaskcode | +| `reprocess` | Reprocess | financialtaskcode | +| `release` | Release | financialtaskcode | +| `status` | Status | financialtaskcode | +| `nullify` | Close a claim the provider submitted | financialtaskcode | +| `suspend` | Suspend a preauthorisation or claim the provider submitted; no exchange carries it | financialtaskcode | +| `search` | Search | NHCX value set | +| `deliver` | Deliver | ndhm-task-codes | +| `approve` | Approve | task-code | + +### Task reasons + +| Code | Meaning | Notes | +| :-- | :-- | :-- | +| `treatmentplanchanged` | Treatment plan changed | cancel | +| `patientrequest` | Patient request | cancel | +| `financialconstraints` | Financial constraints | cancel | +| `alternativetreatment` | Alternative treatment | cancel | +| `duplicateclaim` | Duplicate claim | cancel | +| `administrativeerror` | Administrative error | cancel | +| `other` | Other | cancel | +| `claimrejected` | Claim rejected | reprocess | +| `partialpayment` | Partial payment | reprocess, release | +| `erroneousclaim` | Erroneous claim | reprocess | +| `referred` | Referred | reprocess | +| `erroneousregistration` | Erroneous registration | reprocess | +| `wrongdiagnosis` | Wrong diagnosis | reprocess | +| `tatquery` | Turnaround alert | communication | +| `grievance` | Grievance | communication | +| `walletupdate` | Wallet update | communication | +| `policychange` | Policy change | communication | +| `additionalinfo` | Additional information | communication | +| `claimArbitration` | Claim arbitration | communication | + +### Task input types and output values + +System `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code`. + +| Code | Meaning | Notes | +| :-- | :-- | :-- | +| `PayerId` | Payer | input | +| `ProviderId` | Provider | input | +| `PolicyNumber` | Policy | input | +| `ProductNumber` | Product | input | +| `ClaimNumber` | Case number | input | +| `IntimationNumber` | Intimation number | input | +| `FromDate` | Search window start | input | +| `ToDate` | Search window end | input | +| `FinanceYear` | Financial year | input | +| `ServiceCode` | Benefit or service | input | +| `paymentack` | Payment acknowledged | output | +| `claimcancelled` | Claim cancelled | output | +| `claimreinitiated` | Claim reinitiated | output | +| `claimsuspended` | Claim suspended | output | +| `taskak` | Task acknowledged | output | +| `taskdelivered` | Task delivered | output | + +### Money types on a reconciliation + +| Code | Meaning | Notes | +| :-- | :-- | :-- | +| `approvedamount` | Approved amount | | +| `claimedamount` | Claimed amount | | +| `tds` | Tax deducted at source | | +| `servicetax` | Service tax | | +| `advance` | Advance | | +| `recovered` | Recovered | | +| `penality` | Penalty, spelled so | | +| `Payment` | The net line | | + +### Deduction reasons + +| Code | Meaning | Notes | +| :-- | :-- | :-- | +| `Non-CoveredService` | Service not covered | | +| `ExceededCoverageLimit` | Coverage limit exceeded | | +| `DuplicateClaim` | Duplicate claim | | +| `Coordination-of-Benefits` | Coordination of benefits | | +| `IncompleteDocumentation` | Incomplete documentation | | +| `PolicyDeductible` | Policy deductible | | +| `Co-Payment` | Co-payment | | +| `FraudulentClaim` | Fraudulent claim | | +| `MedicalNecessity` | Medical necessity | | +| `BenefitLimitReached` | Benefit limit reached | | +| `MissedFilingDeadline` | Missed filing deadline | | +| `PaymentAlreadyMade` | Payment already made | | + +### Claim error codes + +Adjudication reasons a payer gives on a claim, from the value-set sheet of the requests-and-responses workbook. Meanings are as that sheet gives them, spelling included. `ClaimError-1` is a deduction and sits among the deduction reasons there. `ClaimError-16` to `ClaimError-27` repeat earlier texts, as noted. + +| Code | Meaning | Notes | +| :-- | :-- | :-- | +| `ClaimError-1` | There is an error in the claim submission, leading to a deduction until the correct information is provided. | | +| `ClaimError-2` | Claim has been rejected due to less than 24 hours of hospitalization | | +| `ClaimError-3` | Claim has been rejected as the Package is Reserved to Public Hospital | | +| `ClaimError-4` | Claim has been closed due to Incomplete submission of documents by hospital after multiple queries | | +| `ClaimError-5` | Claim has been rejected as there was misrepresentation of bed category booked | | +| `ClaimError-6` | Claim has been rejected due to Outside Scope of cover (Exclusions as per scheme) | | +| `ClaimError-7` | Claim has been rejected as the claim was found be False/Fraudulent | | +| `ClaimError-8` | Claim has been rejected due to Mismatch of package and disease/diagnosis/treatment | | +| `ClaimError-9` | Claim has been rejected due to Hospital not empanelled for this speciality | | +| `ClaimError-10` | Claim has been closed due to non submission of the documents | | +| `ClaimError-11` | Claim rejected as the treatment provided does not support the blocked package, request you to book a fresh relevant package | | +| `ClaimError-12` | Claim has been closed as the photo of the operative site is not available | | +| `ClaimError-13` | Claim has been rejected due to apparent manipulation in medical record | | +| `ClaimError-14` | Claim has been rejected as the hospital expenses have been paid by patient | | +| `ClaimError-15` | Claim has been closed due Missing Pre-Auth patient photo/post operative photo/After discharge photo | | +| `ClaimError-16` | Claim has been rejected due to less tha 24 hours of hospitalization | Same as `ClaimError-2` | +| `ClaimError-17` | Claim has been closed as Referral Letter Mandatory for Package Selected has not been provided | | +| `ClaimError-18` | Claim has been rejected as the need for hospitalization was not justified based on the availabe documents | | +| `ClaimError-19` | Claim has been rejected as the Package is Reserved to Public Hospital | Same as `ClaimError-3` | +| `ClaimError-20` | Claim has been closed due to Incomplete submission of documents by hospital after multiple queries | Same as `ClaimError-4` | +| `ClaimError-21` | Claim has been rejected as there was misrepresentation of bed category booked | Same as `ClaimError-5` | +| `ClaimError-22` | Claim has been rejected due to Outside Scope of cover (Exclusions as per scheme) | Same as `ClaimError-6` | +| `ClaimError-23` | Claim has been rejected as the claim was found be False/Fraudulent | Same as `ClaimError-7` | +| `ClaimError-24` | Claim has been rejected due to Mismatch of package and disease/diagnosis/treatment | Same as `ClaimError-8` | +| `ClaimError-25` | Claim has been rejected due to Hospital not empanelled for this speciality | Same as `ClaimError-9` | +| `ClaimError-26` | Claim has been closed due to non submission of the documents | Same as `ClaimError-10` | +| `ClaimError-27` | Claim rejected as the treatment provided does not support the blocked package, request you to book a fresh relevant package | Same as `ClaimError-11` | +| `ClaimError-28` | Others | | + +### Preauthorisation error codes + +Adjudication reasons a payer gives on a preauthorisation, from the same sheet, meanings as it gives them. No `PreauthError-14` is defined: the list runs to 13, then 15. + +| Code | Meaning | Notes | +| :-- | :-- | :-- | +| `PreauthError-1` | Pre-Auth has been rejected as the diagnosis is outside Scope of cover (Exclusions as per scheme) | | +| `PreauthError-2` | Pre-auth has been rejected due to delay in raising enhancement requests | | +| `PreauthError-3` | Pre-Auth has been rejected as it was found to be False/Fraudulent | | +| `PreauthError-4` | Pre-Auth has been closed due to delay in preauth Intimation (as per state guidelines) | | +| `PreauthError-5` | Pre-Auth has been rejected as the Hospital is not empanelled for this speciality | | +| `PreauthError-6` | Pre- Auth has been rejected due to mismatch in dialysis records | | +| `PreauthError-7` | Enhancement request rejected as the medical necessity of enhancement request not met | | +| `PreauthError-8` | Pre-Auth rejected as the Medical necessity of ICU bed category not met | | +| `PreauthError-9` | Pre-Auth has been rejected as the package selected is reserved for public hospital | | +| `PreauthError-10` | Pre-Auth has been closed due to non submision of mandatory document as per STG | | +| `PreauthError-11` | Pre-Auth has been rejected as the Surgery was Done Before Pre auth Approval | | +| `PreauthError-12` | Pre-auth enhancement rejected due to missing patient photo to depict bed category | | +| `PreauthError-13` | Pre-Auth has been rejected as the diagnosis is outside Scope of cover (Exclusions as per scheme) | Same as `PreauthError-1` | +| `PreauthError-15` | Others | | + +## Where the systems are wrong + +The code is usually right. The system it is bound to often is not. Match on the code, and take the system from the exchange you are building. + +| What | The problem | +| :-- | :-- | +| Package codes | The same code appears under a payer host, under SNOMED and under two ValueSet URLs, depending on the exchange. None is a SNOMED concept | +| Supporting-info category | Document entries bind `category` to the supporting-info code system rather than the category system; the plan does the reverse | +| Claim.type | Binds to a ValueSet URL where a CodeSystem URL belongs | +| Adjudication categories | Some senders bind them to an HTML documentation page, `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| Plan cost types | Bind to the plan-type system under a `www.` host, with values that are not plan types | +| Missing systems | `deductible`, the claim-level status and some package codings carry no `system` at all | diff --git a/site/docs/nhcx/v1/reference/fhir/communication.md b/site/docs/nhcx/v1/reference/fhir/communication.md new file mode 100644 index 000000000..45b1f985c --- /dev/null +++ b/site/docs/nhcx/v1/reference/fhir/communication.md @@ -0,0 +1,301 @@ +--- +title: Communication +sidebar_label: Communication +sidebar_position: 17 +description: Out-of-band communication payloads and reason codes +verification: unverified +source: nhcx-package/docs/05-FHIR Reference/17-Communication.md +generated: true +--- + +# Communication + +The payer's asynchronous channel to the provider: a turnaround alert, a grievance, a policy or wallet change, or a request for documents. The provider acknowledges within thirty seconds, whether or not the issue is resolved. + +## The request + +Sent on `/v1/communication/request`. + +### The bundle + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `Task` | [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html) | +| 2 | `CommunicationRequest` | [CommunicationRequest](https://nrces.in/ndhm/fhir/r4/StructureDefinition-CommunicationRequest.html) | +| 3 | `Claim` | [Claim](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Claim.html) | +| 4 | `Patient` | [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html) | +| 5 | `Organization (ins)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 6 | `Organization (prov)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 7 | `Practitioner` | [Practitioner](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Practitioner.html) | +| 8 | `Coverage` | [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html) | + +### Elements + +#### 1. Task + +NRCeS profile: [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html). + +| Element | Example | +| :-- | :-- | +| `status` | `requested` | +| `intent` | `order` | +| `reasonCode.coding[]` | `additionalinfo` Additional Information Request in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-reason-code` | +| `code.coding[]` | `poll` in `http://terminology.hl7.org/CodeSystem/financialtaskcode` | +| `description` | `Share the pre-operative X-ray and the clinical notes.` | +| `authoredOn` | `2026-09-10T23:51:47+05:30` | +| `requester` | reference `urn:uuid:39cd4b51-bddd-5cc1-a65a-6fa4a2a83cb5`, display `Organization` | +| `owner` | reference `urn:uuid:84d112ec-041c-57f8-986c-6619ccd8245e`, display `Organization` | +| `input[].type.coding[]` | `include` in `http://terminology.hl7.org/CodeSystem/financialtaskinputtype` | +| `input[].valueReference` | reference `urn:uuid:4b35a6eb-3f99-5d0c-b0c8-5b2f049fdbde`, display `CommunicationRequest` | + +#### 2. CommunicationRequest + +NRCeS profile: [CommunicationRequest](https://nrces.in/ndhm/fhir/r4/StructureDefinition-CommunicationRequest.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | value `NM-26-0SE00002I` | +| `basedOn[]` | reference `urn:uuid:c1a17d6e-c718-58de-8d3d-fd4c0607d729`, display `Claim-preauth` | +| `status` | `active` | +| `category[].coding[]` | `alert` in `http://terminology.hl7.org/CodeSystem/communication-category` | +| `priority` | `routine` | +| `payload[]` | contentString `Share the pre-operative X-ray and the clinical notes.` | +| `authoredOn` | `2026-09-10T23:51:47+05:30` | +| `requester` | reference `urn:uuid:39cd4b51-bddd-5cc1-a65a-6fa4a2a83cb5`, display `Organization` | +| `recipient[]` | reference `urn:uuid:84d112ec-041c-57f8-986c-6619ccd8245e`, display `Organization` | +| `sender` | reference `urn:uuid:39cd4b51-bddd-5cc1-a65a-6fa4a2a83cb5`, display `Organization` | +| `reasonCode[]` | text `Share the pre-operative X-ray and the clinical notes.` | +| `reasonCode[].coding[]` | `additionalinfo` Additional Information Request in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-reason-code` | + +The `Claim`, `Patient`, `Organization`, `Practitioner`, `Coverage` entries are shaped as in the chapters that introduce them. + +## A notification + +Sent on `/v1/communication/request`, workflow N02. + +### The bundle + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `Task` | none declared; NRCeS [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html) | +| 2 | `CommunicationRequest` | none declared; NRCeS [CommunicationRequest](https://nrces.in/ndhm/fhir/r4/StructureDefinition-CommunicationRequest.html) | +| 3 | `Organization (pay)` | none declared; NRCeS [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 4 | `Organization (prov)` | none declared; NRCeS [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | + +### Elements + +#### 1. Task + +NRCeS profile: [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html). + +| Element | Example | +| :-- | :-- | +| `status` | `completed` | +| `intent` | `proposal` | +| `code.coding[]` | `poll` Poll in `http://terminology.hl7.org/CodeSystem/financialtaskcode` | +| `reasonCode.coding[]` | `information` Information in `http://terminology.hl7.org/CodeSystem/communication-category` | +| `input[].type.coding[]` | `include` Include in `http://terminology.hl7.org/CodeSystem/financialtaskinputtype` | +| `input[].valueReference` | reference `https://payer.pmajy.nha.gov.in/CommunicationRequest/1a857700-c6f3-49e1-b5d1-049…`, display `Communication` | + +#### 2. CommunicationRequest + +NRCeS profile: [CommunicationRequest](https://nrces.in/ndhm/fhir/r4/StructureDefinition-CommunicationRequest.html). + +| Element | Example | +| :-- | :-- | +| `status` | `completed` | +| `category[].coding[]` | `notification` Notification in `http://terminology.hl7.org/CodeSystem/communication-category` | +| `payload[]` | contentString `Required Message for the provider` | +| `recipient[]` | reference `https://payer.nha.gov.in/v1/communication/request/organization/provider/1000003…` | +| `sender` | reference `https://payer.nha.gov.in/v1/communication/request/organization/payer/1518@hcx` | + +The `Organization` entries are shaped as in the chapters that introduce them. + +## The acknowledgement + +Sent on `/v1/communication/on_request`. + +### The bundle + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `Task` | [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html) | +| 2 | `Communication` | [Communication](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Communication.html) | +| 3 | `CommunicationRequest` | [CommunicationRequest](https://nrces.in/ndhm/fhir/r4/StructureDefinition-CommunicationRequest.html) | +| 4 | `Claim` | [Claim](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Claim.html) | +| 5 | `Patient` | [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html) | +| 6 | `Organization (prov)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 7 | `Organization (pay)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 8 | `Practitioner` | [Practitioner](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Practitioner.html) | +| 9 | `Coverage` | [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html) | + +### Elements + +#### 1. Task + +NRCeS profile: [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html). + +| Element | Example | +| :-- | :-- | +| `authoredOn` | `2026-03-08T11:01:00+05:30` | +| `code.coding[]` | `deliver` in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-codes` | +| `input[].type.coding[]` | `include` in `http://terminology.hl7.org/CodeSystem/financialtaskinputtype` | +| `input[].valueReference` | display `Communication`, reference `urn:uuid:7d9e2a64-3b1f-4f0c-8a5e-6c4b2d9f1e37` | +| `intent` | `order` | +| `owner` | display `Organization`, reference `https://nhcx.abdm.gov.in/payer` | +| `reasonCode.coding[]` | `additionalinfo` Additional information request in `https://nhcx.abdm.gov.in/communication-reason` | +| `requester` | display `Organization`, reference `https://nhcx.abdm.gov.in/provider` | +| `status` | `completed` | + +#### 2. Communication + +NRCeS profile: [Communication](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Communication.html). + +| Element | Example | +| :-- | :-- | +| `about[]` | display `Claim VB26AA2600001`, reference `https://nhcx.abdm.gov.in/preauth/request` | +| `basedOn[]` | display `CommunicationRequest`, reference `urn:uuid:08f1bb6f-c3f5-4578-b5e8-c042764e2477` | +| `category[].coding[]` | `notification` in `http://terminology.hl7.org/CodeSystem/communication-category` | +| `identifier[]` | value `4524657454` | +| `payload[]` | contentString `The angiography report is attached.` | +| `payload[].contentAttachment` | contentType `application/pdf`, title `Angiography report` | +| `payload[].extension[]` | url ``, valueString `DIA` | +| `priority` | `routine` | +| `recipient[]` | display `Organization`, reference `https://nhcx.abdm.gov.in/payer` | +| `sender` | display `Organization`, reference `https://nhcx.abdm.gov.in/provider` | +| `status` | `completed` | + +The `CommunicationRequest`, `Claim`, `Patient`, `Organization`, `Practitioner`, `Coverage` entries are shaped as in the chapters that introduce them. + +## Rules + +### 1. The push pattern + +`Task.code` `poll` with an input of type `include` referencing the resource being delivered, a `CommunicationRequest` from the payer. `intent` is `order` on a request and `proposal` on a notification. Resolve the reference and read its type. + +### 2. Switch on the reason + +`Task.reasonCode` from `ndhm-reason-code`: `tatquery`, `grievance`, `walletupdate`, `policychange`, `additionalinfo`, `claimArbitration`. Accept the misspelling `claimArbitartion` on receipt. + +### 3. Notifications + +A notification carries its reason under the communication-category system, such as `information`, and a `CommunicationRequest` with category `notification` and the message in `payload`. + +### 4. Category, priority, topic + +`category` `alert`, `reminder`, `notification`, `instruction` or `questionnaire`; `priority` `routine`, `urgent`, `asap` or `stat`; `topic` `progress-update` for anything about a live case. + +### 5. completed is the event + +`Task.status` and `Communication.status` read `completed` when the message is delivered. Do not close a case on them. + +### 6. The acknowledgement + +A `Task` coded `deliver`, `completed`, whose `include` input references a `Communication` with `basedOn` naming the request. Same correlation id. Take each organisation's role from `Organization.type`, not from the identifier type. + +## PMJAY + +The generic bundle above is what every payer takes, IRDAI-regulated insurers and TPAs included. PMJAY takes it with the changes and requirements below. + +### What changes in the bundle + +PMJAY sends this exchange in the generic shape. + +### What PMJAY specifies + +- PMJAY does not use this channel for queries. A PMJAY `CommunicationRequest` is a notification: a turnaround alert, a grievance, a wallet or policy change, or an arbitration intimation. + +### What PMJAY requires + +- Acknowledge within thirty seconds with the same Task bundle and `Task.status` `completed`, and leave the case's status alone. + +## Use cases, APIs and data elements + +### C6 Raise a communication (payer) + +A message about a case, typed by its reason code: additionalinfo, tatquery for a turnaround breach, grievance, walletupdate, policychange, claimArbitration. A generic or IRDAI payer raises its document queries here, as a CommunicationRequest task bundle carrying 24, 241 or 27, and takes the answer as a Communication task bundle on on_request echoing the correlation id and workflow id. PMJAY does not use it for queries; its query is the ClaimResponse on the case's own thread. + +| | | +| :-- | :-- | +| **API** | `/v1/communication/request` [`apis/07-communication/v1-communication-request.bru`](/docs/nhcx/v1/api/communication/endpoints/communication-v1-communication-request) | +| **Callback** | `/v1/communication/on_request` [`apis/07-communication/v1-communication-on-request.bru`](/docs/nhcx/v1/api/communication/endpoints/communication-v1-communication-on-request) | +| **Workflow** | 24, 241, 27 for a generic payer's queries; N02 and the intimation codes for the rest | +| **Carries JWE** | yes | +| **Focal resource** | `CommunicationRequest / Task` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `x-hcx-sender_code` | `1518@hcx` | +| `x-hcx-recipient_code` | `1000004446@hcx` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-request_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{$guid}}` | +| `x-hcx-workflow_id` | `15` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `request.initiated` | +| `x-hcx-ben-abha-id` | `91711234567890` | + +**Workflow codes** + +| Code | Name | Authored by | `x-hcx-status` | Means | +| :-- | :-- | :-- | :-- | :-- | +| `24` | Preauth Request Queried | payer | `request.initiated` | Payer needs more information - respond using workflow 19 | +| `241` | Enhancement Request Queried | payer | `request.initiated` | Enhancement request queried by payer | +| `27` | Claim Request Queried | payer | `request.initiated`, `response.partial/complete` | Final claim queried - payer needs additional documents; under PMJAY answer with 161 | +| `N02` | Notifications Intended To Provider | status sheet only | `request.initiated` | | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `taskReason` | Query Reason | Query | `code` | `1..1` | `Task.reasonCode.coding[0].code` | `additionalinfo` | | +| `queryText` | Query Questions | Query | `string` | `1..1` | `CommunicationRequest.payload[0].contentString` | `Please attach pre-operative ultrasound scan.` | | + +NRCeS profiles: [CommunicationRequest](https://nrces.in/ndhm/fhir/r4/StructureDefinition-CommunicationRequest.html), [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html). + +### B4 Respond to a communication (provider) + +Acknowledge or answer a message the payer sent about a case. A generic or IRDAI payer raises its query here, as a CommunicationRequest task bundle carrying 24, 241 or 27; the answer is a Communication task bundle on on_request that echoes the request's correlation id and workflow id. The payer's reason code says what kind of message it was. + +| | | +| :-- | :-- | +| **API** | `/v1/communication/on_request` [`apis/07-communication/v1-communication-on-request.bru`](/docs/nhcx/v1/api/communication/endpoints/communication-v1-communication-on-request) | +| **Callback** | `/v1/communication/request` [`apis/07-communication/v1-communication-request.bru`](/docs/nhcx/v1/api/communication/endpoints/communication-v1-communication-request) | +| **Workflow** | 24, 241 or 27, echoed from the payer's request | +| **Carries JWE** | yes | +| **Focal resource** | `Communication / Task` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `x-hcx-sender_code` | `1000004446@hcx` | +| `x-hcx-recipient_code` | `1518@hcx` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-request_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{$guid}}` | +| `x-hcx-workflow_id` | `15` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `response.complete` | +| `x-hcx-ben-abha-id` | `91711234567890` | + +**Workflow codes** + +| Code | Name | Authored by | `x-hcx-status` | Means | +| :-- | :-- | :-- | :-- | :-- | +| `24` | Preauth Request Queried | payer | `request.initiated` | Payer needs more information - respond using workflow 19 | +| `241` | Enhancement Request Queried | payer | `request.initiated` | Enhancement request queried by payer | +| `27` | Claim Request Queried | payer | `request.initiated`, `response.partial/complete` | Final claim queried - payer needs additional documents; under PMJAY answer with 161 | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `communicationId` | Communication Identifier | Case | `string` | `1..1` | `Communication.identifier[0].value` | `COMM-RESP-001` | | +| `queryRequestId` | Original Query Reference | Case | `reference` | `1..1` | `Communication.basedOn[0].reference` | `Task/task-comm-req-1` | | +| `replyText` | Clarification Text | Payload | `string` | `0..1` | `Communication.payload[0].contentString` | `Platelet count attached as requested.` | | +| `attachmentData` | Attached Document Base64 | Payload | `base64Binary` | `0..*` | `Communication.payload[0].contentAttachment.data` | `JVBERi0xLjQK...` | | + +NRCeS profiles: [Communication](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Communication.html). diff --git a/site/docs/nhcx/v1/reference/fhir/coverage-eligibility-request.md b/site/docs/nhcx/v1/reference/fhir/coverage-eligibility-request.md new file mode 100644 index 000000000..401c8a11a --- /dev/null +++ b/site/docs/nhcx/v1/reference/fhir/coverage-eligibility-request.md @@ -0,0 +1,264 @@ +--- +title: Coverage eligibility request +sidebar_label: Coverage eligibility request +sidebar_position: 2 +description: Resource breakdown and fields +verification: unverified +source: nhcx-package/docs/05-FHIR Reference/02-Coverage Eligibility Request.md +generated: true +--- + +# Coverage eligibility request + +The provider asks the payer whether a policy is live, what it covers, and what a package will need. One `CoverageEligibilityRequest` carries all of that, and `purpose` decides which question is asked. It is the first exchange in a case, sent at registration or before treatment planning. + +Sent on `/v1/coverageeligibility/check`, answered on `/v1/coverageeligibility/on_check`. + +## The bundle + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `CoverageEligibilityRequest` | [CoverageEligibilityRequest](https://nrces.in/ndhm/fhir/r4/StructureDefinition-CoverageEligibilityRequest.html) | +| 2 | `Patient` | [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html) | +| 3 | `Organization (prov)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 4 | `Organization (pay)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 5 | `Location` | none declared; NRCeS [Location](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Location.html) | +| 6 | `Coverage` | [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html) | +| 7 | `PractitionerRole` | [PractitionerRole](https://nrces.in/ndhm/fhir/r4/StructureDefinition-PractitionerRole.html) | + +## Elements + +### 1. CoverageEligibilityRequest + +NRCeS profile: [CoverageEligibilityRequest](https://nrces.in/ndhm/fhir/r4/StructureDefinition-CoverageEligibilityRequest.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system `https://nhcx.abdm.gov.in` | +| `status` | `active` | +| `priority.coding[]` | `normal` Normal in `http://terminology.hl7.org/CodeSystem/processpriority` | +| `purpose` | `auth-requirements` | +| `patient` | reference `https://nhcx.abdm.gov.in/patient` | +| `created` | `2026-09-10T23:53:57+05:30` | +| `enterer` | reference `https://nhcx.abdm.gov.in/practitioner-role` | +| `provider` | reference `https://nhcx.abdm.gov.in/provider` | +| `insurer` | reference `https://nhcx.abdm.gov.in/payer` | +| `facility` | reference `https://nhcx.abdm.gov.in/location` | +| `insurance[]` | focal `true` | +| `insurance[].coverage` | reference `https://nhcx.abdm.gov.in/coverage` | +| `item[].category.coding[]` | `Surgical` Surgical in `https://nhcx.abdm.gov.in/category-code` | +| `item[].productOrService.coding[]` | `PROC-KNEE-01` Total Knee Replacement (Unilateral) in `https://nhcx.abdm.gov.in/product-code` | +| `item[].quantity` | value `1` | + +### 2. Patient + +NRCeS profile: [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | value `MRAV1985001` | +| `identifier[].type.coding[]` | `PMJAY` Pradhan Mantri Jan Aarogya Yojana (PMJAY) ID in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| | `MB` Member Number in `http://terminology.hl7.org/CodeSystem/v2-0203` | + +### 3. Organization (prov) + +NRCeS profile: [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system `https://nhcx.abdm.gov.in`, value `IN1910000151` | +| `identifier[].type.coding[]` | `NPI` National provider identifier in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `type[].coding[]` | `prov` Healthcare Provider in `http://terminology.hl7.org/CodeSystem/organization-type` | +| `name` | `KyroCare Multispeciality Hospital` | + +### 4. Organization (pay) + +NRCeS profile: [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system `https://nhcx.abdm.gov.in`, value `1000004805` | +| `identifier[].type.coding[]` | `NIIP` National Insurance Payor Identifier (Payor) in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `type[].coding[]` | `pay` Payer in `http://terminology.hl7.org/CodeSystem/organization-type` | +| `name` | `Sandbox Payer` | + +### 5. Location + +NRCeS profile: [Location](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Location.html). + +| Element | Example | +| :-- | :-- | +| `name` | `KyroCare Multispeciality Hospital` | +| `managingOrganization` | reference `https://nhcx.abdm.gov.in/provider` | + +### 6. Coverage + +NRCeS profile: [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html). + +| Element | Example | +| :-- | :-- | +| `status` | `active` | +| `type.coding[]` | `HIP` health insurance plan policy in `http://terminology.hl7.org/CodeSystem/v3-ActCode` | +| `identifier[]` | value `POL7UMU001` | +| `identifier[].type.coding[]` | `NH` National Health Plan Identifier in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `subscriber` | reference `https://nhcx.abdm.gov.in/patient` | +| `subscriberId` | `MRAV1985001` | +| `beneficiary` | reference `https://nhcx.abdm.gov.in/patient` | +| `relationship.coding[]` | `self` in `http://terminology.hl7.org/CodeSystem/subscriber-relationship` | +| `payor[]` | reference `https://nhcx.abdm.gov.in/payer` | + +### 7. PractitionerRole + +NRCeS profile: [PractitionerRole](https://nrces.in/ndhm/fhir/r4/StructureDefinition-PractitionerRole.html). + +| Element | Example | +| :-- | :-- | +| `code[].coding[]` | `307988006` Medical technician in `http://snomed.info/sct` | + +## The four purposes + +One builder, with `purpose` switched. The purposes differ in what they send and what the payer must return. + +| Variant | What it asks | purpose | item | +| :-- | :-- | :-- | :-- | +| Discovery | Which policies does this person hold? Searches by ABHA or demographic identifiers. | `discovery` | none | +| Validation | Is the policy in force, and what is left in the wallet? | `validation` | none | +| Benefits | Is this package covered for this beneficiary? | `benefits` | `MG004C` Dengue shock syndrome (Dengue fever) in `https://nhcx.abdm.gov.in/product-code` | +| Auth-requirements | What must a preauthorisation carry for this package? | `auth-requirements` | `MG004C` Dengue shock syndrome (Dengue fever) in `https://nhcx.abdm.gov.in/product-code` | + +## Rules + +### 1. One purpose per request + +`purpose[]` carries one of `discovery`, `validation`, `benefits`, `auth-requirements`. + +### 2. Items make a question answerable + +`item[]` is what makes `benefits` and `auth-requirements` answerable. `validation` does not need it. `discovery` omits `item[]` and `Coverage`. + +### 3. Date of service + +`servicedDate` is the date of service, not the date of asking. + +### 4. The Coverage you send is a stub + +It names the policy you mean, not its terms. Take the term and the class from the payer's `Coverage` in the response. + +### 5. Parties by reference + +`provider` and `insurer` reference `Organization` entries typed `prov` and `pay`, identified by `NPI` and `NIIP`. `facility` references a `Location` the provider manages, and `enterer` a `PractitionerRole`. + +## PMJAY + +The generic bundle above is what every payer takes, IRDAI-regulated insurers and TPAs included. PMJAY takes it with the changes and requirements below. + +### What changes in the bundle + +#### Elements PMJAY adds + +| Element | Example | +| :-- | :-- | +| `CoverageEligibilityRequest.item[].modifier[].coding[]` | `STRAT006a` Routine Ward | + +### What PMJAY specifies + +- `item.category` is the package master's specialty code, such as `MG`, and `item.productOrService` the master's package code and display. +- The `Coverage` carries the scheme policy code typed `NH`, of the form `PMJAY//S/G`, from the policy lookup. +- Validation after registration returns the wallet; benefits and auth-requirements before a preauthorisation return what the package needs attached, including the consent questionnaire when there is no biometric token. + +### What PMJAY requires + +- The ward tier rides as `item.modifier` when the package allows one. +- Register the patient only after coverage is validated, and validate again every time treatment is added. + +## Use cases, APIs and data elements + +### B1 Check coverage eligibility (provider) + +Is the policy in force, what is left in the wallet, and what must be attached. One endpoint, four purposes: discovery, validation, benefits, auth-requirements. + +| | | +| :-- | :-- | +| **API** | `/v1/coverageeligibility/check` [`apis/02-eligibility/v1-coverageeligibility-check.bru`](/docs/nhcx/v1/api/eligibility/endpoints/eligibility-v1-coverageeligibility-check) | +| **Callback** | `/v1/coverageeligibility/on_check` [`apis/02-eligibility/v1-coverageeligibility-on-check.bru`](/docs/nhcx/v1/api/eligibility/endpoints/eligibility-v1-coverageeligibility-on-check) | +| **Workflow** | none; sits beside registration 10 and admission 11 | +| **Carries JWE** | yes | +| **Focal resource** | `CoverageEligibilityRequest` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `x-hcx-sender_code` | `1000004446@hcx` | +| `x-hcx-recipient_code` | `1518@hcx` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-request_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{$guid}}` | +| `x-hcx-workflow_id` | `11` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `request.initiated` | +| `x-hcx-ben-abha-id` | `91711234567890` | + +**Workflow codes** + +| Code | Name | Authored by | `x-hcx-status` | Means | +| :-- | :-- | :-- | :-- | :-- | +| `10` | Patient Registered | provider | `request.initiated` | Patient registered in system | +| `11` | Patient Admitted | provider | `request.initiated` | Patient admitted to hospital | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `purpose` | Eligibility Purpose | Case | `code` | `1..1` | `CoverageEligibilityRequest.purpose[0]` | `auth-requirements` | code system `http://hl7.org/fhir/eligibilityrequest-purpose` | +| `caseNumber` | Provider Reference | Case | `string` | `1..1` | `CoverageEligibilityRequest.identifier[0].value` | `PA0000000001` | also at `Bundle.id` | +| `servicedDate` | Date of Service | Case | `date` | `1..1` | `CoverageEligibilityRequest.servicedDate` | `2026-02-26` | | +| `patientName` | Patient Full Name | Beneficiary | `string` | `1..1` | `Patient.name[0].text` | `Ramesh Chandra Sharma` | | +| `memberId` | Scheme / Insurer Member ID | Beneficiary | `string` | `1..1` | `Patient.identifier[type=PMJAY].value` | `PMJAY-HP-2024-998811` | also at `Coverage.subscriberId` | +| `abhaNumber` | ABHA Number | Beneficiary | `string` | `0..1` | `Patient.identifier[type=ABHA].value` | `91234567890123` | | +| `gender` | Gender | Beneficiary | `code` | `1..1` | `Patient.gender` | `male` | code system `http://hl7.org/fhir/administrative-gender` | +| `birthDate` | Date of Birth | Beneficiary | `date` | `1..1` | `Patient.birthDate` | `1982-06-15` | | +| `patientPhone` | Mobile Phone | Beneficiary | `string` | `0..1` | `Patient.telecom[system=phone].value` | `9876543210` | | +| `policyNumber` | Policy Number | Coverage | `string` | `1..1` | `Coverage.identifier[0].value` | `PMJAY/HP/S/G` | | +| `facilityId` | Hospital Facility ID (HFR/NPI) | Provider | `string` | `1..1` | `Organization[type=prov].identifier[system=https://facility.abdm.gov.in].value` | `IN1910000151` | | +| `providerName` | Hospital Name | Provider | `string` | `1..1` | `Organization[type=prov].name` | `Apex Multispeciality Hospital` | | +| `payerId` | Payer Identifier (NIIP) | Payer | `string` | `1..1` | `Organization[type=pay].identifier[system=https://irdai.gov.in].value` | `1000003538` | | +| `payerName` | Payer Name | Payer | `string` | `1..1` | `Organization[type=pay].name` | `National Health Authority - PMJAY` | | +| `productOrService` | Package Code | Item | `string` | `0..*` | `CoverageEligibilityRequest.item[].productOrService.coding[0].code` | `MG004A` | | + +NRCeS profiles: [CoverageEligibilityRequest](https://nrces.in/ndhm/fhir/r4/StructureDefinition-CoverageEligibilityRequest.html), [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html), [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html), [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html). + +### D3 Check coverage eligibility (pmjay) + +Validation after registration returns the wallet, one benefit entry per wallet with allowed and used. Benefits and auth-requirements before a pre-authorisation return what the package needs attached. Register only after coverage is validated, and validate again every time treatment is added. + +| | | +| :-- | :-- | +| **API** | `/v1/coverageeligibility/check` [`apis/02-eligibility/v1-coverageeligibility-check.bru`](/docs/nhcx/v1/api/eligibility/endpoints/eligibility-v1-coverageeligibility-check) | +| **Callback** | `/v1/coverageeligibility/on_check` [`apis/02-eligibility/v1-coverageeligibility-on-check.bru`](/docs/nhcx/v1/api/eligibility/endpoints/eligibility-v1-coverageeligibility-on-check) | +| **Workflow** | none (or 5 under PMJAY) | +| **Carries JWE** | yes | +| **Focal resource** | `CoverageEligibilityRequest` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `x-hcx-sender_code` | `1000004446@hcx` | +| `x-hcx-recipient_code` | `1518@hcx` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-request_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{$guid}}` | +| `x-hcx-workflow_id` | `11` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `request.initiated` | +| `x-hcx-ben-abha-id` | `91711234567890` | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `memberId` | PMJAY Family ID | Beneficiary | `string` | `1..1` | `Patient.identifier[type=PMJAY].value` | `PMJAY-HP-2024-998811` | | +| `purpose` | Purpose | Case | `code` | `1..1` | `CoverageEligibilityRequest.purpose[0]` | `validation` | | + +NRCeS profiles: [CoverageEligibilityRequest](https://nrces.in/ndhm/fhir/r4/StructureDefinition-CoverageEligibilityRequest.html), [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html). diff --git a/site/docs/nhcx/v1/reference/fhir/coverage-eligibility-response.md b/site/docs/nhcx/v1/reference/fhir/coverage-eligibility-response.md new file mode 100644 index 000000000..5b3e61c06 --- /dev/null +++ b/site/docs/nhcx/v1/reference/fhir/coverage-eligibility-response.md @@ -0,0 +1,255 @@ +--- +title: Coverage eligibility response +sidebar_label: Coverage eligibility response +sidebar_position: 3 +description: Response bundle, wallet breakdown, and inforce flags +verification: unverified +source: nhcx-package/docs/05-FHIR Reference/03-Coverage Eligibility Response.md +generated: true +--- + +# Coverage eligibility response + +The payer's answer on `on_check`. It says whether the coverage is in force, what is left in the wallet, and which items need authorisation and which documents. + +Sent on `/v1/coverageeligibility/on_check`. + +## The bundle + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `CoverageEligibilityResponse` | [CoverageEligibilityResponse](https://nrces.in/ndhm/fhir/r4/StructureDefinition-CoverageEligibilityResponse.html) | +| 2 | `Patient` | [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html) | +| 3 | `Coverage` | [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html) | +| 4 | `CoverageEligibilityRequest` | [CoverageEligibilityRequest](https://nrces.in/ndhm/fhir/r4/StructureDefinition-CoverageEligibilityRequest.html) | +| 5 | `Organization (ins)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | + +## Elements + +### 1. CoverageEligibilityResponse + +NRCeS profile: [CoverageEligibilityResponse](https://nrces.in/ndhm/fhir/r4/StructureDefinition-CoverageEligibilityResponse.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system ``, value `SUB-00001` | +| `status` | `active` | +| `purpose` | `auth-requirements` | +| `patient` | reference `urn:uuid:89aac2db-25ae-5b55-90a7-886c6be48ca7`, display `Ravi Kumar` | +| `created` | `2026-09-10` | +| `request` | reference `urn:uuid:4955a87f-deb4-59e6-b795-100a2d705c98`, display `CoverageEligibilityRequest` | +| `outcome` | `complete` | +| `disposition` | `Policy is in force until 2026-12-31. INR 5000 of cover remains. All 1 requested…` | +| `insurer` | reference `urn:uuid:39cd4b51-bddd-5cc1-a65a-6fa4a2a83cb5`, display `Sandbox Payer` | +| `insurance[]` | inforce `true` | +| `insurance[].coverage` | reference `urn:uuid:966d4b2b-591b-50b6-bbbb-d504d3c6897f`, display `Sandbox Default Policy` | +| `insurance[].benefitPeriod` | start `2026-01-01`, end `2026-12-31` | +| `insurance[].item[]` | authorizationRequired `true` | +| `insurance[].item[].productOrService` | text `Total Knee Replacement (Unilateral)` | +| `insurance[].item[].productOrService.coding[]` | `PROC-KNEE-01` Total Knee Replacement (Unilateral) in `` | +| | `737481003` Total Knee Replacement (Unilateral) in `http://snomed.info/sct` | +| | `0SRC0JZ` Total Knee Replacement (Unilateral) in `http://www.cms.gov/Medicare/Coding/ICD10` | +| `insurance[].item[].benefit[].type.coding[]` | `benefit` Benefit in `http://terminology.hl7.org/CodeSystem/benefit-type` | +| `insurance[].item[].benefit[].allowedMoney` | value `150000`, currency `INR` | +| `insurance[].item[].authorizationSupporting[]` | text `Type: pre +Procedure Code: PROC-KNEE-01` | +| | text `Type: post +Procedure Code: PROC-KNEE-01` | +| | text `fullUrl: ` | +| `insurance[].item[].authorizationSupporting[].coding[]` | `POI` Proof of Identity (Aadhaar / Passport / Voter ID) in `` | +| | `CER` Medical Certificate / Doctor Referral in `` | +| | `RAD` Radiology / X-Ray / CT / MRI Scan Reports in `` | +| | and 7 more | + +### 2. Patient + +NRCeS profile: [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system ``, value `MRAV1985001` | +| | system `https://healthid.ndhm.gov.in`, value `91-1234-1234-1234` | +| `identifier[].type.coding[]` | `ABHA` Ayushman Bharat Health Account (ABHA) ID in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| `name[]` | text `Ravi Kumar` | +| `telecom[]` | system `phone`, value `9876543210`, use `mobile` | +| `gender` | `male` | +| `birthDate` | `1985-06-15` | + +### 3. Coverage + +NRCeS profile: [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system ``, value `SUB-00001` | +| `status` | `active` | +| `type.coding[]` | `HIP` health insurance plan policy in `http://terminology.hl7.org/CodeSystem/v3-ActCode` | +| `subscriber` | reference `urn:uuid:89aac2db-25ae-5b55-90a7-886c6be48ca7`, display `Ravi Kumar` | +| `subscriberId` | `MRAV1985001` | +| `beneficiary` | reference `urn:uuid:89aac2db-25ae-5b55-90a7-886c6be48ca7`, display `Ravi Kumar` | +| `relationship.coding[]` | `self` Self in `http://terminology.hl7.org/CodeSystem/subscriber-relationship` | +| `period` | start `2026-01-01`, end `2026-12-31` | +| `payor[]` | reference `urn:uuid:39cd4b51-bddd-5cc1-a65a-6fa4a2a83cb5`, display `Sandbox Payer` | +| `class[]` | value `POL7UMU002`, name `Sandbox Default Policy` | +| `class[].type.coding[]` | `plan` Plan in `http://terminology.hl7.org/CodeSystem/coverage-class` | + +### 4. CoverageEligibilityRequest + +NRCeS profile: [CoverageEligibilityRequest](https://nrces.in/ndhm/fhir/r4/StructureDefinition-CoverageEligibilityRequest.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system ``, value `4955a87f-deb4-59e6-b795-100a2d705c98` | +| `status` | `active` | +| `priority.coding[]` | `normal` Normal in `http://terminology.hl7.org/CodeSystem/processpriority` | +| `purpose` | `auth-requirements` | +| `patient` | reference `urn:uuid:89aac2db-25ae-5b55-90a7-886c6be48ca7`, display `Ravi Kumar` | +| `created` | `2026-09-10T23:53:59+05:30` | +| `insurer` | reference `urn:uuid:39cd4b51-bddd-5cc1-a65a-6fa4a2a83cb5`, display `Sandbox Payer` | +| `insurance[]` | focal `true` | +| `insurance[].coverage` | reference `urn:uuid:966d4b2b-591b-50b6-bbbb-d504d3c6897f`, display `Sandbox Default Policy` | + +### 5. Organization (ins) + +NRCeS profile: [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html). + +| Element | Example | +| :-- | :-- | +| `type[].coding[]` | `ins` Insurance Company in `http://terminology.hl7.org/CodeSystem/organization-type` | +| `name` | `Sandbox Payer` | +| `address[]` | city `Bengaluru`, state `Karnataka`, country `India` | + +## Rules + +### 1. Read the answer in three places + +`outcome`, `insurance[].inforce` and `insurance[].item[]`. `disposition` is prose for a human. + +### 2. Match to the request by reference + +Use `CoverageEligibilityResponse.request.reference`, never a resource id, to join the answer to what you sent. + +### 3. Index entries by fullUrl + +A response can carry more than one `Patient` or `Organization`. Index by `fullUrl`, not by resource type. + +### 4. Money + +`allowedMoney` is the balance remaining and `usedMoney` the amount used, not the sum insured. There is one benefit per wallet; read them all. + +### 5. Build for the fuller form + +`benefit[]` with `Procedure`, `Investigation` and `Stratification` types for benefits, and `authorizationSupporting[]` with the mandatory document codes for auth-requirements. Tolerate a leaner answer. + +### 6. Documents by stage + +`authorizationSupporting[]` lists the documents the next request must carry. Its `text` names the stage: pre for the preauthorisation, post for the claim. + +### 7. The identifier is not a correlation key + +`CoverageEligibilityResponse.identifier` identifies the beneficiary at the hospital. Correlate on the protocol headers. + +## PMJAY + +The generic bundle above is what every payer takes, IRDAI-regulated insurers and TPAs included. PMJAY takes it with the changes and requirements below. + +### What changes in the bundle + +PMJAY uses a different bundle for this step, headed by `CoverageEligibilityRequest` rather than `CoverageEligibilityResponse`. + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `CoverageEligibilityRequest` | [CoverageEligibilityRequest](https://nrces.in/ndhm/fhir/r4/StructureDefinition-CoverageEligibilityRequest.html) | +| 2 | `Patient` | [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html) | +| 3 | `Organization (prov)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 4 | `Organization (pay)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 5 | `Location` | none declared; NRCeS [Location](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Location.html) | +| 6 | `Coverage` | [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html) | +| 7 | `PractitionerRole` | [PractitionerRole](https://nrces.in/ndhm/fhir/r4/StructureDefinition-PractitionerRole.html) | +| 8 | `CoverageEligibilityResponse` | [CoverageEligibilityResponse](https://hl7.org/fhir/R4/coverageeligibilityresponse.html) | +| 9 | `Patient` | none declared; NRCeS [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html) | +| 10 | `Coverage` | none declared; NRCeS [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html) | +| 11 | `Organization (pay)` | none declared; NRCeS [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 12 | `Organization (prov)` | none declared; NRCeS [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | + +##### 8. CoverageEligibilityResponse + +NRCeS profile: [CoverageEligibilityResponse](https://nrces.in/ndhm/fhir/r4/StructureDefinition-CoverageEligibilityResponse.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system `https://hcx.pmjay.gov.in/v1/coverageeligibility/check`, value `PMJAY0000X-IN1910000151` | +| `status` | `active` | +| `purpose` | `auth-requirements` | +| `patient` | reference `https://payer.nha.gov.in/coverageeligibility/v1/coverageeligibility/on_check/co…` | +| `created` | `2026-09-11T00:32:42+05:30` | +| `requestor` | reference `https://payer.nha.gov.in/coverageeligibility/v1/coverageeligibility/on_check/co…` | +| `request` | reference `https://nhcx.abdm.gov.in/coverage-eligibility/request` | +| `outcome` | `complete` | +| `disposition` | `Policy is currently in-force` | +| `insurer` | reference `https://payer.nha.gov.in/coverageeligibility/v1/coverageeligibility/on_check/co…` | +| `insurance[]` | inforce `true` | +| `insurance[].coverage` | reference `https://payer.nha.gov.in/coverageeligibility/v1/coverageeligibility/on_check/co…` | +| `insurance[].item[]` | excluded `false`, authorizationRequired `true` | +| `insurance[].item[].category.coding[]` | `MG` General Medicine | +| `insurance[].item[].productOrService.coding[]` | `MG0111A` Pleural Effusion (Pleural Effusion) | +| | `MG072C` Acute Haemodialysis (Acute Haemodialysis) | +| `insurance[].item[].benefit[].type.coding[]` | `Procedure` Procedure in `https://hl7.org/fhir/R4/codesystem-benefit-type.html` | +| `insurance[].item[].benefit[].allowedMoney` | value `2070`, currency `INR` | +| | value `1725`, currency `INR` | +| `insurance[].item[].authorizationSupporting[]` | text `Type: pre + Procedure Code:MG0111A` | +| | text `fullUrl: https://payer.gov.in/policy/questionnaire/100003` | +| | text `fullUrl: https://payer.gov.in/policy/questionnaire/100008` | +| | and 7 more | +| `insurance[].item[].authorizationSupporting[].coding[]` | `MAND0409` any investigations done | +| | `MAND0408` Clinical notes detailing history and Admission notes showing vitals and examina… | +| | `MAND0455` CXR PA view or CECT chest abdomen and pelvis | +| | and 9 more | + +The `CoverageEligibilityRequest`, `Patient`, `Organization`, `Location`, `Coverage`, `PractitionerRole` entries are shaped as in the chapters that introduce them. + +### What PMJAY specifies + +- The bundle echoes the whole request first and then gives the answer, with the payer's own `Patient`, `Coverage` and both `Organization` entries. +- A PMJAY answer can carry only `item.excluded` and `item.authorizationRequired`, without `benefitPeriod`, `benefit[]` or `authorizationSupporting[]`. The documents then come from the plan. +- The payer's `Patient` can differ from yours in name, gender and birth date. Do not overwrite your record from it. + +## Use cases, APIs and data elements + +### C3 Respond to coverage eligibility (payer) + +The eligibility and plan details for the beneficiary asked about. A payer may instead answer with a forward instruction, asking the exchange to pass the request to another payer. + +| | | +| :-- | :-- | +| **API** | `/v1/coverageeligibility/on_check` [`apis/02-eligibility/v1-coverageeligibility-on-check.bru`](/docs/nhcx/v1/api/eligibility/endpoints/eligibility-v1-coverageeligibility-on-check) | +| **Callback** | `/v1/coverageeligibility/check` [`apis/02-eligibility/v1-coverageeligibility-check.bru`](/docs/nhcx/v1/api/eligibility/endpoints/eligibility-v1-coverageeligibility-check) | +| **Workflow** | none (or 5 under PMJAY) | +| **Carries JWE** | yes | +| **Focal resource** | `CoverageEligibilityResponse` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `x-hcx-sender_code` | `1518@hcx` | +| `x-hcx-recipient_code` | `1000004446@hcx` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-request_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{$guid}}` | +| `x-hcx-workflow_id` | `11` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `response.complete` | +| `x-hcx-ben-abha-id` | `91711234567890` | +| `x-hcx-debug_flag` | `INFO` | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `outcome` | Verdict Outcome | Verdict | `code` | `1..1` | `CoverageEligibilityResponse.outcome` | `complete` | | +| `inforce` | Policy In Force | Coverage | `boolean` | `1..1` | `CoverageEligibilityResponse.insurance[0].inforce` | `true` | | +| `allowedMoney` | Remaining Balance Amount | Benefit | `decimal` | `0..1` | `CoverageEligibilityResponse.insurance[0].item[].benefit[type=benefit].allowedMoney.value` | `485000.00` | | + +NRCeS profiles: [CoverageEligibilityResponse](https://nrces.in/ndhm/fhir/r4/StructureDefinition-CoverageEligibilityResponse.html). diff --git a/site/docs/nhcx/v1/reference/fhir/index.md b/site/docs/nhcx/v1/reference/fhir/index.md new file mode 100644 index 000000000..57b836dac --- /dev/null +++ b/site/docs/nhcx/v1/reference/fhir/index.md @@ -0,0 +1,302 @@ +--- +title: Bundles and conventions +sidebar_label: Bundles and conventions +sidebar_position: 1 +description: Universal bundle rules, profiles, IDs, base64 encoding, and size limits +verification: unverified +source: nhcx-package/docs/05-FHIR Reference/01-Bundles and Conventions.md +generated: true +--- + +# Bundles and conventions + +Everything that crosses the exchange is one FHIR R4 Bundle of type `collection`, built to the NRCeS profiles for NHCX. The bundles in this reference are generic: any payer on the exchange takes them, private insurers and TPAs regulated by IRDAI as well as government schemes. Each chapter shows the generic bundle for one exchange in one direction, then what PMJAY changes and what PMJAY requires on top. The package's sample collection is read the same way: a provider's bundles are either examples written to this specification or captures from the sandbox run against the PMJAY payer, and a payer's are either the generic payer's or PMJAY's own. This chapter holds the rules every bundle obeys before any exchange is considered. + +## Rules + +### 1. Bundle type + +`collection`, not `document` and not `transaction`. Entries are resources placed directly, with no request or response elements. The open-protocol page describes claim objects as `document` bundles with a root `Composition`; the exchange accepts `collection`, and a `Composition` appears only at the head of an embedded clinical record. + +### 2. Profiles + +Declare the NRCeS profile in `meta.profile` on every resource you send, for example `https://nrces.in/ndhm/fhir/r4/StructureDefinition/Claim`. Declare only profiles NRCeS publishes: there is no NRCeS `QuestionnaireResponse` profile, so a `QuestionnaireResponse` takes the base FHIR definition. Do not require a profile on what you receive: payer-generated resources often carry none. + +### 3. References + +Resources in one bundle reference each other by `urn:uuid:`, with the same UUID as the entry's `fullUrl`. Absolute URLs are also accepted. Parse both. + +### 4. Timestamps + +ISO 8601 with the Indian offset, `+05:30`. UTC fails validation. Read `Bundle.timestamp` for the send time; `meta.lastUpdated` can be stale. + +### 5. Identifier types come from two systems + +`PMJAY`, `ABHA`, `CLN`, `UTR`, `HPID` and `HPIN` from NRCeS at `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code`. `NPI` for a hospital's HFR ID, `NIIP` for a payer's registry ID, `NH` for a plan, `MB` for a member number, and `JHN`, `MD` and `MR` from HL7 at `http://terminology.hl7.org/CodeSystem/v2-0203`. Take the system from the exchange you are building, not from the code. + +### 6. The HFR ID inside the bundle + +Must equal the registry ID on the sender's participant record, whichever element carries it. + +### 7. Sequences link things + +A `Claim.item` points at its diagnosis, procedure, care team and supporting information by sequence number, not by reference. Resolve through the `sequence` field, never by array position. + +### 8. Documents arrive two ways + +A supporting-info entry carries the file inline in `valueAttachment`, or points with `valueReference` at a resource in the same bundle: a `DocumentReference`, or the `Composition` heading an embedded ABDM record. One document per entry, 2 MB each, 20 MB per claim or preauthorisation bundle. Plan responses run past 20 MB; size clients and proxies for 25 MB. + +### 9. Category decides structured or not + +Supporting-info categories `DIA`, `HDS`, `CD` and `INF` take a reference to a structured record. `POI`, `POA`, `DOB`, `DEF`, `FIR`, `ATT` and `MB` take an attachment. + +### 10. Encode attachments once + +Base64 the file once. On receipt, check the decoded bytes for a file signature before trusting them, because double-encoded attachments are in circulation and render as a blank page. + +### 11. One Claim, three uses + +`Claim.use` is `preauthorization`, `claim` or `predetermination`, and nothing else changes. `pre-auth` and `pre-det` are not codes. + +### 12. Codes and displays match the plan + +Character for character, including the plan's own misspellings. A payer rejects a package whose display differs from the plan's. + +### 13. Match on the code, not the system + +The same package code appears under different systems in different exchanges. Match incoming codes on the code, and emit the system the exchange you are building expects. + +## Resources by exchange + +Each resource the bundles carry, its NRCeS profile, and the exchanges that use it. + +### Claim + +NRCeS profile: [Claim](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Claim.html). + +- [Preauthorisation request](/docs/nhcx/v1/reference/fhir/preauthorisation-request) +- [Preauthorisation enhancement](/docs/nhcx/v1/reference/fhir/preauthorisation-enhancement) +- [Preauthorisation query and answer](/docs/nhcx/v1/reference/fhir/preauthorisation-query-and-answer) +- [Claim request](/docs/nhcx/v1/reference/fhir/claim-request) +- [Claim query and answer](/docs/nhcx/v1/reference/fhir/claim-query-and-answer) +- [Communication](/docs/nhcx/v1/reference/fhir/communication) +- [Predetermination, status and search](/docs/nhcx/v1/reference/fhir/predetermination-status-and-search) + +### ClaimResponse + +NRCeS profile: [ClaimResponse](https://nrces.in/ndhm/fhir/r4/StructureDefinition-ClaimResponse.html). + +- [Preauthorisation response](/docs/nhcx/v1/reference/fhir/preauthorisation-response) +- [Preauthorisation query and answer](/docs/nhcx/v1/reference/fhir/preauthorisation-query-and-answer) +- [Claim response](/docs/nhcx/v1/reference/fhir/claim-response) +- [Claim query and answer](/docs/nhcx/v1/reference/fhir/claim-query-and-answer) +- [Cancel, reprocess and shortfall](/docs/nhcx/v1/reference/fhir/cancel-reprocess-and-shortfall) +- [Predetermination, status and search](/docs/nhcx/v1/reference/fhir/predetermination-status-and-search) + +### Communication + +NRCeS profile: [Communication](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Communication.html). + +- [Preauthorisation query and answer](/docs/nhcx/v1/reference/fhir/preauthorisation-query-and-answer) +- [Claim query and answer](/docs/nhcx/v1/reference/fhir/claim-query-and-answer) +- [Communication](/docs/nhcx/v1/reference/fhir/communication) + +### CommunicationRequest + +NRCeS profile: [CommunicationRequest](https://nrces.in/ndhm/fhir/r4/StructureDefinition-CommunicationRequest.html). + +- [Preauthorisation query and answer](/docs/nhcx/v1/reference/fhir/preauthorisation-query-and-answer) +- [Claim query and answer](/docs/nhcx/v1/reference/fhir/claim-query-and-answer) +- [Communication](/docs/nhcx/v1/reference/fhir/communication) + +### Coverage + +NRCeS profile: [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html). + +- [Coverage eligibility request](/docs/nhcx/v1/reference/fhir/coverage-eligibility-request) +- [Coverage eligibility response](/docs/nhcx/v1/reference/fhir/coverage-eligibility-response) +- [Preauthorisation request](/docs/nhcx/v1/reference/fhir/preauthorisation-request) +- [Preauthorisation response](/docs/nhcx/v1/reference/fhir/preauthorisation-response) +- [Preauthorisation enhancement](/docs/nhcx/v1/reference/fhir/preauthorisation-enhancement) +- [Preauthorisation query and answer](/docs/nhcx/v1/reference/fhir/preauthorisation-query-and-answer) +- [Claim request](/docs/nhcx/v1/reference/fhir/claim-request) +- [Claim response](/docs/nhcx/v1/reference/fhir/claim-response) +- [Claim query and answer](/docs/nhcx/v1/reference/fhir/claim-query-and-answer) +- [Cancel, reprocess and shortfall](/docs/nhcx/v1/reference/fhir/cancel-reprocess-and-shortfall) +- [Communication](/docs/nhcx/v1/reference/fhir/communication) +- [Predetermination, status and search](/docs/nhcx/v1/reference/fhir/predetermination-status-and-search) + +### CoverageEligibilityRequest + +NRCeS profile: [CoverageEligibilityRequest](https://nrces.in/ndhm/fhir/r4/StructureDefinition-CoverageEligibilityRequest.html). + +- [Coverage eligibility request](/docs/nhcx/v1/reference/fhir/coverage-eligibility-request) +- [Coverage eligibility response](/docs/nhcx/v1/reference/fhir/coverage-eligibility-response) + +### CoverageEligibilityResponse + +NRCeS profile: [CoverageEligibilityResponse](https://nrces.in/ndhm/fhir/r4/StructureDefinition-CoverageEligibilityResponse.html). + +- [Coverage eligibility response](/docs/nhcx/v1/reference/fhir/coverage-eligibility-response) + +### InsurancePlan + +NRCeS profile: [InsurancePlan](https://nrces.in/ndhm/fhir/r4/StructureDefinition-InsurancePlan.html). + +- [Insurance plan response](/docs/nhcx/v1/reference/fhir/insurance-plan-response-overview) +- [Insurance plan response, package-based](/docs/nhcx/v1/reference/fhir/insurance-plan-response-package-based) +- [Insurance plan response, coverage-based](/docs/nhcx/v1/reference/fhir/insurance-plan-response-coverage-based) + +### Location + +NRCeS profile: [Location](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Location.html). + +- [Coverage eligibility request](/docs/nhcx/v1/reference/fhir/coverage-eligibility-request) +- [Coverage eligibility response](/docs/nhcx/v1/reference/fhir/coverage-eligibility-response) + +### Organization + +NRCeS profile: [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html). + +- [Coverage eligibility request](/docs/nhcx/v1/reference/fhir/coverage-eligibility-request) +- [Coverage eligibility response](/docs/nhcx/v1/reference/fhir/coverage-eligibility-response) +- [Insurance plan response](/docs/nhcx/v1/reference/fhir/insurance-plan-response-overview) +- [Insurance plan response, package-based](/docs/nhcx/v1/reference/fhir/insurance-plan-response-package-based) +- [Insurance plan response, coverage-based](/docs/nhcx/v1/reference/fhir/insurance-plan-response-coverage-based) +- [Preauthorisation request](/docs/nhcx/v1/reference/fhir/preauthorisation-request) +- [Preauthorisation response](/docs/nhcx/v1/reference/fhir/preauthorisation-response) +- [Preauthorisation enhancement](/docs/nhcx/v1/reference/fhir/preauthorisation-enhancement) +- [Preauthorisation query and answer](/docs/nhcx/v1/reference/fhir/preauthorisation-query-and-answer) +- [Claim request](/docs/nhcx/v1/reference/fhir/claim-request) +- [Claim response](/docs/nhcx/v1/reference/fhir/claim-response) +- [Claim query and answer](/docs/nhcx/v1/reference/fhir/claim-query-and-answer) +- [Cancel, reprocess and shortfall](/docs/nhcx/v1/reference/fhir/cancel-reprocess-and-shortfall) +- [Payment notice and acknowledgement](/docs/nhcx/v1/reference/fhir/payment-notice-and-acknowledgement) +- [Communication](/docs/nhcx/v1/reference/fhir/communication) +- [Predetermination, status and search](/docs/nhcx/v1/reference/fhir/predetermination-status-and-search) + +### Patient + +NRCeS profile: [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html). + +- [Coverage eligibility request](/docs/nhcx/v1/reference/fhir/coverage-eligibility-request) +- [Coverage eligibility response](/docs/nhcx/v1/reference/fhir/coverage-eligibility-response) +- [Preauthorisation request](/docs/nhcx/v1/reference/fhir/preauthorisation-request) +- [Preauthorisation response](/docs/nhcx/v1/reference/fhir/preauthorisation-response) +- [Preauthorisation enhancement](/docs/nhcx/v1/reference/fhir/preauthorisation-enhancement) +- [Preauthorisation query and answer](/docs/nhcx/v1/reference/fhir/preauthorisation-query-and-answer) +- [Claim request](/docs/nhcx/v1/reference/fhir/claim-request) +- [Claim response](/docs/nhcx/v1/reference/fhir/claim-response) +- [Claim query and answer](/docs/nhcx/v1/reference/fhir/claim-query-and-answer) +- [Cancel, reprocess and shortfall](/docs/nhcx/v1/reference/fhir/cancel-reprocess-and-shortfall) +- [Communication](/docs/nhcx/v1/reference/fhir/communication) +- [Predetermination, status and search](/docs/nhcx/v1/reference/fhir/predetermination-status-and-search) + +### PaymentNotice + +NRCeS profile: [PaymentNotice](https://nrces.in/ndhm/fhir/r4/StructureDefinition-PaymentNotice.html). + +- [Payment notice and acknowledgement](/docs/nhcx/v1/reference/fhir/payment-notice-and-acknowledgement) + +### PaymentReconciliation + +NRCeS profile: [PaymentReconciliation](https://nrces.in/ndhm/fhir/r4/StructureDefinition-PaymentReconciliation.html). + +- [Payment notice and acknowledgement](/docs/nhcx/v1/reference/fhir/payment-notice-and-acknowledgement) + +### Practitioner + +NRCeS profile: [Practitioner](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Practitioner.html). + +- [Preauthorisation request](/docs/nhcx/v1/reference/fhir/preauthorisation-request) +- [Preauthorisation enhancement](/docs/nhcx/v1/reference/fhir/preauthorisation-enhancement) +- [Preauthorisation query and answer](/docs/nhcx/v1/reference/fhir/preauthorisation-query-and-answer) +- [Claim request](/docs/nhcx/v1/reference/fhir/claim-request) +- [Claim query and answer](/docs/nhcx/v1/reference/fhir/claim-query-and-answer) +- [Communication](/docs/nhcx/v1/reference/fhir/communication) +- [Predetermination, status and search](/docs/nhcx/v1/reference/fhir/predetermination-status-and-search) + +### PractitionerRole + +NRCeS profile: [PractitionerRole](https://nrces.in/ndhm/fhir/r4/StructureDefinition-PractitionerRole.html). + +- [Coverage eligibility request](/docs/nhcx/v1/reference/fhir/coverage-eligibility-request) +- [Coverage eligibility response](/docs/nhcx/v1/reference/fhir/coverage-eligibility-response) + +### Procedure + +NRCeS profile: [Procedure](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Procedure.html). + +- [Preauthorisation request](/docs/nhcx/v1/reference/fhir/preauthorisation-request) +- [Preauthorisation enhancement](/docs/nhcx/v1/reference/fhir/preauthorisation-enhancement) +- [Preauthorisation query and answer](/docs/nhcx/v1/reference/fhir/preauthorisation-query-and-answer) +- [Claim request](/docs/nhcx/v1/reference/fhir/claim-request) +- [Claim query and answer](/docs/nhcx/v1/reference/fhir/claim-query-and-answer) +- [Predetermination, status and search](/docs/nhcx/v1/reference/fhir/predetermination-status-and-search) + +### Questionnaire + +- [Insurance plan response](/docs/nhcx/v1/reference/fhir/insurance-plan-response-overview) +- [Insurance plan response, package-based](/docs/nhcx/v1/reference/fhir/insurance-plan-response-package-based) +- [Insurance plan response, coverage-based](/docs/nhcx/v1/reference/fhir/insurance-plan-response-coverage-based) + +### QuestionnaireResponse + +- [Preauthorisation request](/docs/nhcx/v1/reference/fhir/preauthorisation-request) +- [Preauthorisation enhancement](/docs/nhcx/v1/reference/fhir/preauthorisation-enhancement) +- [Preauthorisation query and answer](/docs/nhcx/v1/reference/fhir/preauthorisation-query-and-answer) +- [Claim request](/docs/nhcx/v1/reference/fhir/claim-request) +- [Claim query and answer](/docs/nhcx/v1/reference/fhir/claim-query-and-answer) + +### Task + +NRCeS profile: [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html). + +- [Insurance plan request](/docs/nhcx/v1/reference/fhir/insurance-plan-request) +- [Preauthorisation query and answer](/docs/nhcx/v1/reference/fhir/preauthorisation-query-and-answer) +- [Claim query and answer](/docs/nhcx/v1/reference/fhir/claim-query-and-answer) +- [Cancel, reprocess and shortfall](/docs/nhcx/v1/reference/fhir/cancel-reprocess-and-shortfall) +- [Payment notice and acknowledgement](/docs/nhcx/v1/reference/fhir/payment-notice-and-acknowledgement) +- [Communication](/docs/nhcx/v1/reference/fhir/communication) +- [Predetermination, status and search](/docs/nhcx/v1/reference/fhir/predetermination-status-and-search) + +## Profiles in use + +The profiles the bundles declare in `meta.profile`, each linked to its published definition. + +- [`http://hl7.org/fhir/StructureDefinition/CoverageEligibilityResponse`](https://hl7.org/fhir/R4/coverageeligibilityresponse.html) +- [`https://nrces.in/ndhm/fhir/r4/StructureDefinition/Claim`](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Claim.html) +- [`https://nrces.in/ndhm/fhir/r4/StructureDefinition/ClaimResponse`](https://nrces.in/ndhm/fhir/r4/StructureDefinition-ClaimResponse.html) +- [`https://nrces.in/ndhm/fhir/r4/StructureDefinition/Communication`](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Communication.html) +- [`https://nrces.in/ndhm/fhir/r4/StructureDefinition/CommunicationRequest`](https://nrces.in/ndhm/fhir/r4/StructureDefinition-CommunicationRequest.html) +- [`https://nrces.in/ndhm/fhir/r4/StructureDefinition/Coverage`](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html) +- [`https://nrces.in/ndhm/fhir/r4/StructureDefinition/CoverageEligibilityRequest`](https://nrces.in/ndhm/fhir/r4/StructureDefinition-CoverageEligibilityRequest.html) +- [`https://nrces.in/ndhm/fhir/r4/StructureDefinition/CoverageEligibilityResponse`](https://nrces.in/ndhm/fhir/r4/StructureDefinition-CoverageEligibilityResponse.html) +- [`https://nrces.in/ndhm/fhir/r4/StructureDefinition/InsurancePlan`](https://nrces.in/ndhm/fhir/r4/StructureDefinition-InsurancePlan.html) +- [`https://nrces.in/ndhm/fhir/r4/StructureDefinition/Location`](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Location.html) +- [`https://nrces.in/ndhm/fhir/r4/StructureDefinition/Organization`](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) +- [`https://nrces.in/ndhm/fhir/r4/StructureDefinition/Patient`](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html) +- [`https://nrces.in/ndhm/fhir/r4/StructureDefinition/Practitioner`](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Practitioner.html) +- [`https://nrces.in/ndhm/fhir/r4/StructureDefinition/PractitionerRole`](https://nrces.in/ndhm/fhir/r4/StructureDefinition-PractitionerRole.html) +- [`https://nrces.in/ndhm/fhir/r4/StructureDefinition/Procedure`](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Procedure.html) +- `https://nrces.in/ndhm/fhir/r4/StructureDefinition/QuestionnaireResponse`, which NRCeS does not publish; base FHIR [QuestionnaireResponse](https://hl7.org/fhir/R4/questionnaireresponse.html) +- [`https://nrces.in/ndhm/fhir/r4/StructureDefinition/Task`](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html) + +## PMJAY + +The generic bundle above is what every payer takes, IRDAI-regulated insurers and TPAs included. PMJAY takes it with the changes and requirements below. + +### What PMJAY specifies + +- Payer-generated bundles carry the case number as `Bundle.identifier`, under the payer's own host. The host arrives spelled both `payer.pmjay.nha.gov.in` and `payer.pmajy.nha.gov.in`; echo the spelling that arrived. +- Payer-generated bundles tag every resource `SUBSETTED` from `http://terminology.hl7.org/CodeSystem/v3-ObservationValue`, "Resource encoded in summary mode". It marks a projection of the payer's record, not an error. +- Identifier systems on the payer's side are NHA hosts such as `https://hcx.pmjay.gov.in/v1/preauthorization` and `https://payer.nha.gov.in`. +- A preauthorisation with its embedded clinical records runs to around 30 entries, a claim to over 40, a query answer to nearly a hundred. + +### What PMJAY requires + +- Element ids on every Claim bundle: the `Claim` its claim number, each `item` `Item/n`, each `procedure` `Procedure/n`, each `supportingInfo` `SupportingInformation/n`; `1` for `Patient`, `Coverage` and the provider `Organization`, `2` for the payer `Organization`. Refused with `PAYR-1027` otherwise. +- The `Practitioner` carries the HPR id typed `HPIN` under `https://hpr.abdm.gov.in`, beside `HPID` and the registration number typed `MD`. Refused with `PAYR-1083` otherwise. +- Items coded from the package master: `item.category` is the master's specialty code, and the ward tier rides as `item.modifier` with the master's stratification code. +- Every `supportingInfo` carries a `sequence`, numbered from 1 with no gaps. Refused with `PAYR-1019` otherwise. +- Attachments as `application/pdf`, `application/jpg`, `application/jpeg`, `application/png` or `application/fhir+json`. Anything else is refused with `PAYR-1008`. diff --git a/site/docs/nhcx/v1/reference/fhir/insurance-plan-request.md b/site/docs/nhcx/v1/reference/fhir/insurance-plan-request.md new file mode 100644 index 000000000..a9aa5aa17 --- /dev/null +++ b/site/docs/nhcx/v1/reference/fhir/insurance-plan-request.md @@ -0,0 +1,152 @@ +--- +title: Insurance plan request +sidebar_label: Insurance plan request +sidebar_position: 4 +description: Task-based plan polling request +verification: unverified +source: nhcx-package/docs/05-FHIR Reference/04-Insurance Plan Request.md +generated: true +--- + +# Insurance plan request + +One `Task` asking a payer for the plan behind a policy. There is no patient and no clinical content, because the plan belongs to the policy and the hospital, not to an admission. Sent once per policy and cached. + +Sent on `/v1/insuranceplan/request`, answered on `/v1/insuranceplan/on_request`. + +## The bundle + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `Task` | [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html) | + +## Elements + +### 1. Task + +NRCeS profile: [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html). + +| Element | Example | +| :-- | :-- | +| `status` | `requested` | +| `intent` | `order` | +| `code.coding[]` | `poll` in `http://terminology.hl7.org/CodeSystem/financialtaskcode` | +| `input[]` | valueString `POL7UMU001` | +| | valueString `IN1910000151` | +| `input[].type.coding[]` | `policyNumber` in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code` | +| | `providerId` in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code` | + +## Rules + +### 1. The Task code system + +`poll` under `http://terminology.hl7.org/CodeSystem/financialtaskcode`, not the older `https://nhcx.abdm.gov.in/api`. + +### 2. Intent + +`order`. Some element tables say `original-order`; the bundle sends `order`. + +### 3. Inputs + +`valueString`, typed `policyNumber` and `providerId` under `ndhm-task-input-type-code`. At least one; both narrow the answer to the packages this hospital is empanelled for. + +### 4. No case yet + +No case exists, so the bundle carries no case number. The callback is the only link between request and answer. + +### 5. Task codes differ by system across the exchange + +`poll`, `cancel`, `reprocess`, `release` and `status` in `financialtaskcode`; `deliver` in `ndhm-task-codes`; `approve` in `http://hl7.org/fhir/CodeSystem/task-code`. Switch on system and code together. + +### 6. When to send it + +Once per policy, not per patient. Refresh on a `policychange` communication and on your own schedule. + +## PMJAY + +The generic bundle above is what every payer takes, IRDAI-regulated insurers and TPAs included. PMJAY takes it with the changes and requirements below. + +### What changes in the bundle + +The PMJAY bundle has the same resources, elements and systems as the generic one. + +### What PMJAY specifies + +- `policyNumber` is the beneficiary's own policy code from the policy lookup, of the form `PMJAY//S/G`. +- `providerId` is the hospital's HFR ID, the same value as on its participant record. + +### What PMJAY requires + +- A policy the hospital is not empanelled under is refused with `PAYR-1401`. +- Refresh weekly per the FRD, or every fifteen days per the scenario sheet, and at once on renewal, amendment or a `policychange` communication. + +## Use cases, APIs and data elements + +### B2 Request insurance plan (provider) + +A Task with code poll, keyed on policy number and provider id. The answer is the policy as a benefit structure: packages, rates, documents, questionnaires. + +| | | +| :-- | :-- | +| **API** | `/v1/insuranceplan/request` [`apis/09-insurance-plan/v1-insuranceplan-request.bru`](/docs/nhcx/v1/api/insurance-plan/endpoints/insurance-plan-v1-insuranceplan-request) | +| **Callback** | `/v1/insuranceplan/on_request` [`apis/09-insurance-plan/v1-insuranceplan-on-request.bru`](/docs/nhcx/v1/api/insurance-plan/endpoints/insurance-plan-v1-insuranceplan-on-request) | +| **Carries JWE** | yes | +| **Focal resource** | `Task` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `x-hcx-sender_code` | `1000004446@hcx` | +| `x-hcx-recipient_code` | `1518@hcx` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-request_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{$guid}}` | +| `x-hcx-workflow_id` | `` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `request.initiated` | +| `x-hcx-ben-abha-id` | `` | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `taskCode` | Task Code | Task | `code` | `1..1` | `Task.code.coding[0].code` | `poll` | | +| `policyNumber` | Policy Number | Task Input | `string` | `1..1` | `Task.input[type=PolicyNumber].valueString` | `PMJAY/HP/S/G` | | +| `facilityId` | Provider HFR ID | Task Input | `string` | `1..1` | `Task.input[type=ProviderId].valueString` | `IN1910000151` | | + +NRCeS profiles: [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html). + +### D1 Fetch the insurance plan (pmjay) + +Keyed on provider id, policy code and participant id. The answer is the scheme configuration for this hospital: specialities, packages, rates, Claim-Condition flags, mandatory documents and questionnaires. Over twenty megabytes; store it queryable, version it, refresh weekly and on any policychange communication. + +| | | +| :-- | :-- | +| **API** | `/v1/insuranceplan/request` [`apis/09-insurance-plan/v1-insuranceplan-request.bru`](/docs/nhcx/v1/api/insurance-plan/endpoints/insurance-plan-v1-insuranceplan-request) | +| **Callback** | `/v1/insuranceplan/on_request` [`apis/09-insurance-plan/v1-insuranceplan-on-request.bru`](/docs/nhcx/v1/api/insurance-plan/endpoints/insurance-plan-v1-insuranceplan-on-request) | +| **Carries JWE** | yes | +| **Focal resource** | `Task` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `x-hcx-sender_code` | `1000004446@hcx` | +| `x-hcx-recipient_code` | `1518@hcx` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-request_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{$guid}}` | +| `x-hcx-workflow_id` | `` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `request.initiated` | +| `x-hcx-ben-abha-id` | `` | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `taskCode` | Task Code | Task | `code` | `1..1` | `Task.code.coding[0].code` | `poll` | | +| `schemeId` | Scheme Policy Identifier | Task Input | `string` | `1..1` | `Task.input[type=PolicyNumber].valueString` | `PMJAY/HP/S/G` | | + +NRCeS profiles: [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html). diff --git a/site/docs/nhcx/v1/reference/fhir/insurance-plan-response-coverage-based.md b/site/docs/nhcx/v1/reference/fhir/insurance-plan-response-coverage-based.md new file mode 100644 index 000000000..645779537 --- /dev/null +++ b/site/docs/nhcx/v1/reference/fhir/insurance-plan-response-coverage-based.md @@ -0,0 +1,162 @@ +--- +title: Insurance plan response, coverage-based +sidebar_label: Insurance plan response, coverage-based +sidebar_position: 7 +description: Commercial insurance plan layout +verification: unverified +source: nhcx-package/docs/05-FHIR Reference/07-Insurance Plan Response, Coverage-Based.md +generated: true +--- + +# Insurance plan response, coverage-based + +The shape a private insurer or its TPA sends, and the generic shape on the exchange. An indemnity policy lists benefits with money limits, and the hospital bills against those limits rather than against a package price. + +## The bundle + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `InsurancePlan` | [InsurancePlan](https://nrces.in/ndhm/fhir/r4/StructureDefinition-InsurancePlan.html) | +| 2 | `Organization (ins)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 3 | `Questionnaire` | none | +| 4 | `Questionnaire` | none | +| 5 | `Questionnaire` | none | +| 6 | `Questionnaire` | none | +| 7 | `Questionnaire` | none | + +## Elements + +NRCeS profile: [InsurancePlan](https://nrces.in/ndhm/fhir/r4/StructureDefinition-InsurancePlan.html). + +| Element | Example | +| :-- | :-- | +| `coverage[].type.coding[]` | `737481003` Inpatient care management (procedure) in `http://snomed.info/sct` | +| | `710967003` Management of health status after discharge from hospital (procedure) in `http://snomed.info/sct` | +| | `409972000` Pre-hospital care in `http://snomed.info/sct` | +| | and 6 more | +| `coverage[].benefit[].type.coding[]` | `309904001` Intensive care unit (environment) in `http://snomed.info/sct` | +| | `87612001` Blood in `http://snomed.info/sct` | +| | `24099007` Oxygen (substance) in `http://snomed.info/sct` | +| | and 20 more | +| `coverage[].benefit[].limit[].value` | value `90`, comparator `<=`, unit `day` | +| | value `60`, comparator `<=`, unit `day` | +| `coverage[].benefit[]` | id `PROC-PED-05` | +| | id `PROC-CARD-04` | +| | id `PROC-CAT-03` | +| | and 2 more | +| `coverage[].benefit[].type` | text `Paediatric Pneumonia, PICU Management` | +| | text `Percutaneous Transluminal Coronary Angioplasty (PTCA)` | +| | text `Cataract Surgery with Foldable IOL` | +| | and 2 more | +| `plan[].identifier[]` | use `official`, value `Sandbox Default Policy` | +| `plan[].type.coding[]` | `01` Individual in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-plan-type` | +| `plan[].generalCost[].cost` | value `500000`, currency `INR` | +| `plan[].specificCost[].category.coding[]` | `49122002` Ambulance, device (physical object) in `http://snomed.info/sct` | +| | `224663004` Single room (environment) in `http://snomed.info/sct` | +| | `309904001` Intensive care unit (environment) in `http://snomed.info/sct` | +| | and 4 more | +| `plan[].specificCost[].benefit[].type.coding[]` | `49122002` Ambulance, device (physical object) in `http://snomed.info/sct` | +| | `224663004` Single room (environment) in `http://snomed.info/sct` | +| | `309904001` Intensive care unit (environment) in `http://snomed.info/sct` | +| | and 16 more | +| `plan[].specificCost[].benefit[].cost[].type.coding[]` | `fullcoverage` | +| | `Procedure` Selected treatment or service or product is a type of procedure or package in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-plan-type` | +| `plan[].specificCost[].benefit[].cost[].value` | value `5000`, unit `INR` | +| | value `10000`, unit `INR` | +| | value `20000`, unit `INR` | +| | and 6 more | +| `plan[].specificCost[].benefit[]` | id `PROC-PED-05` | +| | id `PROC-CARD-04` | +| | id `PROC-CAT-03` | +| | and 2 more | +| `plan[].specificCost[].benefit[].type` | text `Paediatric Pneumonia, PICU Management` | +| | text `Percutaneous Transluminal Coronary Angioplasty (PTCA)` | +| | text `Cataract Surgery with Foldable IOL` | +| | and 2 more | + +## Claim-Condition flags + +| Flag | Values in the plan | What it governs | +| :-- | :-- | :-- | +| `ProcedureType` | `Critical Care`, `Day Care`, `Surgical` | The kind of care the benefit covers, such as surgical, day care or critical care | +| `IsDayCare` | `N`, `Y` | Day-care treatment, no overnight stay | +| `ImplantApplicable` | `N`, `Y` | Whether an implant may be billed under the benefit | + +## Supporting-information requirements + +| Code | Display | Stage | System | +| :-- | :-- | :-- | :-- | +| `POI` | Proof of identity | preauth | `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| `DIA` | Diagnostic report | preauth | `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| `RAD` | Radiology / X-Ray / CT / MRI Scan Reports | preauth | `` | +| `HDS` | Hospital discharge summary | discharge | `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| `CD` | Clinical document | discharge | `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| `ICU` | ICU Flow Chart & Vital Monitoring Log | discharge | `` | +| `HDS` | Hospital discharge summary | claim | `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| `MB` | Medical bill | claim | `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| `FCF` | Filled claim form | claim | `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| `INF` | Additional info related to claim | any | `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| `STG` | Standard Treatment Guidelines | any | `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| `ANG` | Coronary Angiography Film & CD Report | preauth | `` | +| `ECG` | 12-Lead Electrocardiogram (ECG) Strip | preauth | `` | +| `MB` | Medical bill | preauth | `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| `EST` | Detailed Pre-Auth Cost Estimate | preauth | `` | +| `IMP` | Document Type - Implant | discharge | `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| `IMP` | Document Type - Implant | claim | `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| `CER` | Medical Certficate | preauth | `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| `MB` | Medical bill | discharge | `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| `DIA` | Diagnostic report | claim | `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| `HIS_PATH` | Histopathology / Biopsy Report | claim | `` | +| `CD` | Clinical document | claim | `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| `OTR` | Operation Theatre Notes & Surgical Summary | claim | `` | + +10 of the requirements link a questionnaire through `documentationUrl`. + +## Exclusions + +| category | statement | item | +| :-- | :-- | :-- | +| Excl01 | Expenses related to the treatment of a pre-existing Disease (PED) and its direc… | | +| Excl02 | Expenses related to the treatment of the listed conditions, surgeries and treat… | 86077009 | +| Excl03 | Expenses related to the treatment of any illness within 30 days from the first … | | +| Excl08 | Expenses for cosmetic or plastic surgery are excluded unless required as part o… | | + +## Questionnaires + +| Title | Items | Item types | Question in | +| :-- | :-- | :-- | :-- | +| Paediatric Pneumonia, PICU Management, Standard Treatment Guidelines | 4 | `string` | `text` | +| Percutaneous Transluminal Coronary Angioplasty (PTCA), Standard Treatment Guide… | 5 | `string` | `text` | +| Cataract Surgery with Foldable IOL, Standard Treatment Guidelines | 4 | `string` | `text` | +| Acute Appendectomy (Laparoscopic), Standard Treatment Guidelines | 4 | `string` | `text` | +| Total Knee Replacement (Unilateral), Standard Treatment Guidelines | 5 | `string` | `text` | + +## Rules + +### 1. One structure per benefit + +Everything about a benefit, its conditions and required documents, hangs off `coverage[].benefit[]`, with its money cap in `limit[]`. `plan[].specificCost[]` carries the cost per benefit category. + +### 2. Conditions are prose + +The `Claim-Condition` extension on a benefit carries a sentence, such as a window after discharge, with the number in `limit[]` as a value, a comparator and a unit. + +### 3. Benefit types are the insurer's vocabulary + +No closed value set is published for indemnity benefit types. Ask the insurer for its list before building a picker. + +### 4. Requirements by stage + +Supporting-info requirements name the stage they apply to, preauthorisation, discharge or claim, in the extension url. + +### 5. Exclusions + +Waiting periods, pre-existing-condition rules and excluded procedures are `Claim-Exclusion` extensions on the plan, each with a category and a statement. + +### 6. What the screen caps + +The amount, against the benefit's limit. Submission is blocked by an amount over the limit or a missing mandatory document. + +## PMJAY + +PMJAY does not send this shape. Its plan is package-based; see the previous chapter. diff --git a/site/docs/nhcx/v1/reference/fhir/insurance-plan-response-overview.md b/site/docs/nhcx/v1/reference/fhir/insurance-plan-response-overview.md new file mode 100644 index 000000000..286cbe994 --- /dev/null +++ b/site/docs/nhcx/v1/reference/fhir/insurance-plan-response-overview.md @@ -0,0 +1,221 @@ +--- +title: Insurance plan response +sidebar_label: Insurance plan response +sidebar_position: 5 +description: Collection bundle overview and questionnaires +verification: unverified +source: nhcx-package/docs/05-FHIR Reference/05-Insurance Plan Response Overview.md +generated: true +--- + +# Insurance plan response + +The payer's answer to the poll, and the largest message on NHCX. It is the policy as data: what the hospital may bill, at what rate, under what rules, with which documents and on which forms. Everything on a treatment-planning screen comes from here. + +Sent on `/v1/insuranceplan/on_request`. + +## The bundle + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `InsurancePlan` | [InsurancePlan](https://nrces.in/ndhm/fhir/r4/StructureDefinition-InsurancePlan.html) | +| 2 | `Organization (ins)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 3 | `Questionnaire` | none | +| 4 | `Questionnaire` | none | +| 5 | `Questionnaire` | none | +| 6 | `Questionnaire` | none | +| 7 | `Questionnaire` | none | + +## Elements + +### 1. InsurancePlan + +NRCeS profile: [InsurancePlan](https://nrces.in/ndhm/fhir/r4/StructureDefinition-InsurancePlan.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system `https://irdai.gov.in`, value `SANDBOX-DEFAULT-01` | +| `status` | `active` | +| `type[].coding[]` | `01` Hospitalisation Indemnity Policy in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-insuranceplan-type` | +| `name` | `Sandbox Default Policy` | +| `alias` | `Sandbox Default`, `Default` | +| `period` | start `2026-01-01`, end `2026-12-31` | +| `ownedBy` | reference `urn:uuid:39cd4b51-bddd-5cc1-a65a-6fa4a2a83cb5`, display `Sandbox Payer` | +| `administeredBy` | reference `urn:uuid:39cd4b51-bddd-5cc1-a65a-6fa4a2a83cb5`, display `Sandbox Payer` | +| `plan[].identifier[]` | use `official`, value `Sandbox Default Policy` | +| `plan[].type.coding[]` | `01` Individual in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-plan-type` | +| `plan[].generalCost[].cost` | value `500000`, currency `INR` | + +### 2. Organization (ins) + +NRCeS profile: [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html). + +| Element | Example | +| :-- | :-- | +| `type[].coding[]` | `ins` Insurance Company in `http://terminology.hl7.org/CodeSystem/organization-type` | +| `name` | `Sandbox Payer` | +| `address[]` | city `Bengaluru`, state `Karnataka`, country `India` | + +### 3. Questionnaire + +| Element | Example | +| :-- | :-- | +| `url` | `` | +| `name` | `STG Questionnaire` | +| `title` | `Paediatric Pneumonia, PICU Management, Standard Treatment Guidelines` | +| `status` | `active` | + +### 4. Questionnaire + +| Element | Example | +| :-- | :-- | +| `url` | `` | +| `name` | `STG Questionnaire` | +| `title` | `Percutaneous Transluminal Coronary Angioplasty (PTCA), Standard Treatment Guide…` | +| `status` | `active` | + +### 5. Questionnaire + +| Element | Example | +| :-- | :-- | +| `url` | `` | +| `name` | `STG Questionnaire` | +| `title` | `Cataract Surgery with Foldable IOL, Standard Treatment Guidelines` | +| `status` | `active` | + +### 6. Questionnaire + +| Element | Example | +| :-- | :-- | +| `url` | `` | +| `name` | `STG Questionnaire` | +| `title` | `Acute Appendectomy (Laparoscopic), Standard Treatment Guidelines` | +| `status` | `active` | + +### 7. Questionnaire + +| Element | Example | +| :-- | :-- | +| `url` | `` | +| `name` | `STG Questionnaire` | +| `title` | `Total Knee Replacement (Unilateral), Standard Treatment Guidelines` | +| `status` | `active` | + +## Questionnaires + +| Title | Items | Item types | Question in | +| :-- | :-- | :-- | :-- | +| Paediatric Pneumonia, PICU Management, Standard Treatment Guidelines | 4 | `string` | `text` | +| Percutaneous Transluminal Coronary Angioplasty (PTCA), Standard Treatment Guide… | 5 | `string` | `text` | +| Cataract Surgery with Foldable IOL, Standard Treatment Guidelines | 4 | `string` | `text` | +| Acute Appendectomy (Laparoscopic), Standard Treatment Guidelines | 4 | `string` | `text` | +| Total Knee Replacement (Unilateral), Standard Treatment Guidelines | 5 | `string` | `text` | + +## Rules + +### 1. Two shapes + +Coverage-based, sent by private insurers and TPAs: benefits with money limits, rules as prose. Package-based, sent by government schemes: named packages at fixed rates, rules as flags. The next two chapters take each shape. + +### 2. Two type codes + +`InsurancePlan.type` says what kind of insurance this is. `plan.type` says how it is sold, individual or group. + +### 3. Identifier + +A private insurer's plan is identified under `https://irdai.gov.in`. A scheme plan is identified under NHA hosts, with the policy code and the revision. + +### 4. The wallet + +`plan.generalCost` is the sum insured, or the family wallet under a scheme. + +### 5. Cache per policy + +Stamp the cache with the plan's revision identifier, and record on every preauthorisation and claim which revision it was built against. + +### 6. The first line of validation + +Codes and displays, amounts, quantities and mandatory documents are checked against the cached plan on the server before anything is sent. + +### 7. The forms + +The `Questionnaire` resources are the payer's forms. Render them from the plan, never hard-code them, because they change with the plan. + +## PMJAY + +The generic bundle above is what every payer takes, IRDAI-regulated insurers and TPAs included. PMJAY takes it with the changes and requirements below. + +### What changes in the bundle + +#### Elements PMJAY adds + +| Element | Example | +| :-- | :-- | +| `InsurancePlan.identifier[].type.coding[]` | `NH` National Health Plan Identifier in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| | `XV` Health Plan Identifier in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `Organization.identifier[]` | system `https://facility.abdm.gov.in`, value `1518` | +| `Organization.identifier[].type.coding[]` | `NIIP` National Insurance Payor Identifier (Payor) in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `Organization.active` | `true` | +| `Organization.contact[].telecom[]` | system `phone`, value `9000000003` | + +#### Elements PMJAY leaves out + +| Element | Example | +| :-- | :-- | +| `InsurancePlan.alias` | `Sandbox Default`, `Default` | +| `InsurancePlan.plan[].identifier[]` | use `official`, value `Sandbox Default Policy` | +| `Organization.address[]` | city `Bengaluru`, state `Karnataka`, country `India` | + +#### Systems PMJAY binds differently + +| Element | Generic | PMJAY | +| :-- | :-- | :-- | +| `InsurancePlan.identifier[]` | `https://irdai.gov.in` | `https://hcx.pmjay.gov.in/v1/InsurancePlan`, `https://payer.nha.gov.in` | + +### What PMJAY specifies + +- Package-based throughout: `InsurancePlan.type` `07` Universal Health Policy, `plan.type` `03` Group. +- `identifier` carries the policy code typed `NH` and the scheme revision typed `XV`; the revision is what the cache is stamped with. +- A full scheme plan carries thousands of `Questionnaire` entries, many of them repeated. Deduplicate on `fullUrl`. + +### What PMJAY requires + +- Keep the revision on every submission. An outdated tariff causes a rate mismatch and a rejection on suspicion of tampering. + +## Use cases, APIs and data elements + +### C4 Respond to insurance plan request (payer) + +The plan as a benefit structure. Under PMJAY this is the scheme configuration for one hospital and can exceed twenty megabytes. + +| | | +| :-- | :-- | +| **API** | `/v1/insuranceplan/on_request` [`apis/09-insurance-plan/v1-insuranceplan-on-request.bru`](/docs/nhcx/v1/api/insurance-plan/endpoints/insurance-plan-v1-insuranceplan-on-request) | +| **Callback** | `/v1/insuranceplan/request` [`apis/09-insurance-plan/v1-insuranceplan-request.bru`](/docs/nhcx/v1/api/insurance-plan/endpoints/insurance-plan-v1-insuranceplan-request) | +| **Workflow** | none (or 5 under PMJAY) | +| **Carries JWE** | yes | +| **Focal resource** | `InsurancePlan` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `x-hcx-sender_code` | `1518@hcx` | +| `x-hcx-recipient_code` | `1000004446@hcx` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-request_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{$guid}}` | +| `x-hcx-workflow_id` | `` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `response.complete` | +| `x-hcx-ben-abha-id` | `` | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `planName` | Insurance Plan Name | Plan | `string` | `1..1` | `InsurancePlan.name` | `PMJAY Ayushman Bharat` | | +| `packageCode` | Benefit Package Code | Plan Cost | `string` | `1..*` | `InsurancePlan.plan[].specificCost[].benefit[].type.coding[0].code` | `MG004A` | | +| `packageRate` | Agreed Tariff Rate | Plan Cost | `decimal` | `1..*` | `InsurancePlan.plan[].specificCost[].benefit[].cost[0].value.value` | `15500.00` | | + +NRCeS profiles: [InsurancePlan](https://nrces.in/ndhm/fhir/r4/StructureDefinition-InsurancePlan.html). diff --git a/site/docs/nhcx/v1/reference/fhir/insurance-plan-response-package-based.md b/site/docs/nhcx/v1/reference/fhir/insurance-plan-response-package-based.md new file mode 100644 index 000000000..fe84744d1 --- /dev/null +++ b/site/docs/nhcx/v1/reference/fhir/insurance-plan-response-package-based.md @@ -0,0 +1,231 @@ +--- +title: Insurance plan response, package-based +sidebar_label: Insurance plan response, package-based +sidebar_position: 6 +description: PMJAY package structure and claim condition extensions +verification: unverified +source: nhcx-package/docs/05-FHIR Reference/06-Insurance Plan Response, Package-Based.md +generated: true +--- + +# Insurance plan response, package-based + +The shape government schemes send, and PMJAY sends throughout. A package is a named procedure at a fixed, all-inclusive rate. The plan carries every package the hospital may bill and the rules that govern each one. Everything in this chapter is what PMJAY specifies. + +## The bundle + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `InsurancePlan` | none declared; NRCeS [InsurancePlan](https://nrces.in/ndhm/fhir/r4/StructureDefinition-InsurancePlan.html) | +| 2 | `Organization (pay)` | none declared; NRCeS [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 3 | `Questionnaire` | none | +| 4 | `Questionnaire` | none | +| 5 | `Questionnaire` | none | +| 6 | `Questionnaire` | none | +| 7 | `Questionnaire` | none | + +## Elements + +NRCeS profile: [InsurancePlan](https://nrces.in/ndhm/fhir/r4/StructureDefinition-InsurancePlan.html). + +| Element | Example | +| :-- | :-- | +| `coverage[].type.coding[]` | `MG` General Medicine in `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-benefitcategory` | +| | `SG` General Surgery in `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-benefitcategory` | +| | `MO` Medical Oncology in `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-benefitcategory` | +| | and 4 more | +| `coverage[].benefit[]` | id `MG004A` | +| | id `MG005A` | +| | id `MG072C` | +| | and 16 more | +| `coverage[].benefit[].type.coding[]` | `MG004A` Dengue fever (Dengue fever) in `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-productorservice` | +| | `MG005A` Chikungunya fever (Chikungunya fever) in `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-productorservice` | +| | `MG072C` Acute Haemodialysis (Acute Haemodialysis) in `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-productorservice` | +| | and 16 more | +| `coverage[].benefit[].limit[]` | id `MGMG004A` | +| | id `MGMG004ASTRAT006a` | +| | id `MGMG004ASTRAT006b` | +| | and 77 more | +| `coverage[].benefit[].limit[].value` | value `0`, unit `INR` | +| | value `1800`, unit `INR` | +| | value `2700`, unit `INR` | +| | and 14 more | +| `coverage[].benefit[].limit[].code.coding[]` | `MG004A` Dengue fever (Dengue fever) | +| | `STRAT006a` Routine Ward | +| | `STRAT006b` HDU | +| | and 23 more | +| `plan[].type.coding[]` | `03` Group in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-plan-type` | +| `plan[].generalCost[].cost` | value `500000`, currency `INR` | +| `plan[].specificCost[]` | id `MG` | +| | id `SG` | +| | id `MO` | +| | and 2 more | +| `plan[].specificCost[].category.coding[]` | `MG` General Medicine in `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-benefitcategory` | +| | `SG` General Surgery in `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-benefitcategory` | +| | `MO` Medical Oncology in `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-benefitcategory` | +| | and 2 more | +| `plan[].specificCost[].benefit[]` | id `PlanBenefit/MG004A` | +| | id `PlanBenefit/MG005A` | +| | id `PlanBenefit/MG072C` | +| | and 12 more | +| `plan[].specificCost[].benefit[].type.coding[]` | `MG004A` Dengue fever (Dengue fever) in `http://hl7.org/fhir/ValueSet/procedure-category` | +| | `MG005A` Chikungunya fever (Chikungunya fever) in `http://hl7.org/fhir/ValueSet/procedure-category` | +| | `MG072C` Acute Haemodialysis (Acute Haemodialysis) in `http://hl7.org/fhir/ValueSet/procedure-category` | +| | and 12 more | +| `plan[].specificCost[].benefit[].cost[].type.coding[]` | `Procedure` Selected treatment or service or proudct is a type of procedure or package in `https://www.nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-plan-type` | +| | `Stratification` Selected treatment or service or proudct is a type of stratification in `https://www.nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-plan-type` | +| `plan[].specificCost[].benefit[].cost[].value` | value `0`, unit `INR` | +| | value `1800`, unit `INR` | +| | value `2700`, unit `INR` | +| | and 11 more | +| `plan[].specificCost[].benefit[].cost[].qualifiers[].coding[]` | `STRAT006a` Routine Ward in `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-productorservice` | +| | `STRAT006b` HDU in `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-productorservice` | +| | `STRAT006c` ICU - Without Ventilator in `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-productorservice` | +| | and 3 more | + +## Claim-Condition flags + +| Flag | Values in the plan | What it governs | +| :-- | :-- | :-- | +| `ProcedureType` | `Conservative`, `Medical`, `Surgical` | Surgical, Medical or Conservative. Decides the clinical pathway, the document set, and the one-conservative-package-per-case rule | +| `GovtReserved` | `N` | `Y` means only a government hospital may bill it. Hide it in a private facility | +| `ApprovalNotRequired` | `Y`, `N` | `Y` means treatment need not wait for a decision. The case auto-approves if it is the first preauthorisation and every package has it | +| `EnhancementAllowed` | `Y`, `N` | `Y` means the package may be added on an enhancement | +| `ScheduledTATApproval` | `Y`, `N` | `Y` means the payer's silence within the turnaround window is approval | +| `QuantityAllowed` | `1`, `6` | Maximum quantity per approval | +| `IsDayCare` | `Y`, `N` | Day-care procedure, no overnight stay | +| `ImplantApplicable` | `N`, `Y` | Whether an implant line may be added | +| `StratificationAllowed` | `Y`, `N` | Whether a ward tier may ride as `item.modifier` | +| `MultipleImplantsAllowed` | `N` | Whether more than one implant may be added | +| `MultipleStratificationAllowed` | `Y`, `N` | Whether more than one ward tier may be added | +| `MaximumImplantsAllowed` | `1`, `0` | Cap on the number of implants | +| `MaximumStratificationAllowed` | `1`, `0` | Cap on the number of ward tiers | +| `CyclicProcedure` | `N`, `Y` | Repeatable under one approval, one supporting-info entry per cycle | +| `MaximumCyclesAllowed` | `0`, `6` | Cap on the number of cycles | +| `Standalone` | `N` | Refuse any other package alongside it | +| `ParentProcedure` | `NA`, `IN015A,SB003C,SB015C,SB072A,SB088MLA,SB103MLC,SB106MLA,SL038MLA,SM001MLA,SM003B…`, `IN058A,IN071A,MC023MLA,SB095MLB,SB100MLB,SB108MLA,SE012MLA,SM007B,SM027MLA,SN05…` | On an implant, the package it may accompany | +| `Unspecified` | `N`, `Y` | Free-text name and free-entry amount, validated against the wallet | +| `LamaDamaProcedure` | `Y` | Offer only on a LAMA or DAMA discharge | +| `DischargeStagesLamaDamaProcedure` | `Before Surgery, During Surgery` | The discharge stages at which a LAMA or DAMA package may be billed, before or during surgery | +| `los` | not carried | Maximum length of stay; bounds the days claimed, the `LM100` count included | + +## Supporting-information requirements + +| Code | Display | Stage | System | +| :-- | :-- | :-- | :-- | +| `POI` | Proof of identity | any | `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| `ADN` | Aadhaar Number | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `INF` | Additional info related to claim ( conveying additional situation and condition… | any | `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| `ODN` | Other document | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `DIA` | Diagnostic report | any | `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| `MAND0409` | any investigations done | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0064` | All investigations reports | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0006` | Detailed discharge summary | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0062` | Detailed ICPs | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0063` | Treatment details | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `CD` | | any | `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| `MAND0408` | Clinical notes detailing history and Admission notes showing vitals and examina… | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `STG` | Standard Treatment Guidelines | any | `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| `MAND0952` | MLC/ FIR +/- Nerve conduction velocity (NCV) + /- MRI + /- MRA + /- EMG (Electr… | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0300` | Detailed operatives notes | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0309` | Intra operative still photograph | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0946` | Clinical notes detailing the injury and need of surgery | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `HDS` | | any | `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| `MAND0368` | Procedure / Operative Notes, Detailed Discharge Summary | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND1045` | Clinical notes with planned line of treatment (including indication for need of… | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0384` | MLC/ FIR if traumatic | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0592` | X Ray of affected limb | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0008` | Detailed Procedure / Operative Notes | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0112` | Post Procedure clinical photgraph | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0582` | clinical photograph of affected part | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0604` | clinical notes justifying the indication | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0067` | CBC | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0459` | CECT Thorax, abdomen and Pelvis | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0564` | histopathology (non small cell - adenocarcinoma or adenosquamous carcinoma) | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0074` | LFT | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0457` | RBS | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0447` | RFT | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0099` | BAR CODE OF THE DRUGS | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0102` | CHARTS OF CHEMOTHERAPY REGIMEN | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0101` | DISCHARGE SUMMARY OF INPATIENT DEPARTMENT / DISCHARGE SUMMARY OF DAY CARE DEPAR… | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0100` | REPORTS OF THE TESTS (PATHOLOGY, RADIOLOGY, MICROBIOLOGY, HEMATOLOGY, BIOCHEMIS… | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0103` | TRANFUSION SLIPS | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0189` | Histopathology report | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0226` | Post Procedure Photograph of affected part | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0030` | Procedure / Operative Notes | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0822` | Clinical notes with planned line of treatment justifying indication | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0647` | FIR/MLC in case of accident | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0161` | operative notes | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0159` | Still image of the the procedure with pt. ID and date | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0003` | Clinical notes | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0588` | clinical photograph | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0649` | doctors notes | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0648` | Patient details | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0650` | photo | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0162` | Discharge notes | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0163` | microbiology report | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0164` | Still image of the patient undergoing the procedure with date stamp | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0622` | CECT | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0621` | FNAC/ BIOPSY | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0152` | HPE report | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0151` | Post Procedure Photographs of surgical site | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0339` | Clinical notes with planned line of treatment | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0831` | Audiogram report justfying surgery | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0832` | CT- TEMPORAL BONE of affected side /X-RAY BOTH MASTOIDS | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0730` | USG/CT Abdomen | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0327` | Detailed discharge summary; | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | +| `MAND0326` | Reports of all investigations done and consultation paper of treating doctor me… | any | `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-supportinginfo-code` | + +5 of the requirements link a questionnaire through `documentationUrl`. + +## Questionnaires + +| Title | Items | Item types | Question in | +| :-- | :-- | :-- | :-- | +| Discharge Information | 7 | `attachment`, `choice`, `dateTime` | `text` | +| General Findings | 9 | `string`, `choice` | `text` | +| Personal History | 6 | `choice` | `text` | +| Family History | 7 | `choice` | `text` | +| Admission Details | 4 | `dateTime`, `choice` | `text` | + +## Rules + +### 1. Two parallel structures + +`coverage[]` carries the rules: flags, document requirements, questionnaire links and `limit[]` rates. `plan[].specificCost[]` carries the money: `cost[]` lines by type. Both hold the same package codes. Index both by package code and join; neither is complete alone. + +### 2. Categories + +`coverage[].type` and `specificCost[].category` bind to `https://nrces.in/ndhm/fhir/r4/ValueSet/ndhm-benefitcategory`. Codes beginning `S` are surgical, `M` medical. + +### 3. Flags are strings + +Every flag except `ParentProcedure` is a `valueString`. `"N"` is truthy in most languages; compare against the literal `"Y"`. + +### 4. Cost lines + +`Procedure` is the base package rate. `Stratification` is the rate for a ward tier, named in `cost.qualifiers[]`. `Implant` is added over the package rate. + +### 5. A zero base rate + +A base limit of 0 means the payable amount is set entirely by the ward tier chosen. It is not missing data. Never submit a zero-value item. + +### 6. Document requirements come in two shapes + +Nested, one sub-extension per document, and flat, with `category`, `code` and `documentationUrl` directly under the extension. Recurse, or one shape is silently dropped. + +### 7. Where the question is + +Policy-level questionnaires put the question in `item.text`, STG questionnaires in `item.prefix`. Read `text` and fall back to `prefix`. + +### 8. Implant codes repeat + +Once per parent procedure they may accompany. Key on the package code with its parent, or on the element `id`. + +### 9. Extension urls change form + +The absolute `https://nrces.in/ndhm/fhir/r4/StructureDefinition/Claim-Condition` and the relative `claim-condition` both occur. Match on the last segment. + +## PMJAY + +This is the PMJAY shape; the rules above are PMJAY's. diff --git a/site/docs/nhcx/v1/reference/fhir/payment-notice-and-acknowledgement.md b/site/docs/nhcx/v1/reference/fhir/payment-notice-and-acknowledgement.md new file mode 100644 index 000000000..c87f95e21 --- /dev/null +++ b/site/docs/nhcx/v1/reference/fhir/payment-notice-and-acknowledgement.md @@ -0,0 +1,304 @@ +--- +title: Payment notice and acknowledgement +sidebar_label: Payment notice and acknowledgement +sidebar_position: 16 +description: Payment notices, reconciliations, and payment receipts +verification: unverified +source: nhcx-package/docs/05-FHIR Reference/16-Payment Notice and Acknowledgement.md +generated: true +--- + +# Payment notice and acknowledgement + +The payer's notice that money has moved against an approved claim, and the provider's acknowledgement. The only exchange that carries actual money rather than an adjudicated figure. + +## The notice + +Sent on `/v1/paymentnotice/request`, workflow 30 initiated, 31 processed, 33 settled. + +### The bundle + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `Task` | none declared; NRCeS [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html) | +| 2 | `PaymentNotice` | none declared; NRCeS [PaymentNotice](https://nrces.in/ndhm/fhir/r4/StructureDefinition-PaymentNotice.html) | +| 3 | `PaymentReconciliation` | none declared; NRCeS [PaymentReconciliation](https://nrces.in/ndhm/fhir/r4/StructureDefinition-PaymentReconciliation.html) | +| 4 | `Organization (prov)` | none declared; NRCeS [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 5 | `Organization (pay)` | none declared; NRCeS [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | + +### Elements + +#### 1. Task + +NRCeS profile: [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html). + +| Element | Example | +| :-- | :-- | +| `status` | `requested` | +| `intent` | `order` | +| `code.coding[]` | `deliver` deliver in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-codes` | +| `description` | `Settled in full: INR 135000 paid against INR 150000 approved.` | +| `authoredOn` | `2026-09-10T23:53:39+05:30` | +| `requester` | reference `` | +| `owner` | reference `` | +| `input[].type.coding[]` | `status` Status code in `http://terminology.hl7.org/CodeSystem/financialtaskinputtype` | +| `input[].valueReference` | reference `` | + +#### 2. PaymentNotice + +NRCeS profile: [PaymentNotice](https://nrces.in/ndhm/fhir/r4/StructureDefinition-PaymentNotice.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system ``, value `NM-26-0SE00002L` | +| `identifier[].type.coding[]` | `CLN` Claim number in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| `status` | `active` | +| `created` | `2026-09-10T23:53:39+05:30` | +| `payment` | reference `` | +| `recipient` | reference `` | +| `amount` | value `135000`, currency `INR` | +| `paymentStatus.coding[]` | `cleared` Cleared in `http://terminology.hl7.org/CodeSystem/paymentstatus` | + +#### 3. PaymentReconciliation + +NRCeS profile: [PaymentReconciliation](https://nrces.in/ndhm/fhir/r4/StructureDefinition-PaymentReconciliation.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system ``, value `NM-26-0SE00002L` | +| `identifier[].type.coding[]` | `CLN` Claim number in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| `status` | `active` | +| `created` | `2026-09-10T23:53:39+05:30` | +| `disposition` | `Settled in full: INR 135000 paid against INR 150000 approved.` | +| `paymentDate` | `2026-09-10` | +| `paymentAmount` | value `135000`, currency `INR` | +| `paymentIdentifier` | system ``, value `UTR1789064619092` | +| `paymentIdentifier.type.coding[]` | `UTR` Unique Transaction Reference in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| `detail[]` | id `PAY-2026-0009/TDS`, date `2026-09-10` | +| | id `PAY-2026-0009/Payment`, date `2026-09-10` | +| `detail[].identifier` | system ``, value `PAY-2026-0009/TDS` | +| | system ``, value `PAY-2026-0009/Payment` | +| `detail[].identifier.type.coding[]` | `PLAC` Placer Identifier in `https://https://nrces.in/ndhm/fhir/r4/ValueSet-ndhm-identifier-type-code.html` | +| `detail[].type.coding[]` | `TDS` TDS in `http://hl7.org/fhir/ValueSet/payment-type` | +| | `Payment` Payment in `http://hl7.org/fhir/ValueSet/payment-type` | +| `detail[].amount` | value `15000` | +| | value `135000` | + +The `Organization` entries are shaped as in the chapters that introduce them. + +## The acknowledgement + +Sent on `/v1/paymentnotice/on_request`, workflow 30 echoed; 17 under PMJAY. + +### The bundle + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `Task` | [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html) | +| 2 | `Organization (prov)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 3 | `Organization (pay)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | + +### Elements + +#### 1. Task + +NRCeS profile: [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html). + +| Element | Example | +| :-- | :-- | +| `status` | `completed` | +| `intent` | `order` | +| `code.coding[]` | `status` in `http://terminology.hl7.org/CodeSystem/financialtaskcode` | +| `authoredOn` | `2026-09-10T23:53:40+05:30` | +| `requester` | reference `https://nhcx.abdm.gov.in/provider` | +| `owner` | reference `https://nhcx.abdm.gov.in/payer` | +| `description` | `Received the payment for claim NM-26-0SE00002L` | +| `output[].type.coding[]` | `status` Status in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-output-type` | +| | `claimNumber` ClaimNumber in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-input-type-code` | +| `output[].valueCodeableConcept.coding[]` | `paymentack` Payment is acknowledged in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-output-value` | +| `output[]` | valueString `NM-26-0SE00002L` | + +The `Organization` entries are shaped as in the chapters that introduce them. + +## Rules + +### 1. The notice + +A `Task` coded `deliver` in `ndhm-task-codes` whose input references the `PaymentNotice`. `PaymentNotice.amount` is the net that reaches the account. `PaymentReconciliation` carries the payment date, the `UTR` and one `detail[]` line per money type. + +### 2. The arithmetic + +Net plus the deductions equals the adjudicated benefit, not the submitted amount. Run the check on every notice and flag a case that fails it. + +### 3. The acknowledgement + +A `Task` coded `status` in `financialtaskcode`, `completed`, with an output `paymentack` and the claim number as a second output. It confirms receipt, not agreement. + +### 4. Three notices + +30, 31 and 33, each with its own correlation id. The bank reference arrives on 33. Keep the path for the acknowledgement configurable per payer. + +## PMJAY + +The generic bundle above is what every payer takes, IRDAI-regulated insurers and TPAs included. PMJAY takes it with the changes and requirements below. + +### What changes in the bundle + +#### The notice + +##### Systems PMJAY binds differently + +| Element | Generic | PMJAY | +| :-- | :-- | :-- | +| `PaymentNotice.identifier[]` | `` | `https://hcx.pmjay.gov.in/v1/preauthorization` | +| `PaymentReconciliation.identifier[]` | `` | `https://hcx.pmjay.gov.in/v1/preauthorization` | +| `PaymentReconciliation.paymentIdentifier` | `` | `https://payer.gov.in` | +| `PaymentReconciliation.detail[].identifier` | `` | `https://hcx.pmjay.gov.in/v1/claim` | + +#### The acknowledgement + +The PMJAY bundle has the same resources, elements and systems as the generic one. + +### What PMJAY specifies + +- Deduction lines use the scheme's own codes, such as `RF`, beside the `Payment` line. +- The notice names the claim under `https://hcx.pmjay.gov.in/v1/preauthorization`. +- Before 33 the `UTR` field can carry a scheme reference rather than a bank reference. Store it; reconcile against the bank only on 33. + +### What PMJAY requires + +- Acknowledge each notice on 17. +- Keep the UTR from 33; the shortfall window opens only once 33 is acknowledged. + +## Use cases, APIs and data elements + +### C9 Send payment notice (payer) + +The money, on a new thread of its own, with the reconciliation itemised by type: approved, claimed, tds, servicetax, advance, recovered, penality. The bank's UTR rides on the settled notice. + +| | | +| :-- | :-- | +| **API** | `/v1/paymentnotice/request` [`apis/06-payment-notice/v1-paymentnotice-request.bru`](/docs/nhcx/v1/api/payment-notice/endpoints/payment-notice-v1-paymentnotice-request) | +| **Callback** | `/v1/paymentnotice/on_request` [`apis/06-payment-notice/v1-paymentnotice-on-request.bru`](/docs/nhcx/v1/api/payment-notice/endpoints/payment-notice-v1-paymentnotice-on-request) | +| **Workflow** | 30 initiated, 31 processed, 33 settled | +| **Carries JWE** | yes | +| **Focal resource** | `PaymentReconciliation` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `x-hcx-sender_code` | `1518@hcx` | +| `x-hcx-recipient_code` | `1000004446@hcx` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-request_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{$guid}}` | +| `x-hcx-workflow_id` | `30` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `request.initiated` | +| `x-hcx-ben-abha-id` | `91711234567890` | + +**Workflow codes** + +| Code | Name | Authored by | `x-hcx-status` | Means | +| :-- | :-- | :-- | :-- | :-- | +| `30` | Payment Initiated | payer | `request.initiated`, `response.partial`, `response.error` | Payment initiated by payer, on a new thread | +| `31` | Payment Processed | payer | `request.initiated` | Payment has been processed | +| `33` | Payment Settled | payer | `request.initiated` | Payment has been fully settled | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `utrNumber` | Bank UTR Number | Payment | `string` | `1..1` | `PaymentReconciliation.paymentIdentifier.value` | `CMS2602260081728` | | +| `paymentDate` | Remittance Date | Payment | `date` | `1..1` | `PaymentReconciliation.paymentDate` | `2026-03-05` | | +| `settledAmount` | Net Bank Remittance Amount | Payment | `decimal` | `1..1` | `PaymentReconciliation.paymentAmount.value` | `14850.00` | | +| `tdsDeduction` | Tax Deducted at Source (TDS) | Payment Detail | `decimal` | `0..1` | `PaymentReconciliation.detail[type=tds].amount.value` | `650.00` | | + +NRCeS profiles: [PaymentReconciliation](https://nrces.in/ndhm/fhir/r4/StructureDefinition-PaymentReconciliation.html). + +### B7 Acknowledge payment notice (provider) + +The receipt for a payment notice, as a Task on this endpoint. The notice arrives on a new thread of its own; a generic payer takes the acknowledgement with the notice's 30 echoed, PMJAY with 17. + +| | | +| :-- | :-- | +| **API** | `/v1/paymentnotice/on_request` [`apis/06-payment-notice/v1-paymentnotice-on-request.bru`](/docs/nhcx/v1/api/payment-notice/endpoints/payment-notice-v1-paymentnotice-on-request) | +| **Callback** | `/v1/paymentnotice/request` [`apis/06-payment-notice/v1-paymentnotice-request.bru`](/docs/nhcx/v1/api/payment-notice/endpoints/payment-notice-v1-paymentnotice-request) | +| **Workflow** | 30 echoed from the notice on the generic network; 17 under PMJAY | +| **Carries JWE** | yes | +| **Focal resource** | `PaymentReconciliation / Task` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `x-hcx-sender_code` | `1000004446@hcx` | +| `x-hcx-recipient_code` | `1518@hcx` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-request_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{$guid}}` | +| `x-hcx-workflow_id` | `17` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `response.complete` | +| `x-hcx-ben-abha-id` | `91711234567890` | +| `x-hcx-debug_flag` | `INFO` | + +**Workflow codes** + +| Code | Name | Authored by | `x-hcx-status` | Means | +| :-- | :-- | :-- | :-- | :-- | +| `30` | Payment Initiated | payer | `request.initiated`, `response.partial`, `response.error` | Payment initiated by payer, on a new thread | +| `17` | Payment Received | provider | `response.complete` | Payment received acknowledgment under PMJAY; a generic payer takes it with the notice's 30 echoed | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `settlementNumber` | Payment Reference | Settlement | `string` | `1..1` | `PaymentReconciliation.identifier[0].value` | `SETTLE-2026-001` | | +| `status` | Acknowledgment Status | Settlement | `code` | `1..1` | `PaymentReconciliation.status` | `active` | | + +NRCeS profiles: [PaymentReconciliation](https://nrces.in/ndhm/fhir/r4/StructureDefinition-PaymentReconciliation.html). + +### D13 Acknowledge the payment notice (pmjay) + +Three notices may arrive: 30 when the transfer is initiated, 31 when the bank processes it, 33 when it settles with the UTR. The reconciliation splits the amount into what was paid and what was deducted as tax. Keep the UTR; it is the reference for any dispute. + +| | | +| :-- | :-- | +| **API** | `/v1/paymentnotice/on_request` [`apis/06-payment-notice/v1-paymentnotice-on-request.bru`](/docs/nhcx/v1/api/payment-notice/endpoints/payment-notice-v1-paymentnotice-on-request) | +| **Callback** | `/v1/paymentnotice/request` [`apis/06-payment-notice/v1-paymentnotice-request.bru`](/docs/nhcx/v1/api/payment-notice/endpoints/payment-notice-v1-paymentnotice-request) | +| **Workflow** | 17 | +| **Carries JWE** | yes | +| **Focal resource** | `PaymentReconciliation / Task` | +| **Simulator console** | `/builder?family=paymentnotice&usecase=acknowledge` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `x-hcx-sender_code` | `1000004446@hcx` | +| `x-hcx-recipient_code` | `1518@hcx` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-request_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{$guid}}` | +| `x-hcx-workflow_id` | `17` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `response.complete` | +| `x-hcx-ben-abha-id` | `91711234567890` | +| `x-hcx-debug_flag` | `INFO` | + +**Workflow codes** + +| Code | Name | Authored by | `x-hcx-status` | Means | +| :-- | :-- | :-- | :-- | :-- | +| `17` | Payment Received | provider | `response.complete` | Payment received acknowledgment under PMJAY; a generic payer takes it with the notice's 30 echoed | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `settlementNumber` | Settlement Advice Number | Payment | `string` | `1..1` | `PaymentReconciliation.identifier[0].value` | `SETTLE-PMJAY-001` | | +| `workflowId` | Workflow Code | Header | `string` | `1..1` | `Header.x-hcx-workflow_id` | `17` | | + +NRCeS profiles: [PaymentReconciliation](https://nrces.in/ndhm/fhir/r4/StructureDefinition-PaymentReconciliation.html). diff --git a/site/docs/nhcx/v1/reference/fhir/preauthorisation-enhancement.md b/site/docs/nhcx/v1/reference/fhir/preauthorisation-enhancement.md new file mode 100644 index 000000000..f8bd27994 --- /dev/null +++ b/site/docs/nhcx/v1/reference/fhir/preauthorisation-enhancement.md @@ -0,0 +1,298 @@ +--- +title: Preauthorisation enhancement +sidebar_label: Preauthorisation enhancement +sidebar_position: 10 +description: "Enhancement payload, header `x-hcx-use_case: Enhancement`, and increment totals" +verification: unverified +source: nhcx-package/docs/05-FHIR Reference/10-Preauthorisation Enhancement.md +generated: true +--- + +# Preauthorisation enhancement + +Extends an approved preauthorisation: a longer stay or an added package. The same endpoint and the same case number, under workflow 13, with the header `x-hcx-use_case: Enhancement` and a new correlation id. + +Sent on `/v1/preauth/submit`, answered on `/v1/preauth/on_submit`, workflow 13, and 131 to answer an enhancement query. + +## The bundle + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `Claim` | [Claim](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Claim.html) | +| 2 | `Patient` | [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html) | +| 3 | `Organization (prov)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 4 | `Organization (pay)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 5 | `Coverage` | [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html) | +| 6 | `Practitioner` | [Practitioner](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Practitioner.html) | +| 7 | `Procedure` | [Procedure](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Procedure.html) | +| 8 | `Procedure` | [Procedure](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Procedure.html) | +| 9 | `QuestionnaireResponse` | `QuestionnaireResponse`, which NRCeS does not publish; base FHIR [QuestionnaireResponse](https://hl7.org/fhir/R4/questionnaireresponse.html) | + +## Elements + +### 1. Claim + +NRCeS profile: [Claim](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Claim.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system `https://nhcx.abdm.gov.in`, value `NM-26-0SE00002G` | +| `identifier[].type.coding[]` | `CLN` Claim number in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| `status` | `active` | +| `type.coding[]` | `737481003` Inpatient care management (procedure) in `http://snomed.info/sct` | +| `use` | `preauthorization` | +| `patient` | reference `https://nhcx.abdm.gov.in/patient` | +| `billablePeriod` | start `2026-09-10T00:00:00+05:30`, end `2026-09-10T00:00:00+05:30` | +| `created` | `2026-09-10T23:50:33+05:30` | +| `insurer` | reference `https://nhcx.abdm.gov.in/payer` | +| `provider` | reference `https://nhcx.abdm.gov.in/provider` | +| `priority.coding[]` | `normal` Normal in `http://terminology.hl7.org/CodeSystem/processpriority` | +| `careTeam[]` | sequence `1` | +| `careTeam[].provider` | reference `https://nhcx.abdm.gov.in/practitioner` | +| `careTeam[].role.coding[]` | `primary` Primary provider in `http://terminology.hl7.org/CodeSystem/claimcareteamrole` | +| `careTeam[].qualification.coding[]` | `394802001` General medicine in `http://snomed.info/sct` | +| `supportingInfo[]` | id `SupportingInformation/1`, sequence `1` | +| | id `SupportingInformation/2`, sequence `2` | +| | id `SupportingInformation/3`, sequence `3` | +| | and 9 more | +| `supportingInfo[].category.coding[]` | `INV` Document Type - Investigation in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| | `ONS` Period, start or end dates of aspects of the Condition. (e.g. admission, discha… in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| | `OTH` Other in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| | and 1 more | +| `supportingInfo[].code.coding[]` | `POI` Proof of Identity (Aadhaar / Passport / Voter ID) in `https://nhcx.abdm.gov.in/document-code` | +| | `CER` Medical Certificate / Doctor Referral in `https://nhcx.abdm.gov.in/document-code` | +| | `RAD` Radiology / X-Ray / CT / MRI Scan Reports in `https://nhcx.abdm.gov.in/document-code` | +| | and 9 more | +| `supportingInfo[].valueAttachment` | contentType `application/pdf`, title `Proof of Identity (Aadhaar / Passport / Voter ID)` | +| | contentType `application/pdf`, title `Medical Certificate / Doctor Referral` | +| | contentType `application/pdf`, title `Radiology / X-Ray / CT / MRI Scan Reports` | +| | and 6 more | +| `supportingInfo[].valueReference` | reference `https://nhcx.abdm.gov.in/questionnaireresponse/1`, display `Total Knee Replacement (Unilateral), Standard Treatment Guidelines` | +| `diagnosis[]` | sequence `1` | +| `diagnosis[].diagnosisCodeableConcept.coding[]` | `E11.9` Type 2 diabetes mellitus without complications in `http://hl7.org/fhir/sid/icd-10` | +| `diagnosis[].type[].coding[]` | `admitting` Admitting Diagnosis in `http://terminology.hl7.org/CodeSystem/ex-diagnosistype` | +| `diagnosis[].onAdmission.coding[]` | `yes` Yes in `http://terminology.hl7.org/CodeSystem/ex-diagnosis-on-admission` | +| `procedure[]` | id `Procedure/1`, sequence `1`, date `2026-09-10T00:00:00+05:30` | +| | id `Procedure/2`, sequence `2`, date `2026-09-10T00:00:00+05:30` | +| `procedure[].type[].coding[]` | `surgical` Surgical in `https://nhcx.abdm.gov.in/procedure-type` | +| `procedure[].procedureReference` | reference `https://nhcx.abdm.gov.in/procedure/1`, display `Total Knee Replacement (Unilateral)` | +| | reference `https://nhcx.abdm.gov.in/procedure/2`, display `Acute Appendectomy (Laparoscopic)` | +| `insurance[]` | sequence `1`, focal `true` | +| `insurance[].coverage` | reference `https://nhcx.abdm.gov.in/coverage` | +| `item[]` | id `Item/1`, sequence `1`, factor `1`, careTeamSequence `1`, diagnosisSequence `1`, procedureSequence `1`, informationSequence `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`, `9`, `10`, `11`, `12` | +| | id `Item/2`, sequence `2`, factor `0.5`, careTeamSequence `1`, diagnosisSequence `1`, procedureSequence `2`, informationSequence `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`, `9`, `10`, `11`, `12` | +| `item[].productOrService.coding[]` | `PROC-KNEE-01` Total Knee Replacement (Unilateral) in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-procedure-code` | +| | `PROC-APP-02` Acute Appendectomy (Laparoscopic) in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-procedure-code` | +| `item[].servicedPeriod` | start `2026-09-10`, end `2026-09-10` | +| `item[].quantity` | value `1` | +| `item[].unitPrice` | value `150000`, currency `INR` | +| | value `45000`, currency `INR` | +| `item[].net` | value `150000`, currency `INR` | +| | value `45000`, currency `INR` | +| `item[].category.coding[]` | `Surgical` Surgical in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-benefit-category` | +| `total` | value `195000`, currency `INR` | + +### 2. Patient + +NRCeS profile: [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | value `MRAV1985001` | +| | value `91-1234-1234-1234` | +| `identifier[].type.coding[]` | `PMJAY` Pradhan Mantri Jan Aarogya Yojana (PMJAY) ID in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| | `ABHA` Ayushman Bharat Health Account (ABHA) ID in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| | `MB` Member Number in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `name[]` | text `` | +| `telecom[]` | system `phone`, value `9876543210` | +| `gender` | `male` | +| `birthDate` | `1985-06-15` | + +### 3. Organization (prov) + +NRCeS profile: [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system `https://nhcx.abdm.gov.in`, value `IN1910000151` | +| `identifier[].type.coding[]` | `NPI` National provider identifier in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `type[].coding[]` | `prov` Healthcare Provider in `http://terminology.hl7.org/CodeSystem/organization-type` | +| `name` | `KyroCare Multispeciality Hospital` | + +### 4. Organization (pay) + +NRCeS profile: [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system `https://nhcx.abdm.gov.in`, value `1000004805` | +| `identifier[].type.coding[]` | `NIIP` National Insurance Payor Identifier (Payor) in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `type[].coding[]` | `pay` Payer in `http://terminology.hl7.org/CodeSystem/organization-type` | +| `name` | `Sandbox Payer` | + +### 5. Coverage + +NRCeS profile: [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | value `POL7UMU001` | +| `identifier[].type.coding[]` | `NH` National Health Plan Identifier in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `status` | `active` | +| `type.coding[]` | `HIP` health insurance plan policy in `http://terminology.hl7.org/CodeSystem/v3-ActCode` | +| `subscriber` | reference `https://nhcx.abdm.gov.in/patient` | +| `subscriberId` | `MRAV1985001` | +| `beneficiary` | reference `https://nhcx.abdm.gov.in/patient` | +| `relationship.coding[]` | `self` in `http://terminology.hl7.org/CodeSystem/subscriber-relationship` | +| `payor[]` | reference `https://nhcx.abdm.gov.in/payer` | + +### 6. Practitioner + +NRCeS profile: [Practitioner](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Practitioner.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system `https://nhcx.abdm.gov.in`, value `71-8422-5818-7201` | +| | system `https://hpr.abdm.gov.in`, value `71-8422-5818-7201` | +| `identifier[].type.coding[]` | `HPID` Healthcare Professional ID (HPID) in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| | `HPIN` Health Practitioner ID issued by NDHM in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| `name[]` | text `Dr. Ananya Rao` | +| `qualification[].code.coding[]` | `MD` Doctor of Medicine in `http://terminology.hl7.org/CodeSystem/v2-0360` | + +### 7. Procedure + +NRCeS profile: [Procedure](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Procedure.html). + +| Element | Example | +| :-- | :-- | +| `status` | `preparation` | +| `code` | text `Total Knee Replacement (Unilateral)` | +| `code.coding[]` | `71388002` Procedure (procedure) in `http://snomed.info/sct` | +| `subject` | reference `https://nhcx.abdm.gov.in/patient` | +| `performedDateTime` | `2026-09-10T00:00:00+05:30` | + +### 8. Procedure + +NRCeS profile: [Procedure](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Procedure.html). + +| Element | Example | +| :-- | :-- | +| `status` | `preparation` | +| `code` | text `Acute Appendectomy (Laparoscopic)` | +| `code.coding[]` | `71388002` Procedure (procedure) in `http://snomed.info/sct` | +| `subject` | reference `https://nhcx.abdm.gov.in/patient` | +| `performedDateTime` | `2026-09-10T00:00:00+05:30` | + +### 9. QuestionnaireResponse + +| Element | Example | +| :-- | :-- | +| `questionnaire` | `` | +| `status` | `completed` | +| `subject` | reference `https://nhcx.abdm.gov.in/patient` | +| `authored` | `2026-09-10T23:50:33+05:30` | +| `item[]` | linkId `PROC-KNEE-01/stg/1`, text `Duration of symptoms and the conservative treatment tried (months of physiother…` | +| | linkId `PROC-KNEE-01/stg/2`, text `Kellgren-Lawrence grade of osteoarthritis on the standing X-ray` | +| | linkId `PROC-KNEE-01/stg/3`, text `Range of motion and deformity of the knee (flexion contracture, varus/valgus)` | +| | and 2 more | +| `item[].answer[]` | valueString `Recorded.` | + +## Rules + +### 1. The protocol says enhancement, not the payload + +`Claim.use` stays `preauthorization` and the case number is unchanged. The workflow code and `x-hcx-use_case` declare the enhancement. + +### 2. Cumulative + +Carry the approved items and the ones now sought. `Claim.total` is the sum of all of them. + +### 3. No link in the payload + +`Claim.related` is absent. The case number and your stored correlation ids are the thread. + +### 4. One at a time + +Refused when there is no approval, when a request on the case is still open, or after the claim has been raised. + +### 5. Order + +Response items can come back out of order; read by `itemSequence`. Order a case's messages by receipt, not by `Bundle.timestamp`. + +## PMJAY + +The generic bundle above is what every payer takes, IRDAI-regulated insurers and TPAs included. PMJAY takes it with the changes and requirements below. + +### What changes in the bundle + +#### Resources + +- PMJAY adds 1 `QuestionnaireResponse`. + +#### Elements PMJAY adds + +| Element | Example | +| :-- | :-- | +| `Claim.item[].modifier[].coding[]` | `STRAT006a` Routine Ward | +| `Claim.item[].programCode[].coding[]` | `AB-PMJAY` Ayushman Bharat Pradhan Mantri Jan Arogya Yojana (AB-PMJAY) in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-program-code` | +| `QuestionnaireResponse.item[].answer[].valueAttachment` | contentType `application/pdf`, title `Medical Superintendent Declaration Form (During Admission)` | + +### What PMJAY specifies + +- On the response, the `benefit` total is the increment and the wallet's `eligible` total is cumulative. +- The acknowledgement carries no `preAuthRef`. Carry the parent case id onto the enhancement yourself. +- A query on an enhancement arrives on 241 and is answered by a fresh submit on 131. + +### What PMJAY requires + +- Only packages flagged `EnhancementAllowed` `Y` may be added. +- One `Conservative` package per case. Refused with `PAYR-1245`. +- One request at a time on a case. Refused with `PAYR-1322`. + +## Use cases, APIs and data elements + +### D6 Raise an enhancement (pmjay) + +Adds to an approved pre-authorisation, as many times as needed until discharge, one at a time, and only for packages whose plan flag allows it. The bundle carries the approved items and the ones now sought. A query on it arrives as a ClaimResponse on 241, on the case's own thread, and is answered by a fresh submit on 131. + +| | | +| :-- | :-- | +| **API** | `/v1/preauth/submit` [`apis/03-preauth/v1-preauth-enhancement.bru`](/docs/nhcx/v1/api/preauth/endpoints/preauth-v1-preauth-submit) | +| **Callback** | `/v1/preauth/on_submit` [`apis/03-preauth/v1-preauth-on-submit.bru`](/docs/nhcx/v1/api/preauth/endpoints/preauth-v1-preauth-on-submit) | +| **Workflow** | 13, and 131 to answer an enhancement query raised on 241 | +| **Carries JWE** | yes | +| **Focal resource** | `Claim` | +| **Simulator console** | `/builder?family=preauth&usecase=enhance` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `x-hcx-sender_code` | `1000004446@hcx` | +| `x-hcx-recipient_code` | `1518@hcx` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-request_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{$guid}}` | +| `x-hcx-workflow_id` | `13` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `request.initiated` | +| `x-hcx-ben-abha-id` | `91711234567890` | +| `x-hcx-use_case` | `Enhancement` | + +**Workflow codes** + +| Code | Name | Authored by | `x-hcx-status` | Means | +| :-- | :-- | :-- | :-- | :-- | +| `13` | Enhancement Request Initiated | provider | `request.initiated` | Enhancement (additional amount) request | +| `131` | Enhancement Query Response Submitted | provider | `response.partial`, `response.error`, `response.complete` | Response to enhancement query | +| `241` | Enhancement Request Queried | payer | `request.initiated` | Enhancement request queried by payer | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `claimNumber` | Case Number | Case | `string` | `1..1` | `Claim.identifier[0].value` | `VB26AA2600001` | | +| `preAuthRef` | Initial Approval Reference | Case | `string` | `1..1` | `Claim.insurance[0].preAuthRef[0]` | `APPR-2026-HP-00891` | | +| `workflowId` | Workflow Code | Header | `string` | `1..1` | `Header.x-hcx-workflow_id` | `13` | | + +NRCeS profiles: [Claim](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Claim.html). diff --git a/site/docs/nhcx/v1/reference/fhir/preauthorisation-query-and-answer.md b/site/docs/nhcx/v1/reference/fhir/preauthorisation-query-and-answer.md new file mode 100644 index 000000000..5fd98e5b1 --- /dev/null +++ b/site/docs/nhcx/v1/reference/fhir/preauthorisation-query-and-answer.md @@ -0,0 +1,374 @@ +--- +title: Preauthorisation query and answer +sidebar_label: Preauthorisation query and answer +sidebar_position: 11 +description: Query resolution on preauth thread (wf 24 / 19) +verification: unverified +source: nhcx-package/docs/05-FHIR Reference/11-Preauthorisation Query and Answer.md +generated: true +--- + +# Preauthorisation query and answer + +When the payer wants more before it decides. A private insurer raises the query as a communication and takes the answer as one. PMJAY raises it as a `ClaimResponse` on the case's own thread and takes the answer as the whole preauthorisation, resubmitted. + +## The query + +Sent on `/v1/communication/request`, workflow 24. + +### The bundle + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `Task` | [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html) | +| 2 | `CommunicationRequest` | [CommunicationRequest](https://nrces.in/ndhm/fhir/r4/StructureDefinition-CommunicationRequest.html) | +| 3 | `Claim` | [Claim](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Claim.html) | +| 4 | `Patient` | [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html) | +| 5 | `Organization (ins)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 6 | `Organization (prov)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 7 | `Practitioner` | [Practitioner](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Practitioner.html) | +| 8 | `Coverage` | [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html) | + +### Elements + +#### 1. Task + +NRCeS profile: [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html). + +| Element | Example | +| :-- | :-- | +| `status` | `requested` | +| `intent` | `order` | +| `reasonCode.coding[]` | `additionalinfo` Additional Information Request in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-reason-code` | +| `code.coding[]` | `poll` in `http://terminology.hl7.org/CodeSystem/financialtaskcode` | +| `description` | `Share the pre-operative X-ray and the clinical notes.` | +| `authoredOn` | `2026-09-10T23:51:47+05:30` | +| `requester` | reference `urn:uuid:39cd4b51-bddd-5cc1-a65a-6fa4a2a83cb5`, display `Organization` | +| `owner` | reference `urn:uuid:84d112ec-041c-57f8-986c-6619ccd8245e`, display `Organization` | +| `input[].type.coding[]` | `include` in `http://terminology.hl7.org/CodeSystem/financialtaskinputtype` | +| `input[].valueReference` | reference `urn:uuid:4b35a6eb-3f99-5d0c-b0c8-5b2f049fdbde`, display `CommunicationRequest` | + +#### 2. CommunicationRequest + +NRCeS profile: [CommunicationRequest](https://nrces.in/ndhm/fhir/r4/StructureDefinition-CommunicationRequest.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | value `NM-26-0SE00002I` | +| `basedOn[]` | reference `urn:uuid:c1a17d6e-c718-58de-8d3d-fd4c0607d729`, display `Claim-preauth` | +| `status` | `active` | +| `category[].coding[]` | `alert` in `http://terminology.hl7.org/CodeSystem/communication-category` | +| `priority` | `routine` | +| `payload[]` | contentString `Share the pre-operative X-ray and the clinical notes.` | +| `authoredOn` | `2026-09-10T23:51:47+05:30` | +| `requester` | reference `urn:uuid:39cd4b51-bddd-5cc1-a65a-6fa4a2a83cb5`, display `Organization` | +| `recipient[]` | reference `urn:uuid:84d112ec-041c-57f8-986c-6619ccd8245e`, display `Organization` | +| `sender` | reference `urn:uuid:39cd4b51-bddd-5cc1-a65a-6fa4a2a83cb5`, display `Organization` | +| `reasonCode[]` | text `Share the pre-operative X-ray and the clinical notes.` | +| `reasonCode[].coding[]` | `additionalinfo` Additional Information Request in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-reason-code` | + +The `Claim`, `Patient`, `Organization`, `Practitioner`, `Coverage` entries are shaped as in the chapters that introduce them. + +## The answer + +Sent on `/v1/communication/on_request`, workflow 24, echoed. + +### The bundle + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `Task` | [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html) | +| 2 | `Communication` | [Communication](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Communication.html) | +| 3 | `CommunicationRequest` | [CommunicationRequest](https://nrces.in/ndhm/fhir/r4/StructureDefinition-CommunicationRequest.html) | +| 4 | `Claim` | [Claim](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Claim.html) | +| 5 | `Patient` | [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html) | +| 6 | `Organization (prov)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 7 | `Organization (pay)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 8 | `Practitioner` | [Practitioner](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Practitioner.html) | +| 9 | `Coverage` | [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html) | + +### Elements + +#### 1. Task + +NRCeS profile: [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html). + +| Element | Example | +| :-- | :-- | +| `status` | `completed` | +| `intent` | `order` | +| `code.coding[]` | `deliver` in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-codes` | +| `authoredOn` | `2026-09-10T23:51:53+05:30` | +| `requester` | reference `https://nhcx.abdm.gov.in/provider`, display `Organization` | +| `owner` | reference `https://nhcx.abdm.gov.in/payer`, display `Organization` | +| `input[].type.coding[]` | `include` in `http://terminology.hl7.org/CodeSystem/financialtaskinputtype` | +| `input[].valueReference` | reference `urn:uuid:3e398f2b-ab14-41e5-8939-d7746eea43de`, display `Communication` | +| `reasonCode.coding[]` | `additionalinfo` Additional Information Request in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-reason-code` | + +#### 2. Communication + +NRCeS profile: [Communication](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Communication.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | value `NM-26-0SE00002I` | +| `basedOn[]` | reference `urn:uuid:4b35a6eb-3f99-5d0c-b0c8-5b2f049fdbde`, display `CommunicationRequest` | +| `inResponseTo[]` | reference `urn:uuid:4b35a6eb-3f99-5d0c-b0c8-5b2f049fdbde`, display `CommunicationRequest` | +| `about[]` | reference `https://nhcx.abdm.gov.in/preauth/request`, display `Claim urn:uuid:c1a17d6e-c718-58de-8d3d-fd4c0607d729` | +| `status` | `completed` | +| `category[].coding[]` | `notification` in `http://terminology.hl7.org/CodeSystem/communication-category` | +| `priority` | `routine` | +| `recipient[]` | reference `https://nhcx.abdm.gov.in/payer`, display `Organization` | +| `sender` | reference `https://nhcx.abdm.gov.in/provider`, display `Organization` | +| `payload[]` | contentString `X-ray and clinical notes attached as asked.` | +| `payload[].contentAttachment` | contentType `application/pdf`, title `Proof of Identity (Aadhaar / Passport / Voter ID)`, creation `2026-09-10T23:51:40+05:30` | +| | contentType `application/pdf`, title `Medical Certificate / Doctor Referral`, creation `2026-09-10T23:51:40+05:30` | +| | contentType `application/pdf`, title `Radiology / X-Ray / CT / MRI Scan Reports`, creation `2026-09-10T23:51:40+05:30` | +| | and 6 more | +| `payload[].extension[]` | url ``, valueString `POI` | +| | url ``, valueString `CER` | +| | url ``, valueString `RAD` | +| | and 6 more | + +The `CommunicationRequest`, `Claim`, `Patient`, `Organization`, `Practitioner`, `Coverage` entries are shaped as in the chapters that introduce them. + +## Rules + +### 1. The generic query + +A `Task` coded `poll`, reason `additionalinfo`, with an `include` input referencing a `CommunicationRequest` whose `basedOn` names the preauthorisation. Sent on `/v1/communication/request` under 24. + +### 2. The generic answer + +A `Task` coded `deliver` in `ndhm-task-codes`, `completed`, with an `include` input referencing a `Communication` whose `basedOn` names the request and whose `payload` carries the message and the documents. Posted on `/v1/communication/on_request`, echoing the correlation id and workflow id. + +## PMJAY + +The generic bundle above is what every payer takes, IRDAI-regulated insurers and TPAs included. PMJAY takes it with the changes and requirements below. + +### What changes in the bundle + +#### The query + +PMJAY uses a different bundle for this step, headed by `ClaimResponse` rather than `Task`. + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `ClaimResponse` | none declared; NRCeS [ClaimResponse](https://nrces.in/ndhm/fhir/r4/StructureDefinition-ClaimResponse.html) | +| 2 | `Patient` | none declared; NRCeS [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html) | +| 3 | `Organization (pay)` | none declared; NRCeS [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 4 | `Organization (prov)` | none declared; NRCeS [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 5 | `Coverage` | none declared; NRCeS [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html) | + +###### 1. ClaimResponse + +NRCeS profile: [ClaimResponse](https://nrces.in/ndhm/fhir/r4/StructureDefinition-ClaimResponse.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system `https://hcx.pmjay.gov.in/v1/preauthorization`, value `NM-26-0SF000031` | +| `identifier[].type.coding[]` | `CLN` Claim number in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| `status` | `active` | +| `use` | `preauthorization` | +| `patient` | reference `https://payer.nha.gov.in/preauthorization/v1/preauth/on_submit/claimresponse/pa…` | +| `created` | `2026-09-11T00:33:03+05:30` | +| `insurer` | reference `https://payer.nha.gov.in/preauthorization/v1/preauth/on_submit/claimresponse/or…` | +| `requestor` | reference `https://payer.nha.gov.in/preauthorization/v1/preauth/on_submit/claimresponse/or…` | +| `outcome` | `partial` | +| `disposition` | `query` | +| `preAuthRef` | `2026091110000817` | +| `payeeType.coding[]` | `provider` Provider in `http://terminology.hl7.org/CodeSystem/payeetype` | +| `item[]` | id `Item/Item/2`, itemSequence `2` | +| | id `Item/Item/1`, itemSequence `1` | +| `item[].adjudication[].category.coding[]` | `submitted` Submitted Amount in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| | `eligible` Eligible Amount in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| | `reason` Reason for Adjudication in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| | and 3 more | +| `item[].adjudication[].amount` | value `1500` | +| | value `1725` | +| | value `1800` | +| | and 1 more | +| `item[].adjudication[].reason.coding[]` | display ` : Request acknowledged and accepted for further processing.` | +| | `Queried` Queried | +| | `Approved` Approved | +| `item[].adjudication[]` | value `0` | +| | value `100` | +| | value `1` | +| `adjudication[].category.coding[]` | `status` Status | +| `adjudication[].reason.coding[]` | `queried` Queried | +| `total[].category.coding[]` | `benefit` Benefit Amount in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| | `submitted` Submitted Amount in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| | `tax` Tax in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| | and 2 more | +| `total[].amount` | value `2070` | +| | value `1725` | +| | value `0` | +| | and 1 more | +| `total[]` | id `PMJAY0000X/PMJAY-T` | + +The `Patient`, `Organization`, `Coverage` entries are shaped as in the chapters that introduce them. + +#### The answer + +PMJAY uses a different bundle for this step, headed by `Claim` rather than `Task`. + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `Claim` | [Claim](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Claim.html) | +| 2 | `Patient` | [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html) | +| 3 | `Organization (prov)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 4 | `Organization (pay)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 5 | `Coverage` | [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html) | +| 6 | `Practitioner` | [Practitioner](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Practitioner.html) | +| 7 | `Procedure` | [Procedure](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Procedure.html) | +| 8 | `QuestionnaireResponse` | `QuestionnaireResponse`, which NRCeS does not publish; base FHIR [QuestionnaireResponse](https://hl7.org/fhir/R4/questionnaireresponse.html) | +| 9 | `QuestionnaireResponse` | `QuestionnaireResponse`, which NRCeS does not publish; base FHIR [QuestionnaireResponse](https://hl7.org/fhir/R4/questionnaireresponse.html) | + +###### 1. Claim + +NRCeS profile: [Claim](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Claim.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system `https://nhcx.abdm.gov.in`, value `NM-26-0SE00002N` | +| `identifier[].type.coding[]` | `CLN` Claim number in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| `status` | `active` | +| `type.coding[]` | `737481003` Inpatient care management (procedure) in `http://snomed.info/sct` | +| `use` | `preauthorization` | +| `patient` | reference `https://nhcx.abdm.gov.in/patient` | +| `billablePeriod` | start `2026-09-10T00:00:00+05:30`, end `2026-09-10T00:00:00+05:30` | +| `created` | `2026-09-10T23:55:36+05:30` | +| `insurer` | reference `https://nhcx.abdm.gov.in/payer` | +| `provider` | reference `https://nhcx.abdm.gov.in/provider` | +| `priority.coding[]` | `normal` Normal in `http://terminology.hl7.org/CodeSystem/processpriority` | +| `careTeam[]` | sequence `1` | +| `careTeam[].provider` | reference `https://nhcx.abdm.gov.in/practitioner` | +| `careTeam[].role.coding[]` | `primary` Primary provider in `http://terminology.hl7.org/CodeSystem/claimcareteamrole` | +| `careTeam[].qualification.coding[]` | `394802001` General medicine in `http://snomed.info/sct` | +| `supportingInfo[]` | id `SupportingInformation/1`, sequence `1` | +| | id `SupportingInformation/2`, sequence `2` | +| | id `SupportingInformation/3`, sequence `3` | +| | and 6 more | +| `supportingInfo[].category.coding[]` | `INV` Document Type - Investigation in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| | `ONS` Period, start or end dates of aspects of the Condition. (e.g. admission, discha… in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| | `OTH` Other in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| | and 2 more | +| `supportingInfo[].code.coding[]` | `MAND0455` CXR PA view or CECT chest abdomen and pelvis in `https://nhcx.abdm.gov.in/document-code` | +| | `MAND0409` any investigations done in `https://nhcx.abdm.gov.in/document-code` | +| | `MAND0570` Planned line of management in `https://nhcx.abdm.gov.in/document-code` | +| | and 5 more | +| `supportingInfo[].valueAttachment` | contentType `application/pdf`, title `CXR PA view or CECT chest abdomen and pelvis` | +| | contentType `application/pdf`, title `any investigations done` | +| | contentType `application/pdf`, title `Planned line of management` | +| | and 1 more | +| `supportingInfo[].valueReference` | reference `https://nhcx.abdm.gov.in/questionnaireresponse/1`, display `Admission Details` | +| | reference `https://nhcx.abdm.gov.in/questionnaireresponse/2`, display `Authentication Consent` | +| `diagnosis[]` | sequence `1` | +| `diagnosis[].diagnosisCodeableConcept.coding[]` | `E11.9` Type 2 diabetes mellitus without complications in `http://hl7.org/fhir/sid/icd-10` | +| `diagnosis[].type[].coding[]` | `admitting` Admitting Diagnosis in `http://terminology.hl7.org/CodeSystem/ex-diagnosistype` | +| `diagnosis[].onAdmission.coding[]` | `yes` Yes in `http://terminology.hl7.org/CodeSystem/ex-diagnosis-on-admission` | +| `procedure[]` | id `Procedure/1`, sequence `1`, date `2026-09-10T00:00:00+05:30` | +| `procedure[].type[].coding[]` | `conservative` Conservative in `https://nhcx.abdm.gov.in/procedure-type` | +| `procedure[].procedureReference` | reference `https://nhcx.abdm.gov.in/procedure/1`, display `Pleural Effusion (Pleural Effusion)` | +| `insurance[]` | sequence `1`, focal `true` | +| `insurance[].coverage` | reference `https://nhcx.abdm.gov.in/coverage` | +| `item[]` | id `Item/1`, sequence `1`, factor `1`, careTeamSequence `1`, diagnosisSequence `1`, procedureSequence `1`, informationSequence `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`, `9` | +| `item[].productOrService.coding[]` | `MG0111A` Pleural Effusion (Pleural Effusion) in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-procedure-code` | +| `item[].servicedPeriod` | start `2026-09-10`, end `2026-09-10` | +| `item[].quantity` | value `1` | +| `item[].unitPrice` | value `1800`, currency `INR` | +| `item[].net` | value `1800`, currency `INR` | +| `item[].category.coding[]` | `MG` General Medicine in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-benefit-category` | +| `item[].modifier[].coding[]` | `STRAT006a` Routine Ward | +| `item[].programCode[].coding[]` | `AB-PMJAY` Ayushman Bharat Pradhan Mantri Jan Arogya Yojana (AB-PMJAY) in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-program-code` | +| `total` | value `1800`, currency `INR` | + +###### 8. QuestionnaireResponse + +| Element | Example | +| :-- | :-- | +| `questionnaire` | `https://payer.gov.in/policy/questionnaire/100020` | +| `status` | `completed` | +| `subject` | reference `https://nhcx.abdm.gov.in/patient` | +| `authored` | `2026-09-10T23:55:36+05:30` | +| `item[]` | linkId `100075`, text `Admission Date` | +| | linkId `100074`, text `Surgery/Treatment Start Date` | +| | linkId `100073`, text `Admission Type` | +| | and 1 more | +| `item[].answer[]` | valueDateTime `2026-09-10T18:25:00+05:30` | +| | valueString `PLANNED` | +| | valueString `Yes` | + +###### 9. QuestionnaireResponse + +| Element | Example | +| :-- | :-- | +| `questionnaire` | `https://payer.gov.in/policy/questionnaire/100024` | +| `status` | `completed` | +| `subject` | reference `https://nhcx.abdm.gov.in/patient` | +| `authored` | `2026-09-10T23:55:36+05:30` | +| `item[]` | linkId `100093`, text `Medical Superintendent Declaration Form (During Admission)` | +| | linkId `100095`, text `Remarks` | +| `item[].answer[].valueAttachment` | contentType `application/pdf`, title `Medical Superintendent Declaration Form (During Admission)` | +| `item[].answer[]` | valueString `Recorded.` | + +The `Patient`, `Organization`, `Coverage`, `Practitioner`, `Procedure` entries are shaped as in the chapters that introduce them. + +### What PMJAY specifies + +- The query arrives on `/v1/preauth/on_submit` under 24: a `ClaimResponse` with `outcome` `partial` and reason `queried`. +- The question is free text in `item.adjudication` where the category is `reason`, in `reason.coding.display`. On a live case it grows into a log, split by `|` into turns and by `~` into user, timestamp, type, comment and desk. Tolerate a single segment, treat the literal `null` as empty, and never put `|` or `~` in anything you send back. +- The log is cumulative. The answer you sent reappears in it on the next response, which is the only sign it was read. +- The answer is the whole preauthorisation bundle again on `/v1/preauth/submit` under 19, on the same case number, with the reply text in `item.productOrService.text`. + +### What PMJAY requires + +- Answer on 19, never on a new 12, which opens a second case. +- Put the query remarks under `supportingInfo` category `NMI`, code `CQD`, as a `valueString`. +- Supporting-info dates in `+05:30`. + +## Use cases, APIs and data elements + +### D7 Answer a pre-authorisation query (pmjay) + +The query arrived as a ClaimResponse on 24, on the case's own thread, with the question in the item adjudication, not on the communication API. Answer with a fresh submit of the same bundle shape on this code, never as a new 12, which opens a second case. + +| | | +| :-- | :-- | +| **API** | `/v1/preauth/submit` [`apis/03-preauth/v1-preauth-submit.bru`](/docs/nhcx/v1/api/preauth/endpoints/preauth-v1-preauth-submit) | +| **Callback** | `/v1/preauth/on_submit` [`apis/03-preauth/v1-preauth-on-submit.bru`](/docs/nhcx/v1/api/preauth/endpoints/preauth-v1-preauth-on-submit) | +| **Workflow** | 19 | +| **Carries JWE** | yes | +| **Focal resource** | `Claim` | +| **Simulator console** | `/builder?family=preauth&usecase=query-answer` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `x-hcx-sender_code` | `1000004446@hcx` | +| `x-hcx-recipient_code` | `1518@hcx` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-request_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{$guid}}` | +| `x-hcx-workflow_id` | `19` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `request.initiated` | +| `x-hcx-ben-abha-id` | `91711234567890` | +| `x-hcx-use_case` | `New` | + +**Workflow codes** + +| Code | Name | Authored by | `x-hcx-status` | Means | +| :-- | :-- | :-- | :-- | :-- | +| `19` | Preauth Query Response Submitted | provider | `response.complete` | Response to payer's query on preauth | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `claimNumber` | Case Number | Case | `string` | `1..1` | `Claim.identifier[0].value` | `VB26AA2600001` | | +| `workflowId` | Workflow Code | Header | `string` | `1..1` | `Header.x-hcx-workflow_id` | `19` | | +| `nmiDocument` | Need More Info (NMI) Document | Documents | `base64Binary` | `1..1` | `Claim.supportingInfo[category=NMI].valueAttachment.data` | `JVBERi0xLjQK...` | | + +NRCeS profiles: [Claim](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Claim.html). diff --git a/site/docs/nhcx/v1/reference/fhir/preauthorisation-request.md b/site/docs/nhcx/v1/reference/fhir/preauthorisation-request.md new file mode 100644 index 000000000..16ddf43c9 --- /dev/null +++ b/site/docs/nhcx/v1/reference/fhir/preauthorisation-request.md @@ -0,0 +1,411 @@ +--- +title: Preauthorisation request +sidebar_label: Preauthorisation request +sidebar_position: 8 +description: Preauth Claim bundle, items, and ABDM clinical attachments +verification: unverified +source: nhcx-package/docs/05-FHIR Reference/08-Preauthorisation Request.md +generated: true +--- + +# Preauthorisation request + +The first bundle with clinical content. The provider asks the payer to approve a treatment before it is given. The spine is a `Claim` with `use` set to `preauthorization`. + +Sent on `/v1/preauth/submit`, answered on `/v1/preauth/on_submit`, workflow 12 new, 121 resubmission. + +## The bundle + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `Claim` | [Claim](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Claim.html) | +| 2 | `Patient` | [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html) | +| 3 | `Organization (prov)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 4 | `Organization (pay)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 5 | `Coverage` | [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html) | +| 6 | `Practitioner` | [Practitioner](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Practitioner.html) | +| 7 | `Procedure` | [Procedure](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Procedure.html) | +| 8 | `QuestionnaireResponse` | `QuestionnaireResponse`, which NRCeS does not publish; base FHIR [QuestionnaireResponse](https://hl7.org/fhir/R4/questionnaireresponse.html) | + +## Elements + +### 1. Claim + +NRCeS profile: [Claim](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Claim.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system `https://nhcx.abdm.gov.in`, value `NM-26-0SE00002M` | +| `identifier[].type.coding[]` | `CLN` Claim number in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| `status` | `active` | +| `type.coding[]` | `737481003` Inpatient care management (procedure) in `http://snomed.info/sct` | +| `use` | `preauthorization` | +| `patient` | reference `https://nhcx.abdm.gov.in/patient` | +| `billablePeriod` | start `2026-09-10T00:00:00+05:30`, end `2026-09-10T00:00:00+05:30` | +| `created` | `2026-09-10T23:53:57+05:30` | +| `insurer` | reference `https://nhcx.abdm.gov.in/payer` | +| `provider` | reference `https://nhcx.abdm.gov.in/provider` | +| `priority.coding[]` | `normal` Normal in `http://terminology.hl7.org/CodeSystem/processpriority` | +| `careTeam[]` | sequence `1` | +| `careTeam[].provider` | reference `https://nhcx.abdm.gov.in/practitioner` | +| `careTeam[].role.coding[]` | `primary` Primary provider in `http://terminology.hl7.org/CodeSystem/claimcareteamrole` | +| `careTeam[].qualification.coding[]` | `394802001` General medicine in `http://snomed.info/sct` | +| `supportingInfo[]` | id `SupportingInformation/1`, sequence `1` | +| | id `SupportingInformation/2`, sequence `2` | +| | id `SupportingInformation/3`, sequence `3` | +| | and 9 more | +| `supportingInfo[].category.coding[]` | `INV` Document Type - Investigation in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| | `ONS` Period, start or end dates of aspects of the Condition. (e.g. admission, discha… in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| | `OTH` Other in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| | and 1 more | +| `supportingInfo[].code.coding[]` | `POI` Proof of Identity (Aadhaar / Passport / Voter ID) in `https://nhcx.abdm.gov.in/document-code` | +| | `CER` Medical Certificate / Doctor Referral in `https://nhcx.abdm.gov.in/document-code` | +| | `RAD` Radiology / X-Ray / CT / MRI Scan Reports in `https://nhcx.abdm.gov.in/document-code` | +| | and 9 more | +| `supportingInfo[].valueAttachment` | contentType `application/pdf`, title `Proof of Identity (Aadhaar / Passport / Voter ID)` | +| | contentType `application/pdf`, title `Medical Certificate / Doctor Referral` | +| | contentType `application/pdf`, title `Radiology / X-Ray / CT / MRI Scan Reports` | +| | and 6 more | +| `supportingInfo[].valueReference` | reference `https://nhcx.abdm.gov.in/questionnaireresponse/1`, display `Total Knee Replacement (Unilateral), Standard Treatment Guidelines` | +| `diagnosis[]` | sequence `1` | +| `diagnosis[].diagnosisCodeableConcept.coding[]` | `E11.9` Type 2 diabetes mellitus without complications in `http://hl7.org/fhir/sid/icd-10` | +| `diagnosis[].type[].coding[]` | `admitting` Admitting Diagnosis in `http://terminology.hl7.org/CodeSystem/ex-diagnosistype` | +| `diagnosis[].onAdmission.coding[]` | `yes` Yes in `http://terminology.hl7.org/CodeSystem/ex-diagnosis-on-admission` | +| `procedure[]` | id `Procedure/1`, sequence `1`, date `2026-09-10T00:00:00+05:30` | +| `procedure[].type[].coding[]` | `surgical` Surgical in `https://nhcx.abdm.gov.in/procedure-type` | +| `procedure[].procedureReference` | reference `https://nhcx.abdm.gov.in/procedure/1`, display `Total Knee Replacement (Unilateral)` | +| `insurance[]` | sequence `1`, focal `true` | +| `insurance[].coverage` | reference `https://nhcx.abdm.gov.in/coverage` | +| `item[]` | id `Item/1`, sequence `1`, factor `1`, careTeamSequence `1`, diagnosisSequence `1`, procedureSequence `1`, informationSequence `1`, `2`, `3`, `4`, `5`, `6`, `7`, `8`, `9`, `10`, `11`, `12` | +| `item[].productOrService.coding[]` | `PROC-KNEE-01` Total Knee Replacement (Unilateral) in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-procedure-code` | +| `item[].servicedPeriod` | start `2026-09-10`, end `2026-09-10` | +| `item[].quantity` | value `1` | +| `item[].unitPrice` | value `150000`, currency `INR` | +| `item[].net` | value `150000`, currency `INR` | +| `item[].category.coding[]` | `Surgical` Surgical in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-benefit-category` | +| `total` | value `150000`, currency `INR` | + +### 2. Patient + +NRCeS profile: [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | value `MRAV1985001` | +| | value `91-1234-1234-1234` | +| `identifier[].type.coding[]` | `PMJAY` Pradhan Mantri Jan Aarogya Yojana (PMJAY) ID in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| | `ABHA` Ayushman Bharat Health Account (ABHA) ID in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| | `MB` Member Number in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `name[]` | text `` | +| `telecom[]` | system `phone`, value `9876543210` | +| `gender` | `male` | +| `birthDate` | `1985-06-15` | + +### 3. Organization (prov) + +NRCeS profile: [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system `https://nhcx.abdm.gov.in`, value `IN1910000151` | +| `identifier[].type.coding[]` | `NPI` National provider identifier in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `type[].coding[]` | `prov` Healthcare Provider in `http://terminology.hl7.org/CodeSystem/organization-type` | +| `name` | `KyroCare Multispeciality Hospital` | + +### 4. Organization (pay) + +NRCeS profile: [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system `https://nhcx.abdm.gov.in`, value `1000004805` | +| `identifier[].type.coding[]` | `NIIP` National Insurance Payor Identifier (Payor) in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `type[].coding[]` | `pay` Payer in `http://terminology.hl7.org/CodeSystem/organization-type` | +| `name` | `Sandbox Payer` | + +### 5. Coverage + +NRCeS profile: [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | value `POL7UMU001` | +| `identifier[].type.coding[]` | `NH` National Health Plan Identifier in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `status` | `active` | +| `type.coding[]` | `HIP` health insurance plan policy in `http://terminology.hl7.org/CodeSystem/v3-ActCode` | +| `subscriber` | reference `https://nhcx.abdm.gov.in/patient` | +| `subscriberId` | `MRAV1985001` | +| `beneficiary` | reference `https://nhcx.abdm.gov.in/patient` | +| `relationship.coding[]` | `self` in `http://terminology.hl7.org/CodeSystem/subscriber-relationship` | +| `payor[]` | reference `https://nhcx.abdm.gov.in/payer` | + +### 6. Practitioner + +NRCeS profile: [Practitioner](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Practitioner.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system `https://nhcx.abdm.gov.in`, value `71-8422-5818-7201` | +| | system `https://hpr.abdm.gov.in`, value `71-8422-5818-7201` | +| `identifier[].type.coding[]` | `HPID` Healthcare Professional ID (HPID) in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| | `HPIN` Health Practitioner ID issued by NDHM in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| `name[]` | text `Dr. Ananya Rao` | +| `qualification[].code.coding[]` | `MD` Doctor of Medicine in `http://terminology.hl7.org/CodeSystem/v2-0360` | + +### 7. Procedure + +NRCeS profile: [Procedure](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Procedure.html). + +| Element | Example | +| :-- | :-- | +| `status` | `preparation` | +| `code` | text `Total Knee Replacement (Unilateral)` | +| `code.coding[]` | `71388002` Procedure (procedure) in `http://snomed.info/sct` | +| `subject` | reference `https://nhcx.abdm.gov.in/patient` | +| `performedDateTime` | `2026-09-10T00:00:00+05:30` | + +### 8. QuestionnaireResponse + +| Element | Example | +| :-- | :-- | +| `questionnaire` | `` | +| `status` | `completed` | +| `subject` | reference `https://nhcx.abdm.gov.in/patient` | +| `authored` | `2026-09-10T23:53:57+05:30` | +| `item[]` | linkId `PROC-KNEE-01/stg/1`, text `Duration of symptoms and the conservative treatment tried (months of physiother…` | +| | linkId `PROC-KNEE-01/stg/2`, text `Kellgren-Lawrence grade of osteoarthritis on the standing X-ray` | +| | linkId `PROC-KNEE-01/stg/3`, text `Range of motion and deformity of the knee (flexion contracture, varus/valgus)` | +| | and 2 more | +| `item[].answer[]` | valueString `Recorded.` | + +## Rules + +### 1. The case number + +`Claim.identifier`, typed `CLN`, carries the provider's case number. Every later message on the case, the payer's included, names it. + +### 2. One focal insurance + +Exactly one `Claim.insurance[]` entry carries `focal: true`. + +### 3. Items + +Each item links to the care team, diagnosis and procedure by sequence. `net` is `unitPrice` times `quantity`; do not compute with `factor`. `Claim.total` equals the sum of the item nets. + +### 4. Documents + +The mandatory document codes are the ones the auth-requirements answer returned. Send each code and display exactly as given. + +### 5. The STG answers + +Each package's STG questionnaire is answered as a `QuestionnaireResponse` in the bundle, with the `linkId`s the plan gives. + +### 6. Claim.type + +SNOMED `737481003`, Inpatient care management. Payers echo it, some under the `ndhm-claim-type` ValueSet URL. + +### 7. References to records + +A `valueReference` may point at the `Composition` heading an embedded record rather than at a `DocumentReference`. Follow the reference, then walk the record. + +## PMJAY + +The generic bundle above is what every payer takes, IRDAI-regulated insurers and TPAs included. PMJAY takes it with the changes and requirements below. + +### What changes in the bundle + +#### Resources + +- PMJAY adds 1 `QuestionnaireResponse`. + +#### Elements PMJAY adds + +| Element | Example | +| :-- | :-- | +| `Claim.item[].modifier[].coding[]` | `STRAT006a` Routine Ward | +| `Claim.item[].programCode[].coding[]` | `AB-PMJAY` Ayushman Bharat Pradhan Mantri Jan Arogya Yojana (AB-PMJAY) in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-program-code` | +| `QuestionnaireResponse.item[].answer[].valueAttachment` | contentType `application/pdf`, title `Medical Superintendent Declaration Form (During Admission)` | + +### What PMJAY specifies + +- `item.programCode` carries `AB-PMJAY` under `ndhm-program-code`. +- `item.modifier` carries the ward tier from the master's stratification codes, and `item.category` the master's specialty code. +- The Authentication Consent answer is a second `QuestionnaireResponse` beside the STG answers, with its attachments as `valueAttachment` and its dates as `valueDateTime`. +- Document codes are the `MAND` codes the auth-requirements answer returned. + +### What PMJAY requires + +- The biometric user token on the request, or the plan's Authentication Consent questionnaire answered as a `QuestionnaireResponse`. Refused with `PAYR-1256` otherwise. +- The STG questionnaire answered for every package that needs one. Refused with `PAYR-1254` otherwise. +- Not more than one day before admission, with the registration and admission dates as supporting information. +- One live preauthorisation per beneficiary per hospital. Refused with `PAYR-1238` while another is open. +- `LM100` is not allowed on a preauthorisation. Refused with `PAYR-1270`. +- Auto-approval only when this is the first preauthorisation on the case and every package carries `ApprovalNotRequired` `Y`. + +## Use cases, APIs and data elements + +### B3 Submit pre-authorisation (provider) + +Permission to treat. A resubmission, an enhancement and a query answer all reuse the same bundle with a new correlation id and the original reference; only the workflow code tells them apart. The acknowledgement on 20 brings the payer's own case number, and the desk files everything under it. + +| | | +| :-- | :-- | +| **API** | `/v1/preauth/submit` [`apis/03-preauth/v1-preauth-submit.bru`](/docs/nhcx/v1/api/preauth/endpoints/preauth-v1-preauth-submit) | +| **Callback** | `/v1/preauth/on_submit` [`apis/03-preauth/v1-preauth-on-submit.bru`](/docs/nhcx/v1/api/preauth/endpoints/preauth-v1-preauth-on-submit) | +| **Workflow** | 12 new, 121 resubmission, 13 enhancement; under PMJAY 19 answers a query and 131 an enhancement query | +| **Carries JWE** | yes | +| **Focal resource** | `Claim` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `x-hcx-sender_code` | `1000004446@hcx` | +| `x-hcx-recipient_code` | `1518@hcx` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-request_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{$guid}}` | +| `x-hcx-workflow_id` | `12` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `request.initiated` | +| `x-hcx-ben-abha-id` | `91711234567890` | +| `x-hcx-use_case` | `New` | + +**Workflow codes** + +| Code | Name | Authored by | `x-hcx-status` | Means | +| :-- | :-- | :-- | :-- | :-- | +| `12` | Preauth Request Initiated | provider | `request.initiated` | New preauth submission | +| `121` | Preauth Request Resubmitted | provider | `request.initiated` | Resubmission after query/rejection | +| `13` | Enhancement Request Initiated | provider | `request.initiated` | Enhancement (additional amount) request | +| `19` | Preauth Query Response Submitted | provider | `response.complete` | Response to payer's query on preauth | +| `131` | Enhancement Query Response Submitted | provider | `response.partial`, `response.error`, `response.complete` | Response to enhancement query | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `claimNumber` | Pre-auth Case Number | Case | `string` | `1..1` | `Claim.identifier[0].value` | `PA20260226001` | also at `Bundle.id` | +| `use` | Claim Use | Case | `code` | `1..1` | `Claim.use` | `preauthorization` | | +| `preAuthRef` | Approval Reference (if enhancement) | Case | `string` | `0..1` | `Claim.insurance[0].preAuthRef[0]` | `APPR-2026-HP-00891` | | +| `patientName` | Patient Full Name | Beneficiary | `string` | `1..1` | `Patient.name[0].text` | `Ramesh Chandra Sharma` | | +| `memberId` | Scheme / Insurer Member ID | Beneficiary | `string` | `1..1` | `Patient.identifier[type=PMJAY].value` | `PMJAY-HP-2024-998811` | also at `Coverage.subscriberId` | +| `abhaNumber` | ABHA Number | Beneficiary | `string` | `0..1` | `Patient.identifier[type=ABHA].value` | `91234567890123` | | +| `gender` | Gender | Beneficiary | `code` | `1..1` | `Patient.gender` | `male` | code system `http://hl7.org/fhir/administrative-gender` | +| `birthDate` | Date of Birth | Beneficiary | `date` | `1..1` | `Patient.birthDate` | `1982-06-15` | | +| `patientPhone` | Mobile Phone | Beneficiary | `string` | `0..1` | `Patient.telecom[system=phone].value` | `9876543210` | | +| `policyNumber` | Policy Number | Coverage | `string` | `1..1` | `Coverage.identifier[0].value` | `PMJAY/HP/S/G` | | +| `facilityId` | Hospital Facility ID (HFR/NPI) | Provider | `string` | `1..1` | `Organization[type=prov].identifier[system=https://facility.abdm.gov.in].value` | `IN1910000151` | | +| `providerName` | Hospital Name | Provider | `string` | `1..1` | `Organization[type=prov].name` | `Apex Multispeciality Hospital` | | +| `payerId` | Payer Identifier (NIIP) | Payer | `string` | `1..1` | `Organization[type=pay].identifier[system=https://irdai.gov.in].value` | `1000003538` | | +| `payerName` | Payer Name | Payer | `string` | `1..1` | `Organization[type=pay].name` | `National Health Authority - PMJAY` | | +| `practitionerId` | Practitioner ID (HPID/HPIN) | Practitioner | `string` | `1..1` | `Practitioner.identifier[system=https://hpr.abdm.gov.in].value` | `21-8899-4455-6677` | | +| `practitionerName` | Doctor Name | Practitioner | `string` | `1..1` | `Practitioner.name[0].text` | `Dr. Arvind Kumar` | | +| `admissionDate` | Admission Date | Stay | `dateTime` | `1..1` | `Claim.billablePeriod.start` | `2026-02-26T10:00:00+05:30` | | +| `dischargeDate` | Discharge Date | Stay | `dateTime` | `1..1` | `Claim.billablePeriod.end` | `2026-03-02T14:30:00+05:30` | | +| `careSetting` | Care Setting | Stay | `code` | `1..1` | `Claim.type.coding[0].code` | `institutional` | code system `http://terminology.hl7.org/CodeSystem/claim-type` | +| `primaryDiagnosisCode` | Primary Diagnosis (ICD-10) | Clinical | `string` | `1..1` | `Claim.diagnosis[0].diagnosisCodeableConcept.coding[0].code` | `A97.0` | code system `http://hl7.org/fhir/sid/icd-10` | +| `procedureCode` | Package / Procedure Code | Clinical | `string` | `1..1` | `Claim.procedure[0].procedureCodeableConcept.coding[0].code` | `MG004A` | | +| `estimatedTotal` | Estimated Package Amount | Billing | `decimal` | `1..1` | `Claim.total.value` | `15500.00` | | + +NRCeS profiles: [Claim](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Claim.html), [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html), [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html), [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html), [Practitioner](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Practitioner.html). + +### D4 Submit pre-authorisation (pmjay) + +Not more than one day before admission, with the biometric token or the consent response, the documents the auth-requirements answer asked for, the STG questionnaire for each package, and the registration and admission dates as supporting info. Auto-approved only if it is the first pre-authorisation for the case and every package allows it. + +| | | +| :-- | :-- | +| **API** | `/v1/preauth/submit` [`apis/03-preauth/v1-preauth-submit.bru`](/docs/nhcx/v1/api/preauth/endpoints/preauth-v1-preauth-submit) | +| **Callback** | `/v1/preauth/on_submit` [`apis/03-preauth/v1-preauth-on-submit.bru`](/docs/nhcx/v1/api/preauth/endpoints/preauth-v1-preauth-on-submit) | +| **Workflow** | 12 | +| **Carries JWE** | yes | +| **Focal resource** | `Claim` | +| **Simulator console** | `/builder?family=preauth&usecase=initiate` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `x-hcx-sender_code` | `1000004446@hcx` | +| `x-hcx-recipient_code` | `1518@hcx` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-request_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{$guid}}` | +| `x-hcx-workflow_id` | `12` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `request.initiated` | +| `x-hcx-ben-abha-id` | `91711234567890` | +| `x-hcx-use_case` | `New` | + +**Workflow codes** + +| Code | Name | Authored by | `x-hcx-status` | Means | +| :-- | :-- | :-- | :-- | :-- | +| `12` | Preauth Request Initiated | provider | `request.initiated` | New preauth submission | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `claimNumber` | PMJAY Case Number | Case | `string` | `1..1` | `Claim.identifier[0].value` | `VB26AA2600001` | | +| `patientName` | Patient Full Name | Beneficiary | `string` | `1..1` | `Patient.name[0].text` | `Ramesh Chandra Sharma` | | +| `memberId` | Scheme / Insurer Member ID | Beneficiary | `string` | `1..1` | `Patient.identifier[type=PMJAY].value` | `PMJAY-HP-2024-998811` | also at `Coverage.subscriberId` | +| `abhaNumber` | ABHA Number | Beneficiary | `string` | `0..1` | `Patient.identifier[type=ABHA].value` | `91234567890123` | | +| `gender` | Gender | Beneficiary | `code` | `1..1` | `Patient.gender` | `male` | code system `http://hl7.org/fhir/administrative-gender` | +| `birthDate` | Date of Birth | Beneficiary | `date` | `1..1` | `Patient.birthDate` | `1982-06-15` | | +| `patientPhone` | Mobile Phone | Beneficiary | `string` | `0..1` | `Patient.telecom[system=phone].value` | `9876543210` | | +| `facilityId` | Hospital Facility ID (HFR/NPI) | Provider | `string` | `1..1` | `Organization[type=prov].identifier[system=https://facility.abdm.gov.in].value` | `IN1910000151` | | +| `providerName` | Hospital Name | Provider | `string` | `1..1` | `Organization[type=prov].name` | `Apex Multispeciality Hospital` | | +| `payerId` | Payer Identifier (NIIP) | Payer | `string` | `1..1` | `Organization[type=pay].identifier[system=https://irdai.gov.in].value` | `1000003538` | | +| `payerName` | Payer Name | Payer | `string` | `1..1` | `Organization[type=pay].name` | `National Health Authority - PMJAY` | | +| `practitionerId` | Practitioner ID (HPID/HPIN) | Practitioner | `string` | `1..1` | `Practitioner.identifier[system=https://hpr.abdm.gov.in].value` | `21-8899-4455-6677` | | +| `practitionerName` | Doctor Name | Practitioner | `string` | `1..1` | `Practitioner.name[0].text` | `Dr. Arvind Kumar` | | +| `primaryDiagnosisCode` | Primary Diagnosis (ICD-10) | Clinical | `string` | `1..1` | `Claim.diagnosis[0].diagnosisCodeableConcept.coding[0].code` | `A97.0` | code system `http://hl7.org/fhir/sid/icd-10` | +| `procedureCode` | Package / Procedure Code | Clinical | `string` | `1..1` | `Claim.procedure[0].procedureCodeableConcept.coding[0].code` | `MG004A` | | +| `patientPhoto` | Patient Photo on Bed (POI) | Documents | `base64Binary` | `1..1` | `Claim.supportingInfo[category=POI].valueAttachment.data` | `JVBERi0xLjQK...` | | + +NRCeS profiles: [Claim](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Claim.html), [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html), [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html), [Practitioner](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Practitioner.html). + +### D5 Resubmit pre-authorisation (pmjay) + +Revises an approved or rejected case for a different amount or package. Nullifies every earlier instance; the payer treats it as the new base request. + +| | | +| :-- | :-- | +| **API** | `/v1/preauth/submit` [`apis/03-preauth/v1-preauth-submit.bru`](/docs/nhcx/v1/api/preauth/endpoints/preauth-v1-preauth-submit) | +| **Callback** | `/v1/preauth/on_submit` [`apis/03-preauth/v1-preauth-on-submit.bru`](/docs/nhcx/v1/api/preauth/endpoints/preauth-v1-preauth-on-submit) | +| **Workflow** | 121 | +| **Carries JWE** | yes | +| **Focal resource** | `Claim` | +| **Simulator console** | `/builder?family=preauth&usecase=resubmit` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `x-hcx-sender_code` | `1000004446@hcx` | +| `x-hcx-recipient_code` | `1518@hcx` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-request_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{$guid}}` | +| `x-hcx-workflow_id` | `121` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `request.initiated` | +| `x-hcx-ben-abha-id` | `91711234567890` | +| `x-hcx-use_case` | `Resubmit` | + +**Workflow codes** + +| Code | Name | Authored by | `x-hcx-status` | Means | +| :-- | :-- | :-- | :-- | :-- | +| `121` | Preauth Request Resubmitted | provider | `request.initiated` | Resubmission after query/rejection | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `claimNumber` | Existing Case Number | Case | `string` | `1..1` | `Claim.identifier[0].value` | `VB26AA2600001` | | +| `workflowId` | Workflow Code | Header | `string` | `1..1` | `Header.x-hcx-workflow_id` | `121` | | + +NRCeS profiles: [Claim](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Claim.html). diff --git a/site/docs/nhcx/v1/reference/fhir/preauthorisation-response.md b/site/docs/nhcx/v1/reference/fhir/preauthorisation-response.md new file mode 100644 index 000000000..29b0f3147 --- /dev/null +++ b/site/docs/nhcx/v1/reference/fhir/preauthorisation-response.md @@ -0,0 +1,229 @@ +--- +title: Preauthorisation response +sidebar_label: Preauthorisation response +sidebar_position: 9 +description: ClaimResponse, approvals, queries, and verified rejection bundles (wf 23) +verification: unverified +source: nhcx-package/docs/05-FHIR Reference/09-Preauthorisation Response.md +generated: true +--- + +# Preauthorisation response + +The payer's answer, on the provider's `/v1/preauth/on_submit` callback. A collection bundle whose spine is a `ClaimResponse` carrying the request's case number. The same shape carries an acknowledgement, an approval, a query and a rejection. + +Sent on `/v1/preauth/on_submit`. + +## The bundle + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `ClaimResponse` | none declared; NRCeS [ClaimResponse](https://nrces.in/ndhm/fhir/r4/StructureDefinition-ClaimResponse.html) | +| 2 | `Patient` | none declared; NRCeS [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html) | +| 3 | `Organization (pay)` | none declared; NRCeS [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 4 | `Organization (prov)` | none declared; NRCeS [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 5 | `Coverage` | none declared; NRCeS [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html) | + +## Elements + +### 1. ClaimResponse + +NRCeS profile: [ClaimResponse](https://nrces.in/ndhm/fhir/r4/StructureDefinition-ClaimResponse.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system ``, value `NM-26-0SE00002M` | +| `identifier[].type.coding[]` | `CLN` Claim number in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| `status` | `active` | +| `use` | `preauthorization` | +| `patient` | reference `` | +| `created` | `2026-09-10T23:54:09+05:30` | +| `insurer` | reference `` | +| `requestor` | reference `` | +| `outcome` | `complete` | +| `disposition` | `Approved after the status enquiry.` | +| `preAuthRef` | `CL/26/0SE000108` | +| `payeeType.coding[]` | `provider` Provider in `http://terminology.hl7.org/CodeSystem/payeetype` | +| `item[]` | id `Item/LI-899f9802`, itemSequence `1` | +| `item[].adjudication[].category.coding[]` | `submitted` Submitted Amount in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| | `eligible` Eligible Amount in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| | `reason` Reason for Adjudication in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| | and 1 more | +| `item[].adjudication[].amount` | value `150000` | +| `item[].adjudication[].reason.coding[]` | display `Approved after the status enquiry.` | +| | `Approved` Approved | +| `adjudication[].category.coding[]` | `status` Status | +| `adjudication[].reason.coding[]` | `approved` Approved | +| `total[].category.coding[]` | `benefit` Benefit Amount in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| | `submitted` Submitted Amount in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| | `eligible` Eligible Amount | +| `total[].amount` | value `150000` | +| `total[]` | id `MRAV1985001/SANDBOX-DEFAULT-01` | + +### 2. Patient + +NRCeS profile: [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system ``, value `MRAV1985001` | +| `identifier[].type.coding[]` | `MB` Member Number in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `name[]` | family `Kumar`, given `Ravi`, text `Ravi Kumar` | +| `gender` | `male` | +| `birthDate` | `1985-06-15` | + +### 3. Organization (pay) + +NRCeS profile: [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html). + +| Element | Example | +| :-- | :-- | +| `active` | `true` | +| `identifier[]` | system `https://facility.abdm.gov.in`, value `1000004805` | +| `identifier[].type.coding[]` | `NIIP` National Insurance Payor Identifier (Payor) in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `type[].coding[]` | `pay` Payer in `http://terminology.hl7.org/CodeSystem/organization-type` | +| `name` | `Sandbox Payer` | + +### 4. Organization (prov) + +NRCeS profile: [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html). + +| Element | Example | +| :-- | :-- | +| `active` | `true` | +| `identifier[]` | system `https://facility.abdm.gov.in`, value `IN1910000151` | +| `identifier[].type.coding[]` | `NPI` National provider identifier in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `type[].coding[]` | `prov` Healthcare Provider in `http://terminology.hl7.org/CodeSystem/organization-type` | +| `name` | `KyroCare Multispeciality Hospital` | + +### 5. Coverage + +NRCeS profile: [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system ``, value `SANDBOX-DEFAULT-01` | +| `identifier[].type.coding[]` | `NH` National Health Plan Identifier in `http://terminology.hl7.org/CodeSystem/v2-0203` | +| `status` | `active` | +| `type.coding[]` | `HIP` health insurance plan policy in `http://terminology.hl7.org/CodeSystem/v3-ActCode` | +| `beneficiary` | reference `` | +| `period` | start `2026-01-01T00:00:00+05:30`, end `2026-12-31T00:00:00+05:30` | +| `payor[]` | reference `` | +| `class[]` | id `POL7UMU002`, value `SANDBOX-DEFAULT-01` | +| `class[].type.coding[]` | `XV` Health Plan Identifier in `http://terminology.hl7.org/CodeSystem/v2-0203` | + +## The answers + +The same bundle, told apart by the workflow code, `outcome` and the claim-level adjudication reason. + +| Variant | Workflow | outcome | reason | +| :-- | :-- | :-- | :-- | +| Acknowledged | `20` | `queued` | `submitted` Submitted | +| Approved | `21` | `complete` | `approved` Approved | +| Enhancement approved | `22` | `complete` | `approved` Approved | +| Rejected | `23` | `error` | `rejected` Rejected | +| Queried | `24` | `partial` | `queried` Queried | + +## Rules + +### 1. Read outcome with the reason + +`outcome` `complete` covers approval and rejection alike. Read it with `adjudication[].reason` at claim level. + +### 2. Answer early, decide later + +Acknowledge at once on 20 as `response.partial`, then decide on 21 or 23 as `response.complete`, or the exchange retires the correlation before the adjudicator gets to it. + +### 3. The case number + +`preAuthRef` carries the payer's own case number. Store it on arrival; later requests on the case name it. + +### 4. Items by sequence + +Read item adjudication by `itemSequence`, never by array position. A reduced amount does not force `outcome` to `partial`; reconcile the amounts yourself. + +### 5. Totals + +`total[]` carries `benefit`, `submitted` and `eligible`. The `eligible` total names the member and the plan in its `id`; key on the category and the `id` together. + +### 6. disposition is prose + +For a human. Route on `outcome` and the adjudication codes. + +### 7. Match on the case number + +Join the response to the request on `identifier` and `preAuthRef`, never on the provider identifier or name, which can change shape between request and response. + +### 8. Adjudication systems + +Some senders bind adjudication categories to a documentation URL. Match on the code. + +## PMJAY + +The generic bundle above is what every payer takes, IRDAI-regulated insurers and TPAs included. PMJAY takes it with the changes and requirements below. + +### What changes in the bundle + +PMJAY sends this exchange in the generic shape. + +### What PMJAY specifies + +- A rejection is `outcome` `error` with reason `rejected` and benefit 0. Generic payers send `complete` with `cancelled` or `rejected`. Handle both. +- A query is `outcome` `partial` with reason `queried`, the question as free text in the item adjudication; see the query chapter. +- `preAuthRef` carries the scheme's case id. It is what the payer service uses to address the case. + +### What PMJAY requires + +- Store the case reference the moment it arrives. Enhancements, claims and the payer service address the case by it. + +## Use cases, APIs and data elements + +### C5 Respond to pre-authorisation (payer) + +The adjudicated pre-authorisation. The acknowledgement on 20 travels as response.partial and carries the payer's own case number; the decisions travel as response.complete. Read outcome and the adjudication amounts together: complete covers approval and denial alike. Under PMJAY a query is this ClaimResponse on 24 or 241, on the case's own thread. + +| | | +| :-- | :-- | +| **API** | `/v1/preauth/on_submit` [`apis/03-preauth/v1-preauth-on-submit.bru`](/docs/nhcx/v1/api/preauth/endpoints/preauth-v1-preauth-on-submit) | +| **Callback** | `/v1/preauth/submit` [`apis/03-preauth/v1-preauth-submit.bru`](/docs/nhcx/v1/api/preauth/endpoints/preauth-v1-preauth-submit) | +| **Workflow** | 20 received, 21 approved, 23 rejected, 24 queried, 22 enhancement approved, 231 denied, 241 queried | +| **Carries JWE** | yes | +| **Focal resource** | `ClaimResponse` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `x-hcx-sender_code` | `1518@hcx` | +| `x-hcx-recipient_code` | `1000004446@hcx` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-request_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{$guid}}` | +| `x-hcx-workflow_id` | `21` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `response.complete` | +| `x-hcx-ben-abha-id` | `91711234567890` | +| `x-hcx-debug_flag` | `INFO` | + +**Workflow codes** + +| Code | Name | Authored by | `x-hcx-status` | Means | +| :-- | :-- | :-- | :-- | :-- | +| `20` | Preauth Request Received | payer | `response.partial`, `response.error` | Payer has received and acknowledged the preauth request | +| `21` | Preauth Request Approved | payer | `response.complete` | Preauth fully approved - proceed with treatment | +| `23` | Preauth Request Rejected | payer | `response.complete` | Preauth rejected - review error/processNote for reason | +| `24` | Preauth Request Queried | payer | `request.initiated` | Payer needs more information - respond using workflow 19 | +| `22` | Enhancement Request Approved | payer | `response.complete` | Enhancement request approved by payer | +| `231` | Enhancement Deny | status sheet only | `response.complete` | | +| `241` | Enhancement Request Queried | payer | `request.initiated` | Enhancement request queried by payer | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `outcome` | Verdict Outcome | Verdict | `code` | `1..1` | `ClaimResponse.outcome` | `complete` | | +| `preAuthRef` | Payer Case Tracking ID | Verdict | `string` | `0..1` | `ClaimResponse.preAuthRef` | `APPR-2026-HP-00891` | | +| `approvedAmount` | Approved Pre-auth Sanction | Financials | `decimal` | `0..1` | `ClaimResponse.total[category=benefit].amount.value` | `15500.00` | | +| `disposition` | Adjudicator Remarks | Verdict | `string` | `0..1` | `ClaimResponse.disposition` | `Approved by PPD-Trust committee` | | + +NRCeS profiles: [ClaimResponse](https://nrces.in/ndhm/fhir/r4/StructureDefinition-ClaimResponse.html). diff --git a/site/docs/nhcx/v1/reference/fhir/predetermination-status-and-search.md b/site/docs/nhcx/v1/reference/fhir/predetermination-status-and-search.md new file mode 100644 index 000000000..a8adef9be --- /dev/null +++ b/site/docs/nhcx/v1/reference/fhir/predetermination-status-and-search.md @@ -0,0 +1,426 @@ +--- +title: Predetermination, status and search +sidebar_label: Predetermination, status and search +sidebar_position: 18 +description: Specification and schemas for predetermination, status, and search +verification: unverified +source: nhcx-package/docs/05-FHIR Reference/18-Predetermination, Status and Search.md +generated: true +--- + +# Predetermination, status and search + +Three exchanges that are specified and seldom used. Confirm support with the payer before building any of them. + +## Predetermination request + +Sent on `/v1/predetermination/submit`. + +### The bundle + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `Claim` | [Claim](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Claim.html) | +| 2 | `Patient` | [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html) | +| 3 | `Organization (prov)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 4 | `Organization (pay)` | [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 5 | `Coverage` | [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html) | +| 6 | `Practitioner` | [Practitioner](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Practitioner.html) | +| 7 | `Procedure` | [Procedure](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Procedure.html) | + +### Elements + +#### 1. Claim + +NRCeS profile: [Claim](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Claim.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system `https://nhcx.abdm.gov.in`, value `PD0000000001` | +| `identifier[].type.coding[]` | `CLN` Claim number in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| `status` | `active` | +| `type.coding[]` | `737481003` Inpatient care management (procedure) in `http://snomed.info/sct` | +| `use` | `predetermination` | +| `patient` | reference `https://nhcx.abdm.gov.in/patient` | +| `billablePeriod` | start `2026-02-22T10:00:00+05:30`, end `2026-02-27T11:00:00+05:30` | +| `created` | `2026-02-22T15:49:36+05:30` | +| `insurer` | reference `https://nhcx.abdm.gov.in/payer` | +| `provider` | reference `https://nhcx.abdm.gov.in/provider` | +| `priority.coding[]` | `normal` Normal in `http://terminology.hl7.org/CodeSystem/processpriority` | +| `careTeam[]` | sequence `1` | +| `careTeam[].provider` | reference `https://nhcx.abdm.gov.in/practitioner` | +| `careTeam[].role.coding[]` | `primary` Primary provider in `http://terminology.hl7.org/CodeSystem/claimcareteamrole` | +| `careTeam[].qualification.coding[]` | `394802001` General medicine in `http://snomed.info/sct` | +| `supportingInfo[]` | id `SupportingInformation/1`, sequence `1` | +| | id `SupportingInformation/2`, sequence `2` | +| | id `SupportingInformation/3`, sequence `3` | +| | and 3 more | +| `supportingInfo[].category.coding[]` | `INV` Document Type - Investigation in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| | `ONS` Period, start or end dates of aspects of the Condition. (e.g. admission, discha… in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| | `OTH` Other in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-supportinginfo-category` | +| `supportingInfo[].code.coding[]` | `MAND0408` Clinical notes detailing history and Admission notes showing vitals and examina… in `https://nhcx.abdm.gov.in/document-code` | +| | `MAND0455` CXR PA view or CECT chest abdomen and pelvis in `https://nhcx.abdm.gov.in/document-code` | +| | `MAND0409` Any investigations done in `https://nhcx.abdm.gov.in/document-code` | +| | and 3 more | +| `supportingInfo[].valueAttachment` | contentType `application/pdf`, title `Clinical notes detailing history and Admission notes showing vitals and examina…` | +| | contentType `application/pdf`, title `CXR PA view or CECT chest abdomen and pelvis` | +| | contentType `application/pdf`, title `Any investigations done` | +| | and 1 more | +| `diagnosis[]` | sequence `1` | +| `diagnosis[].diagnosisCodeableConcept.coding[]` | `A97` Dengue in `http://hl7.org/fhir/sid/icd-10` | +| `diagnosis[].type[].coding[]` | `admitting` Admitting Diagnosis in `http://terminology.hl7.org/CodeSystem/ex-diagnosistype` | +| `diagnosis[].onAdmission.coding[]` | `yes` Yes in `http://terminology.hl7.org/CodeSystem/ex-diagnosis-on-admission` | +| `procedure[]` | id `Procedure/1`, sequence `1`, date `2026-02-24T09:30:00+05:30` | +| `procedure[].type[].coding[]` | `conservative` Conservative in `https://nhcx.abdm.gov.in/procedure-type` | +| `procedure[].procedureReference` | reference `https://nhcx.abdm.gov.in/procedure/1`, display `Pleural Effusion` | +| `insurance[]` | sequence `1`, focal `true` | +| `insurance[].coverage` | reference `https://nhcx.abdm.gov.in/coverage` | +| `item[]` | id `Item/1`, sequence `1`, careTeamSequence `1`, diagnosisSequence `1`, procedureSequence `1`, informationSequence `1`, `2`, `3`, `4`, `5`, `6`, factor `0.5` | +| `item[].category.coding[]` | `MG` General Medicine in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-benefit-category` | +| `item[].productOrService.coding[]` | `MG0111A` Pleural Effusion in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-procedure-code` | +| `item[].modifier[].coding[]` | `STRAT006b` HDU | +| `item[].programCode[].coding[]` | `AB-PMJAY` Ayushman Bharat Pradhan Mantri Jan Arogya Yojana (AB-PMJAY) in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-program-code` | +| `item[].servicedPeriod` | start `2026-02-22`, end `2026-02-27` | +| `item[].quantity` | value `1` | +| `item[].unitPrice` | value `3300`, currency `INR` | +| `item[].net` | value `3300`, currency `INR` | +| `total` | value `3300`, currency `INR` | + +The `Patient`, `Organization`, `Coverage`, `Practitioner`, `Procedure` entries are shaped as in the chapters that introduce them. + +## Predetermination response + +Sent on `/v1/predetermination/on_submit`. + +### The bundle + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `ClaimResponse` | none declared; NRCeS [ClaimResponse](https://nrces.in/ndhm/fhir/r4/StructureDefinition-ClaimResponse.html) | +| 2 | `Patient` | none declared; NRCeS [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html) | +| 3 | `Organization (pay)` | none declared; NRCeS [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 4 | `Organization (prov)` | none declared; NRCeS [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 5 | `Coverage` | none declared; NRCeS [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html) | + +### Elements + +#### 1. ClaimResponse + +NRCeS profile: [ClaimResponse](https://nrces.in/ndhm/fhir/r4/StructureDefinition-ClaimResponse.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system ``, value `NM-26-0SE00002M` | +| `identifier[].type.coding[]` | `CLN` Claim number in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | +| `status` | `active` | +| `use` | `predetermination` | +| `patient` | reference `` | +| `created` | `2026-09-10T23:54:09+05:30` | +| `insurer` | reference `` | +| `requestor` | reference `` | +| `outcome` | `complete` | +| `disposition` | `Approved after the status enquiry.` | +| `preAuthRef` | `CL/26/0SE000108` | +| `payeeType.coding[]` | `provider` Provider in `http://terminology.hl7.org/CodeSystem/payeetype` | +| `item[]` | id `Item/LI-899f9802`, itemSequence `1` | +| `item[].adjudication[].category.coding[]` | `submitted` Submitted Amount in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| | `eligible` Eligible Amount in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| | `reason` Reason for Adjudication in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| | and 1 more | +| `item[].adjudication[].amount` | value `150000` | +| `item[].adjudication[].reason.coding[]` | display `Approved after the status enquiry.` | +| | `Approved` Approved | +| `adjudication[].category.coding[]` | `status` Status | +| `adjudication[].reason.coding[]` | `approved` Approved | +| `total[].category.coding[]` | `benefit` Benefit Amount in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| | `submitted` Submitted Amount in `https://hl7.org/fhir/R4/valueset-adjudication.html` | +| | `eligible` Eligible Amount | +| `total[].amount` | value `150000` | +| `total[]` | id `MRAV1985001/SANDBOX-DEFAULT-01` | + +The `Patient`, `Organization`, `Coverage` entries are shaped as in the chapters that introduce them. + +## Status + +A sender asks what became of a request it made. There is no FHIR payload either way. The Status sheet of the requests-and-responses workbook says the request payload "should be empty string": no bundle, no `Task`, no resource. Everything the call needs travels in the protected header. `x-hcx-correlation_id` is the `x-hcx-api_call_id` of the request whose status is sought, `x-hcx-status` is `request.initiated`, `x-hcx-workflow_id` and `x-hcx-use_case` (`New`, `Enhancement` or `Resubmit`) are optional, and `x-hcx-ben-abha-id` is mandatory. The status comes back on `/v1/on_status`, again in the protected header: `x-hcx-status` `request.dispatched`, the correlation id of the request, and `x-hcx-error_details` (`code`, `message`, `trace`) where it failed. The sheet gives the callback no payload section. The sandbox exit checklists word the request payload as the "encrypted payload of request for which the status is seeking for" and describe no bundle for it. + +Sent on `/v1/status`, answered on `/v1/on_status`. + +## Search + +Sent on `/v1/search/submit`. + +### The bundle + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `Task` | [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html) | +| 2 | `Organization` | none declared; NRCeS [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | +| 3 | `Organization` | none declared; NRCeS [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | + +### Elements + +#### 1. Task + +NRCeS profile: [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html). + +| Element | Example | +| :-- | :-- | +| `identifier[]` | system `https://nhcx.gov.in/task`, value `SR0000000001` | +| `status` | `requested` | +| `intent` | `order` | +| `code.coding[]` | `search` Search in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-codes` | +| `description` | `Search claim records for case CL0000000001` | +| `authoredOn` | `2026-02-26T12:00:00+05:30` | +| `requester` | reference `urn:uuid:e0000001-0000-0000-0000-000000000002` | +| `owner` | reference `urn:uuid:e0000001-0000-0000-0000-000000000003` | +| `input[]` | valueString `CL0000000001` | +| `input[].type.coding[]` | `ClaimNumber` Claim Number in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code` | + +The `Organization` entries are shaped as in the chapters that introduce them. + +## Search response + +Sent on `/v1/search/on_submit`. + +### The bundle + +| # | Resource | Profile | +| :-- | :-- | :-- | +| 1 | `Task` | [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html) | +| 2 | `ClaimResponse` | none declared; NRCeS [ClaimResponse](https://nrces.in/ndhm/fhir/r4/StructureDefinition-ClaimResponse.html) | +| 3 | `Patient` | none declared; NRCeS [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html) | +| 4 | `Organization` | none declared; NRCeS [Organization](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Organization.html) | + +### Elements + +#### 1. Task + +NRCeS profile: [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html). + +| Element | Example | +| :-- | :-- | +| `status` | `completed` | +| `intent` | `order` | +| `code.coding[]` | `search` Search in `https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-task-codes` | +| `output[].type.coding[]` | `ClaimResponse` in `http://hl7.org/fhir/resource-types` | +| `output[].valueReference` | reference `urn:uuid:e0000001-0000-0000-0000-000000000011` | + +#### 2. ClaimResponse + +NRCeS profile: [ClaimResponse](https://nrces.in/ndhm/fhir/r4/StructureDefinition-ClaimResponse.html). + +| Element | Example | +| :-- | :-- | +| `status` | `active` | +| `type.coding[]` | `institutional` | +| `use` | `claim` | +| `patient` | reference `Patient/1` | +| `insurer` | reference `Organization/2` | +| `outcome` | `complete` | + +The `Patient`, `Organization` entries are shaped as in the chapters that introduce them. + +## Rules + +### 1. Predetermination + +What would the payer approve for this treatment? The preauthorisation bundles with `Claim.use` `predetermination`. Nothing is reserved. + +### 2. Status + +No bundle and no `Task`. Send an empty payload with the correlation id set to the call id of the request you are asking about, and read the answer from the callback's protected header. + +### 3. Search + +`Task.code` `search` in `ndhm-task-codes`, with inputs from the task input-type value set, such as `ClaimNumber`, `PolicyNumber`, `FromDate` and `ToDate`. The answer is a `Task`, `completed`, whose outputs reference the matching `ClaimResponse` resources in the same bundle, possibly across several callbacks on one correlation id. + +### 4. Agree the codes + +The task code for search is given more than one way in the specifications. Agree it with the payer in writing first. + +## PMJAY + +The generic bundle above is what every payer takes, IRDAI-regulated insurers and TPAs included. PMJAY takes it with the changes and requirements below. + +### What changes in the bundle + +PMJAY sends this exchange in the generic shape. + +### What PMJAY requires + +- A status enquiry as a `Task` is refused. Read where a case stands from the payer service's role lookup. + +## Use cases, APIs and data elements + +### B9 Submit predetermination (provider) + +What would the payer approve for this treatment? Same bundle shape as a pre-authorisation, asked before committing to one. + +| | | +| :-- | :-- | +| **API** | `/v1/predetermination/submit` [`apis/04-predetermination/v1-predetermination-submit.bru`](/docs/nhcx/v1/api/predetermination/endpoints/predetermination-v1-predetermination-submit) | +| **Callback** | `/v1/predetermination/on_submit` [`apis/04-predetermination/v1-predetermination-on_submit.bru`](/docs/nhcx/v1/api/predetermination/endpoints/predetermination-v1-predetermination-on-submit) | +| **Carries JWE** | yes | +| **Focal resource** | `Claim` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `Content-Type` | `application/json` | +| `x-hcx-sender_code` | `{{participantCode}}` | +| `x-hcx-recipient_code` | `{{recipientCode}}` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{correlationId}}` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `request.initiated` | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `claimNumber` | Predetermination Reference | Case | `string` | `1..1` | `Claim.identifier[0].value` | `PD0000000001` | | +| `use` | Claim Use | Case | `code` | `1..1` | `Claim.use` | `predetermination` | | +| `patientName` | Patient Full Name | Beneficiary | `string` | `1..1` | `Patient.name[0].text` | `Ramesh Chandra Sharma` | | +| `memberId` | Scheme / Insurer Member ID | Beneficiary | `string` | `1..1` | `Patient.identifier[type=PMJAY].value` | `PMJAY-HP-2024-998811` | also at `Coverage.subscriberId` | +| `abhaNumber` | ABHA Number | Beneficiary | `string` | `0..1` | `Patient.identifier[type=ABHA].value` | `91234567890123` | | +| `gender` | Gender | Beneficiary | `code` | `1..1` | `Patient.gender` | `male` | code system `http://hl7.org/fhir/administrative-gender` | +| `birthDate` | Date of Birth | Beneficiary | `date` | `1..1` | `Patient.birthDate` | `1982-06-15` | | +| `patientPhone` | Mobile Phone | Beneficiary | `string` | `0..1` | `Patient.telecom[system=phone].value` | `9876543210` | | +| `policyNumber` | Policy Number | Coverage | `string` | `1..1` | `Coverage.identifier[0].value` | `PMJAY/HP/S/G` | | +| `primaryDiagnosisCode` | Primary Diagnosis (ICD-10) | Clinical | `string` | `1..1` | `Claim.diagnosis[0].diagnosisCodeableConcept.coding[0].code` | `A97.0` | code system `http://hl7.org/fhir/sid/icd-10` | +| `procedureCode` | Package / Procedure Code | Clinical | `string` | `1..1` | `Claim.procedure[0].procedureCodeableConcept.coding[0].code` | `MG004A` | | + +NRCeS profiles: [Claim](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Claim.html), [Patient](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Patient.html), [Coverage](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Coverage.html). + +### C11 Respond to predetermination (payer) + +What the payer would approve for the proposed treatment. + +| | | +| :-- | :-- | +| **API** | `/v1/predetermination/on_submit` [`apis/04-predetermination/v1-predetermination-on_submit.bru`](/docs/nhcx/v1/api/predetermination/endpoints/predetermination-v1-predetermination-on-submit) | +| **Callback** | `/v1/predetermination/submit` [`apis/04-predetermination/v1-predetermination-submit.bru`](/docs/nhcx/v1/api/predetermination/endpoints/predetermination-v1-predetermination-submit) | +| **Carries JWE** | yes | +| **Focal resource** | `ClaimResponse` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `Content-Type` | `application/json` | +| `x-hcx-sender_code` | `{{participantCode}}` | +| `x-hcx-recipient_code` | `{{recipientCode}}` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{correlationId}}` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `response.complete` | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `use` | Claim Use | Verdict | `code` | `1..1` | `ClaimResponse.use` | `predetermination` | | +| `estimatedApproval` | Estimated Approved Benefit | Verdict | `decimal` | `1..1` | `ClaimResponse.total[category=benefit].amount.value` | `15500.00` | | + +NRCeS profiles: [ClaimResponse](https://nrces.in/ndhm/fhir/r4/StructureDefinition-ClaimResponse.html). + +### A5 Get status (shared) + +Where any request you made got to, by its correlation id. The sandbox's own status page answers without a token. + +| | | +| :-- | :-- | +| **API** | `/v1/status` [`apis/08-status/v1-status.bru`](/docs/nhcx/v1/api/status/endpoints/status-v1-status) | +| **Callback** | `/v1/on_status` [`apis/13-other/v1-on_status.bru`](/docs/nhcx/v1/api/other/endpoints/other-v1-on-status) | +| **Carries JWE** | yes | +| **Focal resource** | `None; the payload is an empty string and the protected header carries the call` | +| **Simulator console** | `/status` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `x-hcx-sender_code` | `1000004446@hcx` | +| `x-hcx-recipient_code` | `1518@hcx` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-request_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{originalApiCallId}}` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `request.initiated` | +| `x-hcx-ben-abha-id` | `91711234567890` | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `correlationId` | API call ID of the request being checked | Header | `uuid` | `1..1` | `Header.x-hcx-correlation_id` | `4f9d2b80-13b4-4e2a-9e12-8f9024a56789` | | +| `status` | Dispatch Status | Callback Header | `string` | `1..1` | `Header.x-hcx-status` | `request.dispatched` | | + +### B6 Search claims (provider) + +Look up claim information by criteria. The provider sandbox exit checklist names /v1/search/submit for claim search, while the Technical Specifications route /search/submit from NHA through NHCX to the payer: a cross-payer search for NHA or a regulator. A provider's search over its own cases is /claim/search in the protocol, which the access-control policy allows for requests that originated from the provider. No source confirms which of the two the sandbox accepts from a provider. + +| | | +| :-- | :-- | +| **API** | `/v1/search/submit` [`apis/08-status/v1-search-submit.bru`](/docs/nhcx/v1/api/status/endpoints/status-v1-search-submit) | +| **Callback** | `/v1/search/on_submit` [`apis/08-status/v1-search-on-submit.bru`](/docs/nhcx/v1/api/status/endpoints/status-v1-search-on-submit) | +| **Carries JWE** | yes | +| **Focal resource** | `Task` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `x-hcx-sender_code` | `1000004446@hcx` | +| `x-hcx-recipient_code` | `1518@hcx` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-request_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{$guid}}` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `request.initiated` | +| `x-hcx-ben-abha-id` | `91711234567890` | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `taskCode` | Task Code | Task | `code` | `1..1` | `Task.code.coding[0].code` | `search` | | +| `claimNumber` | Search Claim Number | Task Input | `string` | `0..1` | `Task.input[type=ClaimNumber].valueString` | `CL0000000001` | | +| `policyNumber` | Search Policy Number | Task Input | `string` | `0..1` | `Task.input[type=PolicyNumber].valueString` | `PMJAY/HP/S/G` | | + +NRCeS profiles: [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html). + +### C8 Respond to search (payer) + +The ClaimResponse objects matching the criteria asked for. + +| | | +| :-- | :-- | +| **API** | `/v1/search/on_submit` [`apis/08-status/v1-search-on-submit.bru`](/docs/nhcx/v1/api/status/endpoints/status-v1-search-on-submit) | +| **Callback** | `/v1/search/submit` [`apis/08-status/v1-search-submit.bru`](/docs/nhcx/v1/api/status/endpoints/status-v1-search-submit) | +| **Carries JWE** | yes | +| **Focal resource** | `Task` | + +**Request headers** + +| Header | Example value | +| :-- | :-- | +| `x-hcx-sender_code` | `1518@hcx` | +| `x-hcx-recipient_code` | `1000004446@hcx` | +| `x-hcx-api_call_id` | `{{$guid}}` | +| `x-hcx-request_id` | `{{$guid}}` | +| `x-hcx-correlation_id` | `{{$guid}}` | +| `x-hcx-timestamp` | `{{$isoTimestamp}}` | +| `x-hcx-status` | `response.complete` | +| `x-hcx-ben-abha-id` | `91711234567890` | + +**Data elements** + +| Element | Label | Group | Type | Card. | FHIR path | Example | Notes | +| :-- | :-- | :-- | :-- | :--: | :-- | :-- | :-- | +| `taskStatus` | Search Task Status | Task | `code` | `1..1` | `Task.status` | `completed` | | +| `claimResponseRef` | Matching ClaimResponse | Task Output | `reference` | `0..*` | `Task.output[].valueReference.reference` | `ClaimResponse/cr-approved-1` | | + +NRCeS profiles: [Task](https://nrces.in/ndhm/fhir/r4/StructureDefinition-Task.html). diff --git a/site/docs/nhcx/v1/reference/governance-and-audit.md b/site/docs/nhcx/v1/reference/governance-and-audit.md new file mode 100644 index 000000000..e2d996046 --- /dev/null +++ b/site/docs/nhcx/v1/reference/governance-and-audit.md @@ -0,0 +1,221 @@ +--- +title: Governance and audit +sidebar_label: Governance and audit +sidebar_position: 15 +description: Security layers, dual JWTs, log retention, grievance redressal, and onboarding checklist +verification: unverified +source: nhcx-package/docs/06-Reference/05-Governance and Audit.md +generated: true +--- + +# Governance and audit + +What a participant owes the network beyond making the calls work: how messages +are secured in transit and at the API layer, what must be logged and for how +long, how grievances are handled, how a participant joins and how one is +removed. None of it is a claim exchange and all of it is binding on anyone +operating in production. + +## The security layers + +Three, and they do different jobs. A system that has one is not secure. + +| Layer | Mechanism | What it protects | +| :---- | :---- | :---- | +| Transport | HTTPS with TLS, mandatory in production | The channel | +| Message | JWE with the recipient's public key | The payload, from everyone including the exchange | +| API | JWT bearer tokens with a mandatory expiry | Access to the endpoints | + +Transport security is stated without qualification: all communication between +the exchange and participating entities uses TLS, and all APIs work only over +HTTPS in production. + +## The two JWTs, and they are not the same + +This is the part most often built wrong, because the same word covers two +tokens signed by different parties with different algorithms. + +**Your token, calling the gateway.** Signed `HS256`, with the participant's +`client_secret` as the key. Claims `jti`, `iss` (the exchange instance), `sub` +(your client ID), `iat` and `exp`. You obtain it from the sessions endpoint +with your client ID and secret, and you present it on the `Authorization` +header. Session Token in Getting Started covers obtaining it; note that NHCX's +own endpoints read it from `bearer_auth` in practice, which is why the safe +course is to send both header names. + +**The exchange's token, calling you.** Signed `RS256`, with the exchange's own +private key. Claims `jti`, `iss`, `sub` set to the same value as `iss`, `iat` +and `exp`. Participant systems are expected to validate it against the +exchange's public key. + +**The public key is still not published.** Neither is the header it arrives on. +Receiving a Callback in Getting Started sets out what that means: every +integration built from these documents has shipped with signature checking +disabled, because rejecting everything makes the endpoint useless. Ask for the +key during onboarding, at the same time you register your endpoint, hold the +gap open deliberately rather than silently, and defend the endpoint with an +address allow-list and whatever else your edge offers until you have it. + +**Revocation.** The exchange revokes a participant's API access by generating a +new `client_secret` and updating the registry. Your tokens stop working and you +mint new ones with the new secret. There is no separate revocation call to +watch for, so a sudden authentication failure across every call is a state to +recognise. + +## Key rotation + +- Rotate the encryption key pair **once a year**. The specification recommends + it; the certificate a self-signed X.509 generates by default expires in a + year anyway. +- Mechanisms must exist for providers, payers and the exchange to **tell the + ecosystem about a suspected key compromise**. Decide in advance who at your + organisation makes that call and how. +- A certificate-only change in production skips the passcode steps. Creating + and Updating a Participant has the call. +- The practical failure is asymmetric and worth naming: if the certificate on + your record does not match the private key you hold, everybody else can seal + messages you cannot open, and nothing tells you until traffic fails. + +## What must be logged + +The event-audit guidelines are the strictest obligation in this chapter and the +least implemented. + +- **Every event in the claims flow must be digitally signed and logged**, in + both directions, between provider systems, beneficiary apps and payer + systems. Claim created, claim forwarded, data requested, authorisation, + payment. +- **Logs must be append-only.** They must not be editable. The stated purpose is + immutability, non-tamperability and non-repudiability. +- **Retention is set by the law of the land**, configurable, and the material + deliberately does not name a period. +- **The audit trail must be transparently available to the customer.** + +The exchange keeps its own audit log of every API call it receives: the domain +headers, the signature and encryption details, sender and recipient, and +whether validation passed. It never logs the payload, because it cannot read +it. + +Two requirements on that log are worth knowing because they are things you can +use rather than things you must build. + +- **The audit log is queryable through an API**, so a participant can retrieve + the trail of its own transactions. +- **The exchange publishes reports against it** for payers, providers, + beneficiaries, regulators and observers, and each instance publishes the list + of reports it supports and the level of detail in each. + +Each instance also defines an archival policy covering retention, deletion and +how to reach logs after archival. Ask for your instance's policy and its report +list during onboarding; neither is in the published material. + +## Grievance redressal + +The claims desk meets grievances as a communication reason code. The governance +layer underneath it is a published policy that every operator must produce and +every participant signs. + +What the guidelines require of that policy: + +- Digital initiation, routing and tracking of a grievance raised by any + participant against any other. +- A published list of grievances covered, and a mechanism for those that are + not. +- **Every participant must run a nodal governance body**, contactable at the + digital and physical addresses given at onboarding, and those contact details + are readable by every other participant through the registry. The exchange + publishes its own governance body the same way. +- Published types, priorities and **service levels per grievance type**. +- A due-diligence cycle before responding, the right to **reopen**, and + escalation to the exchange operator on accelerated timelines when the + requester is not satisfied. +- Versioning, signature by new members at onboarding, and proactive notice of + any change. + +Two consequences for a build. Your registry entry is a published contact point +for disputes, so the mobile number and email on it are operational rather than +administrative. And a grievance has a service level attached, so the +communication inbox that receives one is not a mailbox somebody reads when they +can. + +The guidelines are aligned with IRDAI's own grievance-redressal guidelines and +are explicitly a draft for consultation. The model policy has not been +published. + +## Beneficiary authentication, generally + +PMJAY biometrics are one case of a wider expectation. Provider systems are +expected to support Aadhaar eKYC for beneficiary verification, and Aadhaar +authentication by mobile OTP or biometric to initiate a claim transaction. The +guidelines note that provider systems enrolled with ABDM already hold biometric +devices, because health ID creation needs them. Payer systems and the exchange +integrate Aadhaar authentication for verifying the beneficiary at claim +validation. + +Biometric Authentication in Building a Provider covers the scheme's own +implementation of this. + +## Joining, and being removed + +Onboarding is two stages, and the first certifies the second. + +**Sandbox.** Apply, be verified as eligible, receive credentials, integrate, +then pass the functional and security tests that apply to your role. The +operator may require additional security review such as STQC or CERT-In. You +submit your test results, including how your application uses and interacts +with the exchange APIs, and on approval receive a completion certificate +**valid for a configured period**. Nobody states that period; ask. + +**Production.** Register, using Health Facility Registry authentication where +you have it and documentary verification from IRDAI or an equivalent agency +where you do not. Your sandbox certificate is reviewed. Production credentials +are issued. Then go live, with the advice to plan change management, train +staff and pilot with a small set of clients first. + +**Deboarding** happens three ways, and the second is the one to design against. + +| Kind | Initiated by | Examples | +| :---- | :---- | :---- | +| Involuntary, by a regulator | IRDAI or a legal authority | A provider suspended for fraud; a TPA or payer deactivated | +| Involuntary, by the exchange | The operator | Serious or repeated policy violation, including grave service-level breaches; attempted unauthorised access; behaviour that destabilises the exchange, such as **frequent bursts of requests beyond authorised rate limits** | +| Voluntary | The participant | Moving to another exchange, shutting down, merging | + +Involuntary removal comes with an elaborate warning mechanism and a right of +appeal through the grievance process. + +That rate-limit clause is the only acknowledgement in the corpus that rate +limits exist. No number is published anywhere. Build a client that backs off +rather than one that retries hard, and ask for your instance's limits at +onboarding. + +## What to ask for at onboarding + +Everything the published material leaves blank, in this chapter and across the +documentation, collected so it is asked once. + +- The exchange's **public key** for validating inbound JWTs, and the header the + token arrives on. +- The instance's **audit report list** and the address of the audit query API. +- The instance's **archival policy**: retention, deletion, post-archival access. +- The **grievance policy**, its version, its covered types and their service + levels, and the nodal contact you are expected to publish. +- The **rate limits** your participant code is subject to. +- The **validity period** of your sandbox certificate. +- Whether **STQC or CERT-In** review applies to you. +- The **turnaround-time windows** for preauthorisation and claim. The plan's + `ScheduledTATApproval` flag says the period "varies with policy" and the FAQ + says there is no fixed TAT as of now; no values are published. +- The **forward instruction** on coverage eligibility: its fields and its flow. + The specification gives it one sentence. +- The **`/v1/error` body schema**. The sources say to implement the endpoint + and receive the reject details, but its field names are not published. +- The **currency rule** for money fields. The claim sample carries no + `currency` on `Claim.total`, the payment notice sample carries it on the paid + amount, and no source states a rule. +- The **coverage-based insurance plan**. Only the package-based plan is + sampled, in either direction. +- **Payment notices 31 and 33**. Only the initiation is sampled, so the notice + that carries a real bank reference has never been observed. +- The **timestamp form**, format and zone. The handbook says Indian time + (`+05:30`) and that UTC fails validation, the FAQ says UTC with a trailing + `Z`, and the samples use `+05:30`. diff --git a/site/docs/nhcx/v1/reference/notifications-and-patient-apps.md b/site/docs/nhcx/v1/reference/notifications-and-patient-apps.md new file mode 100644 index 000000000..51d463a35 --- /dev/null +++ b/site/docs/nhcx/v1/reference/notifications-and-patient-apps.md @@ -0,0 +1,233 @@ +--- +title: Notifications and patient apps +sidebar_label: Notifications and patient apps +sidebar_position: 17 +description: Beneficiary service provider integration, subscription model, and push events +verification: unverified +source: nhcx-package/docs/06-Reference/07-Notifications and Patient Apps.md +generated: true +--- + +# Notifications and patient apps + +The third kind of participant. A personal health record app registers on the +exchange as a beneficiary service provider, subscribes on a beneficiary's +behalf, and receives a readable message every time something happens to that +beneficiary's claim. It sends no claims and answers no queries. It is the only +role on the network whose whole job is to be told things. + +This chapter is for anyone building such an app, and for a hospital or payer +that also runs one. + +## The model: subscribe on login, last linked wins + +When a beneficiary logs into an app with their ABHA, that app calls subscribe +and becomes the recipient of every notification for that ABHA. **Any earlier +subscription is replaced.** Only one app receives notifications for a +beneficiary at any moment. + +That rule is deliberate and it has consequences worth designing around. + +- There is no duplicate delivery to handle, and no fan-out. +- A beneficiary who opens a second app silently stops receiving notifications + in the first. Neither app is told. +- Subscription is an action to take on every login, not once at install. + +```mermaid +sequenceDiagram + box Beneficiary + participant A as Patient app + end + box Exchange + participant X as NHCX + end + box Provider side + participant H as Hospital + end + box Payer side + participant Y as Payer + end + A->>X: subscribe for this ABHA, on login + X-->>A: subscription confirmed + H->>X: preauth/submit + X->>Y: forwards + Y->>X: preauth/on_submit, approved + X->>H: callback to the hospital + X->>A: notification with a readable message +``` + +## Before you start + +- **Milestone 1.** The app must have completed ABDM Milestone 1 integration. +- **Registration as a beneficiary service provider.** Sandbox testing, sandbox + certification, then onboarding to the production registry. The role code is + 10009 and the registry ID may be the app's own client ID. +- **An HTTPS endpoint** with TLS 1.2 or newer, and the ability to generate and + validate JWTs. + +## Subscribing + +```bash +curl --location --request POST 'https://hcxsbx.abdm.gov.in/v1/notification/subscribe' \ + --header 'Content-Type: application/json' \ + --header 'Authorization: Bearer ' \ + --header 'x-hcx-sender_code: phr-app-xyz@bsp' \ + --header 'x-hcx-recipient_code: nhcx-gateway@hcx' \ + --header 'x-hcx-timestamp: ' \ + --header 'x-hcx-correlation_id: ' \ + --data-raw '{ + "payload": "eyJhbGciOiJSU0EtT0FFUCIsImVuYyI6IkEyNTZHQ00iLCJ4LWhjeC1zZW5kZXJfY29kZSI6InBoci1hcHAteHl6QGJzcCJ9.encrypted_key.iv.ciphertext.tag", + "_payload_plaintext": { + "subscription_id": "sub_ravi_001", + "topic_code": [ + "workflow_events" + ], + "recipient_code": "phr-app-xyz@bsp", + "subscriber": { + "id": "ravi@abdm" + }, + "on_notification_url": "https://api.phrapp.com/v1/hcx/notification/on_subscribe" + } + }' +``` + +[Notification subscribe in the API reference](/docs/nhcx/v1/api/other/endpoints/other-v1-notification-subscribe) + +The call is sealed like any other message on the exchange, with the app as +sender and the gateway as recipient. The subscription service's live +specification is at +`https://hcxsbx.abdm.gov.in/subscriptionhcxservice/swagger-ui/index.html`, and +Environments and Addresses lists it with the others. + +| Field | Required | What it carries | +| :---- | :---- | :---- | +| `subscription_id` | Yes | Your own unique identifier for this subscription | +| `topic_code` | Yes | An array of topics, see below | +| `recipient_code` | Yes | Your participant code | +| `subscriber.id` | Yes | The beneficiary's ABHA address, for example `ravi@abdm` | +| `on_notification_url` | Yes | Where notifications should be delivered | +| `expiry` | No | When the subscription lapses | + +```json +{ + "subscription_id": "sub_ravi_001", + "topic_code": ["workflow_events"], + "recipient_code": "phr-app-xyz@bsp", + "subscriber": { "id": "ravi@abdm" }, + "on_notification_url": "https://api.phrapp.example/v1/hcx/notification/on_subscribe" +} +``` + +### Topics + +| Topic | What arrives | +| :---- | :---- | +| `workflow_events` | Claim lifecycle: preauthorisation, claim, payment | +| `network_events` | Exchange platform updates and maintenance | +| `participant_events` | Changes to payer and provider registrations | + +Most apps need `workflow_events` alone. The field is an array, so subscribe to +more than one where you have a reason. + +The workflow codes for this exchange are N01 to a payer, N02 to a provider, N03 +to a beneficiary and N04 for the acknowledgement. + +## Receiving a notification + +The exchange posts to the `on_notification_url` you registered. + +| Field | What it carries | +| :---- | :---- | +| `notification_id` | Unique per notification | +| `topic_code` | The topic it arrived under | +| `timestamp` | ISO 8601 | +| `subscriber.id` | The beneficiary's ABHA | +| `message` | **A human-readable sentence the app can display as it stands** | +| `domain_values` | Optional map of the domain headers, for audit or richer rendering | + +```json +{ + "notification_id": "notif_20260428_001", + "topic_code": "workflow_events", + "timestamp": "2026-04-28T14:30:00+05:30", + "subscriber": { "id": "ravi@abdm" }, + "message": "Preauthorization approved for Rs. 50,000. Valid from 2026-04-28 to 2026-05-05. Reference: PA-2026-004567", + "domain_values": { + "x-hcx-correlation_id": "corr_20260428_12345", + "x-hcx-status": "response.complete", + "x-hcx-action": "preauth_response", + "x-hcx-amount_submitted": "75000.00" + } +} +``` + +**The `message` field is the point of the whole exchange.** It is written by +the exchange to be shown to a patient without parsing, and an app that ignores +it and renders its own sentence from `domain_values` is doing avoidable work +and will drift from what every other app shows. + +`domain_values` is where the named domain headers actually appear, and it is +the clearest evidence in the corpus that domain headers are a real mechanism +rather than a placeholder. Envelope Fields lists them. + +## Event types + +| Event | Status values | +| :---- | :---- | +| `preauth_request` | `queued`, `processing` | +| `preauth_response` | `approved`, `rejected` | +| `claim_request` | `queued`, `processing` | +| `claim_response` | `approved`, `rejected` | +| `payment_notice` | `paid`, `pending` | +| `communication` | `information_required` | + +Note that this vocabulary is not the workflow-code vocabulary and not the +status-word vocabulary. It is a third, simpler set, designed for display. + +## Errors + +| Code | Meaning | What to do | +| :---- | :---- | :---- | +| `401` | Token expired | Regenerate and retry | +| `403` | Not authorised | Check your registry entry and role | +| `409` | Subscription already exists | Should not occur under last-linked-wins | +| `500` | Gateway problem | Retry with backoff | + +## What the payer and provider do + +Nothing extra. The exchange generates notifications from the traffic that +already flows. A payer's ordinary responses feed them, and the payer's own +notifications carry workflow N01. + +For a hospital that also runs a patient app, the two are separate participants +with separate codes and separate certificates, even inside one organisation. + +## Security and privacy + +Four requirements from the integration document, none of them optional in +production. + +- Store the access token encrypted, refresh before expiry, and never log the + participant secret. +- Enforce HTTPS with TLS 1.2 or newer on the callback. +- Validate the JWT the exchange signs its call with, and check that + `sender_code` is the exchange. The public key problem described in Governance + and Audit applies here too. +- **Obtain explicit consent from the beneficiary before subscribing**, and show + the subscription state somewhere the beneficiary can find and change it. + +That last one is the substantive difference between this role and the others. +A hospital's participation is contracted; a patient app's is consented to, one +beneficiary at a time. + +## What this chapter cannot tell you + +The integration document is written against an older reading of the protocol +than the rest of the corpus. It gives `alg` as `RSA-OAEP` rather than +`RSA-OAEP-256`, and a token life of +6,000 seconds where other sources say 300 or 1,200. Follow the current +protocol as Envelope Fields and Session Token give it, and treat the document's +payload shapes as the part that is specific to notifications. + +No sample notification bundle exists in the corpus, and no participant is +recorded as having exercised this exchange. diff --git a/site/docs/nhcx/v1/reference/troubleshooting.md b/site/docs/nhcx/v1/reference/troubleshooting.md new file mode 100644 index 000000000..916c1bdb2 --- /dev/null +++ b/site/docs/nhcx/v1/reference/troubleshooting.md @@ -0,0 +1,151 @@ +--- +title: Troubleshooting +sidebar_label: Troubleshooting +sidebar_position: 12 +description: Five-layer fault isolation model and symptom-first diagnostic playbook +verification: unverified +source: nhcx-package/docs/06-Reference/02-Troubleshooting.md +generated: true +--- + +# Troubleshooting + +A symptom-first chapter. Everything else in this documentation is organised by +what you are building; this one is organised by what has gone wrong, because +that is the only thing you know at the moment you need it. + +## Isolate the layer first + +A message crosses five layers on its way to a decision, and each one refuses in +a different way. Work out which layer stopped it before you look anything up, +because the same symptom means different things at different layers. + +| Layer | What refuses | How you hear | Code family | +| :---- | :---- | :---- | :---- | +| 1. Transport | Your HTTP call to the gateway | Synchronously, in the response to your own call | HTTP `4xx`, `5xx` | +| 2. Gateway | The exchange, reading the envelope | Synchronously, or later on `/v1/error` | `NHCX-1xxx` | +| 3. Encryption | The recipient, opening the letter | On your callback, as a protocol response | `PAYR-1001`, `PAYR-1002`, `PAYR-1097` | +| 4. Bundle | The recipient, validating FHIR | On your callback, inside the sealed response | `PAYR-10xx` | +| 5. Adjudication | The payer's rules | On your callback, inside the sealed response | `PAYR-11xx` to `PAYR-14xx` | + +The layers are strictly ordered. Reaching a layer means every layer before it +passed, which is why a scheme-rule refusal is good news about your bundle. + +## The symptom table + +| What you see | Layer | Most likely cause | What to do | +| :---- | :---- | :---- | :---- | +| `401` on the sessions call | 1 | Wrong client ID or secret, or Milestone 1 incomplete | Check the credentials against onboarding | +| `401` naming a header on the sessions call | 1 | `REQUEST-ID` reused or absent, `TIMESTAMP` stale or malformed, `X-CM-ID` missing | Generate a fresh UUID per call; take the time from the system clock | +| `401 Sender is not authorized to execute the operation` | 1 | Token expired | Fetch a new token and retry once. Never retry with the same token | +| `401` immediately after a fresh token | 1 | `Bearer ` prefix missing, or the token sent on the wrong header name | Send `bearer_auth: Bearer `, and `Authorization` alongside it | +| `401` on policy link or de-link only | 1 | The client ID calling is not the one that created the participant | Run the linking job under the credentials that created the record | +| `400` on a use-case call | 2 | Envelope failed validation | Check every `x-hcx-` field against Envelope Fields | +| `NHCX-1005` invalid request header | 2 | A header missing, malformed or of the wrong type | As above | +| `NHCX-1006` duplicate request | 2 | A correlation ID reused, usually on a retry after a failure | Mint a fresh correlation ID. A failed correlation is retired | +| `NHCX-1011` invalid status | 2 | The status word does not match the leg of the message | Requests send `request.initiated`; responses send `response.partial`, `complete` or `error` | +| `NHCX-1018` invalid ABHA number | 2 | ABHA sent in the wrong shape | The gateway wants `XX-XXXX-XXXX-XXXX` on this field, though the bundle carries it without hyphens | +| `NHCX-1010` no data with given correlation id | 2 | You answered a request whose correlation the exchange had already retired | Acknowledge every submission immediately, then send the decision on the same thread | +| `NHCX-1002` or `NHCX-1003` not registered | 2 | Sender or recipient is not active on the exchange | Check the participant record's status. Only `Active` can send or receive | +| Nothing at all arrives on your callback | 2 | Address, firewall, routing, or no receipt sent | See the callback checklist below | +| `PAYR-1001` decryption failed | 3 | You encrypted with a certificate that is not the one on the recipient's record | Re-fetch the recipient's certificate and resend. Clear your cache | +| `PAYR-1002` encryption failed | 3 | The payer cannot encrypt for you: your registered certificate is stale or absent | Update your `encryption_cert` on your participant record | +| `PAYR-1097` no payload | 3 | The ciphertext part of the JWE is empty | Check you are serialising all five parts, compact | +| `PAYR-1005` time limit exceeded | 3 | `x-hcx-timestamp` is more than 24 hours behind the current time | Send the current time. This is the only numeric tolerance the sources state | +| `PAYR-1004` or `PAYR-1008` malformed or invalid bundle | 4 | The bundle does not parse or fails profile validation | Run it through the NRCeS validator before anything else | +| `PAYR-1009` to `PAYR-1016` no identifier or type found | 4 | A resource is missing its `identifier`, or an identifier is missing its `type` | Every resource that names a party needs both | +| `PAYR-1019` invalid sequence in supporting info | 4 | A `supportingInfo` entry has no `sequence` | Number the whole list once it is assembled, from 1, with no gaps | +| `PAYR-1027` invalid item id | 4 | `Claim.item` has no FHIR element `id`. Nothing to do with the package code | Give each item `Item/n`, each procedure `Procedure/n`, each supporting-info entry `SupportingInformation/n` | +| `PAYR-1028`, `PAYR-1029` | 4 | The same fault on the item sequence and the bundle id | As above | +| `PAYR-1083` no HPR details | 4 | The `Practitioner` carries no identifier typed `HPIN` | Send the HPR id as `HPIN` as well as `HPID` | +| `PAYR-1093`, `PAYR-1094` composition faults | 4 | An embedded clinical document does not follow the NRCeS profile | Check the `Encounter` structure definition | +| `PAYR-1095` invalid discharge information | 4 | A claim with no discharge status | Send category `DIS` with a code among `DTH`, `DTM`, `LAMA`, `DAMA` | +| `PAYR-1096` invalid death date | 4 | Discharge type is death and no death date was sent | Send category `ONS`, code `DTM` | +| `PAYR-1008` invalid content type | 4 | A document outside PDF, JPG, JPEG, PNG and FHIR JSON | Convert it. `text/plain` is refused | +| `PAYR-1114`, `PAYR-1202` invalid speciality code | 5 | `item.category` is not the master's category code for that package | Read the specialty off the plan, not off your own list | +| `PAYR-1238` active preauthorisation exists | 5 | The scheme allows one live preauthorisation per beneficiary per hospital | Cancel the existing one, or raise its claim. The reference number names it | +| `PAYR-1245` one conservative procedure | 5 | A second package typed `Conservative` on one case | An enhancement must add a `Medical` package or an allowed add-on | +| `PAYR-1256`, `PAYR-1363` consent questionnaire missing | 5 | No biometric token and no authentication-consent response | Answer the plan's questionnaire, found by title in the master | +| `PAYR-1301` claim already raised | 5 | One case, one claim | Nothing to resubmit. Use a Task | +| `PAYR-1302` no approved preauthorisation | 5 | The claim went out under a number of its own | Send the claim under the pre-authorisation's number | +| `PAYR-1321` | 5 | A claim query answered under the wrong workflow id | Answer on 161, not 151, 19 or 16 | +| `PAYR-1322` active instance found | 5 | Another request is already open on that case | The scheme takes one at a time. Wait | +| `PAYR-1401` policy not allowed for the hospital | 5 | The plan was asked for under a policy the hospital is not empanelled under | Ask under the beneficiary's own policy from the eligibility answer | +| `PAYR-1406` existing request in progress | 5 | A second plan request before the first was answered | Wait 15 to 60 minutes. Past 60, raise it with support | +| `ERR-PYR-CLM-007` no prior record for case number | 5 | As `PAYR-1302` | As above | + +## When nothing arrives on your callback + +The commonest report, and it is almost always one of six things. The portal +lists the first five; the sixth is the one people miss. + +1. **The address.** A domain name, not an IP address and not a port number. +2. **The location.** The server must be hosted in India. +3. **The firewall.** Allow the exchange's outbound addresses: `3.109.99.210`, + `13.126.152.0`, `13.200.129.223`. +4. **The rules.** Check nothing else is dropping the inbound connection. +5. **Application routing.** The request reaches the server and is dispatched to + the wrong handler by a mismatched route, a load balancer rule or a version + prefix. +6. **The receipt.** You answered, but not with `202` and the receipt body + within 30 seconds. A slow `200` is read as a failed delivery. After five + attempts the exchange gives up and retires the correlation ID, and tells you + on `/v1/error`, which you must also be hosting. + +Test the whole path rather than the parts. Call your own registered public +address from outside your network and confirm that what answers is the service +you think it is. + +## When a case has gone quiet + +In order, and stop at the first that explains it. + +1. **Did you get a receipt?** No receipt means the exchange never took the + message. It is not a payer problem. +2. **Did anything arrive on `/v1/error`?** That is where an undeliverable + request is reported. A system without the endpoint never learns. +3. **Ask the exchange.** The status exchange reports where a message got to. + Status and Search in Getting Started has the shape. +4. **Under PMJAY, ask the payer service.** A case sits at + `request.initiated` until someone acts on it in the scheme's own system. The + role lookup says where it is. PMJAY Adjudication APIs has it. +5. **Only then treat it as slow.** The scheme decides on its own schedule. An + enhancement approved in a minute on one run was still queued five minutes on + in another, with the same bundle. + +## Things that look like faults and are not + +- **A queued acknowledgement.** Both live payers answer twice on one + correlation: an interim response saying the request is with an adjudicator, + then the decision. Treat the first as an acknowledgement, not as the answer. +- **`outcome: complete` on a rejection.** `complete` means the payer finished + processing. The adjudication reason is what separates approval from + rejection. +- **A reduced amount without `partial`.** The reference payer approves at a + lower figure and still sends `complete` with no note. Reconcile amounts + yourself. +- **Zero benefit on a query.** It means no benefit has been determined yet, not + that the claim was refused. +- **A base rate of zero in the plan.** Some packages are priced entirely by the + bed category chosen. +- **`PAYR-1238` on a preauthorisation.** It arrives only after the bundle has + passed validation, so it is the first evidence the bundle is right. +- **A `SUBSETTED` meta tag.** Every payer-generated bundle carries it. It marks + a projection of the payer's record, not an error. + +## Before you raise it with support + +Have these to hand. Every one of them is something the exchange or the payer +will ask for, and a report without them cannot be traced. + +- The correlation ID, and the API call ID of the specific message. +- The timestamp, and which environment. +- Your participant code and the recipient's. +- The workflow code and the status word you sent. +- The raw sealed message as sent, and the raw response as received. Store both + before you interpret either; this is the only reason that instruction is + repeated throughout this documentation. +- The error code and the payer's message verbatim, not your rendering of it. + +Integration questions go to `hcx.integration@nha.gov.in`. FHIR profile and +validation questions go to `nrc-help@cdac.in`. diff --git a/site/docs/nhcx/v1/registries/README.md b/site/docs/nhcx/v1/registries/README.md deleted file mode 100644 index 1ee3f5972..000000000 --- a/site/docs/nhcx/v1/registries/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Registries - -One page per registry this gateway reads or writes (ABHA, HPR, HFR, ...). -A registry with sub-registries gets a folder with an `index.md` and one page -per child. - diff --git a/site/docs/nhcx/v1/registries/_category_.json b/site/docs/nhcx/v1/registries/_category_.json index 8600eabf1..84a171ee0 100644 --- a/site/docs/nhcx/v1/registries/_category_.json +++ b/site/docs/nhcx/v1/registries/_category_.json @@ -1,5 +1,4 @@ { "label": "Registries", - "position": 3, - "className": "sidebar-icon sidebar-icon--database" + "position": 4 } diff --git a/site/docs/nhcx/v1/registries/index.md b/site/docs/nhcx/v1/registries/index.md index f66a24e6e..a6648ff98 100644 --- a/site/docs/nhcx/v1/registries/index.md +++ b/site/docs/nhcx/v1/registries/index.md @@ -1,45 +1,151 @@ --- -title: Registries -sidebar_label: Participants and identifiers -description: The participant registry NHCX runs, and how ABDM's three identifiers appear on this gateway. -verification: unverified -source: NHCX__NHCX-Website_DocumentDetails.md +title: Participants and policies +sidebar_label: Participants and policies sidebar_position: 3 +description: Registry records, identifiers, policy lookups +verification: unverified +source: nhcx-package/docs/01-Overview/03-Participants and Policies.md +generated: true --- -# Registries +# Participants and policies + +Nothing in the previous chapter can happen until two questions are answered: who am I sending this to, and which policy is it about. Neither is a claim exchange. Both are preconditions, and a system that skips them fails later with errors that look like claim problems but are not. + +This chapter covers how a participant joins the network, how it makes itself reachable, how participants find and address each other, and how a policy is located and linked to a beneficiary. + +## Becoming a participant + +Every entity on the exchange is a registered participant with three identifiers that do different jobs. + +- **Participant ID.** The address on the exchange, written as `1518@hcx`. The part after the `@` names the exchange. This is what goes on the envelope as sender and recipient. +- **Client ID and secret.** The login used to get an access token. These are the same credentials a hospital already holds from its ABDM Milestone 1 integration. There is no separate NHCX login. +- **Registry ID.** Proof of who you are, issued by a registry the exchange trusts. For a hospital it is the Health Facility Registry (HFR) ID. For an insurer or TPA it is the IRDAI registry ID, sent without leading zeros, so 0123 becomes 123. For a patient app it is the app's own client ID. + +When a participant is created, its role and its registry are given as numbered codes. + +| Role | Code | | Registry | Code | +| :---- | :---- | :---- | :---- | :---- | +| Provider | 10001 | | HFR | 10001 | +| Payer | 10002 | | NIN | 10002 | +| TPA | 10003 | | ROHINI | 10003 | +| Regulator | 10004 | | Payer registry | 10004 | +| Research | 10005 | | | | +| Insurance marketplace | 10006 | | | | +| Scheme sponsor | 10007 | | | | +| Another exchange | 10008 | | | | +| Patient app | 10009 | | | | + +A hospital group with several facilities holds one participant ID per HFR ID, all created with the same credentials. + +Each role comes with a fixed list of what it may send and receive, and the exchange checks every call against it. Access Control and Roles in the Reference section has that list. + +**The registry ID must match at both layers.** The HFR ID sent inside a FHIR bundle has to be the same as the registry ID recorded against that sender on the exchange. A mismatch is rejected by the gateway, and it is a common failure for integrators who take the registry entry and the bundle content from different places. + +## Registering + +Registration is a short sequence of calls to the participant service. Each is confirmed by a one-time passcode sent to the mobile number the registry holds, so nobody can register a hospital they do not control. + +1. **Create.** Send the registry type, registry ID, role, mobile number and email. The mobile number must be the one on the HFR record, or for a payer the one NHA holds. The exchange returns a participant ID and a transaction number, and sends a passcode to that phone. The participant now exists but is pending. +2. **Confirm.** Send the transaction number and passcode. The participant becomes active. +3. **Configure.** Send the participant's public certificate and the address the exchange should call back on, which the portal calls the bridge URL. A second passcode arrives. +4. **Confirm again.** The address and certificate go live. The exchange can now reach you. + +A participant record also carries a status the exchange maintains: created but not yet verified, active, inactive, or blocked. Only an active participant can send or receive. + +Passcodes and transaction numbers last 24 hours. Lose one and you repeat that step. A certificate can be replaced later without a passcode, through a dedicated certificate-update call. The sandbox offers a simpler create, update and delete without the passcode steps. + +## Your own key + +How Claims Move on NHCX said the letter is sealed with the receiver's key. That means every participant needs a key of its own and has to publish the public half. + +Make a 2048-bit RSA key, sign your own X.509 certificate with it (the portal gives the three openssl commands), encode the certificate in base64, and register it in the configure step above. The private half stays with you; it is what opens every letter addressed to you. NHA recommends replacing the key once a year and expects a participant to report a key that may have leaked. + +## Where the exchange calls you + +The callback address registered during configuration is where every answer arrives, so it comes with rules. + +- A domain name, not an IP address or a port number. +- HTTPS, with TLS 1.2 or newer. +- Hosted in India. +- Reachable from the exchange's outbound addresses, which must be allowed through your firewall: `3.109.99.210`, `13.126.152.0` and `13.200.129.223`. +- Answering within 30 seconds with an acceptance receipt, otherwise the exchange assumes delivery failed and tries again. + +The portal lists one further cause that is not about the address at all: application routing. The request reaches the server but is dispatched to the wrong handler by a mismatched route, a load balancer rule or an endpoint version. + +## Finding a participant + +A Provider does not hard-code the payers it deals with. It asks the registry. + +The participant list call takes a role, so a Provider asks for everyone registered as a Payer, and can narrow by date range and by whether the entity is government or private. The calling system then filters by name if the user is looking for a specific insurer. + +What matters downstream is the chosen payer's participant code, because it is one half of the address on every subsequent envelope. The other half, which is not always the same code, comes from the policy lookup below. + +## Authenticating + +Every call carries a bearer token. The token comes from the ABDM gateway's sessions endpoint, not from NHCX itself, using the Milestone 1 client ID and secret. + +Tokens are short-lived. The portal's documents disagree on exactly how short, with five minutes, twenty minutes and a hundred minutes all appearing. Build for the strictest: refresh automatically, and treat a `401` as "get a new token and retry" rather than as a failure. + +Sandbox addresses: + +- Sessions: `https://dev.abdm.gov.in/api/hiecm/gateway/v3/sessions` +- Participant service: `https://apisbx.abdm.gov.in/pmjay/sbxhcx/participanthcxservice` +- Use cases: `https://apisbx.abdm.gov.in/hcx/v1` + +The production participant service is at `https://apisprod.nha.gov.in/pmjay/hcx/participanthcxservice`. The production use-case address is `https://apisprod.nha.gov.in/hcx`. + +## Certificates and encryption + +Before sending anything to a participant, the sender needs that participant's public key. + +The certificate fetch takes a participant ID and returns its key material, as a PEM-encoded X.509 certificate or, for shorter keys, an SPKI public key. Try the X.509 import first and fall back to SPKI. + +**Cache certificates.** Fetching a payer's key before every request is a round trip that buys nothing, since keys change rarely. A 24-hour cache is the practical default. + +## Finding a policy + +Once the payer is known, the beneficiary has to be matched to a policy with that payer. The lookup accepts three identifiers, and a system that does not know which will work should try them in order of reliability. + +- **ABHA number.** The strongest, and the one to try first. +- **Member ID.** The policy or member number captured at admission. +- **Mobile number.** The weakest, since a number may be shared or out of date. + +What comes back, for each policy, is the insurer, who processes claims for it, the member ID, and the product. Two of those are participant codes and they are not always the same. + +**Send claims to the processor, not the insurer.** An insurer may handle its own claims, in which case its `payerid` and `processingid` are the same code. Or it may use a TPA, in which case `processingid` is the TPA's participant code and that is where every request must go. The policy lookup tells you which. Put `processingid` on the envelope as the recipient. Pointing at `payerid` instead is the portal's seventh most common mistake, and the request goes nowhere useful. + +A lookup that succeeds is worth keeping. The policy set for a patient does not change between one department and the next, so cache against the patient and provide a way to force a refresh. If the lookup returns no processor code, stop; no claim-side call can be addressed. + +## Linking a policy to ABHA + +The reason an ABHA number works as a policy identifier at all is that someone linked it earlier. -NHCX has a registry of its own, and it is not a registry of people. After this page you will know -what is registered on this gateway and what is not. +Linking is a Payer-side action, performed when the policy is created. The insurer links the beneficiary's ABHA number, mobile and member ID to the policy's products, naming itself as the payer and its TPA, or itself, as the processor. Only the party named as payer or processor can de-link it later; the exchange checks the caller's credentials against the link. If an insurer changes TPA, every affected policy is de-linked and re-linked with the new processor. -## The participant registry +The effect is felt at the point of care. A beneficiary who walks in with only an ABHA number can be resolved to a policy without a card or a member ID, which is the whole point of linking it in the first place. -Every provider and every payer onboards as a participant, in sandbox first and then in -production. The participant is the entry: an organisation with a role, not a doctor and not a -patient. +## From sandbox to production -The production onboarding document, row 5 of [the index](/docs/nhcx/v1), is where the role and -registry enums live, along with the validations applied to them. Row 16 is the Postman collection -for the participant service APIs. The enum values live there and are not reproduced here. +Joining the network is a certification, not a form. The path for a hospital runs: -The participant service is also what a claim is routed by: NHCX sits in the middle and moves -messages between registered participants. +1. **Register the facility** in the Health Facility Registry. +2. **Apply on the ABDM sandbox**, choosing Providers and Payers with Milestone 1 as the intent. This yields the client ID and secret. +3. **Complete Milestone 1**, which is ABHA creation and verification, then functional testing, the WASA security audit and the HTC demo. NHCX requires M1 to be in place first. +4. **Register on the NHCX sandbox** with the same credentials and create a participant for each facility. +5. **Integrate and test** against the sandbox, using the dummy payer described in NHCX Use Cases. +6. **Get certified.** Email sample FHIR bundles to `hcx.integration@nha.gov.in` for NRCeS validation, give an internal demo to the NHA team, then the HTC demo before NRCeS, IRDAI, TCS and NHA. +7. **Go to production.** NHA confirms, adds the provider role to the production client ID, and the participant is created there through the registration steps above. +8. **Pilot, train, go live.** NHA recommends a small pilot and staff training before switching fully. -## ABDM's three registries +Payers follow the same shape but enrol through the NHA or IRDAI portal, which registers them after scrutiny and asks the ABDM gateway team to issue credentials with the payer or TPA role. -[ABHA](/docs/nhcx/v1/getting-started/glossary#abha) identifies a patient, the HPR a practitioner, the HFR a -facility. All three are ABDM wide, and a hospital that is on both gateways will already hold the -last two from its [HIE-CM](/docs/nhcx/v1/getting-started/glossary#hie-cm) onboarding. +A participant can also leave. Voluntarily, when a business shuts, merges or moves exchange. Involuntarily, when a regulator suspends it, when it repeatedly breaches service levels, or when it misuses the network. Involuntary removal comes with warnings and a right of appeal through the grievance process. -How each appears inside a claim is not yet published. No row describes a -field, and the two gateways share no API surface, so a mapping copied from HIE-CM would be a -guess. The value sets a bundle must use are row 11. +## Why this comes first -If you need the identifiers themselves, they are written on HIE-CM: -[registries](/docs/hiecm/v3/registries) has all three, and -[M4](/docs/hiecm/v3/api/m4) is the milestone that creates the provider side. +A patient is not cashless simply because they hold insurance. Two things have to be true: the admission record must carry the scheme, payer, identifier and policy number, and the system must have resolved a valid processor code, product code and member ID. A patient can look correctly admitted as insured on screen while every NHCX call still fails, because the second condition was never met. -## Next +The order is fixed. Discover the payer, then discover the policy. Take the processor code, member ID and product from what came back, fetch the plan and its benefits, check eligibility, and only then submit a preauthorisation. -- [Core concepts](/docs/nhcx/v1/concepts), what a claim is made of -- [NHCX](/docs/nhcx/v1), the full document index +JWE, Status and Errors opens the envelope every one of those calls travels in. NHCX Use Cases lists the calls themselves. diff --git a/site/docs/nhcx/v1/roles/_category_.json b/site/docs/nhcx/v1/roles/_category_.json new file mode 100644 index 000000000..5182cc2ff --- /dev/null +++ b/site/docs/nhcx/v1/roles/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Choose your path", + "position": 3 +} diff --git a/site/docs/nhcx/v1/roles/payer/_category_.json b/site/docs/nhcx/v1/roles/payer/_category_.json new file mode 100644 index 000000000..40d616491 --- /dev/null +++ b/site/docs/nhcx/v1/roles/payer/_category_.json @@ -0,0 +1,9 @@ +{ + "label": "Building a payer", + "position": 2, + "customProps": { + "roles": [ + "payer" + ] + } +} diff --git a/site/docs/nhcx/v1/roles/payer/adjudicating-claims.md b/site/docs/nhcx/v1/roles/payer/adjudicating-claims.md new file mode 100644 index 000000000..913c93ecf --- /dev/null +++ b/site/docs/nhcx/v1/roles/payer/adjudicating-claims.md @@ -0,0 +1,82 @@ +--- +title: Adjudicating claims +sidebar_label: Adjudicating claims +sidebar_position: 5 +description: Adjudicating claims, deductions, dispute handling, and rejection bundles +verification: unverified +source: nhcx-package/docs/04-Building a Payer/05-Adjudicating Claims.md +generated: true +sidebar_custom_props: + roles: + - payer +--- + +# Adjudicating claims + +The claim is where money is decided. The payer receives the finalised bill and the full document set, and checks them against the approved preauthorisation and the discharge evidence. It then issues a decision that, once final, cannot be reopened except through the appeal Task. + +## What the adjudicator sees + +The claim queue, opened against the approved preauthorisation, side by side: what was approved, what is now claimed, and the difference highlighted. The discharge type and stage, the dates, the discharge summary as a record, the bill, the post-operative evidence. The four evaluation dimensions the handbook names, as a checklist: within cover and limits, clinically appropriate, documents complete and consistent, amounts within package rates and financial rules. + +Actions: approve, approve at a reduced amount with a note per item, query, reject with a denial code. And two interim states that are not decisions: in process, and forwarded to another entity. + +## What the system hosts + +``` +/v1/claim/submit answer on /v1/claim/on_submit +``` + +Workflow 15 is the claim; 151 is an answer to your query. Under PMJAY there is no separate discharge submission; the claim asserts the discharge and carries its details. On the general network a provisional discharge submission (14) may arrive first, answered with 261, 262 or 263. + +Acknowledge receipt with 25 and `response.partial`. A claim may receive several interim answers before the final one; each is `response.partial` on the same correlation ID, and only the final carries `response.complete`. + +## Validate before queueing + +- An approved preauthorisation exists for the case number; no claim already raised against it. +- Every item, implant and investigation on the claim was on the preauthorisation, was not rejected there, and is not claimed at a higher quantity. +- Registration, admission, surgery and discharge dates present and well-formed; a discharge stage present, from the allowed set. +- Amount within the preauthorisation's approved amount and the wallet. +- Under PMJAY, the discharge biometric token. For a LAMA or DAMA before surgery, only `LM100`, with a quantity equal to the stay. For a death, a death date. For a newborn, the parent's card and the child's documents. + +## What goes in the answer + +The same `ClaimResponse` as for preauthorisation with `use = claim`. + +| Decision | `outcome` | `adjudication.reason` | Workflow | +| :---- | :---- | :---- | :---- | +| Approved | `complete` | `approved` | 26 | +| Approved, reduced | `partial` | `approved` | 26, with `processNote` | +| Queried | `partial` | `queried` | 27 | +| In process | `partial` | | 28 | +| Forwarded | `partial` | | 29 | +| Rejected | `complete` | `cancelled` | 291 | + +A rejection closes the claim number. Nothing further arrives against it except a Task. Use the scheme's denial codes so the provider's appeal screen can show a reason. Less than 24 hours of hospitalisation, package reserved for public hospitals, incomplete documents after multiple queries, bed category misrepresented. Then outside scope of cover, fraudulent, package does not match diagnosis, hospital not empanelled for the specialty, and the rest of the `ClaimError` list. + +Each final approval carries the totals accounts will pay from: submitted, eligible, benefit, tax deducted, incentive, patient-liable. Those figures reappear on the payment notice; keep them consistent. + +## The arithmetic on every final approval + +Accounts pays from these figures and the provider reconciles against them, so they have to agree with the payment notice that follows. + +| Category | What it is | +| :---- | :---- | +| `submitted` | What the hospital asked for, per item and in total | +| `eligible` | What is within cover before deductions | +| `copay` | The patient's share. Zero under PMJAY, which is fully cashless | +| `benefit` | What you will pay. This is the number the provider shows as approved | + +Then at claim level, the tax deducted, any incentive, and the patient-liable amount where the scheme has them. The payment notice's `TDS` and `Payment` lines should sum to the approved amount here; a provider that finds they do not will raise a query or a shortfall. + +## Appeals + +Rejections and shortfalls come back as a `Task` on `/v1/task/submit`, workflow 36, code `reprocess`, reason `claimrejected` or `partialpayment`, with a document attached and, for a shortfall, the amount. Route both to the Claim Review Committee. + +Acknowledge with 37, then answer on `/v1/task/on_submit` with a `Task` whose `status` is `completed` and whose output references a `ClaimResponse` inside the same bundle. The `ClaimResponse` is read by the provider's ordinary parser, so build it with the same outcome and reason fields: 252 approved, 253 rejected, 254 queried. + +Under PMJAY the payer enforces four rules. One appeal per claim. A shortfall claim only after payment 33 has been sent and acknowledged. The amount never above the difference. The Committee's decision final, with no shortfall claim allowed after it. A cancellation Task, code `cancel`, is answered with PC02 and refused once payment has begun. + +## Search + +Regulators, and the scheme sponsor, can search claims across payers with a `Task` of code `search` on `/v1/search/submit`. Answer on `/v1/search/on_submit` with the matching `ClaimResponse`s. A provider may only search its own cases; a regulator may search any. diff --git a/site/docs/nhcx/v1/roles/payer/adjudicating-preauthorisation.md b/site/docs/nhcx/v1/roles/payer/adjudicating-preauthorisation.md new file mode 100644 index 000000000..074d5ba96 --- /dev/null +++ b/site/docs/nhcx/v1/roles/payer/adjudicating-preauthorisation.md @@ -0,0 +1,96 @@ +--- +title: Adjudicating preauthorisation +sidebar_label: Adjudicating preauthorisation +sidebar_position: 4 +description: Evaluating medical necessity, raising queries, approval, and rejection +verification: unverified +source: nhcx-package/docs/04-Building a Payer/04-Adjudicating Preauthorisation.md +generated: true +sidebar_custom_props: + roles: + - payer +--- + +# Adjudicating preauthorisation + +The preauthorisation queue is where a payer's clinical judgement meets the exchange. The system's job is to get a case in front of the right doctor with everything they need, and to turn their decision into a `ClaimResponse`. It also enforces the sequencing rules that keep one case from becoming several. + +## What the adjudicator sees + +A queue, ordered by turnaround-time remaining, because a scheme with TAT-based auto-approval pays for every case the doctor does not reach in time. Opening a case shows: + +- The beneficiary, the policy, the wallet balance now and after this request. +- Diagnosis, packages with rates and add-ons, care team, dates. +- Every document, structured ones rendered as records rather than opened as files, and the STG questionnaire answers beside the package they belong to. +- The plan's flags for each package: auto-approvable, enhanceable, reserved, standalone. +- History on the case: earlier preauthorisations, enhancements, queries and answers. + +Four actions: approve, approve at a reduced amount with a note, query, reject with a reason from the scheme's denial list. Item by item, then a total. + +## What the system hosts + +``` +/v1/preauth/submit answer on /v1/preauth/on_submit +``` + +The workflow code says which kind of request it is: 12 new, 121 resubmission, 13 enhancement, 19 an answer to your query. Acknowledge receipt at once with code 20 and `response.partial`, so the provider knows it is in the queue. + +## Validate before queueing + +The reference payer's preauthorisation errors are the checklist. Run them on arrival and refuse with a protocol response rather than wasting a doctor's time: + +- Amount above zero and within the wallet balance. +- Specialty code and display, package code and display, exactly as the plan has them; quantity at least one; net above zero. +- Registration and admission dates present and well-formed. +- Sequencing. No case already in progress for this number. An enhancement or resubmission only where an approved record exists. A new preauthorisation refused where an approved one exists. No preauthorisation once a claim is raised, and nothing at all on a cancelled case. +- One active preauthorisation per beneficiary across all hospitals; tell the provider which hospital holds it. +- Every STG questionnaire the plan demands answered; a biometric token or the consent questionnaire present. +- Under PMJAY, `LM100` never on a preauthorisation; investigations mandatory for private hospitals; newborn cases with date of birth, gender and documents, and within six years. + +## Deciding automatically + +Two rules let a case skip the queue, and both come from the plan: + +- **Auto-approve** when this is the first preauthorisation for the case and every package carries `ApprovalNotRequired`. +- **TAT approve** when the policy allows it and no doctor has acted within the configured window. + +Log which rule fired. The provider sees an approval; the audit sees why. + +## What goes in the answer + +A collection bundle with the `ClaimResponse`, the `Patient`, the `Coverage` and the `Organization`s. `use = preauthorization`. The provider reads `outcome` and the adjudication reason together, so set both deliberately. + +| Decision | `outcome` | `adjudication.reason` | Workflow | Also set | +| :---- | :---- | :---- | :---- | :---- | +| Approved | `complete` | `approved` | 21 | `preAuthRef`, every item's four amounts equal | +| Approved, reduced | `partial` | `approved` | 21 | `processNote` explaining the reduction, linked from the item by `noteNumber` | +| Queried | `partial` | `queried` | 24 | Query text; totals zero; `eligpercent` zero | +| Rejected | `complete` | `cancelled` | 23 | `disposition` and the denial code | +| Enhancement approved or denied | as above | | 22 or 231 | | + +Per item, four adjudication lines: `submitted`, `eligible`, `copay` (zero under PMJAY), `benefit`. Totals at the claim level with the same categories, plus tax, incentive and patient-liable amounts where the scheme has them. + +The `preAuthRef` you issue is what the provider will quote on the claim. Make it unique and durable. + +## What the provider reads from your answer + +Three fields on the response decide what the hospital's screen shows, and getting them wrong misstates the decision rather than failing loudly. + +| What you set | What the provider does with it | +| :---- | :---- | +| `outcome` plus the adjudication reason | Reads them as a pair. `complete` alone means approved or rejected, so the reason is the difference | +| The `benefit` adjudication, per item and at claim level | Shows it as the approved amount. The `submitted` category alongside is what was asked for, and showing that as the decision is the classic provider-side error | +| `processNote`, linked from the item by `noteNumber` | Shows it verbatim as the reduction reason | +| `preAuthRef` | Quotes it on the claim. Make it unique and durable | + +Note what the published PMJAY responses do **not** carry: no `ClaimResponse.request` pointing back at the `Claim`, no `ClaimResponse.type`, and no `preAuthRef` at all. The case number in `identifier[0].value` is what actually travels forward. If your system issues a real `preAuthRef`, you are ahead of the samples, and you should say so to integrators rather than assume they read it. + +## Writing a query + +Under PMJAY the query travels in `item.adjudication.reason.coding.display` as a pipe-delimited audit trail, `USER~datetime~type~comment~trust`, with multiple entries separated by `|`. The provider shows the comment. Keep it specific: name the document or the clarification, and the package it concerns. A vague query costs a full round trip and a day of TAT. + +Under PMJAY the provider answers on the same endpoint with code 19. On the general network a payer may instead raise a Communication with reason `additionalinfo`; the provider answers on the communication endpoint. Do not use both for the same question. + +## Approval letters + +The value set includes form codes for letters: `preauthapproval`, `preauthdenial`, and later `claimapproval`, `claimdenial`, `dischargeapproval`. Where the scheme issues them, attach the letter as a `DocumentReference` referenced from the response. diff --git a/site/docs/nhcx/v1/roles/payer/eligibility-response.md b/site/docs/nhcx/v1/roles/payer/eligibility-response.md new file mode 100644 index 000000000..48aa54e90 --- /dev/null +++ b/site/docs/nhcx/v1/roles/payer/eligibility-response.md @@ -0,0 +1,88 @@ +--- +title: Eligibility response +sidebar_label: Eligibility response +sidebar_position: 3 +description: Constructing coverage eligibility answers across all 4 purposes +verification: unverified +source: nhcx-package/docs/04-Building a Payer/03-Eligibility Response.md +generated: true +sidebar_custom_props: + roles: + - payer +--- + +# Eligibility response + +The eligibility check is the one exchange a payer should answer without a human. It is asked at every registration and before every submission, and a provider that waits on it is a front desk that waits. + +## What the system hosts + +``` +/v1/coverageeligibility/check answer on /v1/coverageeligibility/on_check +``` + +Read `CoverageEligibilityRequest.purpose` and answer accordingly. Four purposes, four answers. + +| Purpose | The question | What to return | +| :---- | :---- | :---- | +| `validation` | Is this coverage in force, and what is left? | `inforce`, and one benefit entry per wallet with allowed (balance) and used money | +| `discovery` | What coverages does this beneficiary have with you? | Every active coverage, so the provider can pick a policy code | +| `benefits` | For these packages, what is covered? | Per item: excluded or not, benefit type, allowed money, including stratification amounts | +| `auth-requirements` | For these packages, is preauthorisation required and what must come with it? | Per item: `authorizationRequired`, and `authorizationSupporting` listing every mandatory document and questionnaire by code | + +Auth-requirements is the one that saves the most rework downstream. The `MAND` codes it returns are what the provider's document checklist is built from; the more precise they are, the fewer queries the adjudicator raises later. + +## What to validate first + +The reference payer refuses, with a named error, before it looks at coverage: + +- An invalid purpose, or an invalid identifier. +- Multiple beneficiary records for one identifier. +- No hospital configuration, or a hospital not authorised for the policy. +- Items or stratifications it has no master data for. +- A quantity below one, an unknown payer ID, or a duplicate reference ID. Each becomes a protocol response with `response.error`, and each is cheaper to catch here than at preauthorisation. + +Under PMJAY, also validate the biometric user token in the header. A request with neither a valid token nor the matching authentication-consent questionnaire response is not evidence of presence, and the payer's own error codes distinguish the two cases. + +## What the four answers actually carry + +The published samples show how much the four purposes differ. Only one of them carries money. + +| Purpose | `insurance[].item[]` | Carries money | Carries `authorizationRequired` | +| :---- | :---- | :---- | :---- | +| `validation` | One item per wallet | Yes: `allowedMoney` and `usedMoney` | Yes | +| `discovery` | Every active coverage | No | No | +| `benefits` | One item per package asked about | Per package | Per package | +| `auth-requirements` | One item per package asked about | Per package | Yes, with `authorizationSupporting` | + +The two money fields are a subtraction the provider has to make. A published sample carries 463,730 allowed against 36,270 used on a 500,000 family wallet, and the plan's `generalCost` reconciles with it exactly. Send both figures; do not send only the balance. + +**One warning about the auth-requirements answer.** It is specified to return the mandatory documents, and the one published sample does not. That sample carries no benefit detail and no supporting-information requirements, and is indistinguishable from the plain benefits answer. A provider building its checklist from your answer alone will show an empty checklist. Populate `authorizationSupporting` properly, with the `MAND` codes and a display, and you save the adjudicator a query per case. + +## What goes in the answer + +A collection bundle: the `CoverageEligibilityResponse`, the `Patient` as the payer knows them, the `Coverage`, and the `Organization`s. + +| Element | Set it to | +| :---- | :---- | +| `status` | `active` | +| `purpose` | Echo the request's | +| `outcome` | `complete` | +| `disposition` | One sentence a desk can read: "Policy is currently in-force" | +| `request` | Reference back to the request | +| `insurance.coverage` | The coverage found | +| `insurance.inforce` | `true` or `false` | +| `insurance.item[]` | Per wallet for validation; per package for benefits and auth-requirements | +| `item.benefit[].allowedMoney`, `usedMoney` | Balance and consumption | +| `item.authorizationRequired` | Whether preauthorisation is needed | +| `item.authorizationSupporting[]` | The mandatory document and questionnaire codes, with a display and a text saying whether pre or post | + +Business refusals, "not a covered member", "policy expired", "coverage insufficient", go inside the sealed response as a `PAYR-10xx` reason, not in the envelope; the exchange never sees them. Protocol refusals go in the envelope. + +## The forward instruction + +The coverage eligibility specification gives it one sentence: a payer might respond with a forward instruction asking NHCX to submit the same request to another payer. No fields or flow are published for it, so there is nothing to build against. Until they are, a request for a coverage you do not hold is a business refusal inside the sealed response, as described above. Governance and Audit lists the question to ask at onboarding. + +## What to log + +Every eligibility answer is a promise the provider will rely on when it registers the patient. Keep the request, the answer, the wallet figures at that moment and the plan version they came from, so that when a claim arrives against them, the adjudicator sees what was said. diff --git a/site/docs/nhcx/v1/roles/payer/index.md b/site/docs/nhcx/v1/roles/payer/index.md new file mode 100644 index 000000000..d70b2fda1 --- /dev/null +++ b/site/docs/nhcx/v1/roles/payer/index.md @@ -0,0 +1,112 @@ +--- +title: Payer overview +sidebar_label: Payer overview +sidebar_position: 1 +description: Insurer and TPA ingestion architecture +verification: unverified +source: nhcx-package/docs/04-Building a Payer/01-Payer Overview.md +generated: true +sidebar_custom_props: + roles: + - payer +--- + +# Payer overview + +A payer system is the insurer's, TPA's or scheme's side of the exchange. Where a provider mostly calls and waits, a payer mostly hosts and answers: it receives eligibility checks, plan requests, preauthorisations and claims, decides, and sends the decision back. It initiates only three things of its own: policy links, payment notices, and communications. + +This section assumes the base framework from Getting Started: token, participant record with the payer role, own key, and a callback endpoint that opens messages. A payer's "callback" endpoints are the `check`, `request` and `submit` sides that providers call. + +## What the payer's staff see + +Under PMJAY the decisions are taken by named roles: the Preauthorisation Processing Doctor at admission, the Claim Processing Doctor at settlement, the Claim Review Committee on appeal, and accounts on payment. A payer UI is a set of work queues for those roles. + +| Screen | Who | What they do | Exchange behind it | +| :---- | :---- | :---- | :---- | +| Policy admin | Operations | Link and de-link beneficiaries to products; name the processor | Link and de-link ABHA | +| Plan configuration | Scheme team | Maintain specialties, packages, rates, add-ons, flags, documents, questionnaires | Insurance plan response | +| Eligibility | System | Answer automatically from policy and wallet data | Coverage eligibility response | +| Preauth queue | PPD | Open a case, see items and documents, approve, reduce, query or reject | Preauthorisation response | +| Claim queue | CPD | Same, against the approved preauthorisation and the discharge evidence | Claim response | +| Query composer | PPD, CPD | Write the query the provider will see | Queried response | +| Appeals | CRC | Reprocess and shortfall requests | Task response | +| Payment run | Accounts | Initiate, process and settle; record UTR and deductions | Payment notice | +| Communications | Any | TAT alerts, grievances, wallet and policy changes | Communication request | + +```mermaid +flowchart LR + E[Eligibility auto-answer] --> P[Preauth queue] + P --> Q[Query composer] + Q --> P + P --> C[Claim queue] + C --> Q + C --> M[Payment run] + C -. appeal .-> A[Appeals] + A --> M +``` + +## What the system hosts and calls + +From the Overview's catalogue, a payer hosts the C-series callbacks and calls the shared A-series plus three of its own. + +Hosts, as the receiving half of each exchange: + +``` +/v1/coverageeligibility/check answer on /v1/coverageeligibility/on_check +/v1/insuranceplan/request answer on /v1/insuranceplan/on_request +/v1/preauth/submit answer on /v1/preauth/on_submit +/v1/claim/submit answer on /v1/claim/on_submit +/v1/task/submit answer on /v1/task/on_submit +/v1/search/submit answer on /v1/search/on_submit +/v1/communication/on_request the provider's acknowledgement +/v1/paymentnotice/on_request the provider's acknowledgement +/v1/on_status, /v1/error +``` + +Calls of its own: + +``` +/participant/link/abha/policy, /participant/delink/abha/policy +/v1/paymentnotice/request +/v1/communication/request +``` + +## The rules for every answer + +The payer exit checklist states four validations on every response a payer sends, and the sandbox certification checks them: + +1. The payload validates against the NRCeS profiles. +2. `api_call_id` and `correlation_id` on the response are different values. +3. `correlation_id` on the response is the request's `correlation_id`, echoed. The checklist words it as the request's `api_call_id`, which is the same value, because a request sets its `correlation_id` to its own `api_call_id`. +4. `recipient_code` on the response equals the `sender_code` of the request. + +The correlation rule is the same everywhere. On a request you initiate, such as a payment notice or a communication, set `correlation_id` to that message's own `api_call_id`. On a response, echo the request's `correlation_id` and give the response a fresh `api_call_id`. On a status enquiry, set `correlation_id` to the `api_call_id` of the message you are asking about. Envelope Fields has the full rule. + +And the status word: `response.complete` for a final answer, `response.partial` for an interim one or a query, `response.error` with a protocol response when the request could not be opened or failed validation. The exit checklist names the type field on a good answer `JWEPayloadResponse`; the sandbox collection uses `JWEPayload`. Accept both when reading, and confirm which to send. + +## Build it in this order + +A payer's work is mostly hosting, and the hosting has a dependency order of its own. + +| Order | Build | Because | +| :---- | :---- | :---- | +| 1 | The base framework, and the four validations on every response | Nothing you send is accepted without them, and certification checks them on every use case | +| 2 | Policy linking | Until a policy is linked, no provider can find the beneficiary and nothing else is reachable | +| 3 | The eligibility answer, by rule | Asked at every registration. A provider waiting on it is a front desk waiting | +| 4 | The insurance plan response | It drives every provider screen, so its correctness decides how many malformed requests you receive | +| 5 | The preauthorisation queue and its response | The first exchange needing a human | +| 6 | The claim queue and its response | Reuses the same `ClaimResponse` shape | +| 7 | Payment notices, all three | The provider cannot close a case without 33 | +| 8 | Communication, and the Task answer for appeals | Needed for sandbox exit | + +Getting 4 right early pays for itself. Most of what a provider sends wrong, it sends wrong because your plan did not tell it otherwise. + +## What the system must keep + +- The policy master: beneficiaries, products, wallets, family limits, and which participant processes each policy. +- The plan master, versioned, because a rate change with no version bump looks like tampering from the provider's side. +- Every case as a state machine driven by what the payer itself sent: received, queried, approved, rejected, claimed, in process, settled, appealed. +- Every raw message received and sent, with its correlation ID, because arbitration is settled on the record. +- Adjudication detail per item: submitted, eligible, co-pay, benefit, and the reason, because that is what a `ClaimResponse` is made of. + +The chapters that follow take each queue in turn, the payer UI Guide turns them into the screens each desk works from, and Payer Checklist is the checklist you have to demonstrate to leave the sandbox. diff --git a/site/docs/nhcx/v1/roles/payer/payer-checklist.md b/site/docs/nhcx/v1/roles/payer/payer-checklist.md new file mode 100644 index 000000000..188cca3df --- /dev/null +++ b/site/docs/nhcx/v1/roles/payer/payer-checklist.md @@ -0,0 +1,197 @@ +--- +title: Payer checklist +sidebar_label: Payer checklist +sidebar_position: 8 +description: Payer sandbox exit list, the four validations, 26 test cases by family (T-ELG, T-PLN, T-PRE, T-CLM, T-TSK, T-PAY, T-COM, T-ENV) +verification: unverified +source: nhcx-package/docs/04-Building a Payer/08-Payer Checklist.md +generated: true +sidebar_custom_props: + roles: + - payer +--- + +# Payer checklist + +What a payer has to demonstrate to leave the sandbox, the validations the certification checks on every response, the test cases to run, and how to test without a real provider. + +## The sandbox exit list + +NHA's payer exit process names fifteen use cases. + +1. Link ABHA with policy, `/participant/link/abha/policy`. +2. Get policy, `/participant/get/policies`. +3. De-link ABHA from policy, `/participant/delink/abha/policy`. +4. Get participant list, `/fetch/participants/list`. +5. Get public key, `/fetch/certs`. +6. Get auth token, `/get/session`. +7. Respond to coverage eligibility, received on `/v1/coverageeligibility/check`, answered on `/v1/coverageeligibility/on_check`. +8. Respond to insurance plan request, received on `/v1/insuranceplan/request`, answered on `/v1/insuranceplan/on_request`. +9. Respond to preauthorisation, received on `/v1/preauth/submit`, answered on `/v1/preauth/on_submit`. +10. Raise a communication request, `/v1/communication/request`, acknowledged on `/v1/communication/on_request`. +11. Respond to claim, received on `/v1/claim/submit`, answered on `/v1/claim/on_submit`. +12. Respond to search, received on `/v1/search/submit`, answered on `/v1/search/on_submit`. +13. Send payment notice, `/v1/paymentnotice/request`, acknowledged on `/v1/paymentnotice/on_request`. +14. Respond to a task, received on `/v1/task/submit`, answered on `/v1/task/on_submit`. +15. Get status, `/v1/status`, answered on `/v1/on_status`. + +Plus `/v1/error` and, where the payer is a scheme, the biometric token validation. + +## The four validations on every response + +The checklist repeats them for every answering use case, so the certification will check them on every one: + +1. Payload validates against the NRCeS profiles. +2. `api_call_id` and `correlation_id` are different values. +3. `correlation_id` matches the request being answered. +4. `recipient_code` equals the request's `sender_code`. + +And each answer is prepared one of two ways: a sealed bundle when the request was processed, or a protocol response when it could not be opened or failed validation. + +## Testing without a provider + +There is no dummy provider on the sandbox. The practical route is to build the provider's calling half from Getting Started and the provider section, point it at your own participant code, and drive your queues from it. The sample bundles on the portal give you real PMJAY-shaped requests to feed in: every eligibility purpose, a preauthorisation and its query answer, an enhancement, a cancellation, a claim and its query answer. + +## Test cases + +One id per case, by family: `ELG` coverage eligibility, `PLN` insurance plan, `PRE` preauthorisation, `CLM` claim, `TSK` tasks, `PAY` payment, `COM` communication, `ENV` envelope and queue. Cases marked PMJAY apply to the scheme only. The workflow codes named are the ones the payer's answer must carry. + +### Coverage eligibility + +#### T-ELG-01 Validate the policy + +A request by ABHA with purpose `validation`. Answer on `/v1/coverageeligibility/on_check` with `inforce: true` and the wallet balance, after checking the ABHA linkage and that the member is active. + +#### T-ELG-02 Auth-requirements + +Purpose `auth-requirements` for a package. Answer with `authorizationRequired: true` and the mandatory documents and STG codes, after checking wallet adequacy and the specialty constraints. + +#### T-ELG-03 Every purpose and the refusals + +`discovery` and `benefits` answered; an exhausted family wallet and a hospital not authorised for the policy refused inside the sealed response, not in the envelope. + +### Insurance plan + +#### T-PLN-01 Publish the plan + +Answer on `/v1/insuranceplan/on_request` with the collection bundle: empanelled packages, claim-condition flags, STG questionnaires and the rate master, carrying a version. + +### Preauthorisation + +#### T-PRE-01 Acknowledge, then approve + +Acknowledge on `20` as `response.partial`, then approve on `21` as `response.complete` with `preAuthRef`, after STG validation and biometric token verification. + +#### T-PRE-02 Query and its answer + +Raise the query on `24`, on the case thread under PMJAY or over communication otherwise. Take the answer on `19`, clear the hold, then decide on `21`. + +#### T-PRE-03 Reject with a denial code + +Decide on `23` with the denial reason inside the `ClaimResponse`. + +#### T-PRE-04 Reduce with a note + +Approve on `21` for less than asked, with the adjudication note that says why. + +#### T-PRE-05 Auto-approval and TAT approval (PMJAY) + +A first preauthorisation whose packages all carry `ApprovalNotRequired` is approved without a desk action. A package flagged `ScheduledTATApproval` is approved by the system when the window lapses, with the disposition "Auto approved by system". + +#### T-PRE-06 Enhancement approved and denied + +Approve on `22`; deny on `231`; query on `241`. + +#### T-PRE-07 Resubmission and cancellation + +A resubmission on `121` treated as the new base request. A cancel Task on `PC01` answered `PC02` before payment, and refused after payment has been initiated. + +### Claim + +#### T-CLM-01 Acknowledge, then approve + +Acknowledge on `25`, then approve on `26`, after verifying the discharge biometric token, matching the preauthorisation, and calculating incentives and tax. + +#### T-CLM-02 Query and its answer + +Raise the query on `27`; take the answer on `151`, or `161` under PMJAY; then decide on `26` or `291`. + +#### T-CLM-03 Reduce, in process, forward, reject + +`26` for less than claimed with the deduction reason per item; `28` in process; `29` forwarded; `291` rejected. + +#### T-CLM-04 Every discharge type (PMJAY) + +`DTH`, `DTM`, `LAMA` and `DAMA` each priced as the scheme rules say, with `LM100` per day for LAMA or DAMA before surgery. + +#### T-CLM-05 Unusual cases (PMJAY) + +An unspecified procedure; a cyclic procedure with per-visit biometrics; a newborn on the parent's card; twins; implants within their maximums. + +### Tasks + +#### T-TSK-01 Reprocess + +A reprocess Task on `36` acknowledged on `37` with the Task `accepted`, then re-adjudicated on `252` or `253`, the `ClaimResponse` in the Task's output. + +#### T-TSK-02 Shortfall + +A `partialpayment` Task accepted after payment notice `33` has been acknowledged, and refused before it. + +#### T-TSK-03 The Committee's answer + +The Claim Review Committee's decision returned inside a Task, not as a bare `ClaimResponse`. + +### Payment + +#### T-PAY-01 Three notices + +`30`, `31` and `33` in turn, with the UTR and the TDS line on `33`, and the provider's acknowledgement recorded. Net plus deductions equals the approved amount. + +#### T-PAY-02 Return payment + +`RP1` intimation, `RP2` acknowledged, `RP3` failed. + +### Communication + +#### T-COM-01 Each reason + +`additionalinfo`, `tatquery`, `grievance`, `walletupdate`, `policychange` and `claimArbitration`, each acknowledged by the provider within thirty seconds; `tatquery` sent when a preauthorisation or claim has passed the payer's own turnaround threshold. + +### Envelope and queue + +#### T-ENV-01 Duplicate request on one correlation id + +The second delivery is recognised and not processed twice. + +#### T-ENV-02 A request while another is in progress + +Refused, with `PAYR-1322` under PMJAY, until the first is decided. + +#### T-ENV-03 A malformed bundle + +Answered with a protocol response, not a sealed bundle. + +#### T-ENV-04 Queue ordered by time remaining + +Preauthorisation and claim queues indexed by `received_at` plus the turnaround window, so the case with the least time left comes first and the breach alert fires before the window lapses. No window values are published. The plan's `ScheduledTATApproval` flag says only that the system approves the case after "a specified time period (varies with policy)", and the FAQ's answer on reprocess is "No fixed TAT as of now". Agree the windows at onboarding; Governance and Audit lists the question. + +## Where payers go wrong + +- Answering with `outcome = complete` and no adjudication reason, so the provider cannot tell approval from rejection. +- Reusing the request's `api_call_id` as the response's. +- Sending business refusals in the envelope, where the exchange logs them, instead of inside the sealed response. +- Rates changed in the plan master without a version bump, so every provider's next claim looks tampered. +- Sending `33` before the bank has confirmed, which opens the shortfall window early. +- TAT auto-approval firing because the queue was not ordered by time remaining. + +## Exchanges this documentation does not cover + +The workflow families that no NHA document describes beyond their codes are listed once, under the same heading in Provider Checklist. A payer may receive one too; log it and escalate rather than ignore it. + +## Before going live + +- Enrolment through the NHA or IRDAI portal with the payer or TPA role, the IRDAI registry id without leading zeros, and the production certificate and callback address. +- Every policy linked with the correct processor. +- The plan master versioned and published for every empanelled hospital. +- FHIR bundles validated by NRCeS; internal demo; HTC demo. diff --git a/site/docs/nhcx/v1/roles/payer/payment-notice-and-communication.md b/site/docs/nhcx/v1/roles/payer/payment-notice-and-communication.md new file mode 100644 index 000000000..def365d79 --- /dev/null +++ b/site/docs/nhcx/v1/roles/payer/payment-notice-and-communication.md @@ -0,0 +1,106 @@ +--- +title: Payment notice and communication +sidebar_label: Payment notice and communication +sidebar_position: 6 +description: Dispatching payment notices and operational intimations +verification: unverified +source: nhcx-package/docs/04-Building a Payer/06-Payment Notice and Communication.md +generated: true +sidebar_custom_props: + roles: + - payer +--- + +# Payment notice and communication + +The two exchanges a payer starts. Payment tells the provider money has moved; communication tells the provider something has changed or is wanted. + +## Payment notices + +### What accounts do + +A payment run screen, built from approved claims: select the claims, initiate the transfer, and record the bank's confirmation and UTR as it comes back. Each stage becomes a notice. Deductions, TDS and any scheme adjustments are entered per claim, and the net is what the bank receives. + +### What the system calls + +``` +POST /v1/paymentnotice/request workflows 30, 31, 33 +receive /v1/paymentnotice/on_request the provider's acknowledgement, workflow 17 +``` + +Three notices per claim as the money moves: 30 initiated, 31 processed by the bank, 33 settled with the UTR. Each is a separate message with its own correlation ID. Send 33 only when the bank has confirmed; under PMJAY it is the gate that lets the provider raise a shortfall claim. + +### What goes in the bundle + +A collection bundle: a `Task` with code `deliver` and an input referencing the notice, a `PaymentNotice`, a `PaymentReconciliation`, and the two `Organization`s. + +#### Task + +`status = requested`, `intent = order`, `code = deliver`. `requester` is the payer, `owner` the provider, and `input[0].valueReference` points at the PaymentNotice. + +#### PaymentNotice + +The claim number as an identifier of type `CLN`, `recipient` the provider, `amount` the net, `paymentStatus` `paid` or `cleared`, and `payment` referencing the reconciliation. + +#### PaymentReconciliation + +The same claim number, `paymentDate`, `paymentAmount` as the net, a `paymentIdentifier` of type `UTR` carrying the bank reference, and `detail[]` with one line per money type: `TDS`, `Payment`, and any of `approvedamount`, `claimedamount`, `servicetax`, `advance`, `recovered`, `penality`. + +The provider will check that net plus deductions equals the approved amount. Make it so. + +### The acknowledgement + +Arrives as a `Task` with `status = completed`, code `status`, and an output whose value is `paymentack`, with the claim number as a second output. It confirms receipt, not agreement. Record it against the claim and consider the payment lifecycle closed once the acknowledgement of 33 is in. + +A return payment, where money has to come back, has its own codes: RP1 intimation, RP2 acknowledged, RP3 failed. + +## Communication requests + +### What the user does + +A composer, usually opened from a case: choose the reason, write the message, set a priority, send. Some are generated by the system rather than a person. A TAT alert when a provider has not answered a query within the window, a wallet update when a beneficiary's balance changes, a policy change when the plan master is versioned. + +### What the system calls + +``` +POST /v1/communication/request +receive /v1/communication/on_request the provider's acknowledgement +``` + +Reasons, on `Task.reasonCode`: `tatquery`, `grievance`, `walletupdate`, `policychange`, `additionalinfo`, `claimArbitration`. The last is sent automatically when an appeal Task is received, so the provider knows it is in the Committee's queue. + +On the general network, `additionalinfo` is how a payer asks for documents outside a formal query. Under PMJAY, document queries go through the queried `ClaimResponse` instead, and this channel is for the other five. + +### What goes in the bundle + +A collection bundle of three parts. + +#### Task + +Code `poll`, `intent = proposal`, `reasonCode` set, and an input of type `include` referencing the Communication. + +#### Communication + +The case number as identifier, `status = completed`, a `category` (reminder, notification, instruction, questionnaire), a `priority` (routine, urgent, asap, stat), a `topic` (progress-update for anything about a live case), and the payload. + +#### The two Organizations + +Payer first, then the provider. + +The acknowledgement comes back as the same shape with the provider `Organization` first and the same correlation ID. It means received, not resolved; track resolution in the case, not in the exchange. + +## What a provider does with each notice + +Sending all three matters more than it looks, because the provider's case state and its shortfall window both hang off them. + +| Workflow | What you have done | What the provider does | +| :---- | :---- | :---- | +| 30 | Initiated the transfer | Shows the case as payment started. Does not close it | +| 31 | The bank has processed it | Updates the same panel. Still does not close it | +| 33 | The bank has confirmed settlement, and you send the UTR | Marks the case settled, reconciles the UTR against the bank statement, and acknowledges | + +Send 33 only when the bank has actually confirmed. Under PMJAY the acknowledgement of 33 is the gate that opens the provider's shortfall window, so sending it early opens that window against a payment that has not landed. + +## Notifying the beneficiary + +Where a beneficiary's app has subscribed, the exchange itself pushes a human-readable message on each event: "Preauthorisation approved for Rs. 50,000, valid until…". The payer does nothing extra; its normal responses feed it. The payer's own notifications carry workflow N01. diff --git a/site/docs/nhcx/v1/roles/payer/policies-and-plans.md b/site/docs/nhcx/v1/roles/payer/policies-and-plans.md new file mode 100644 index 000000000..4d1b631f1 --- /dev/null +++ b/site/docs/nhcx/v1/roles/payer/policies-and-plans.md @@ -0,0 +1,71 @@ +--- +title: Policies and plans +sidebar_label: Policies and plans +sidebar_position: 2 +description: Publishing policy master and 21 MB plan bundles +verification: unverified +source: nhcx-package/docs/04-Building a Payer/02-Policies and Plans.md +generated: true +sidebar_custom_props: + roles: + - payer +--- + +# Policies and plans + +Before a payer can answer a single claim question, two things have to be true on the network: the beneficiary has to be findable, and the policy has to be readable as data. The first is linking. The second is the insurance plan. + +## Linking beneficiaries + +### What the user does + +A policy-admin screen. When a policy is written or renewed, the operator records the holder's ABHA number, mobile and member ID against the products on the policy, and names who will process claims for it. In most payers this should be automatic from the policy system, with the screen kept for corrections. + +The processor is the decision that matters. An insurer that adjudicates its own claims names itself. One that uses a TPA names the TPA's participant code. Get it wrong and every provider will send the case to the wrong place. + +### What the system calls + +``` +POST /participant/link/abha/policy +POST /participant/delink/abha/policy +``` + +Bodies and rules are in Getting Started. Two operational points. Only the participants named as payer or processor on the link can change it, and the exchange checks the caller's token against them. So the linking job must run under the same credentials that created the participant. And a change of TPA is a batch: de-link every affected policy with the old processor, link again with the new; there is no edit. + +## Publishing the plan + +### What the scheme team does + +A plan-configuration screen that maintains, per policy and per empanelled hospital: + +- The specialties, and the packages under each with their rate. +- The add-ons allowed, meaning implants, bed-category stratification, high-end medicines and investigations, with their maximums. +- The flags that govern each package. +- The mandatory documents at policy and package level, and the questionnaires. Every change bumps a version. + +The flags are the scheme's rules made machine-readable, and the provider's screen is built from them. The set the handbook lists is government-reserved, auto-approval, enhancement allowed, scheduled TAT approval, quantity allowed and day care. Then implant applicable and maximum implants, stratification allowed and maximum, standalone, parent procedure, unspecified, and cyclic with maximum cycles. Then LAMA/DAMA procedure and its stages, procedure type (surgical, medical, conservative), length of stay, and GST. + +### What the system hosts + +``` +/v1/insuranceplan/request answer on /v1/insuranceplan/on_request +``` + +The request is a `Task` with code `poll` and inputs `policyNumber` and `providerId`. The answer is scoped to that provider: only the specialties and packages its empanelment allows. That scoping is a validation as much as a filter. The payer's own error codes reject a policy not allowed for the hospital, a renewal code that does not match, a policy with no specialty configured, and an HFR ID it has no enrolment for. + +Answer with a collection bundle: one `InsurancePlan`, the `Organization`s, and one `Questionnaire` per requirement. The reference sample carries 2,215 questionnaires and is 21 MB; that is what a real PMJAY plan looks like. Build the bundle from the plan master, never by hand. + +### The two shapes + +The Insurance Plan guide gives two ways to structure benefits, and a payer picks one per plan. + +**Package-based**, the PMJAY shape: `plan → specificCost → category → benefit → cost → qualifiers`. Specialty is the category, package is the benefit, the rate is the cost, and add-ons are qualifiers on the cost. Claim conditions, exclusions and document requirements hang off the plan as extensions. + +**Coverage-based**, the private-insurer shape: `coverage → benefit → limit`. Coverage types such as in-patient, benefits such as ICU charges and room rent, and a limit per benefit with its own conditions and required documents. + +Element tables for both are in the FHIR Reference. + +### Keeping it honest + +- Refresh is the provider's job, but a `policychange` communication from the payer is what tells providers to do it early. Send one whenever a rate or package changes. +- Concurrency: a second plan request while the first is still being answered is refused by the reference payer with a wait-and-retry error. Design the request handler to be idempotent per correlation ID. diff --git a/site/docs/nhcx/v1/roles/payer/ui-guide.md b/site/docs/nhcx/v1/roles/payer/ui-guide.md new file mode 100644 index 000000000..e352ab8f8 --- /dev/null +++ b/site/docs/nhcx/v1/roles/payer/ui-guide.md @@ -0,0 +1,178 @@ +--- +title: Payer UI guide +sidebar_label: Payer UI guide +sidebar_position: 7 +description: Payer adjudication desk screens and workflow +verification: unverified +source: nhcx-package/docs/04-Building a Payer/07-UI Guide.md +generated: true +sidebar_custom_props: + roles: + - payer +--- + +# Payer UI guide + +A payer system is operated from queues. Cases arrive, sit until a person or a rule acts on them, and leave with a decision. This chapter describes those queues and the screens around them, who works each one, what they see, what they decide, and how the decision becomes a message. It follows the same order as the rest of the section. + +Two rules run through every screen. + +**A decision is not made until it is sent.** The adjudicator's action on screen produces a response that goes to the exchange. The case state changes when the receipt comes back, not when the button is clicked. The screen shows the difference. + +**The payer never types what the provider sent.** Amounts submitted, items, documents, dates and biometric evidence are shown as received and are not editable. What the payer adds is the decision, the eligible and approved amounts, the reason, and the note. + +## Who works which queue + +```mermaid +flowchart LR + IN[Inbound messages] --> E[Eligibility: answered by rule] + IN --> PQ[Preauth queue] + IN --> CQ[Claim queue] + IN --> AQ[Appeals queue] + PQ --> PPD[Preauthorisation doctor] + CQ --> CPD[Claim doctor] + AQ --> CRC[Review committee] + CPD --> PAY[Payment run: accounts] + CRC --> PAY + OPS[Operations] --> POL[Policy admin] + OPS --> PLAN[Plan configuration] + ANY[Any desk] --> COM[Communications] +``` + +| Screen | Role | Input | Output message | +| :---- | :---- | :---- | :---- | +| Policy admin | Operations | Holder identifiers, products, processor | Link, de-link | +| Plan configuration | Scheme team | Specialties, packages, rates, flags, documents, questionnaires, version | Insurance plan response | +| Eligibility monitor | System, watched by support | None | Eligibility response | +| Preauth queue | Preauthorisation doctor | Decision per item, note, query text | Preauthorisation response | +| Claim queue | Claim doctor | Decision per item, note, query text | Claim response | +| Appeals | Review committee | Decision | Task response | +| Payment run | Accounts | Claims to pay, deductions, bank confirmation | Payment notices | +| Communications | Any desk | Reason, message, priority | Communication request | +| Case audit | Anyone | None | None | + +## Flow 1: policy admin + +**Screen.** A search by member, ABHA or mobile, showing the holder's linked products and who processes each. Link and de-link actions, and a bulk tool for moving every policy from one processor to another. + +**What the UI enforces.** The processor field is a pick from the payer's own participants, never typed. A de-link names only products already on the link. A change of processor is a batch with a preview of how many policies it will touch. Because only the two participants on a link may change it, the screen must run under the credentials that created the participant, and should say so when a change is refused. + +**Data flow.** Policy system writes a policy; a job links it on the exchange; the screen shows the exchange's record, not the policy system's, so a link that failed is visible. + +## Flow 2: plan configuration + +**Screen.** A tree: policy, specialty, package. Per package: the rate, the add-ons allowed with their maximums, the flags, the documents required at preauthorisation and at claim, and the questionnaires attached. A version stamp on the plan with a publish action that bumps it. A per-hospital view showing what an empanelled hospital will receive. + +**What the UI enforces.** A rate change without publishing is shown as pending, because an unpublished rate is exactly what makes a provider's next claim look tampered with. Every flag is a control, not a text field. The per-hospital preview is what the plan response will actually contain, generated from the same master. + +```mermaid +sequenceDiagram + participant T as Scheme team + participant S as Plan screen + participant M as Plan master + participant B as Backend + participant X as NHCX + participant H as Hospital + T->>S: change a rate, add a flag + S->>M: save as pending + T->>S: publish + S->>M: new version + B->>X: communication, reason policychange + X->>H: hospitals refresh their plan + H->>X: plan request + X->>B: request for this hospital + B->>M: build plan for this hospital's empanelment + B->>X: sealed plan response, current version +``` + +## Flow 3: eligibility + +No screen for the decision; it is answered by rule from the policy master and the wallet. What operations needs is a monitor: volume by hospital, refusals by reason, and the requests that failed validation with the payer's own error code. That is how a hospital sending a malformed request gets told which field. The monitor should also show the requests answered with "not a covered member" by hospital, because a spike there is a linking problem on the payer's side, not the hospital's. + +## Flow 4: the preauthorisation queue + +**Screen.** A queue ordered by turnaround time remaining, with cases that a rule will auto-approve marked so the doctor can skip them. Opening a case shows, in the payer's order: beneficiary and wallet before and after, diagnosis, and packages with rate, add-ons and the plan's flags. Then care team and dates, documents rendered as records with questionnaires beside the package they belong to, and the case history. + +**The decision panel.** Per item: approve, approve at a lower amount with a note, query, reject with a reason picked from the scheme's preauthorisation denial list. Then a claim-level decision that the system derives from the items and the doctor confirms. + +**What the UI enforces.** A reduction needs a note. A rejection needs a reason code. A query needs text and names the item. The eligible and approved amounts are computed from the items and shown, not typed. Under PMJAY the biometric or consent evidence is shown as a badge on the case before anything else. + +```mermaid +stateDiagram-v2 + [*] --> Received: request validated + Received --> AutoApproved: rule fires + Received --> InQueue: needs a doctor + InQueue --> Deciding: opened + Deciding --> Approved: approve + Deciding --> Reduced: approve at lower amount + Deciding --> Queried: query sent + Deciding --> Rejected: reject with reason + Queried --> Answered: provider replies + Answered --> InQueue + InQueue --> TATApproved: window lapsed +``` + +The doctor sees InQueue cases ordered by how long until TATApproved fires. Get that ordering wrong and the window lapses on cases nobody has looked at. + +## Flow 5: writing a query + +**Screen.** A composer opened from an item or from the whole case. Under PMJAY the text becomes the pipe-delimited audit trail the provider will see, so the composer shows the comment field prominently and fills user, time and type itself. A picker of the documents the plan lists, so the doctor asks for a named document rather than "more documents". + +**What the UI enforces.** A query cannot be sent empty. On the general network the query goes out as a communication with reason additional information; under PMJAY as a queried response on the case. The composer knows which and the doctor does not have to. + +## Flow 6: the claim queue + +**Screen.** The claim opened side by side with the approved preauthorisation, differences highlighted: items added, quantities changed, amounts above approval. Discharge type and stage, dates, discharge summary as a record, bill, post-operative evidence. The four checks the handbook names shown as a checklist the doctor ticks: within cover and limits, clinically appropriate, documents complete and consistent, within package rates. + +**The decision panel.** As for preauthorisation, with two interim actions that are not decisions: mark in process, forward to another entity. And the claim denial list rather than the preauthorisation one. + +**What the UI enforces.** Nothing above the approved amount is approvable without a reduction note. A rejection shows the doctor that it closes the case permanently and that the provider's only route is appeal. Under PMJAY a LAMA or DAMA claim before surgery is shown with the stay line only and the approved packages struck through. + +## Flow 7: appeals + +**Screen.** A committee queue of reprocess and shortfall requests, each opened against the original claim, its decision, its payment, and the document the provider attached. Decision: uphold, revise with amounts, reject. A note that the decision is final and closes the case to further appeal. + +**What the UI enforces.** A shortfall request that arrived before the settlement notice was acknowledged is shown as premature and is not adjudicated. A second appeal on a case already decided is shown as refused. The decision goes out as a Task carrying a claim response, and the screen shows it as sent only on receipt. + +## Flow 8: the payment run + +**Screen.** Approved claims not yet paid, selectable into a run. Per claim: approved amount, deductions itemised (tax deducted at source and any scheme adjustment), net. Actions: initiate, then record the bank's confirmation and UTR. Each action becomes a notice to the provider; the screen shows the three notices per claim and whether the provider acknowledged each. + +**What the UI enforces.** Net plus deductions equals the approved amount, or the run does not proceed. The settlement notice is sent only when the bank confirmation is entered, because under PMJAY that notice opens the provider's shortfall window. A failed transfer is recorded as a rejected notice, not left silent. + +```mermaid +sequenceDiagram + participant A as Accounts + participant S as Payment screen + participant B as Backend + participant X as NHCX + participant H as Hospital + A->>S: select approved claims, enter deductions + S->>S: net + deductions = approved? + A->>S: initiate + B->>X: payment notice, initiated + X->>H: notice + H->>X: acknowledgement + X->>B: acknowledged + A->>S: bank confirms, enter UTR + B->>X: payment notice, settled, with UTR + X->>H: notice + H->>X: acknowledgement + B-->>S: claim closed +``` + +## Flow 9: communications + +**Screen.** A composer with a reason picker: information request, turnaround alert, grievance, wallet change, policy change, arbitration acknowledgement. Message, priority, and the case it concerns. Most of these should be generated by the system rather than a person. A turnaround alert when a query has gone unanswered past the window, a wallet change when a balance moves, a policy change on every plan publish, an arbitration acknowledgement when an appeal arrives. + +**What the UI enforces.** A message about a case carries the case number. Priority is a pick, and only a fraud or safety message may be marked as the highest. The acknowledgement from the provider is shown against each message; it means received, and the screen says so. + +## Flow 10: the case audit trail + +**Screen.** Every case, every message in and out, in order, with the correlation ID, the workflow code, the status word, the raw message and its decrypted content, and who acted on the payer's side. Read only. Exportable. + +This is the screen arbitration is settled on, and every other screen is a view over the same record. Build it early. + +## Errors the adjudicator should see + +A request refused by validation never reaches the queue. It should still reach a support view with the payer's own error code and the hospital that sent it, so that a hospital repeatedly sending a wrong package code can be told. The queues themselves show only cases that passed validation; the doctor's time is for decisions, not for malformed messages. diff --git a/site/docs/nhcx/v1/roles/provider/_category_.json b/site/docs/nhcx/v1/roles/provider/_category_.json new file mode 100644 index 000000000..a89fcb749 --- /dev/null +++ b/site/docs/nhcx/v1/roles/provider/_category_.json @@ -0,0 +1,9 @@ +{ + "label": "Building a provider", + "position": 1, + "customProps": { + "roles": [ + "provider" + ] + } +} diff --git a/site/docs/nhcx/v1/roles/provider/biometric-authentication.md b/site/docs/nhcx/v1/roles/provider/biometric-authentication.md new file mode 100644 index 000000000..6040e7953 --- /dev/null +++ b/site/docs/nhcx/v1/roles/provider/biometric-authentication.md @@ -0,0 +1,383 @@ +--- +title: Biometric authentication +sidebar_label: Biometric authentication +sidebar_position: 3 +description: "ABDM biometric pipeline: Fingerprint, Iris, FaceAuth, and exemption consent" +verification: unverified +source: nhcx-package/docs/03-Building a Provider/03-Biometric Authentication.md +generated: true +sidebar_custom_props: + roles: + - provider +--- + +# Biometric authentication + +PMJAY requires proof that the beneficiary was physically present. A hospital +proves it by authenticating them against their ABHA, biometrically, at +registration, during treatment and at discharge. What comes back is a user +token, and that token rides on the eligibility check, the preauthorisation and +the claim. A request without it, and without the consent form that stands in +for it, is refused by name. + +These are not NHCX APIs. They belong to ABDM and were built for the PMJAY +payer, so nothing in Getting Started applies to them: different hosts, a +different authorisation header, no JWE, no callbacks. PMJAY Provider covers +when to authenticate and what the scheme does with the result. This chapter is +the calls. + +## What you have to build + +All three methods. Fingerprint, iris and face are each mandatory to implement, +because any one of them may be the only one that works for a given patient, and +a case authenticated by fingerprint at admission can be authenticated by face +at discharge. The methods do not have to match across a case. + +```mermaid +flowchart TD + A[Patient at the desk] --> B{Method} + B -- fingerprint or iris --> C["auth/init, then auth/verify
one host"] + B -- face --> D["faceauth/init, QR, capture/pid,
v2/auth/verify, a different host"] + B -- none possible --> E["Aadhaar exemption consent
plus the plan's questionnaire"] + C --> F[User token, 30 minutes] + D --> F + F --> G[Token on the header of eligibility, preauth, claim] +``` + +## Two hosts, and this is the first thing to get right + +| Method | Base | +| :---- | :---- | +| Fingerprint, iris, token refresh | `https://apisbx.abdm.gov.in/hcx/abha/biometric/` | +| Face | `https://apisbx.abdm.gov.in/pmjay/sbxhcx/abdmproxy/abha/biometric/` | + +A client written against one base path will fail on the other, and the failure +looks like a routing problem rather than a configuration one. + +## Headers + +Every call carries the ABDM session token on `Authorization`. The other +headers depend on the call. + +| Call | Headers besides `Authorization` | +| :---- | :---- | +| `auth/init`, `auth/verify` | `process`, `payerid`, `Content-Type: application/json`, `Accept: */*` | +| `auth/refresh/token` | `process`, `payerid`, `R-token: Bearer ` | +| `faceauth/init`, `capture/pid` | `REQUEST-ID`, `TIMESTAMP`, `Content-Type: application/json`, `Accept: application/json` | +| `v2/auth/verify` | The same four, plus `process` and `payerid` | + +No source puts `process` or `payerid` on `faceauth/init` or `capture/pid`. The +face rows follow Biometric Authentication Implementation Steps. The FaceAuth +Postman collection sends less: `Authorization` alone on `faceauth/init`, and +no `REQUEST-ID` or `TIMESTAMP` on any face call. + +Three points that cost time. + +**`Authorization`, not `bearer_auth`.** The exchange's own endpoints in this +documentation read the token from `bearer_auth`. These read it from +`Authorization`. Sending only the habitual header gets a `401` that looks like +an expired token. + +**`process` is a header, and it is the scheme's process type.** `Preauth` at +admission, `Discharge` at discharge and, on a cyclic case, at every visit. The +rules elsewhere in this documentation say "process type Discharge" without +saying it is an HTTP header. This is it. + +**`payerid` names the payer** the authentication is being performed for. + +## Fingerprint and iris + +A two-call pair. Initiate, capture on the device, verify. + +### Initiate + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/hcx/abha/biometric/auth/init' \ + --header 'Accept: */*' \ + --header 'Content-Type: application/json' \ + --header 'Authorization: Bearer ' \ + --header 'process: Preauth' \ + --header 'payerid: ' \ + --data-raw '{ + "scope": [ + "abha-login", + "aadhaar-bio-verify" + ], + "loginHint": "abha-number", + "loginId": "91-XXXX-XXXX-1234", + "otpSystem": "aadhaar", + "authMode": "FINGERPRINT" + }' +``` + +[Biometric auth init in the API reference](/docs/nhcx/v1/api/biometric/endpoints/biometric-auth-init) + +| Field | Fingerprint | Iris | Face | +| :---- | :---- | :---- | :---- | +| `scope` | `["abha-login", "aadhaar-bio-verify"]` | `["abha-login", "aadhaar-iris-verify"]` | `["abha-login", "aadhaar-face-verify"]` | +| `authMode` | `FINGERPRINT` | `IRIS` | `FACE_AUTH` | +| `authMethods`, on verify | `bio` | `iris` | `face` | +| Capture, under `authData` on verify | `bio.fingerPrintAuthPid` | `iris.irisAuthPid` | `face.faceAuthPid` | + +The face column is on this host, not the proxy. The NHCX-PMJAY-HMIS +Integration Guide and the Biometric Authentication APIs Postman collection list +it beside fingerprint and iris, as alternatives in comments on the fingerprint +sample. Neither shows a face request made this way or says where its capture +comes from. Biometric Authentication Implementation Steps takes face through +the separate flow on the proxy host, below, which is the only face path +documented end to end. No published source says when to use one rather than +the other; confirm with NHA before building on this one. + +`loginId` is the ABHA number **with** hyphens here, which is the opposite of +the envelope convention. + +The response carries the transaction ID the verify call quotes: + +```json +{ + "txnId": "8c8a12e3-xxxx-4278-xxxx-10acffa44f07", + "authMode": null, + "message": "FingerPrint authentication request successfully sent.", + "status": null +} +``` + +### Verify + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/hcx/abha/biometric/auth/verify' \ + --header 'Accept: */*' \ + --header 'Content-Type: application/json' \ + --header 'Authorization: Bearer ' \ + --header 'process: Preauth' \ + --header 'payerid: ' \ + --data-raw '{ + "scope": [ + "abha-login", + "aadhaar-bio-verify" + ], + "authData": { + "authMethods": [ + "bio" + ], + "bio": { + "txnId": "", + "fingerPrintAuthPid": "" + } + }, + "authMode": "FINGERPRINT" + }' +``` + +[Biometric auth verify in the API reference](/docs/nhcx/v1/api/biometric/endpoints/biometric-auth-verify) + +`authMethods` and the key the capture goes under follow the method, as the +table above gives them. + +On success: + +```json +{ + "txnId": "d21b3db9-478a-xxxx-xxxx-8f75e7f86b9f", + "authResult": "success", + "message": "… verified successfully", + "token": "eyZhx….", + "refreshToken": "eyZhx….", + "expiresIn": 1800, + "refreshExpiresIn": 1296000, + "accounts": [ { "ABHANumber": "91-XXXX-XXXX-1234", "name": "…", "status": "ACTIVE", "…": "…" } ] +} +``` + +### The WADH, and error K-547 + +The device capture needs a wrapped Aadhaar data hash, and the portal records +one wrong value as the cause of a specific error. If the biometric APIs return +**K-547**, the `lr` parameter was sent as `N` and must be `Y`. + +``` +ra = deviceType // 'F' for fingerprint +rc = 'Y' +lr = 'Y' // the one that is usually wrong +de = 'N' +pfr = 'N' + +text = '2.5' + ra + rc + lr + de + pfr +wadh = Base64(SHA-256(text)) +``` + +This is the only device-level detail the published material gives, and it is +the one failure an integrator cannot reason their way out of. + +## Face authentication + +A four-step flow on the other host, because the capture happens on the +patient's own phone rather than on a hospital device. + +**1. Initiate.** + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/abdmproxy/abha/biometric/faceauth/init' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'Authorization: Bearer ' \ + --header 'REQUEST-ID: ' \ + --header 'TIMESTAMP: ' \ + --data-raw '{ + "scope": [ + "abha-enrol", + "face-auth" + ] + }' +``` + +[Face auth init in the API reference](/docs/nhcx/v1/api/biometric/endpoints/biometric-faceauth-init) + +Returns a `txnId`. + +**2. Show a QR code.** Render +`https://phrsbx.abdm.gov.in/face-auth?txnId=` as a QR code. The patient +scans it with the ABHA app and completes the face scan there. + +**3. Poll for the capture.** + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/abdmproxy/abha/biometric/capture/pid' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'Authorization: Bearer ' \ + --header 'REQUEST-ID: ' \ + --header 'TIMESTAMP: ' \ + --data-raw '{ + "txnId": "" + }' +``` + +[Face auth capture PID in the API reference](/docs/nhcx/v1/api/biometric/endpoints/biometric-faceauth-capture-pid) + +Answers `{"status": "PENDING", "message": "Awaiting PID capture"}` until the +patient finishes, then `{"status": "COMPLETE", "message": "PID capture successful"}`. +Poll this; there is no callback. + +**4. Verify with the encrypted Aadhaar number.** + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/abdmproxy/abha/biometric/v2/auth/verify' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'Authorization: Bearer ' \ + --header 'REQUEST-ID: ' \ + --header 'TIMESTAMP: ' \ + --header 'payerid: ' \ + --header 'process: Preauth' \ + --data-raw '{ + "authData": { + "authMethods": [ + "face_auth" + ], + "face": { + "txnId": "", + "aadhaar": "", + "mobile": "" + } + }, + "authMode": "FACE_AUTH" + }' +``` + +[Face auth verify in the API reference](/docs/nhcx/v1/api/biometric/endpoints/biometric-faceauth-v2-auth-verify) + +**The Aadhaar number is encrypted, not sent in the clear.** Use the X.509 +public key the portal publishes with the transformation +`RSA/ECB/OAEPWithSHA-1AndMGF1Padding`. The ciphertext is roughly 680 base64 +characters for a 4096-bit key. Never log it, never store it, and never attempt +to validate it as a twelve-digit number. + +The response carries the same token pair plus a full ABHA profile: name, date +of birth, gender, photo, address, state and district. Take from it only what +your record needs. + +## The tokens + +| Token | Life | Header it is sent on later | +| :---- | :---- | :---- | +| User token | 1,800 seconds, 30 minutes | The PMJAY claim-event header | +| Refresh token | 1,296,000 seconds, 15 days | `R-token` on the refresh call | + +```bash +curl --location --request GET 'https://apisbx.abdm.gov.in/hcx/abha/biometric/auth/refresh/token' \ + --header 'R-token: Bearer ' \ + --header 'Authorization: Bearer ' \ + --header 'payerid: ' \ + --header 'process: Preauth' +``` + +[Biometric auth refresh token in the API reference](/docs/nhcx/v1/api/biometric/endpoints/biometric-auth-refresh-token) + +Refreshing returns a **new refresh token** whose 15 days run from that moment. +The portal's advice is to call the refresh endpoint once within every ten days +and store the new token, which keeps a chain alive indefinitely. + +Two rules the scheme enforces on top of the lifetimes. + +- **Refresh automatically for the duration of a transaction cycle.** If the user + token lapses mid-case, start a fresh biometric authentication. It is not + enough to have authenticated once at some point. +- **A refresh token is not a capture.** On a cyclic procedure the payer pays + only for cycles with a live biometric, and a refresh token is accepted only + at the final claim. Every visit needs a real capture, with `process` set to + `Discharge`. + +## When biometrics are not possible + +Two separate situations, and they are handled differently. + +**The beneficiary's ABHA is not linked to their PMJAY card.** Biometric +authentication does not apply at all. Follow the scheme's existing KYC +protocols. + +**Biometrics are possible in principle but fail in practice.** Capture an +Aadhaar exemption consent document, signed by both the patient and a hospital +representative, store it digitally against the beneficiary record, and answer +the scheme's authentication-consent questionnaire in the bundle. + +There are two such questionnaires and they come from different places: + +| Form | Where it comes from | Used at | +| :---- | :---- | :---- | +| Authentication Consent | The coverage eligibility response, purpose auth-requirements, and the plan master | Preauthorisation | +| Discharge Consent | The insurance plan | Claim | + +Both are the plan's own forms, found by title in the package master, so read +the URL and the link ids off the master rather than writing them into code. The +answers travel as a `QuestionnaireResponse` referenced from a supporting-info +entry of category `INF`, code `ODN`. The payer refuses a request with neither a +valid token nor the matching response, and names which is missing: +`PAYR-1256` at preauthorisation, `PAYR-1363` at the claim. + +The consent has a prescribed format that the payer's fraud engine checks, and +the exemption undertaking is submitted to the payer at claim time. + +**The one case with no fallback is a cyclic procedure**, where live biometrics +are required at every step and a consent form cannot stand in. + +## What to store + +- The user token and its expiry, against the case rather than the session. +- The transaction ID of every authentication, the method used and the moment it + succeeded. On a cyclic case the payer checks each cycle's recorded start and + end against the biometric timestamp, and a mismatch voids the cycle. +- The exemption consent document, linked to the beneficiary record, where one + was used. +- Nothing else from the ABHA profile beyond what the encounter needs, and never + the encrypted Aadhaar value. + +## What to test + +- Each of the three methods end to end. +- Token expiry mid-case, and automatic refresh. +- A refresh token older than fifteen days. +- The consent fallback at preauthorisation and again at discharge. +- A case authenticated by one method at admission and another at discharge. +- A cyclic case with a capture at every visit, and one deliberately missing, to + confirm the payer pays only for captured cycles. diff --git a/site/docs/nhcx/v1/roles/provider/discharge-and-claim.md b/site/docs/nhcx/v1/roles/provider/discharge-and-claim.md new file mode 100644 index 000000000..d458e7968 --- /dev/null +++ b/site/docs/nhcx/v1/roles/provider/discharge-and-claim.md @@ -0,0 +1,83 @@ +--- +title: Discharge and claim +sidebar_label: Discharge and claim +sidebar_position: 6 +description: Cashless claim submission, discharge types, and billing evidence +verification: unverified +source: nhcx-package/docs/03-Building a Provider/06-Discharge and Claim.md +generated: true +sidebar_custom_props: + roles: + - provider +--- + +# Discharge and claim + +On the general network the claim is two submissions. A provisional one goes before the patient leaves, so the payer can object while corrections are still cheap. The final one goes after discharge, with the finalised bill, and is the one adjudicated for settlement. Both are the same `Claim` resource with `use = claim`, told apart by workflow code. + +## What the user does + +**Discharge.** The user records the discharge type, from the NRCeS set: to home, to mortuary, left against medical advice, discharged against medical advice. Discharge date, and surgery date where there was one. The documents available at this point are attached and the provisional submission goes. + +**Final claim.** After the payer's answer to the provisional submission, the finance section: hospital bill number and date, the bill itself, the amount claimed. Post-operative evidence and anything the payer flagged on the provisional review are attached. The claim amount may not exceed the preauthorisation's approved amount; enforce it before submit. + +## What the system calls + +``` +POST /v1/claim/submit workflow 15, the final claim +callback /v1/claim/on_submit +``` + +The provisional discharge submission carries workflow 14 and the same `Claim` bundle. The workflow sheet defines the code and the handbook describes the stage, but neither names the endpoint it travels on; `/v1/claim/submit` is the natural home, and the sample bundles do not include one. Confirm with the payer before building the provisional step. + +Same recipient, same reference as the preauthorisation, a new correlation ID each time. The handbook's advice is to build the claim from the preauthorisation bundle. Same diagnosis and procedures unless treatment deviated, estimated amounts replaced with the bill, the full document set added, and the `preAuthRef` from the approval carried in. + +## What goes in the bundle + +The same `Claim` as the preauthorisation with `use = claim`. That single field is the difference the payer keys on. What changes in practice: + +- Supporting-info dates grow from two to four, plus the discharge status: + +| Field | Category | Code | +| :---- | :---- | :---- | +| Registration date | `OTH` | `EDT` | +| Admission date | `ADMD`, or `ONS` | `ADDD` | +| Surgery date | `SURD`, or `ONS` | `ADDD`, or `PSP` | +| Discharge date | `DSCHD`, or `ONS` | `ADDD`, or `DSDE` | +| Discharge status | `DIS` | `DTH`, `DTM`, `LAMA` or `DAMA` | +| Death date, if `DTM` | `ONS` | `DTM` | + +**Two forms exist for those three dates and they are not interchangeable.** The payer's own error codes describe the `ONS` form with distinct codes per date. Every one of the twenty-two published sample bundles uses the other: category `ADMD`, `SURD` or `DSCHD`, all three carrying the code `ADDD`, so the category is what tells them apart and the code is noise. Send what the samples send, keep the `ONS` form behind a switch, and settle it with your payer before certification. The Codes and Value Sets chapter sets out both. + +- The discharge summary as a document under category `HDS`. +- The bill under category `MB`, and the remaining mandatory documents the plan lists for claim rather than preauthorisation. + +## Reading the answers + +The provisional submission is answered with 261 approved, 262 rejected or 263 queried. A rejection here means fix and resend before the final claim; nothing is closed. + +The final claim uses the same decision table as preauthorisation, with two additions. The payer may send several interim answers on the same correlation ID before a final one: `28` in process, `29` forwarded, each with `response.partial`. Keep listening until `response.complete`. And a rejection, `291` with reason `cancelled`, closes the claim permanently; nothing further can be submitted against that claim number except a Task. + +The claim is only closed once payment code 33 arrives with a UTR. Adjudication closes the decision; settlement closes the money. + +## What the payer checks on a claim + +On top of the preauthorisation checks, a claim is refused for these. + +| Check | Why it exists | +| :---- | :---- | +| An approved preauthorisation exists for the case number | `ERR-PYR-CLM-007` under PMJAY, where the claim goes out under the pre-authorisation's number rather than a number of its own | +| No claim already raised against it | One case, one claim | +| Every item was on the preauthorisation, was not rejected there, and is not claimed at a higher quantity | The claim cannot grow past what was approved | +| The discharge status and the discharge date are present | They are what tell the payer the episode ended, and when. The gateway checks for them before the payer sees the bundle | +| The amount is within the approved amount and the wallet | Enforce it before enabling submit | +| Under PMJAY, the discharge biometric token or the discharge consent questionnaire | `PAYR-1363` names the missing form | + +## After a decision + +| Situation | What the user does | What the system sends | +| :---- | :---- | :---- | +| Query | Attaches what was asked, replies from the inbox | Communication response, or claim bundle with workflow 151 where the payer takes it there | +| Rejected or reduced | Appeals, with a document | Task, code `reprocess`, workflow 36 | + +The Task names the case by claim number and carries a reason: `claimrejected` for a rejection, `partialpayment` for a shortfall, and the value set also allows `erroneousclaim`. The payer's answer comes on `/v1/task/on_submit` as a Task wrapping a `ClaimResponse`, read with the same parser as any other: 252 approved, 253 rejected, 254 queried. Map the payer's denial reasons, `ClaimError-1` onward, into the appeal screen so the user sees why before deciding whether to appeal. diff --git a/site/docs/nhcx/v1/roles/provider/index.md b/site/docs/nhcx/v1/roles/provider/index.md new file mode 100644 index 000000000..243e033c5 --- /dev/null +++ b/site/docs/nhcx/v1/roles/provider/index.md @@ -0,0 +1,119 @@ +--- +title: Provider overview +sidebar_label: Provider overview +sidebar_position: 1 +description: Hospital integration architecture and queue flow +verification: unverified +source: nhcx-package/docs/03-Building a Provider/01-Provider Overview.md +generated: true +sidebar_custom_props: + roles: + - provider +--- + +# Provider overview + +A provider system is the hospital's side of the exchange. It takes a patient from the front desk to a settled claim without anyone leaving the HMIS. It does that by making a fixed set of calls to the exchange and hosting a fixed set of callbacks for the payer's answers. + +This section assumes the base framework from Getting Started is working: you have a token, a participant record, your own key, and a callback endpoint that opens messages. Everything here is what goes on top. + +Registration and Eligibility, Insurance Plan, Preauthorisation, Discharge and Claim, and Payment and Communication describe the flow as NHCX defines it for any payer. PMJAY runs the same endpoints with different rules around them; those rules are collected in PMJAY Provider so the generic flow stays readable and the scheme's additions are in one place, and Biometric Authentication covers the scheme's proof that the beneficiary was present. UI Guide turns all of it into screens, for whoever is designing the hospital's interface rather than its integration. Provider Checklist is the checklist you have to demonstrate to leave the sandbox. + +## What the hospital sees + +The user-facing shape is a handful of screens that map one-to-one onto exchange calls. The mapping is worth fixing early, because it decides where each API is called from. + +| Screen | What the user does | Exchange call behind it | +| :---- | :---- | :---- | +| Patient search | Finds the beneficiary by ABHA, member ID or mobile; picks the payer | Participant list, policy lookup | +| Registration | Confirms cover and sees the remaining limit | Coverage eligibility, purpose validation | +| Treatment plan | Picks the service or package, sees what is covered and what documents are required | Insurance plan (cached), eligibility with purpose benefits and auth-requirements | +| Preauthorisation | Fills clinical and financial sections, attaches documents, submits | Preauthorisation submit | +| Enhancement | Adds procedures or days against an approved case | Preauthorisation submit, enhancement code | +| Query inbox | Reads a payer request for more, attaches what was asked, replies | Communication request and response | +| Discharge | Records discharge and sends a provisional claim before the patient leaves | Claim submit, discharge code | +| Claim | Confirms the final bill, submits | Claim submit | +| Reprocess | Appeals a rejection or a reduced approval | Task submit | +| Payments | Sees notices, UTR and deductions; acknowledges | Payment notice callback, acknowledgement | +| Case status | One line per case with its current state | Driven by callbacks and status check | + +```mermaid +flowchart LR + S[Patient search] --> R[Registration] + R --> T[Treatment plan] + T --> P[Preauthorisation] + P --> Q[Query inbox] + Q --> P + P --> E[Enhancement] + E --> P + P --> D[Discharge] + D --> C[Claim] + C --> Q + C --> M[Payments] + C -. rejected or short .-> X[Reprocess] +``` + +## What the system calls + +From the Overview's use-case catalogue, a provider calls the B-series and the shared A-series, and hosts the callbacks for each. In sequence for one admission: + +1. `/fetch/participants/list` and `/participant/get/policies`, to find the payer and the policy. +2. `/v1/insuranceplan/request`, once per policy, refreshed on a schedule. +3. `/v1/coverageeligibility/check`, at registration and again before each submission. +4. `/v1/preauth/submit`, for the first request and every follow-up on it. +5. `/v1/claim/submit`, for the provisional discharge submission, the final claim, and query answers. +6. `/v1/task/submit`, to cancel a preauthorisation or appeal a claim. +7. `/v1/status`, whenever a case has gone quiet. + +And hosts `on_check`, `on_request`, `on_submit` for each of those, plus `/v1/communication/request`, `/v1/paymentnotice/request`, `/v1/on_status` and `/v1/error`. + +## What the system must keep + +A provider integration is as much a data model as an API client. Persist, per case: + +- The payer's participant code, the processor code, member ID, product and policy number from the lookups. +- Every correlation ID sent, with the workflow code and what it was for, so callbacks can be matched. +- Every raw callback as received, before it is interpreted. +- The case state, derived from callbacks. The handbook's mapping is a good starting point: approved, partially approved, pending on a query, rejected, cancelled, and then settled once payment code 33 arrives. +- The insurance plan, versioned, with the version used on each submission. + +## Build it in this order + +The exchanges depend on each other, and building them out of order means testing against answers you cannot yet get. + +| Order | Build | Because | +| :---- | :---- | :---- | +| 1 | The base framework from Getting Started | Nothing below works without a token, a key, a participant record and a callback that answers | +| 2 | Participant list and policy lookup | They produce the processor code every later message is addressed to | +| 3 | Coverage eligibility, purpose validation | The cheapest exchange to get right, and the one that proves the whole round trip | +| 4 | Insurance plan, cached | The treatment screen is built from it, and preauthorisation validation depends on it | +| 5 | Preauthorisation, then its query answer | The first bundle with clinical content, and the one payers scrutinise hardest | +| 6 | Claim, then its query answer | Reuses the preauthorisation bundle with one field changed | +| 7 | Payment notice and acknowledgement | Closes the case, and under PMJAY gates the shortfall | +| 8 | Task: cancel and reprocess | Needed for sandbox exit, rarely needed on day one | + +Provider Checklist is the checklist you demonstrate to leave the sandbox, and it names all thirteen use cases NHA asks for. + +## Error families, and which desk they belong to + +Errors arrive from two places and they go to two different people. + +| Family | Where it arrives | Who acts | +| :---- | :---- | :---- | +| `PAYR-10xx`, `PAYR-11xx` | Inside the sealed response | The desk. Show the payer's own sentence | +| `PAYR-102x` structural block | Inside the sealed response | The integration team. It means an id or sequence is missing, not a wrong value | +| `ClaimError-n`, `PreauthError-n` | Inside the sealed response, on a denial | The desk, on the appeal screen, so the user sees why before deciding to appeal | +| `ERR-PYR-CLM-007` | Inside the sealed response | The integration team. The claim was sent under the wrong case number | +| Protocol response, `response.error` | On the callback, in the clear | The integration team. The message could not be opened | +| `NHCX-1010` | From the exchange | The integration team. A verdict was sent after the correlation was retired | + +A protocol response is never a claims-desk problem. Route it away from the queue and toward whoever owns the integration. + +## Where the rules live + +Two rulebooks shape what a provider may send, consulted in this order: + +1. **The insurance plan** says what the policy covers, at what limits, with which documents required. +2. **The eligibility response** says whether this patient is covered right now, how much remains, and which of the plan's requirements apply to the services chosen. + +A scheme adds a third: its own rules for how a case is built. For PMJAY those are in PMJAY Provider. diff --git a/site/docs/nhcx/v1/roles/provider/insurance-plan.md b/site/docs/nhcx/v1/roles/provider/insurance-plan.md new file mode 100644 index 000000000..520cbc818 --- /dev/null +++ b/site/docs/nhcx/v1/roles/provider/insurance-plan.md @@ -0,0 +1,87 @@ +--- +title: Insurance plan +sidebar_label: Insurance plan +sidebar_position: 4 +description: Dynamic package master retrieval and caching +verification: unverified +source: nhcx-package/docs/03-Building a Provider/04-Insurance Plan.md +generated: true +sidebar_custom_props: + roles: + - provider +--- + +# Insurance plan + +The plan is the policy as data. It tells the hospital system what a policy covers, at what limits, under what conditions, and with which documents. So the treatment screen is built from the payer's own rules rather than from a PDF someone once read. Nothing on that screen should be typed in by hand if the plan already knows it. + +## What the user does + +The user never asks for the plan. It is fetched in the background and the treatment screen is built from it. + +**Choose what is being treated.** The specialties, services or packages offered are the ones the plan lists for this hospital. Nothing else is shown. + +**See the terms.** The limit for each benefit, any waiting period or exclusion that applies, and whether preauthorisation is required for it. + +**See the requirements** as a checklist: the documents the plan lists as mandatory at policy level and per benefit, and any questionnaire the payer attaches to a benefit. Render the questionnaire from the plan's Questionnaire resource rather than hard-coding it. + +## What the system calls + +``` +POST /v1/insuranceplan/request Task, code poll, inputs policyNumber and providerId +callback /v1/insuranceplan/on_request +``` + +Fetch once per policy the hospital deals with, and refresh on a schedule and whenever a payer communication with reason `policychange` arrives. The handbook's guidance is to fetch at registration or admission, before treatment planning, and alongside eligibility. + +## What comes back, and how to store it + +A collection bundle with one `InsurancePlan`, the `Organization`s, and one `Questionnaire` per requirement. + +**Two shapes exist, and they are not layout variants.** A payer picks one per product, and which one arrives decides how the treatment screen works. A system that handles both needs two code paths behind one screen. + +| | Package-based | Coverage-based | +| :---- | :---- | :---- | +| Sent by | Government schemes. PMJAY throughout | Private insurers and their TPAs | +| Structure | `plan → specificCost → category → benefit → cost`, with the rules on `coverage[]` alongside | `coverage → benefit → limit` | +| The unit | A named package at a fixed all-inclusive rate | A benefit with a money cap, such as ICU charges or room rent | +| What the user picks | A specialty, then a package. The rate is fixed and not editable | A service, then bills against it | +| Where the amount comes from | The plan's `Procedure` or `Stratification` cost line | The hospital's own bill, checked against the benefit limit | +| Rules arrive as | Sixteen `Claim-Condition` flags per package | `benefit.requirement` strings such as "Pre-authorisation required" | +| What blocks submission | A code or display differing from the plan, character for character | An amount over the limit, or a missing mandatory document | +| Sampled | Yes, one 21 MB payload | No sample in the published corpus | + +PMJAY Provider covers what the package flags do. The FHIR Reference has a chapter for each shape. + +### Storing it + +Store the plan as data, not as a blob. Both shapes need the same five things pulled out and indexed. + +| What to extract | Package-based | Coverage-based | +| :---- | :---- | :---- | +| The pickable list | Specialties from `coverage[].type`, packages from `benefit[]` | Cover types from `coverage[].type`, services from `benefit[]` | +| The money | `specificCost` cost lines, joined to the rules on the package code | `benefit.limit[].value` | +| The rules | The sixteen flags per package | The `requirement` string | +| The document checklist | `Claim-SupportingInfoRequirement`, package level plus plan level | The benefit's required documents | +| The forms | `Questionnaire` resources the requirements point at | As published by the insurer | + +A scheme plan is large. The published PMJAY plan is 21 MB with 2,217 entries, and it cannot be handled by a naive JSON parser inside a request-response cycle. Stream it, or parse it once on a worker and store the result. + +Store the plan as data, not as a blob: benefits with their limits or rates, the conditions and exclusions from the plan's extensions, the document requirements, and the questionnaire URLs. Keep a version stamp on every stored plan, and record which version each submission used. A rate that changed on the payer's side without a refresh on yours is the commonest cause of a reduced approval. + +## What to validate before submitting + +The plan is also the first line of validation, run on the server, not only in the browser: + +- Codes and displays exactly as the plan has them, character for character, **including its misspellings**. The published PMJAY plan carries `Opthalmology` and `Transegender Procedure`, and a preauthorisation whose display differs from the plan's is rejected on the display. +- Amounts within the benefit's limit; quantities within what the plan allows. +- Every document the plan marks mandatory attached before submit is enabled. +- Under a package plan, implant and stratification counts within their maxima, and a standalone package with nothing else beside it. + +A base rate of zero is not an error. In the published plan, package `MG004A` has a base limit of 0 INR and stratification limits of 1,800 to 4,500, meaning the payable amount is decided entirely by the bed category chosen. Do not treat 0 as missing data, and do not submit a zero-value item line. + +## When the plan goes stale + +Refresh on a `policychange` communication, on whatever periodic schedule operations accepts, and before treatment planning if the cached copy has no version stamp. The FRD says weekly; the scenario sheet says every fifteen days. Under PMJAY an outdated tariff version causes a rate mismatch and automatic rejection on suspicion of tampering. + +Stamp the cache with the plan's scheme revision, and record on every preauthorisation and claim which revision it was built against. A rate that changed on the payer's side without a refresh on yours is the commonest cause of a reduced approval. The revision stamp is what turns that into a diagnosable event rather than a mystery. diff --git a/site/docs/nhcx/v1/roles/provider/payment-and-communication.md b/site/docs/nhcx/v1/roles/provider/payment-and-communication.md new file mode 100644 index 000000000..17911ca23 --- /dev/null +++ b/site/docs/nhcx/v1/roles/provider/payment-and-communication.md @@ -0,0 +1,96 @@ +--- +title: Payment and communication +sidebar_label: Payment and communication +sidebar_position: 7 +description: Payment reconciliations (wf 30, 31, 33) and out-of-band communication +verification: unverified +source: nhcx-package/docs/03-Building a Provider/07-Payment and Communication.md +generated: true +sidebar_custom_props: + roles: + - provider +--- + +# Payment and communication + +Two exchanges arrive unasked. The payer initiates both, and the provider's job is to receive, act, and acknowledge. + +## Payment notices + +### What the user sees + +A payments screen, per case, showing the sequence as it happens: initiated, processed, settled. On settlement, the UTR number, the gross amount, the TDS and other deductions, and the net. A button to acknowledge. Reconciliation staff will match the UTR against the bank statement, so print it as text they can read and select. Copyable means a copy control next to the printed value, not the value tucked inside an input box in its place. + +### What the system hosts + +``` +callback /v1/paymentnotice/request workflows 30, 31, 33 +``` + +Three notices can arrive for one claim, and each is a fresh delivery to acknowledge: 30 when the payer initiates, 31 when the bank processes, 33 when it settles. Only 33 carries the UTR. Mark the case settled on 33, not before. + +### What comes in + +A collection bundle: a `Task` with code `deliver` wrapping a `PaymentNotice` and a `PaymentReconciliation`, plus the two `Organization`s. + +- `PaymentNotice.amount` is the net paid; `paymentStatus` is `paid` or `cleared`. +- `PaymentReconciliation.paymentIdentifier.value` is the UTR. +- `PaymentReconciliation.detail[]` itemises the money: one line with type `TDS`, one with type `Payment`, and any others the payer uses (approved amount, service tax, advance, recovered, penalty). Net plus deductions should equal the approved amount; if it does not, flag it. + +### The acknowledgement + +A `Task` with `status = completed`, code `status`, and an output of type `status` whose value is `paymentack`, plus the claim number as a second output. Workflow 17. Send it to the payer. + +Where it goes is stated two ways on the portal: the Payment document and exit checklist say `/v1/paymentnotice/on_request`; the handbook says `/v1/task/submit`. Build to send to `on_request` and make the path configurable per payer. + +## Communication requests + +### What the user sees + +An inbox. Each message has a reason, a priority and a body, and needs a different response. A request for additional information needs documents attached; this is how a payer asks for more on a case. A turnaround-time alert goes to the claims desk to chase. A grievance needs a reply and possibly a corrective action. A benefit update should refresh the balance shown on the case. A policy change should trigger a plan refresh. An arbitration acknowledgement just tells the desk the appeal has been received. + +### What the system hosts + +``` +callback /v1/communication/request +reply /v1/communication/on_request +``` + +Switch on `Task.reasonCode`: `additionalinfo`, `tatquery`, `grievance`, `walletupdate`, `policychange`, `claimArbitration`. Build the `additionalinfo` path first; it is the query channel on the general network. Then `tatquery`, which the handbook reports as the most common reason in live traffic. + +### What comes in, and what goes back + +A collection bundle: a `Task` with code `poll` and an input of type `include` pointing at a `Communication`, plus the `Organization`s. On the `Communication`: `category` (reminder, notification, instruction or questionnaire), `priority` (routine, urgent, asap, stat), `topic` (usually progress-update), and the case reference as its identifier. + +The answer is the same bundle shape sent back with the same correlation ID, the provider `Organization` first, and `Task.status = completed`. For a plain acknowledgement, send it within the 30-second window regardless of whether the underlying issue is resolved. For an `additionalinfo` request, the answer carries the requested documents as well. + +## What to reconcile + +The reconciliation is what accounts works from, so store its lines rather than only the net. + +| Line type | What it is | +| :---- | :---- | +| `Payment` | The net amount the bank moved | +| `TDS` | Tax deducted at source | +| `approvedamount`, `claimedamount` | What was granted and what was asked | +| `servicetax`, `advance`, `recovered`, `penality` | Other adjustments the payer applies. Note the spelling of the last one; it is the payer's | + +Net plus deductions should equal the approved amount. When it does not, flag it rather than silently accepting the difference, because that is the only place a short payment shows up before the shortfall window opens. + +A return payment, where money has to come back, has its own codes: RP1 intimation, RP2 acknowledged, RP3 failed. + +## Two acknowledgements, and they are different things + +The screen should not confuse them, and neither should the code. + +| | Transport acknowledgement | Business acknowledgement | +| :---- | :---- | :---- | +| What it is | The `202` and receipt your callback returns | A `Task` on workflow 17 sent back to the payer | +| When | Automatically, within 30 seconds of the notice arriving | When the notice has been recorded against the claim | +| Who sees it | Nobody. It is protocol | The desk, as a button and a sent state | +| What it means | The message was taken in | The provider has recorded the payment | +| What happens without it | The exchange retries five times, then retires the correlation ID | Under PMJAY, the shortfall window never opens | + +## Notifications for patients + +If the hospital also runs a patient app, it can subscribe on the beneficiary's behalf and receive the same events as human-readable messages. That is a separate participant role, covered under the E-series in the Overview. diff --git a/site/docs/nhcx/v1/roles/provider/pmjay-adjudication-apis.md b/site/docs/nhcx/v1/roles/provider/pmjay-adjudication-apis.md new file mode 100644 index 000000000..c7f2d13c3 --- /dev/null +++ b/site/docs/nhcx/v1/roles/provider/pmjay-adjudication-apis.md @@ -0,0 +1,217 @@ +--- +title: PMJAY adjudication APIs +sidebar_label: PMJAY adjudication APIs +sidebar_position: 12 +description: The two payer service calls that read and drive a PMJAY case, the role walk, and what the desk refuses +verification: unverified +source: nhcx-package/docs/03-Building a Provider/12-PMJAY Adjudication APIs.md +generated: true +sidebar_custom_props: + roles: + - provider +--- + +# PMJAY adjudication APIs + +A PMJAY case is not decided over NHCX. The exchange carries the submission to +the scheme and carries the verdict back, but the decision itself is taken in +the State Health Agency's own Transaction Management System, by a named role, +on that system's schedule. Between the two sits the NHCX Payer Service, which +is how an external integrator reads and drives that queue. + +The previous chapter, PMJAY Sandbox Run, records what one case did; this one +is the interface. + +The source for the endpoints, the roles and their action names is the NHCX +Payer Service API Workflow Guide for External Integrators, a supporting +document on the portal's NHCX-PMJAY-HMIS Integration page, and it remains the +authority on them. What the service did beyond the guide, the case id it +insists on, its refusals and its pace, is from that sandbox run. + +It matters to two audiences. A scheme payer building its own side needs to know +what shape the exchange expects a role-based queue to present. An integrator +testing against the sandbox needs it because there is no other way to make a +PMJAY case move. + +## Two endpoints, two hosts + +| What | Where | +| :---- | :---- | +| Who holds the case | `POST https://apisbx.abdm.gov.in/pmjay/sbxhcx/nhcxpayerservice/v1/get/user-role` | +| Act on the case | `POST https://apisbeta.nha.gov.in/pmjay/hcx/nhcxpayerservice/wrapper/process/case` | + +Both take an ordinary ABDM session token on `bearer_auth`, with +`Content-Type: application/json` and `Accept: application/json`. The token is +the same one every other call uses, minted from the participant's client ID and +secret at the sessions endpoint. In the sandbox it lives 1,200 seconds. + +Note that the two endpoints sit on different hosts. That is not a +documentation error; it is how the service is deployed. + +## Who holds the case + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/nhcxpayerservice/v1/get/user-role' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --data-raw '{ + "caseid": "", + "payerid": "" + }' +``` + +[Adjudicator: role for a case in the API reference](/docs/nhcx/v1/api/adjudicator/endpoints/adjudicator-adjudicator-role) + +```json +{ "currentuserrole": "PPD-Trust", "errormessage": null } +``` + +**`caseid` is the scheme's case id, not the hospital's claim number.** It is +the digits at the end of the case reference the payer issues. Asked about a hospital's own number the +service answers that no data was found and tells you to use the current active +case id. + +A hospital therefore has to learn the scheme's case id for every +preauthorisation it raises. The sandbox gives it out in two places: inside the +`PAYR-1238` refusal of the next request for that beneficiary, and, once a +request is accepted, in the payer's acknowledgement and status answers on the +case. Store it beside your own claim number the moment it appears. + +**Read the role before every action.** The service moves cases on its own +schedule, and the role that answers is the only one whose action names are +legal. A cycle that assumes the next step in the table will be refused. + +**A preauthorisation role on a claim means "not yet".** If the role lookup +still answers `PPD-Trust` while you are asking about a claim, the case has not +left the preauthorisation queue. The role names where the case is, not what you +are asking about. + +## Acting on the case + +One endpoint, one body shape, with the action spelled exactly as the table +gives it for the role that currently holds the case. + +```bash +curl --location --request POST 'https://apisbeta.nha.gov.in/pmjay/hcx/nhcxpayerservice/wrapper/process/case' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --data-raw '{ + "casenumber": "", + "action": "Approve", + "receivercode": "", + "usecase": "PREAUTH", + "correlationid": "", + "sendercode": "", + "memberid": "", + "remarks": "ok" + }' +``` + +[Adjudicator: act on a case in the API reference](/docs/nhcx/v1/api/adjudicator/endpoints/adjudicator-adjudicator-process) + +| Field | What it carries | +| :---- | :---- | +| `casenumber` | The scheme's case id, as above | +| `action` | Exactly as the role's row gives it. Case-sensitive | +| `usecase` | `PREAUTH`, `CLAIM`, or the committee's own name | +| `receivercode` | The payer's registry id, without the `@hcx` suffix | +| `sendercode` | The provider's participant code, without the suffix | +| `memberid` | The beneficiary | +| `correlationid` | **A fresh UUID for every call** | +| `remarks` | Free text the desk records | + +## The role walk + +| Step | Role | Actions | `usecase` | +| :---- | :---- | :---- | :---- | +| Preauthorisation | `PPD-Trust` | `Approve`, `Reject`, `Query` | `PREAUTH` | +| Claim 1 | `CEX-Trust` | `Forward` | `CLAIM` | +| Claim 2 | `CPD-Trust` | `cpdApprove`, `cpdReject`, `Pending` | `CLAIM` | +| Claim 3 | Medical Audit Committee | `Approve`, `Reject`, `iQuery` | `Medical Audit Committee` | +| Claim 4 | `ACO-Trust` | `Approve`, `Reject`, `Pending` | `CLAIM` | +| Claim 5 | `SHA-Trust` | `Approve`, `Reject`, `Pending` | `CLAIM` | +| Claim 6 | Claim Review Committee | `Approve`, `Reject`, `Pending` | `Claim Review Committee` | + +Four things about that table. + +**A preauthorisation is one decision. A claim walks a queue.** The roles map +onto the scheme's own staff: the Preauthorisation Processing Doctor, the claim +executive, the Claim Processing Doctor, the audit and accounts roles, the State +Health Agency and, on appeal, the Claim Review Committee. + +**The action names are not consistent between roles.** `CPD-Trust` takes +`cpdApprove` and `cpdReject`; every other role takes `Approve` and `Reject`. +Sending `Approve` to `CPD-Trust` is refused. + +**`usecase` changes at the two committees** and carries the committee's full +name with spaces, not a code. + +**Not every case walks all six.** On the run recorded in PMJAY Sandbox Run the +claim was forwarded by `CEX-Trust`, approved by `CPD-Trust`, then by +`ACO-Trust` and `SHA-Trust`, after which the role lookup answered with no role +at all. Neither committee held the case. The six steps are the roles a case +*may* pass through, not a queue every case walks. + +## How the decision comes back + +The desk call and the NHCX callback are two halves of one step. Acting on the +case makes the scheme issue its verdict, and that verdict arrives at the +provider over NHCX as an ordinary `ClaimResponse` on the original request's +correlation id. + +So a provider system driving this in a sandbox has to hold both threads: the +payer service call it just made, and the callback it is waiting for. They are +correlated by the case, not by the correlation id of the desk call, which is +fresh every time. + +## What it refuses, and what those refusals mean + +| Message | What it means | +| :---- | :---- | +| `No Data found with the caseid . Please use the current active case id.` | You asked with the hospital's claim number instead of the scheme's case id | +| `Event Meta Log not found for correlationId` | The exchange has not finished delivering the request you are acting on. Try again shortly | +| `Case not found for caseId` | The case is mid-filing. Try again shortly | +| An action refused for the current role | Read the role again. It has moved, or it never was what you assumed | + +The first is a modelling error and needs a fix. The second and third are timing +and are safely retried. + +## What it will not do + +**It is not a status API over NHCX.** A `Task` coded `status` sent to the +scheme is refused, first with `PAYR-1018` for a missing reason code and then +with `PAYR-1008` for a code and reason combination the scheme does not accept. +Where a case stands is read here, not asked for over the exchange. + +**It re-queues rather than answering immediately.** The scheme acknowledges an +enhancement it has been asked to approve by answering `queued` again, and +decides in its own time. On one run the enhancement was approved a minute after +the ask; on another it was still queued five minutes on, with the same bundle. +Nothing in what you send changes that, and a test suite has to report the +scheme's pace rather than assert it away. + +**One request at a time on a case.** `PAYR-1322`, which the sandbox sends as +"active instance found" although the error sheet gives it another message, is +the rule behind most of the timings above. A claim raised while an enhancement is +still queued is refused, and the role lookup still answers with the +preauthorisation role because the case has not left that queue. + +## What a scheme payer should take from this + +If you are building the payer side rather than testing against it, the shape +worth copying is the separation. The exchange carries messages; the queue +decides cases; the two are joined by a case id the payer issues and the +provider stores. Three consequences follow for your own build. + +- **Issue a case number on the first answer and repeat it on every later one.** + The provider files the case under it and every subsequent action names it. A + desk asked about a case by the hospital's own number should still find it, + but the published reference implementation does not, which is why the + provider has to learn yours. +- **Acknowledge before you decide.** Answer every submission at once with an + interim response, or the exchange retires the correlation before your + adjudicator gets to it. Error Codes covers `NHCX-1010`. +- **Expose where a case is.** Whatever your equivalent of the role lookup is, + a provider needs it, because your queue is invisible from the exchange. diff --git a/site/docs/nhcx/v1/roles/provider/pmjay-provider.md b/site/docs/nhcx/v1/roles/provider/pmjay-provider.md new file mode 100644 index 000000000..3d043a2f6 --- /dev/null +++ b/site/docs/nhcx/v1/roles/provider/pmjay-provider.md @@ -0,0 +1,185 @@ +--- +title: PMJAY provider +sidebar_label: PMJAY provider +sidebar_position: 8 +description: PMJAY-specific HMIS rules, STG questionnaires, GST, incentives, and size limits +verification: unverified +source: nhcx-package/docs/03-Building a Provider/08-PMJAY Provider.md +generated: true +sidebar_custom_props: + roles: + - provider +--- + +# PMJAY provider + +The chapters before this one describe the flow NHCX defines for any payer. When the payer is PMJAY the endpoints do not change, but the rules around every screen do. This chapter collects them, in the same order as the generic chapters, so that a hospital building for the scheme reads the generic chapter for the shape and this one for the differences. + +The Overview's PMJAY chapters explain why these rules exist. This chapter is about what to build. + +## What changes, in one table + +| Generic flow | Under PMJAY | +| :---- | :---- | +| Patient found by ABHA, member ID or mobile | Also by Ayushman ID; a member card is shown; the patient is biometrically verified before registration | +| Plan is coverage-based or package-based | Always package-based, with flags on every package that drive the screen | +| Documents are attached as scans | Clinical documents must be structured ABDM health-information types | +| Payer queries arrive as a communication request | Payer queries arrive inside the queried `ClaimResponse`; the answer goes on the preauthorisation or claim endpoint | +| Provisional discharge submission, then final claim | No discharge submission; the claim asserts the discharge and carries its details | +| Appeal once the decision arrives | Reprocess after rejection at once; shortfall only after payment 33 is acknowledged; each once; the Committee is final | +| Communication channel carries document requests | Communication channel carries TAT alerts, grievances, wallet and policy changes, arbitration acknowledgements; never document queries | +| Go live when production credentials arrive | Go live when NHA maps the hospital's HEM ID to its participant ID; in-flight TMS cases finish in TMS | + +## Registration + +**Search** by Ayushman ID, mobile or ABHA. Show the member card once found. + +**Verify the patient biometrically** before registering. Build all three methods, fingerprint, iris and face; any may be the one that works for a given patient, and the scheme requires all three to be available. Fingerprint and iris are an init-then-verify pair. Face is a separate flow: initiate, show a QR code the patient scans in the ABHA app, poll until capture completes, verify with the Aadhaar number encrypted under the key the portal supplies. + +On success the system holds a **user token**, valid 30 minutes, with a refresh token. It goes in the header of the eligibility check and the preauthorisation. Refresh it automatically through the transaction; if it lapses, authenticate again. A fresh authentication is required at discharge, and that token rides on the claim. It need not use the same method as the preauthorisation; a case authenticated by fingerprint at admission can be authenticated by face at discharge. And where biometrics fail at discharge, the discharge authentication-consent questionnaire from the plan stands in, exactly as at registration. + +**Where biometrics are not possible**, capture the Aadhaar exemption consent, signed by patient and hospital representative, as a document on the record, and answer the authentication-consent questionnaire. There are two of them and they come from different places: the one for a preauthorisation arrives in the coverage eligibility response with purpose auth-requirements, the one for discharge is in the insurance plan. The payer refuses a request that has neither a valid biometric token nor the matching consent response, and names which is missing. The FRD adds that the exemption undertaking is submitted to the payer at claim time. The consent has a prescribed format that the payer's fraud engine checks. The one case with no fallback is a cyclic procedure, where live biometrics are required at every step. + +**Applicability.** Biometric verification applies to beneficiaries whose ABHA is linked to their PMJAY card; others follow the scheme's existing KYC. + +**Cover.** Eligibility with purpose validation returns the wallet: one benefit entry per wallet, allowed and used. The whole family shares one annual limit; show what remains, and refuse registration when it is exhausted. + +**Capture** communication address, care plan and attendant details, and upload the authentication consent. + +## Insurance plan + +Package-based, and large: the reference response is 21 MB with over two thousand questionnaires. Store it as data, versioned. + +**The flags drive the screen.** Every package carries claim-condition flags, and the treatment screen must obey them: + +| Flag | What the screen does | +| :---- | :---- | +| `GovtReserved` | Hide from private hospitals | +| `ApprovalNotRequired` | Tell the user the case will auto-approve if it is the first preauthorisation and every package has it | +| `ScheduledTATApproval` | Tell the user the payer's silence within the window means approval | +| `EnhancementAllowed` | Only these packages may be added during an enhancement | +| `QuantityAllowed` | Cap the quantity field | +| `ImplantApplicable` | Show the implant picker | +| `MaximumImplantsAllowed` | Cap the number of implants | +| `MultipleImplantsAllowed` | Allow more than one implant on the package | +| `StratificationAllowed` | Show the bed-category picker | +| `MaximumStratificationAllowed` | Cap the number of bed categories | +| `MultipleStratificationAllowed` | Allow more than one bed category on the package | +| `Standalone` | Refuse any other package alongside it | +| `ParentProcedure` | Require one of the listed parents | +| `Unspecified` | Free-text name and free-entry amount, validated on the server against the wallet | +| `CyclicProcedure` | Ask the number of cycles | +| `MaximumCyclesAllowed` | Cap the number of cycles | +| `LamaDamaProcedure` | Offer only on a LAMA or DAMA discharge | +| `DischargeStagesLamaDamaProcedure` | Offer only at the discharge stages it lists | +| `IsDayCare` | Day-care handling | +| `Procedure Type` | Medical and surgical packages cannot be combined, and one medical package per episode | +| `los` | Maximum length of stay for the package; bounds the days claimed, including the `LM100` day count | +| `gst_applicable` | Whether tax applies to the package | +| `gst_percentage` | The tax rate when it does | +| `incentive_applicable` | Whether a hospital incentive applies | +| `ip_op_flag` | In-patient or out-patient | +| `rules_yn` | Whether further rules attach to the package | + +That table is the specification. The one published plan payload carries sixteen of these flags and not the rest: `Standalone`, `Unspecified`, `LamaDamaProcedure`, `los`, the tax pair, `incentive_applicable`, `ip_op_flag` and `rules_yn` appear nowhere in it. Do not read that as proof they are unused, because the sample is one scheme's plan at one moment. Read it as a warning to code defensively: +- **`gst_applicable` and `gst_percentage`**: The handbook describes the first as whether GST is applicable for the benefit and the second as the "GST % applicable for the given benefit". No published source gives a rate or says which packages carry tax. In the handbook's worked claim response the tax is a claim-level total, `ClaimResponse.total` with category `tax`: 100 on a claim of 13,700. +- **`incentive_applicable`**: Described only as whether an incentive to the hospital is applicable for the benefit. No published source gives the criteria or the rate. The same worked response carries a claim-level total with category `incentive` of 137 on 13,700, and the handbook's approved reprocess example repeats both figures. +- **`los` (Maximum Length of Stay)**: Specifies the ceiling on inpatient days for the procedure. Stays extending beyond `los` require clinical justification or an approved enhancement request (workflow 13); for LAMA/DAMA discharges, procedure `LM100` daily quantity cannot exceed `los`. + +There is a second trap in the same payload, and it will cost a day if you meet it unprepared. The flags and the money live in two different places. The claim-condition flags, the document requirements and the rate limits hang off the plan's coverage benefits, while the costs hang off the plan's own cost list. Both structures carry the same package codes, and neither is complete on its own, so building the treatment screen means joining them on the package code. The Insurance Plan Response chapter in the FHIR Reference sets out both shapes. + +**Refresh** weekly per the FRD, or every fifteen days per the scenario sheet, and immediately on renewal, amendment or a `policychange` communication. An outdated tariff version causes a rate mismatch and automatic rejection on suspicion of tampering; keep the version on every submission. + +**Add-ons** come from the package's cost qualifiers: implant, stratification, high-end medicine, investigation, each with its own code from the plan master, each a separate item on the bundle. + +## Preauthorisation + +The four sections of the generic form, with these additions: + +- Medical information comes from the HMIS record as structured documents: general findings, personal and family history. +- The STG questionnaire for each package is rendered from the plan and answered here; a missing response for a package that demands one is refused by name. +- Documents and questionnaires required for preauthorisation are those the eligibility call with purpose auth-requirements returns. The rest are mandatory at claim. +- Amounts are the plan's rates and are not editable, except on an unspecified package. +- A preauthorisation cannot be raised more than one day before admission. +- The biometric user token, or the consent questionnaire, must be present. +- `LM100` is never valid here. + +**Documents and size limits.** + +- Clinical documents (`DIA`, `HDS`, `CD`, `INF`) go as a reference: a `DocumentReference` whose `attachment.data` is a base64 FHIR bundle, content type `application/json` or `application/fhir+json`. +- Scans (`POI`, `POA`, `DOB`, `DEF`, `FIR`, `ATT`) go as attachments. +- One document per item, 2 MB at most. +- A preauthorisation or claim message is capped at 20 MB. +- The scheme's `InsurancePlan` response is bigger, 21 MB to 25 MB, because it embeds over 2,200 questionnaires. HTTP clients and reverse proxies must accept 25 MB for plan fetches. + +**Auto-approval** applies when this is the first preauthorisation for the case and every package carries `ApprovalNotRequired`, or when the policy allows turnaround-time approval and the payer has not acted in its window. Show the user which rule applied. + +**Queries arrive inside the response.** A queried `ClaimResponse`, workflow 24, carries the query text in `item.adjudication.reason.coding.display` as a pipe-delimited audit trail, `USER~datetime~type~comment~trust`. Parse it as a string and show the comment. The answer is the same preauthorisation bundle, new correlation ID, original reference, workflow 19, on `/v1/preauth/submit`. Not a communication response, and not a resubmission. + +**Enhancement** (13): only against an approved case, only after the previous request has closed, only for packages flagged enhanceable, unlimited until discharge within the wallet. **Resubmission** (121): revises an approved or rejected case for a different amount or package, and voids everything before it. **Cancel** (PC01): allowed until the claim is raised and refused once payment has started. + +**Server-side checks** the payer will make and the screen should make first: + +- Amount above zero and within the wallet. +- Specialty and package codes and displays exactly as the plan has them. +- Quantity at least one. +- Registration and admission dates present. +- One active preauthorisation per beneficiary across all hospitals. +- Investigations, mandatory for private hospitals. +- Newborn cases with date of birth, gender and documents, within six years. + +## Discharge and claim + +**There is no discharge submission.** Raising the claim asserts the discharge, so workflow 14 is not used and the discharge details ride on the claim. + +**Discharge type** is one of the four, and each has a questionnaire in the plan found by title (Death, Life, LAMA, DAMA). Authenticate the patient again here. Download the feedback form, hand it over, and upload it back. Under `DIS` the value is the stage. The gateway's own rejection message lists three, Before Surgery, During Surgery and After Surgery; the FAQ lists two, Before and After, and says the transmitted value must stay within the NRCeS set. Send what the payer's validation accepts and confirm before building. The value is sent for medical cases as well as surgical ones. A death also sends the death date under `ONS` / `DTM`. + +**LAMA or DAMA before or during surgery** voids every approved item. The claim carries the single line `LM100`, at the rate the package master gives it, with no ward tier on it; a claim that still carries the package is refused with `PAYR-1362`. After surgery the surgery items stand and `LM100` is not used. + +**The claim** is built from the preauthorisation with `use = claim`, four dates plus discharge status, the discharge summary as a structured document, the bill, the discharge questionnaire response, and the discharge-stage biometric token in the header. Amount within the preauthorisation's approved amount. The documents mandatory at claim are the plan's list less those already sent at preauthorisation. + +**Queries** on a claim arrive and are answered the same way as on a preauthorisation, with workflow 161 on `/v1/claim/submit`. The payer refuses 151, 19 and 16 with `PAYR-1321`. + +**After the decision**, two Tasks, both on `/v1/task/submit` with workflow 36, code `reprocess`, and a document attached: + +| | Reprocess | Shortfall | +| :---- | :---- | :---- | +| When | Claim rejected outright | Claim paid, but short | +| Reason | `claimrejected` | `partialpayment` | +| Amount | None | The difference, never more | +| Gate | None; raise on rejection | Payment notice 33 received, verified, and acknowledged with 17 | +| Times | Once | Once | +| Decided by | Claim Review Committee, final | Claim Review Committee, final | + +They do not chain; a shortfall cannot follow a Committee decision. The claim number in the Task is the preauthorisation number the hospital generated. + +## Scheme cases that change the bundle + +Five situations the treatment screen has to recognise before it builds anything. The Overview's PMJAY Scheme Rules chapter explains each; this is what the provider system does. + +- **Unspecified procedure.** Offer the specialty's unspecified package only within the treating specialty, with a free-text name and amount, and validate the amount on the server. It is a single line item with nothing else beside it. Auth-requirements is still required. Take the code from the plan rather than building it: the FAQ says the specialty prefix plus `215` and a bare `U100`, while the plan carries the specialty prefix plus `U100`, such as `SGU100`. +- **Cyclic procedure.** Ask the cycles, capped by the plan. Take live biometrics at preauthorisation, at every visit with process type Discharge, and at claim. Enforce the 24-hour rolling gap between visits, and record each visit as a numbered structured document with start and end time. One claim goes after the last cycle, and payment comes only for captured cycles. A change of hospital means discharge and a new preauthorisation. +- **Medical package.** One per episode; never alongside a surgical package. +- **Newborn.** Used while the baby has no member ID of its own. Parent's card and wallet, with the parent as primary `Patient` and the child as a linked `Patient` with `link.type = refer`. Date of birth, gender and proof of birth under `DOB` as `BCF` or `DCB` are all mandatory. Twins are two preauthorisations. Bill as "Baby of" the parent with an attachment. A child older than that and under six draws on the parent's wallet as an ordinary case, without the linked-child construct. +- **Implants and stratification.** Separate items with the plan's codes, within the package's maximums; only where the flags allow. + +## Payment and communication + +The payment flow is the generic one. Two scheme points: the acknowledgement of 33 is the gate on a shortfall claim, and the `TDS` and `Payment` lines on the reconciliation should sum to the approved amount. + +The communication channel never carries a document query under PMJAY. It carries `tatquery`, which the handbook reports as the most common reason in live PMJAY traffic, `grievance`, `walletupdate`, `policychange`, and `claimArbitration` when an appeal has been received. Host it regardless. + +## Verified in the sandbox + +PMJAY Sandbox Run records what the SHA HP sandbox actually did with these rules on 5 and 6 September 2026, from eligibility through to an approved claim. Its findings change what is written above in six places: + +- The item needs a FHIR element id, and every supporting-info entry a sequence. +- The practitioner needs an `HPIN` identifier. +- The item's category is the master's specialty code. +- The consent questionnaires that stand in for biometrics are the **plan's**, found by title in the master. +- The claim goes out under the pre-authorisation's number and bills the package alone. +- Documents must be PDF, JPEG, PNG or FHIR JSON. The adjudication APIs, the case id they insist on, and the roles a claim actually walked are in PMJAY Adjudication APIs. + +## Going live + +The sandbox journey adds a PMJAY team demo to the internal and HTC demos, and the exit form. In production, after the participant is created and configured, the hospital raises a ticket with its HEM ID from TMS and its NHCX participant ID. NHA maps them by hand, and that mapping is the switch. Preauthorisations and claims raised before it finish in TMS; everything after goes through the HMIS. Plan for both running at once, and brief the desk. diff --git a/site/docs/nhcx/v1/roles/provider/pmjay-sandbox-run.md b/site/docs/nhcx/v1/roles/provider/pmjay-sandbox-run.md new file mode 100644 index 000000000..60cf412f2 --- /dev/null +++ b/site/docs/nhcx/v1/roles/provider/pmjay-sandbox-run.md @@ -0,0 +1,217 @@ +--- +title: PMJAY sandbox run +sidebar_label: PMJAY sandbox run +sidebar_position: 11 +description: A full PMJAY case on the sandbox in order, the refusals met and what each means, with placeholders for your own values +verification: unverified +source: nhcx-package/docs/03-Building a Provider/11-PMJAY Sandbox Run.md +generated: true +sidebar_custom_props: + roles: + - provider +--- + +# PMJAY sandbox run + +Everything before this chapter was written from NHA's documents. This one is written from a full case run against the live NHCX sandbox with a State Health Agency (SHA) as the payer: policy lookup, coverage, package master, preauthorisation, adjudication, enhancement, claim and the claim's walk through the payer's roles, to approval. It records what the SHA accepted and refused, in the order a hospital meets it. Where this chapter and an earlier one disagree, this one is the evidence. + +Identifiers, amounts and dates from the run are replaced by placeholders. Yours will differ; the rules will not. + +## Before you start + +- A provider participant on the sandbox, with its certificate and callback URL registered. +- The SHA payer's participant code, and the policy code and member id of a beneficiary it covers, from the policy lookup. +- A session token from the ABDM gateway. The same token is used for the NHCX calls and for the payer service that adjudicates the case. +- One beneficiary per deployment. The scheme allows one live preauthorisation per beneficiary per hospital, so two teams sharing a beneficiary block each other. + +## The journey in order + +### 1. Find the policy + +`/participant/get/policies` by ABHA, member id or mobile. Take the policy code and the `processingid` from the answer. Every later call is addressed to the processing id, and the package master is keyed on this policy code, not on any other the hospital knows of. + +### 2. Check coverage + +`/v1/coverageeligibility/check` with each purpose: `discovery`, `validation`, `benefits`, `auth-requirements`. Validation returns the coverage period and the wallet; auth-requirements returns what the preauthorisation must carry, including the consent questionnaire when there is no biometric token. The reference coverage bundles pass unchanged. + +### 3. Fetch the package master + +`/v1/insuranceplan/request` with a plan Task keyed on the beneficiary's own policy code and the provider id. A policy the hospital is not empanelled under is refused with `PAYR-1401`; ask again with the code from step 1. The master is large, over a thousand packages, so store it queryable and read every package attribute from it rather than from code. + +### 4. Raise the preauthorisation + +`/v1/preauth/submit` on workflow `12`. The acknowledgement comes back on `20`, the decision later on `21`, `23` or `24`, on the request's own correlation id. The bundle passes only with all of the following, each learned from a refusal listed further down: + +- A FHIR element `id` on the Claim and on every item, procedure and supporting-info entry. +- The practitioner identified by `HPIN` as well as `HPID`. +- The package code, display and specialty exactly as the master has them, the specialty being the code of the category the master files the package under. +- The ward tier from the master's stratification codes as `item.modifier`, where the package allows one. +- The plan's authentication consent questionnaire answered, when there is no biometric token. +- A `sequence` on every supporting-info entry, numbered from 1 with no gaps. + +The SHA prices the package itself: the benefit approved is the master's rate for the tier, whatever amount was asked. + +### 5. Adjudicate on the payer service + +A PMJAY case is not decided over NHCX. It sits at `request.initiated` until someone acts on it in the SHA's Transaction Management System. In the sandbox that someone is you, through two endpoints of the NHCX Payer Service. Both take the ordinary session token in `bearer_auth`. + +First ask who holds the case: + +```bash +curl --location --request POST 'https://apisbx.abdm.gov.in/pmjay/sbxhcx/nhcxpayerservice/v1/get/user-role' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --data-raw '{ + "caseid": "", + "payerid": "" + }' +``` + +[Adjudicator: role for a case in the API reference](/docs/nhcx/v1/api/adjudicator/endpoints/adjudicator-adjudicator-role) + +```json +{ "currentuserrole": "PPD-Trust", "errormessage": null } +``` + +`caseid` is the SHA's case id, the digits at the end of its case reference. It is not the hospital's claim number; asked about that, the service answers that no data exists for the case id. The SHA hands the case id out in two places: inside a `PAYR-1238` refusal of a later request, and in its acknowledgement and status answers once a request is accepted. Store it beside the claim number the moment it is seen. + +Then act, with the action spelled as the role that holds the case expects: + +```bash +curl --location --request POST 'https://apisbeta.nha.gov.in/pmjay/hcx/nhcxpayerservice/wrapper/process/case' \ + --header 'Accept: application/json' \ + --header 'Content-Type: application/json' \ + --header 'bearer_auth: Bearer ' \ + --data-raw '{ + "casenumber": "", + "action": "Approve", + "receivercode": "", + "usecase": "PREAUTH", + "correlationid": "", + "sendercode": "", + "memberid": "", + "remarks": "ok" + }' +``` + +[Adjudicator: act on a case in the API reference](/docs/nhcx/v1/api/adjudicator/endpoints/adjudicator-adjudicator-process) + +The roles a case may pass through, and the actions each takes: + +- Preauthorisation, `PPD-Trust`: `Approve`, `Reject`, `Query`; `usecase` is `PREAUTH`. +- Claim, first desk, `CEX-Trust`: `Forward`; `usecase` is `CLAIM`. +- Claim, second desk, `CPD-Trust`: `cpdApprove`, `cpdReject`, `Pending`; `usecase` is `CLAIM`. +- Medical Audit Committee: `Approve`, `Reject`, `iQuery`; `usecase` is `Medical Audit Committee`. +- Claim, `ACO-Trust`: `Approve`, `Reject`, `Pending`; `usecase` is `CLAIM`. +- Claim, `SHA-Trust`: `Approve`, `Reject`, `Pending`; `usecase` is `CLAIM`. +- Claim Review Committee: `Approve`, `Reject`, `Pending`; `usecase` is `Claim Review Committee`. + +Read the role before every action, use the exact spelling, and mint a new correlation id per call. The decision then comes back over NHCX as the `ClaimResponse` on the request's own thread, so the desk call and the callback are two halves of one step. + +### 6. Enhance + +`/v1/preauth/submit` on workflow `13` with `x-hcx-use_case: Enhancement`, carrying the approved items and the ones now sought. Three rules: + +- The acknowledgement carries no `preAuthRef`. The enhancement is decided on the case its parent opened, so carry the parent's case id onto it; the desk answers only for that case. +- Only one package of type `Conservative` per case. An enhancement on a conservative case adds a `Medical` package, or an add-on the master flags as enhanceable, or is refused with `PAYR-1245`. +- One request at a time on a case. A claim raised while the enhancement is still queued is refused with `PAYR-1322`, and the role lookup still answers `PPD-Trust` because the case has not left the preauthorisation queue. + +The SHA may answer `queued` again when asked to approve an enhancement and decide it in its own time, a minute later or several. Report the scheme's pace; do not assert it away. + +### 7. Claim + +`/v1/claim/submit` on workflow `15`. Beyond the preauthorisation rules: + +- Send it under the preauthorisation's own number. A claim under a number of its own finds no case and is refused with `ERR-PYR-CLM-007`. The claim still owns its correlation id, so the answer lands on the right record. +- Bill the package alone, at the whole amount. A PMJAY rate is all-inclusive; room rent, consultations and investigations are not items and are refused as invalid item codes. +- Answer the plan's discharge consent questionnaire when there is no discharge biometric token, or meet `PAYR-1363`. +- Attach documents as `application/pdf`, `application/jpg`, `application/jpeg`, `application/png` or `application/fhir+json`. Anything else, `text/plain` included, is refused with `PAYR-1008`. + +### 8. Walk the claim through the roles + +Read the role, act, read again. On the run the claim was forwarded by `CEX-Trust`, approved by `CPD-Trust` as `cpdApprove`, then by `ACO-Trust` and `SHA-Trust`, after which the role lookup answered with no role at all: the case was decided and the verdict arrived on the claim's own thread. Neither committee held the case. The seven roles are the ones a case may pass through, not a queue every case walks, and a cycle that assumes the next role in the list will be refused. + +Two answers from the desk mean "try again shortly": no event found for the correlation id, while the exchange is still delivering the request, and case not found, while the case is mid-filing. Retry on both. + +## Refusals you will meet + +Each of these arrived on the run, in roughly this order. The message is the SHA's; the reading is what it turned out to mean. + +### PAYR-1027 Invalid item id + +The item has no FHIR element `id`. Not a package-code problem: the same bundle was refused with several valid codes until the ids were added. `PAYR-1028`, invalid item sequence, and `PAYR-1029`, invalid bundle id, are the same kind of fault. + +### PAYR-1083 No HPR details for the practitioner + +The SHA looks the doctor up by the identifier typed `HPIN` from the NRCeS identifier-type code system. Send the HPR id twice, as `HPID` and as `HPIN`, alongside the registration number typed `MD`: + +```json +"identifier": [ + { "type": { "coding": [{ "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code", "code": "HPID" }] }, "system": "https://nhcx.abdm.gov.in", "value": "" }, + { "type": { "coding": [{ "system": "http://terminology.hl7.org/CodeSystem/v2-0203", "code": "MD" }] }, "system": "https://nhcx.abdm.gov.in", "value": "" }, + { "type": { "coding": [{ "system": "https://nrces.in/ndhm/fhir/r4/CodeSystem/ndhm-identifier-type-code", "code": "HPIN" }] }, "system": "https://hpr.abdm.gov.in", "value": "" } +] +``` + +The sandbox did not check the id against the registry; a well-formed one was enough. Production may not be as kind. + +### PAYR-1238 An active preauthorisation exists + +A scheme rule, not a bundle fault, and it arrives after the bundle has passed validation. The refusal names the SHA's case reference; its last digits are the case id the payer service wants. Clear it with a cancel Task on `PC01` from the hospital that raised it, or a `Reject` at `PPD-Trust`. + +### PAYR-1256 and PAYR-1363 Consent questionnaire missing + +No biometric token and no consent answer. The questionnaire is the plan's: its url and link ids come out of the package master and change per SHA, so read them off the master. The answer rides as a `QuestionnaireResponse` naming that url, referenced from a supporting-info entry of category `INF`, code `ODN`. `PAYR-1256` is at the preauthorisation, `PAYR-1363` at the claim. + +### PAYR-1019 Invalid sequence in supporting info + +An entry without a `sequence`, typically one appended after the rest were numbered. Number the list after it is complete. + +### PAYR-1008 Invalid content type, or invalid code and reason + +On an attachment: a content type outside the five the SHA reads. On a Task: a code and reason combination the scheme does not take, see below. + +### ERR-PYR-CLM-007 No prior preauthorisation for the case + +The claim was sent under a number of its own. Send it under the preauthorisation's number. + +### PAYR-1245 Only one conservative procedure per case + +The enhancement added a second `Conservative` package. Add a `Medical` package or an enhanceable add-on instead. + +### PAYR-1322 Active instance found for the case + +A second request while the previous one is still queued. Wait for the decision. + +### PAYR-1401 Policy not allowed for the hospital + +The package master was asked for under a policy the hospital is not empanelled for. Use the beneficiary's policy code from the eligibility answer. + +## What the package master decides + +Read every package attribute from the master; none of it belongs in code. + +- Package code and display: `item.productOrService`, under the NDHM procedure-code system. +- Specialty: `item.category`, under the NDHM benefit-category system. Its value is the code of the category the master files the package under, exactly as `PAYR-1114` says. A generic category is wrong for every PMJAY package. +- `ProcedureType`: `Claim.procedure.type`, `conservative`, `medical` or `surgical`. Decides the one-conservative-per-case rule. +- `StratificationAllowed` and the tiers: whether a ward tier rides as `item.modifier`, code and display only, no system. A general, semi-private, private or deluxe bed is the routine ward tier, an HDU bed the HDU tier, an ICU bed the ICU tier without ventilator unless the record says otherwise. The tier's rate is what the SHA pays; the amount asked stays the hospital's own. +- `ApprovalNotRequired`: whether a preauthorisation is needed at all. +- `EnhancementAllowed`: whether the package may be added on an enhancement. + +The master also says what the claim may carry: the package alone. The generic flow, where every bill line is an item, stays right for an indemnity payer. + +## What the sandbox will not take + +- A status enquiry as a `Task` coded `status`, refused with `PAYR-1018` without a reason code and `PAYR-1008` with one. Where a case stands is read from the payer service's role lookup, not asked for over NHCX. +- A reprocess `Task` with reason `partialpayment` before payment notice `33` has arrived and been acknowledged, refused the same way. The combination is validated before the case is looked at. + +Both refusals cite a document of valid code-and-reason combinations that NHA does not publish with the rest of its material. + +## What this changes in the earlier chapters + +- Bundles and Conventions: element ids on every Claim bundle, and the `HPIN` identifier on every Practitioner. +- Preauthorisation Request: the sample's `factor: 0.5`, its `MP` category system and the SNOMED system on the package code are tolerated, not needed. `factor` 1, the master's category under the NDHM benefit-category system and the package under the NDHM procedure-code system pass. +- Building a Provider 07: the specialty is the master's category code, the ward tier the master's stratification code, the claim the package alone. The mandatory documents the sample carries were not demanded at submission; expect them to be queried for. +- Error Codes: `PAYR-1027`, `PAYR-1019` and `PAYR-1029` are structural, not code lookups. `PAYR-1008` is about a content type or a code-and-reason combination, depending on where it lands. +- Discharge and Claim: under PMJAY the claim carries the preauthorisation's number, the package alone at the whole amount, the discharge consent questionnaire, and documents in a content type the payer reads. diff --git a/site/docs/nhcx/v1/roles/provider/preauthorisation.md b/site/docs/nhcx/v1/roles/provider/preauthorisation.md new file mode 100644 index 000000000..9b13011ac --- /dev/null +++ b/site/docs/nhcx/v1/roles/provider/preauthorisation.md @@ -0,0 +1,110 @@ +--- +title: Preauthorisation +sidebar_label: Preauthorisation +sidebar_position: 5 +description: Preauth request submission, clinical attachments, and query handling +verification: unverified +source: nhcx-package/docs/03-Building a Provider/05-Preauthorisation.md +generated: true +sidebar_custom_props: + roles: + - provider +--- + +# Preauthorisation + +The preauthorisation is the first bundle that carries clinical content, and the one the payer scrutinises hardest. Everything the treatment screen collected becomes a `Claim` resource with `use` set to `preauthorization`. + +## What the user does + +The form has five sections, and the order below is the order payers read them. + +**Medical information.** Findings, history, the clinical picture that justifies admission. + +**Admission information.** Registration date, admission date, admission details. + +**Treatment.** Diagnosis as ICD-10 codes, the treatment plan as services or packages chosen from the plan, investigations, and the care team with each doctor's registration number. + +**Finance.** The amount per line, from the plan where the plan fixes it. The total may not exceed what eligibility said remains; check it on the server before enabling submit. + +**Documents.** The checklist comes from the eligibility call with purpose auth-requirements, made from this screen before submission. Each document is one file of at most 2 MB. Do not let the user submit with a mandatory item missing; the payer will query, and the round trip costs a day. + +## What the system calls + +``` +POST /v1/coverageeligibility/check purpose: benefits, then auth-requirements +POST /v1/preauth/submit workflow 12 +callback /v1/preauth/on_submit +``` + +Send to the processor code. Store the correlation ID against the case; every follow-up on this preauthorisation will reuse the reference and carry a new correlation ID. + +## What goes in the bundle + +A collection bundle. The `Claim` is the spine; everything else is referenced from it by `urn:uuid`. + +| Resource | Why it is there | +| :---- | :---- | +| `Claim` | `use = preauthorization`, `type` inpatient, patient, provider, insurer, coverage, billable period, diagnosis, procedure, items, care team, supporting info, total | +| `Patient` | Member ID and ABHA number as identifiers | +| `Organization` ×2 | Provider with its HFR ID as NPI; insurer with its registry ID as NIIP | +| `Coverage` | The policy, with the product code | +| `Practitioner` per doctor | Name and medical registration number, referenced from the care team | +| `Procedure` | One per procedure, referenced from `Claim.procedure` | +| `DocumentReference` per document | A PDF or image in `attachment.data`, or a structured FHIR bundle where the payer asks for one | +| `QuestionnaireResponse` | Answers to any questionnaire the plan or the eligibility response attached, referenced from a supporting-info entry. A policy or case-level response uses category `INF` with code `ODN`; the FRD gives `INF` with code `AT` for questionnaire answers generally. The payer names `ODN` in its own rejection message, so send that for the case-level one and confirm the rest. | + +The item is where most rejections originate. Each `Claim.item` carries the category, the service or package as `productOrService`, quantity, unit price and net, and points at the diagnosis, procedure, care team and supporting-info entries it relates to by sequence number. The codes and displays must match the plan exactly. + +Two supporting-info entries carry the dates: registration date as code `EDT` under category `OTH`, admission date as code `ADDD` under category `ONS`. Full element tables are in the FHIR Reference. + +## What the payer checks before a human sees it + +The reference payer refuses these on arrival, with a named code, before the case reaches a doctor's queue. Every one of them is cheaper to catch on your own server. + +| Check | The code you get if you skip it | +| :---- | :---- | +| Every `Claim.item` carries a FHIR element `id` | `PAYR-1027`, "invalid item id". Structural, not a code lookup | +| Every `supportingInfo` entry carries a `sequence`, numbered from 1 with no gaps | `PAYR-1019` | +| The `Practitioner` carries an identifier typed `HPIN` | `PAYR-1083` | +| No preauthorisation already live for this beneficiary at this hospital | `PAYR-1238`, which names the reference number holding it | +| Documents in `pdf`, `jpg`, `jpeg`, `png` or `fhir+json` | `PAYR-1008` | +| The package code is in the plan's master | `PAYR-1248`, which names the code | +| The policy is one the hospital is empanelled under | `PAYR-1401` | + +Refusals arrive in order: the bundle is validated first, and scheme rules are applied only to a bundle that passed. So `PAYR-1238`, the one-live-preauthorisation rule, is perversely the first sign the bundle itself is right. + +The `PAYR-102x` block is structural throughout. When you meet one, check ids and sequences before you go looking at values. + +## Reading the answer + +The callback carries a `ClaimResponse`. Read two fields together, never one: + +| `outcome` | Adjudication reason | Meaning | Workflow | +| :---- | :---- | :---- | :---- | +| `complete` | `approved` | Approved. `preAuthRef` is the reference for the claim. | 21 | +| `partial` | `approved` | Approved at a reduced amount. `processNote` says why. | 21 | +| `partial` | `queried` | The payer wants more. The case stays open. | 24 | +| `complete` | `cancelled` | Rejected. Reason in `disposition` and a denial code from the `PreauthError` family. | 23 | + +`outcome = complete` alone does not mean approved; it also means rejected. The adjudication reason is the difference. + +## When the payer wants more + +On the general network, a query arrives as a **communication request** on `/v1/communication/request`, with reason `additionalinfo` and the case number. The provider attaches what was asked and answers on `/v1/communication/on_request`. The payer then issues the decision on `/v1/preauth/on_submit`. The queried `ClaimResponse` with workflow 24 tells the provider the case is waiting; the communication tells it what for. + +Some payers instead take the answer on the preauthorisation endpoint itself with workflow 19. PMJAY does; PMJAY Provider covers it. + +## Follow-ups on the same case + +All reuse this screen's bundle with a new correlation ID, the original reference, and a different workflow code. + +**Answering a query** adds one more entry wherever it is sent: the overall case remarks, under category `NMI` with code `CQD`, as a string. Send it. The handbook says an answer without it is rejected. The one sampled answer that the payer accepted and then approved carries no such entry, so treat it as required until a payer tells you otherwise. + +- **Enhancement** (13). Against an approved case, for additional procedures or days. The bundle lists the already-approved items and the new ones. +- **Resubmission** (121). Revises a request after a query or rejection. +- **Cancel** (PC01). A Task, not a Claim: code `cancel`, the case number as input, a reason from the list (treatment plan changed, patient request, financial constraints, alternative treatment, duplicate, administrative error, other). Allowed until the claim is raised. The workflow sheet gives PC01 for this and PC02 for the answer; the handbook gives 122 in two places, including the heading of its cancellation-reason appendix. Confirm which the payer accepts. + +The Task resource carries more codes than these two. The provider exit checklist names `reprocess`, `cancel`, `release` and `nullify`, and the value set adds `approve`, `search`, `poll` and `suspend`. `nullify` is described in Cancel, Reprocess and Shortfall in the FHIR Reference. `suspend` is not described in any source beyond its place in the value set. + +Payers enforce sequencing and say so: no approved record for this enhancement, a case already in progress, a claim already raised. Surface their errors as they are. diff --git a/site/docs/nhcx/v1/roles/provider/provider-checklist.md b/site/docs/nhcx/v1/roles/provider/provider-checklist.md new file mode 100644 index 000000000..8a3669fee --- /dev/null +++ b/site/docs/nhcx/v1/roles/provider/provider-checklist.md @@ -0,0 +1,255 @@ +--- +title: Provider checklist +sidebar_label: Provider checklist +sidebar_position: 10 +description: Sandbox exit list, 29 test cases by family (T-ML1, T-PLN, T-ELG, T-PRE, T-CLM, T-PAY, T-COM, T-CBK, T-SES), first-week failures +verification: unverified +source: nhcx-package/docs/03-Building a Provider/10-Provider Checklist.md +generated: true +sidebar_custom_props: + roles: + - provider +--- + +# Provider checklist + +What a provider has to demonstrate to leave the sandbox, the test cases to run before asking, and where the first week's failures come from. + +## The sandbox exit list + +NHA's provider exit process names thirteen use cases. Each must be shown working against the dummy payer in the internal demo, then in the HTC demo. + +1. Get participant list, `/fetch/participants/list`. +2. Get policy, `/participant/get/policies`. +3. Get public key, `/fetch/certs`. +4. Get auth token, `/get/session`. +5. Check coverage eligibility, `/v1/coverageeligibility/check`, answered on `/v1/coverageeligibility/on_check`. +6. Request insurance plan, `/v1/insuranceplan/request`, answered on `/v1/insuranceplan/on_request`. +7. Preauthorisation submission, `/v1/preauth/submit`, answered on `/v1/preauth/on_submit`. +8. Respond to a communication request, received on `/v1/communication/request`, answered on `/v1/communication/on_request`. +9. Claim submission, `/v1/claim/submit`, answered on `/v1/claim/on_submit`. +10. Claim search, `/v1/search/submit`, answered on `/v1/search/on_submit`. A caution: the Technical Specifications route `/search/submit` from NHA through NHCX to the payer, a cross-payer search for NHA or a regulator, and a provider's search over its own cases is `/claim/search` under the access-control policy. No source confirms which of the two the sandbox accepts from a provider. +11. Acknowledge payment notice, received on `/v1/paymentnotice/request`, answered on `/v1/paymentnotice/on_request`. +12. Reprocess or cancel, `/v1/task/submit`, answered on `/v1/task/on_submit`. +13. Get status, `/v1/status`, answered on `/v1/on_status`. + +Every callback must accept both a `JWEPayload` and a `ProtocolResponse`, and answer with the 202 receipt within 30 seconds. `/v1/error` is not on the list but is required: it takes a plain JSON report of an undeliverable request and must still be answered `202`. + +Under PMJAY, add biometric authentication in all three modes and the structured health-information types, and expect the PMJAY team demo as an extra step. + +## Test cases + +One id per case, by family: `ML1` beneficiary authentication, `PLN` insurance plan, `ELG` coverage eligibility, `PRE` preauthorisation, `CLM` claim, `PAY` payment, `COM` communication, `CBK` callbacks, `SES` session and keys. Cases marked PMJAY apply to the scheme only. The workflow codes named are the ones each leg must carry; the dummy payer's `process/request` hook drives approve, reject and query on demand, and `paymentNotice/init` drives a payment notice. The full list of NHA's own numbered scenarios is in NHCX Use Cases and the harness bundles in `fixtures/reference/payer/`. + +### Beneficiary authentication + +#### T-ML1-01 Validate the policy by ABHA + +`CoverageEligibilityRequest` with purpose `validation` for a valid ABHA with consent. Expect a `CoverageEligibilityResponse` with `inforce: true`. + +#### T-ML1-02 Biometric authentication in each mode (PMJAY) + +Fingerprint, iris and face, each yielding a user token that rides on the eligibility check and the preauthorisation. + +#### T-ML1-03 Consent fallback (PMJAY) + +No biometric device: the plan's authentication consent questionnaire is answered instead, at admission and again at discharge. + +#### T-ML1-04 Token refresh and expiry (PMJAY) + +A user token refreshed before the preauthorisation; an expired one refused and re-obtained. + +### Insurance plan + +#### T-PLN-01 Fetch the package master + +`InsurancePlan` request keyed on the beneficiary's own policy code and the provider id. Expect the master with packages, inclusions, exclusions, claim conditions and document requirements. A policy the hospital is not empanelled under is refused with `PAYR-1401`. + +### Coverage eligibility + +#### T-ELG-01 Auth-requirements before a preauthorisation + +Purpose `auth-requirements` for a package. Expect eligible, balance sufficient, and the mandatory documents the preauthorisation must carry. + +#### T-ELG-02 Benefits and discovery + +Purpose `benefits` for a package, and `discovery` with no policy to find what the beneficiary holds. + +#### T-ELG-03 Refusals + +A policy not in force; a limit exhausted. The refusal is read off the response, not off a transport error. + +### Preauthorisation + +#### T-PRE-01 Submitted and approved + +Workflow `12`, acknowledged on `20`, approved on `21`. The payer's case number arrives in `preAuthRef`. + +#### T-PRE-02 Queried, answered and approved + +Workflow `12`, `20`, `24`, `19`, `21`. The query on the case thread under PMJAY or over communication with another payer, then a positive adjudication. + +#### T-PRE-03 Rejected, resubmitted, cancelled + +Workflow `12`, `23`, `121`, `PC01`, `PC02`. The rejection carries `preAuthRef`; the resubmission reuses it; the cancel Task withdraws the case. + +#### T-PRE-04 Enhancement queried, answered and approved + +Workflow `13`, `241`, `131`, `22`, with the header `x-hcx-use_case: Enhancement`. A longer stay or an added package on the same case. + +#### T-PRE-05 Implant, stratification and STG (PMJAY) + +A package with an implant line, a ward tier as `item.modifier`, and the STG questionnaire answered under `supportingInfo`. + +#### T-PRE-06 Auto-approval (PMJAY) + +A first preauthorisation on a case whose packages all allow it comes back approved without a desk action. + +### Claim + +#### T-CLM-01 Approved + +Workflow `15`, acknowledged on `25`, approved on `26`, after an approved preauthorisation, with the discharge biometric token or consent. + +#### T-CLM-02 Queried, answered and approved + +Workflow `15`, `25`, `27`, `151`, `26`. Under PMJAY the answer goes on `161`. The documents asked for ride in `supportingInfo`. + +#### T-CLM-03 Rejected and reprocessed + +Workflow `15`, `291`, then a reprocess Task on `36` with the justification attached, acknowledged on `37`, decided on `252` or `253`. + +#### T-CLM-04 Discharge in every mode (PMJAY) + +`DTH`, `DTM`, `LAMA` and `DAMA`, with the amount each one allows: `LM100` per day for LAMA or DAMA before or during surgery, the full package after surgery, and the death date under `ONS/DTM` for `DTM`. + +#### T-CLM-05 Shortfall after partial payment (PMJAY) + +A Task with reason `partialpayment` after payment notice `33` is acknowledged; refused before it. + +#### T-CLM-06 Unusual cases (PMJAY) + +An unspecified procedure `SGU100`; a cyclic procedure across several visits; a newborn on the parent's card; twins. + +#### T-CLM-07 Provisional discharge + +Where the payer supports it: submitted on `14`, then approved, rejected and queried. + +### Payment + +#### T-PAY-01 Payment notices acknowledged + +Notices on `30`, `31` and `33`, each acknowledged on `17` under PMJAY or with the notice's own code on the generic network. The UTR on `33` is stored. + +### Communication + +#### T-COM-01 A communication of each reason + +`additionalinfo`, `tatquery`, `grievance`, `walletupdate`, `policychange`, `claimArbitration`, each acknowledged within thirty seconds without touching the case status. + +### Callbacks + +#### T-CBK-01 The same callback twice + +The second delivery is recognised by `x-hcx-api_call_id` and answered `202` without acting twice. + +#### T-CBK-02 Unknown correlation id + +A callback for a thread this system never opened is answered `202` and logged, not processed. + +#### T-CBK-03 A protocol response + +A `ProtocolResponse` body, with its `x-hcx-error_details`, handled without attempting to decrypt. + +#### T-CBK-04 The error endpoint + +A report on `/v1/error` answered `202` and surfaced to the desk as a failed delivery, not a case under review. + +### Session and keys + +#### T-SES-01 Token expiry mid-flow + +A `401` on any call leads to a fresh session token and one retry, never a retry with the same token. + +#### T-SES-02 Certificate rotation on the payer side + +A decrypt failure on the payer's side clears the cached certificate and fetches it again before resending. + +## PMJAY HMIS test cases + +The NHCX-PMJAY-HMIS test case workbook carries eight worked cases for a hospital system integrating PMJAY through NHCX. They are reproduced here as published. + +| Id | Scenario | Precondition | API or resource | Inputs | Validation | Expected output | Remark | +| :---- | :---- | :---- | :---- | :---- | :---- | :---- | :---- | +| `TC-ABHA-01` | Validate the PMJAY policy using ABHA | Valid ABHA, consent available | `CoverageEligibilityRequest`, purpose `validation` | ABHA `91-XXXX-XXXX-XXXX`, purpose `validation` | ABHA linkage and an active policy | `CoverageEligibilityResponse` with active coverage | Happy path | +| `TC-HBP-01` | Fetch the admissible HBP package | Policy validated | `InsurancePlan` | Plan id `PMJAY-TS-001`, provider id `HOSP123`, payer id `SHA-HARYANA` | Provider validated against the state's network hospitals | `InsurancePlan` with all HBP packages, their inclusions and exclusions, claim conditions and document requirements | State-specific HBP applied | +| `TC-CE-01` | Coverage eligibility for auth-requirements | Wallet available | `CoverageEligibilityRequest`, purpose `auth-requirements` | Amount `25000`, package `HBP-123` | Wallet balance and specialty rules | Eligible, balance sufficient | Preauth allowed | +| `TC-PA-01` | Submit a preauthorisation | Eligibility successful | `/preauth/submit`, `Claim` | Diagnosis `I10`, treatment plan, supporting documents, doctor details | Clinical and financial rules | Preauth id generated, status `PENDING` | Sent to workflow | +| `TC-PA-02` | Submit a preauthorisation query update | Preauthorisation submitted | `/preauth/submit`, `Claim` | Additional documents | Preauthorisation and treatment details match | Query details accepted for adjudication | Sent to workflow | +| `TC-CL-01` | Submit the claim after discharge | Preauthorisation approved | `/claim/submit`, `Claim` | Approved amount `23000`, documents attached | Preauthorisation and treatment details match | Claim accepted for adjudication | Sent to workflow | +| `TC-CL-02` | Submit a claim query update | Claim submitted | `/claim/submit`, `Claim` | Documents | Claim and treatment details match | Query details accepted for adjudication | Sent to workflow | +| `TC-CL-03` | Submit a CRC claim | Claim rejected or partially paid | `/task/submit`, `Task` | Not given | Claim and treatment details match | Not given | Not given | + +`TC-CL-03` is incomplete in the workbook: it gives no inputs, expected output or remark. Both query updates go to the same endpoint as the first submission; the workflow code tells them apart, as PMJAY Provider sets out. + +### The scenario list + +The workbook's second sheet is a bare list of nineteen scenario names, with no steps, inputs or amounts. Many of them have no worked case above. + +| No. | Scenario | +| :---- | :---- | +| 1 | Registration | +| 2 | Wallet update | +| 3 | Registration cancel | +| 4 | Preauthorisation submission | +| 5 | Preauthorisation query | +| 6 | Preauthorisation submitted with the query response | +| 7 | Preauthorisation enhancement | +| 8 | Preauthorisation with implant | +| 9 | Preauthorisation resubmission | +| 10 | Preauthorisation rejection | +| 11 | Preauthorisation approval | +| 12 | Preauthorisation cancel or delete | +| 13 | Discharge in multiple modes, and the amount calculation for each | +| 14 | Claim submission | +| 15 | Claim query | +| 16 | Claim rejection | +| 17 | Claim approval | +| 18 | Claim final paid, and update at the payer's bank transaction detail | +| 19 | CRC in case of claim rejection and partial payment | + +The workbook does not give the amounts for scenario 13. The discharge modes and what each one allows are in T-CLM-04 above. + +## Where the first week goes wrong + +Roughly in the order the portal's own support list has them: + +1. Wrong status word on a leg of the message. +2. No `/v1/error` endpoint. +3. Callback answering with something other than 202 and the receipt. +4. Envelope headers missing or malformed. +5. Registry id inside the bundle not matching the participant record. +6. `Accept: application/json` missing. +7. Sending to `payerid` instead of `processingid`. +8. Reusing a correlation id after an error. +9. Retrying a `401` with the same token. +10. Package code or display not matching the plan, character for character. + +## Exchanges this documentation does not cover + +The workflow sheet defines families that no NHA document describes beyond their codes. A participant may receive one; log it and escalate rather than ignore it. + +- Final bill: `45` submitted, `46` approved, `47` queried, `181` query answered, `491` denied. +- Reimbursement claims: `R15`, `R151`, `R26`, `R27`, `R28`, `R291`, `R122`, `R252` to `R254`. +- Discharge correction: `DC01`, `DC02`. +- Preauthorisation arbitration: `41`, `42`. +- Wallet upgrade `34`, `35`; fraud alert `38`, `39`; grievance `G11`, `G12`, `G13`. +- `16`, for a preauthorisation resubmission. + +## Before going live + +- FHIR bundles emailed for NRCeS validation and passed. +- Internal demo with NHA, then the HTC demo. +- Production participant created through the passcode flow; certificate and callback URL registered; own certificate fetched back and checked. +- Under PMJAY, the HEM-to-participant mapping ticket raised, and staff briefed that in-flight TMS cases finish in TMS; see PMJAY Provider. +- A pilot on a few real cases before switching the whole hospital. diff --git a/site/docs/nhcx/v1/roles/provider/registration-and-eligibility.md b/site/docs/nhcx/v1/roles/provider/registration-and-eligibility.md new file mode 100644 index 000000000..7d7452cee --- /dev/null +++ b/site/docs/nhcx/v1/roles/provider/registration-and-eligibility.md @@ -0,0 +1,143 @@ +--- +title: Registration and eligibility +sidebar_label: Registration and eligibility +sidebar_position: 2 +description: Patient intake, Aadhaar eKYC and biometrics, and the coverage check +verification: unverified +source: nhcx-package/docs/03-Building a Provider/02-Registration and Eligibility.md +generated: true +sidebar_custom_props: + roles: + - provider +--- + +# Registration and eligibility + +This chapter comes before the Insurance Plan chapter because registration comes first at the desk. The calls do not run in that order. The plan is fetched at registration or admission and cached, so by the time a treatment is planned it is already there, and the next chapter covers it. Read the two together. + +The first screen decides whether the rest of the journey can happen. A patient who is registered without a confirmed policy and a confirmed processor code will fail at preauthorisation with errors that look like FHIR problems and are not. + +## What the user does + +**Search.** The front desk enters one identifier: ABHA number, member or policy number, or mobile. The system tries them in that order of strength and shows the matching policies with the insurer's name. The user picks the payer. + +**Beneficiary Verification & KYC.** +Before checking eligibility, the patient's identity is established: +- **Commercial / Private Insurance**: Uses the **Aadhaar Digital eKYC API**. The desk triggers an Aadhaar OTP or demographic validation, retrieving the beneficiary's verified ABHA profile (Name, DOB, Gender, Address, Photo) and unhyphenated ABHA ID for the envelope (`x-hcx-ben-abha-id`). +- **PMJAY Scheme**: Gated by **Mandatory Biometric Authentication**. The patient performs a live biometric verification (Fingerprint, Iris, or FaceAuth) via the ABDM biometric gateway (see Biometric Authentication), returning a user auth token (valid 1,800s). If the patient cannot be biometrically authenticated due to physical trauma, burns, or amputation, the hospital executes the signed **Aadhaar Exemption Consent Form** and submits the Authentication Consent Questionnaire. + +**Confirm cover.** The screen calls eligibility with purpose validation and shows the result in words the desk can act on: policy in force or not, and what remains against the sum insured. Register the patient only once this comes back positive. If the limit is exhausted or the policy is not in force, say so and stop; do not let a registration proceed on a promise. + +**Capture the rest.** Communication address, attendant details, and whatever the payer's plan lists as required at registration. + +## What the system calls + +Two lookups from Getting Started, then one exchange: + +``` +POST participant/get/policies identifiertype + identifiervalue +POST /v1/coverageeligibility/check purpose: validation +``` + +The eligibility request needs the beneficiary's identifiers, the coverage or plan code, the payer ID and the provider ID. Send it to the processor code from the policy lookup. Cache the policy result against the patient. + +Call eligibility again, still with purpose validation, whenever a treatment is added later. The handbook's fallback: if the policy lookup returns nothing, call eligibility with purpose discovery first to learn the active policy code, then validation with it. + +```mermaid +sequenceDiagram + box Provider side + participant D as Front desk + participant B as Provider backend + end + box Exchange + participant X as NHCX + end + box Payer side + participant Y as Payer + end + D->>B: identifier typed at the desk + B->>X: participant/get/policies + X-->>B: payerid, processingid, memberid, productid + D->>B: user picks the policy + B->>X: coverageeligibility/check, purpose validation + X-->>B: 202 receipt, not the answer + X->>Y: forwards + Y->>X: coverageeligibility/on_check + X->>B: sealed CoverageEligibilityResponse + B-->>D: in force, balance remaining + D->>B: register the patient +``` + +## The four purposes + +One `CoverageEligibilityRequest` carries four different questions, and `purpose` decides which. Only `validation` is asked at the desk; the other three belong to the treatment screen in the next chapter. + +| Purpose | The question | When you send it | What comes back | +| :---- | :---- | :---- | :---- | +| `validation` | Is this coverage in force, and what is left? | At registration, and again whenever a treatment is added | `inforce`, and one benefit entry per wallet with allowed and used money | +| `discovery` | What coverages does this beneficiary have with you? | Only as a fallback, when the policy lookup returned nothing | Every active coverage, so you can pick a policy code | +| `benefits` | For these packages, what is covered? | On the treatment screen, once packages are chosen | Per item: excluded or not, benefit type, allowed money | +| `auth-requirements` | Is preauthorisation required, and what must come with it? | Before submitting a preauthorisation | Per item: `authorizationRequired`, and the mandatory document and questionnaire codes | + +`discovery` is defined in the specification and appears in no published sample. The other three do. + +## What goes in the bundle + +A `CoverageEligibilityRequest` in a collection bundle, alongside the `Patient`, the provider and insurer `Organization`s, the `Coverage`, and the `Practitioner` who made the check. + +| Element | Set it to | +| :---- | :---- | +| `purpose` | `validation` at registration; `discovery` as the fallback | +| `patient` | Reference to the Patient, who carries the member ID and ABHA number as identifiers | +| `insurer`, `provider` | References to the two Organizations | +| `insurance.coverage` | Reference to the Coverage carrying the policy code | +| `servicedDate` | Today | +| `enterer` | The desk user. The samples send a `Practitioner`; the handbook asks for a `PractitionerRole`. FHIR allows either and the published bundles use `Practitioner`, so send that | + +Element tables and a worked example are in the FHIR Reference. Two details from the samples save a day each. The `Patient` carries a `PI` identifier that is the hospital's own MRN, and a hospital with none yet sends the literal string `NA`. And `servicedDate` is the date of service, not the date of asking. + +## Reading the answer + +The response comes back on `/v1/coverageeligibility/on_check`. It is not a small message: the payer echoes your entire request back before answering it, so the bundle has eleven entries where you sent six. + +| What you want | Where it is | +| :---- | :---- | +| The yes or no | `insurance[0].inforce` | +| The payer's own sentence for the desk | `disposition`, for example `Policy is currently in-force` | +| Money allowed on the wallet | `insurance[0].item[].benefit[].allowedMoney` | +| Money already used | `insurance[0].item[].benefit[].usedMoney` | +| Whether preauthorisation is needed | `item.authorizationRequired` | +| The match back to your request | `CoverageEligibilityResponse.request.reference` | + +Three traps in that bundle, all of them real in the published sample. + +**Index by `fullUrl`, not by resource type.** Entries 8 to 11 are the payer's own `Patient`, `Coverage` and `Organization`s, and they duplicate the resource types in your echoed request. A parser that finds the first `Patient` reads your own data back and reports it as the payer's answer. + +**Do not match on the request id.** The payer splits `CoverageEligibilityRequest.id` on the last slash and returns only the tail, so an id you sent as `PMJAY/HP/S/G` comes back as `G`. Match on `request.reference`, which is intact. + +**The balance is a subtraction.** `allowedMoney` alone reads as more cover than the patient has. Show allowed less used, and group the digits the Indian way. + +## The forward instruction + +The coverage eligibility specification gives it one sentence: a payer might respond with a forward instruction asking NHCX to submit the same request to another payer. No fields or flow are published for it, so there is nothing to build against. Ask about it at onboarding; Governance and Audit lists the question. + +## Errors you will meet + +Business refusals travel inside the sealed response as a `PAYR-` code; protocol refusals arrive on the envelope. Map each to something the desk can act on. + +| Code | What it means | What the desk should see | +| :---- | :---- | :---- | +| `PAYR-1401` | Policy not allowed for the hospital | The hospital is not empanelled under that policy. Ask again with the beneficiary's own policy from the lookup | +| `PAYR-10xx` family | Not a covered member, policy not found, policy expired | The payer's own sentence, verbatim, and a stop on registration | +| `PAYR-11xx` family | The reference payer's eligibility-specific set | The payer's sentence, plus which field it names | +| `401` on the call itself | Token expired | Nothing. Fetch a new token and retry once | + +A refusal on this exchange is cheap. The same fault met at preauthorisation costs a round trip and a day, which is the argument for calling eligibility again whenever a treatment is added rather than trusting the answer from admission. + +## What to show and store + +- Show `disposition` verbatim; it is the payer's own sentence about the policy. +- Store the response with the case, because the auth-requirements version of this same call is what tells you which documents are mandatory later. +- Store the wallet figures and the moment they were read. When a claim is adjudicated against them months later, the adjudicator needs to see what was promised. +- Store the raw sealed message before you interpret it. Disputes are settled on what was actually received. +- Map the payer's error codes to desk-readable messages: not a covered member, policy not found, policy expired. The `PAYR-10xx` family covers these; the reference payer adds a `PAYR-11xx` set for eligibility specifically. diff --git a/site/docs/nhcx/v1/roles/provider/ui-guide.md b/site/docs/nhcx/v1/roles/provider/ui-guide.md new file mode 100644 index 000000000..2fcfd7e7a --- /dev/null +++ b/site/docs/nhcx/v1/roles/provider/ui-guide.md @@ -0,0 +1,220 @@ +--- +title: Provider UI guide +sidebar_label: Provider UI guide +sidebar_position: 9 +description: Provider desk wireframes and UX recommendations +verification: unverified +source: nhcx-package/docs/03-Building a Provider/09-UI Guide.md +generated: true +sidebar_custom_props: + roles: + - provider +--- + +# Provider UI guide + +This chapter is about the screens. Everything before it said what the provider system calls and what goes in the bundle. This says what the person at the desk sees, what they type, what they must not be allowed to type, and where each piece of data on the screen comes from. It is written for the product owner and the front-end engineer, and it is organised as seven flows across the same ground the rest of the section covers. + +Two rules run through every screen. + +**Nothing the exchange already knows is typed.** Payer names, policy numbers, package names, rates, add-on codes, document lists and questionnaire text all come from elsewhere. From the participant service, the policy lookup, the insurance plan or the eligibility response. A field the user can edit is a field the payer can reject. + +**The screen never shows a decision the exchange has not sent.** Submitting is not approval. Every status on every screen is derived from a callback that was received, decrypted and stored, never from the fact that a request went out. + +That rule has a consequence which is easy to miss. A case the payer has not answered yet exists nowhere in the callback inbox, because nothing has come back. So a system that builds its case list only from received callbacks cannot show a waiting case. The case vanishes between submission and answer, which is the one moment the user most needs to see it. **Keep a record of what you sent as well as what came back.** Store, per request, the action, the protected header, the bundle and the exchange's receipt. Build every case screen from the two halves together. Sent with nothing back is the waiting state, and it is a state you have to be able to render. + +A case is keyed by its correlation ID, which the provider generates and which stays fixed for the whole conversation, so it is the only identifier available at the moment of submission. The payer's own case or preauthorisation number arrives later, on the answer. Show the payer's number to the user, since that is the number they will quote on the phone, but address the case internally by the correlation ID. Screen addresses are yours to choose; the chapter does not prescribe them. + +## Where the data comes from + +```mermaid +flowchart LR + PS[Participant service] --> PL[Payer list] + PS --> PO[Policy lookup] + PL --> UI[Screens] + PO --> UI + IP[Insurance plan cache] --> UI + EL[Eligibility response] --> UI + CB[Callback inbox] --> UI + UI --> BE[Provider backend] + BE --> X((NHCX)) + X --> BE +``` + +| On screen | Comes from | Editable | +| :---- | :---- | :---- | +| Payer name | Participant list, filtered by role | Pick from list | +| Policy, member ID, product | Policy lookup | Pick from list | +| Cover in force, balance remaining | Eligibility response, purpose validation | No | +| Approved amount, reduction note | Claim response on the answer | No | +| Specialty, package, rate | Insurance plan | Pick from list; rate fixed | +| Add-ons allowed and their limits | Insurance plan flags | Pick within limits | +| Required documents, questionnaires | Eligibility response, purpose auth-requirements; plan | No; answer, do not edit | +| Case status | What was sent, plus the callback inbox | No | +| Payer's query text, decision, reason | Callback inbox | No | +| UTR, deductions, net paid | Payment notice callback | No | +| Clinical findings, history, diagnosis, care team | The HMIS record | Yes, in the HMIS | +| Bill number, date, amount claimed | Hospital billing | Yes, within the approved amount | + +## Flow 1: find the patient and register + +**Screen.** One search box with a type selector: ABHA number, member ID, mobile. A results list showing the insurer name for each policy found. A confirm-cover panel that fills after the user picks a policy: in force or not, balance remaining, and the payer's own sentence about the policy shown verbatim. A register button that is disabled until cover is confirmed. + +**What the UI enforces.** Try identifiers in order of strength and tell the user which one matched. The balance remaining is the allowed amount less the amount already used, both of which the eligibility answer carries as money values on the benefit. Show that subtraction, not the allowed amount on its own: the allowed amount alone reads as more cover than the patient has. Group digits the Indian way, so four hundred and fifty thousand reads as 4,50,000, and give the figure a word beside it rather than a bare number. Disable registration when the policy is not in force or the limit is exhausted, and say why in the payer's words. + +**What the backend does behind it.** Resolves the processor code from the policy and stores it against the admission. The screen never shows the difference between insurer and processor, but every later call depends on it. + +```mermaid +sequenceDiagram + participant U as Desk user + participant S as Screen + participant B as Backend + participant X as NHCX + participant Y as Payer + U->>S: enter ABHA number + S->>B: find policies + B->>X: participant list, policy lookup + X-->>B: policies with insurer and processor + B-->>S: list, insurer names + U->>S: pick policy + S->>B: confirm cover + B->>X: eligibility, purpose validation + X-->>B: 202 receipt + Note over S: shows "checking cover", not a result + X->>B: callback, sealed response + B-->>S: in force, balance remaining + U->>S: register +``` + +**States the screen shows.** Searching, policies found, checking cover, cover confirmed, cover refused, registered. + +## Flow 2: plan the treatment + +**Screen.** A specialty picker limited to what the plan says this hospital may use, read from the cached insurance plan. A package picker under it, with the rate shown and locked. Add-on controls that appear only when the package's flags allow them, each capped at the plan's maximum. A live total against the balance remaining, turning red when it would exceed it. A document checklist and questionnaire panel that populate once the packages are chosen. + +**What the UI enforces.** Rate not editable. Quantity capped. A standalone package clears any other selection and says so. A package flagged as needing a parent will not stay selected without one. A government-reserved package is not shown to a private hospital. When the total exceeds the balance, the submit path is closed, not merely warned. + +**What the backend does behind it.** Reads the cached plan and derives the document checklist and questionnaires from the selected packages. Calls eligibility with purpose benefits to confirm the balance. Refreshes the plan if a policy-change communication has arrived since the cache was filled. + +Everything this screen offers comes from the insurance plan. The specialties, the packages, the rates, the add-on allowances, the flags that govern them, the documents each package demands and the questionnaires attached to it are all in the plan. Fetch it and cache it as the Insurance Plan chapter describes. + +The auth-requirements exchange is specified to return the required documents, and the rest of this section says so. The one published sample does not: it carries no benefit detail and no supporting-information requirements, and is indistinguishable from the plain benefits answer. So build the checklist from the plan, which certainly carries the requirements, and use the auth-requirements answer to confirm that authorisation is needed and to add anything it does return. A screen that depends on that answer alone will be empty against the only payer whose response has been published. + +```mermaid +flowchart TD + A[Pick specialty from plan] --> B[Pick package, rate locks] + B --> F{Flags on the package} + F -- implant allowed --> I[Implant picker, capped] + F -- stratification allowed --> R[Bed category picker, capped] + F -- standalone --> S[Clear other selections] + F -- unspecified --> U[Free-text name and amount] + B --> E[Eligibility: benefits, then auth-requirements] + E --> D[Document checklist and questionnaires] + D --> T{Total within balance?} + T -- yes --> P[Continue to preauthorisation] + T -- no --> N[Blocked, show the shortfall] +``` + +## Flow 3: preauthorisation, query, enhancement, cancel + +**Screen.** Four tabs in the payer's own order: medical information, admission information, treatment, finance. A documents panel driven by the checklist from flow 2, with each mandatory item shown as missing until attached and the submit button disabled until none are. After submission, a case panel with one status line and a timeline of everything sent and received. + +**What the UI enforces.** Every mandatory document attached. Every questionnaire the plan demands answered. Registration and admission dates present. Total within balance. Under PMJAY, a biometric token or a consent response, and admission not more than one day ahead. + +**The query inbox.** A queried case shows the payer's text, with the item it concerns highlighted, and a reply form that attaches documents and carries the case remarks. Reply goes out as a query answer, never as a new preauthorisation; the screen should make that impossible to confuse. + +**Enhancement.** Opens only on an approved case with no request in flight, offers only packages the plan marks enhanceable, and shows the already-approved items greyed alongside the new ones. + +**Cancel.** A reason picker with the seven documented reasons and a free-text field that is required when the reason is Other. Hidden once a claim has been raised. + +```mermaid +stateDiagram-v2 + [*] --> Draft + Draft --> Submitted: submit + Submitted --> UnderReview: receipt, then payer ack + UnderReview --> Approved: approved + UnderReview --> Reduced: approved at lower amount + UnderReview --> Queried: query + UnderReview --> Rejected: rejected + Queried --> Answered: reply sent + Answered --> UnderReview + Approved --> EnhancementPending: enhancement sent + EnhancementPending --> Approved: enhancement decided + Approved --> Cancelled: cancel confirmed + Rejected --> Resubmitted: resubmit + Resubmitted --> UnderReview +``` + +What each state shows the user: Submitted means "sent, no word yet", not approval. UnderReview appears only when the payer's receipt has come back. Approved shows the preauthorisation reference, the approved amount, and any reduction note verbatim. + +Three fields on the answer are worth naming, because the response carries several amounts and picking the wrong one misstates the decision. The **approved amount** for the case as a whole is the benefit total on the response, and the same category per line gives the approved amount for each item. The submitted category alongside it is what you asked for, not what you were granted. Showing it as the decision is the classic error. The **preauthorisation reference** is the payer's own number for the case. The **reduction note**, and any other sentence the adjudicator wrote, arrives as process notes and is shown verbatim. The Preauthorisation Response chapter in the FHIR Reference gives the full shape. + +## Flow 4: discharge and claim + +**Screen.** A discharge form: type (home, death, left against advice, discharged against advice), dates, and the documents that type requires. Then the claim form: bill number, date, bill attachment, amount claimed with the approved amount shown beside it, post-operative evidence. A single submit for the claim; under PMJAY the discharge is not a separate submission. + +**What the UI enforces.** Amount claimed not above the approved amount. Discharge type chosen before the claim opens. Under PMJAY: a fresh biometric or the discharge consent; for a LAMA or DAMA leaving before surgery, the line items replaced by the stay line with the user told the approved packages are voided. + +```mermaid +sequenceDiagram + participant U as Billing user + participant S as Screen + participant B as Backend + participant X as NHCX + U->>S: discharge type, dates, documents + U->>S: bill and amount + S->>S: amount within approved? documents complete? + S->>B: submit claim + B->>X: claim, workflow 15 + X-->>B: 202 receipt + Note over S: "submitted", awaiting decision + X->>B: interim callbacks, in process + B-->>S: "in process at payer" + X->>B: final callback + B-->>S: approved amount, or query, or rejection with reason +``` + +**States.** Draft, submitted, in process, forwarded, queried, approved, reduced, rejected. Rejected is final; the only action offered is appeal. + +## Flow 5: appeal a decision + +**Screen.** From a rejected or short-paid case, one appeal form: the payer's reason shown at the top, a document attachment that is required, and for a shortfall an amount field capped at the difference. A notice of how many appeals remain, and, once the Committee has decided, a closed state with the decision. + +**What the UI enforces.** No appeal without a document. Shortfall amount never above the difference. Under PMJAY, the shortfall form stays disabled until the settlement notice has arrived and been acknowledged, and neither form reopens after a Committee decision. + +## Flow 6: payments + +**Screen.** Per case, a payment panel listing each notice as it arrives, and on settlement the UTR as text on the page, gross, deductions itemised, and net. Reconciliation staff copy the UTR, so a copy control beside it earns its place. The value still has to be readable without one: a UTR that exists only inside the `value` attribute of an input box is not on the screen. The same goes for every other figure the payer sent. An acknowledge button per notice. A reconciliation view across cases for accounts, filterable by date and payer, exportable. + +**What the UI enforces.** There are two different acknowledgements here and the screen should not confuse them. The 202 receipt your callback returns is a transport acknowledgement, sent automatically the moment the notice arrives. Separately, the provider sends a real acknowledgement message back to the payer, a Task on workflow 17, and the Payment and Communication chapter gives its shape. That one is a business act, so it belongs on the screen: one button per notice, and a clear indication once it has gone. Send it whether or not the user clicks, and show that it went. A rejected payment notice shows as not paid, in red, with the case kept open. + +## Flow 7: the case list and the inbox + +**Screen.** Every case in one list with its current state and the time of the last callback, sortable by what needs action: queries waiting for an answer, turnaround alerts, payment notices unacknowledged. A separate inbox for payer communications by reason: information requests, turnaround alerts, grievances, wallet changes, policy changes, arbitration acknowledgements, each routed to the desk that owns it. + +**What the UI enforces.** Nothing on this screen is entered. It is a view over what was sent and what came back, and it is honest about silence. A case with no answer for longer than expected shows as waiting, with how long it has been waiting, and never as any decision. Do not offer a refresh or chase button unless you have implemented the status exchange behind it, because a control that does nothing is worse than no control. + +```mermaid +flowchart LR + CB[Callback inbox] --> M{Message type} + M -- decision on a case --> CL[Case list: update state] + M -- query --> Q[Query inbox] + M -- communication --> R{Reason} + R -- information --> Q + R -- TAT alert --> D[Claims desk] + R -- grievance --> G[Grievance desk] + R -- wallet or policy change --> P[Refresh plan or balance] + R -- arbitration ack --> A[Appeals view] + M -- payment notice --> PAY[Payments panel] + M -- protocol response --> E[Error view with the payer's code] +``` + +## Two things that will break a naive screen + +**A delivery failure arriving on a case that already has an answer.** A report on the error endpoint, or a protocol response saying a message could not be opened, is about one message. It is not about the case. A screen that simply shows the most recent thing that arrived will turn an approved preauthorisation into an error, which is wrong and alarming. Show the failure as a flag beside the state, not as the state. + +**The same answer delivered twice.** The exchange retries, so a callback can arrive more than once with the same call ID. A timeline built by appending everything received will show the payer approving the case twice. Treat a repeated call ID as the message you already have, and if the timeline mentions it at all, mention it as a repeat. + +## Errors the user should see + +Show the payer's error as the payer wrote it, with the code, and add one line saying what the user can do. The reference payer's messages already name the field: "Invalid procedure code received as X", "Insufficient wallet balance", "Existing case in progress for case number Y". Do not translate them into a generic failure. A protocol response, meaning the message could not be opened, is a system problem and goes to the integration team, not to the desk. diff --git a/site/docs/nhcx/v1/troubleshooting/_category_.json b/site/docs/nhcx/v1/troubleshooting/_category_.json new file mode 100644 index 000000000..c1e1ed732 --- /dev/null +++ b/site/docs/nhcx/v1/troubleshooting/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Troubleshooting", + "position": 7 +} diff --git a/site/docs/nhcx/v1/troubleshooting/accepted-then-no-callback.md b/site/docs/nhcx/v1/troubleshooting/accepted-then-no-callback.md new file mode 100644 index 000000000..1f1f1ae4e --- /dev/null +++ b/site/docs/nhcx/v1/troubleshooting/accepted-then-no-callback.md @@ -0,0 +1,59 @@ +--- +title: Accepted with 202, and no callback arrives +sidebar_label: Accepted with 202, and no callback arrives +sidebar_position: 4 +description: "The exchange answered 202 and no callback followed: the six checks in order" +verification: unverified +source: nhcx-package/docs/08-Troubleshooting/04-Accepted Then No Callback.md +generated: true +covers: + - nhcx.troubleshooting.accepted-then-no-callback +--- + +# Accepted with 202, and no callback arrives + +Your call returned `202` and no answer has come. The `202` only means the exchange accepted the request. The answer travels three more legs, and any of them can stop it, so find which one. + +## In short + +- Check `/v1/error` first. An undeliverable request is reported there. +- Then check that the exchange can reach your endpoint, and that you answer `202` in time. +- A status check with the request's API call ID says where the request stands. +- Never resubmit on the same correlation ID. Start a new cycle. + +## Prerequisites + +- You have the request's `x-hcx-api_call_id`, `x-hcx-correlation_id` and `x-hcx-timestamp`. +- You host `/v1/error`, where the exchange reports a request it cannot deliver. + +## Work through these in order + +1. **Did `/v1/error` receive anything?** When the exchange cannot deliver your request, the failure comes back to your [error endpoint](/docs/nhcx/v1/api/other/endpoints/other-v1-error). Check its log first. +2. **Can the exchange reach your callback endpoint at all?** Domain name, hosting in India, allowed addresses and routing all matter. See [Your callback URL is rejected or never called](/docs/nhcx/v1/troubleshooting/your-callback-url-is-rejected). +3. **Does your endpoint answer `202` within 30 seconds, with the receipt body?** A slow or malformed receipt counts as a failed delivery. The exchange retries five times, then deletes the request. +4. **Did you address the right recipient?** When a [TPA](/docs/nhcx/v1/getting-started/glossary#organisations-and-programmes) processes the policy, `x-hcx-recipient_code` is the `processingid` from the policy lookup, not the payer's code. +5. **Where does the request stand?** Send one [status check](/docs/nhcx/v1/api/status/endpoints/status-v1-status), with the request's API call ID as its correlation ID. `request.queued` means it is still inside the exchange. `request.dispatched` means the recipient holds it, and a `/v1/on_status` callback follows. +6. **Did the recipient reject it?** A recipient that cannot process your request answers with a clear-text `ProtocolResponse` instead of a sealed payload. Its `x-hcx-status` is `response.error`. A handler that accepts only sealed bodies drops it, so read `x-hcx-error_details`. + +## What you see when it works + +The callback reaches your endpoint carrying the correlation ID you sent. Your endpoint answers it `202` within 30 seconds, with the receipt body. The next request of the same kind completes the same way. + +## When it goes wrong + +Do not resubmit with the same correlation ID. The exchange refuses it as a duplicate, `NHCX-1006`. Once you know the old cycle failed, start a new one with a new correlation ID. + +If every check passes and nothing arrives, write to `hcx.integration@nha.gov.in`. Include the API call ID, the correlation ID, the timestamp and the `202` body. + +| Code | What it means | +| :---- | :---- | +| `NHCX-1001` | The receiver system is not reachable | +| `NHCX-1006` | A request with the same correlation ID already exists | +| `NHCX-1010` | No data for the correlation ID of a callback | +| `NHCX-1012` | No records for the API call ID of a status check | + +## Next steps + +- [Status and Search](/docs/nhcx/v1/getting-started/status-and-search): the status check in full. +- [The recipient cannot decrypt your message](/docs/nhcx/v1/troubleshooting/the-recipient-cannot-decrypt): when the rejection carries `PAYR-1001`. +- [The payer rejects your FHIR bundle](/docs/nhcx/v1/troubleshooting/the-payer-rejects-your-bundle): when it names a bundle fault. diff --git a/site/docs/nhcx/v1/troubleshooting/every-call-returns-401.md b/site/docs/nhcx/v1/troubleshooting/every-call-returns-401.md new file mode 100644 index 000000000..07ecb9723 --- /dev/null +++ b/site/docs/nhcx/v1/troubleshooting/every-call-returns-401.md @@ -0,0 +1,51 @@ +--- +title: Every NHCX call returns 401 +sidebar_label: Every NHCX call returns 401 +sidebar_position: 2 +description: "Every endpoint fails the same way: the token, its prefix, its header or its environment" +verification: unverified +source: nhcx-package/docs/08-Troubleshooting/02-Every Call Returns 401.md +generated: true +covers: + - nhcx.troubleshooting.everything-returns-401 +--- + +# Every NHCX call returns 401 + +Every call fails with `401`, often with the message `Sender is not authorized to execute the operation`. When every endpoint fails the same way, the fault is your token or the header carrying it. It is not any one call. + +## In short + +- An expired token is the usual cause. Fetch a new one and retry the failing call once. +- The header value is `Bearer`, a space, then the token. +- Send the same value in `bearer_auth` and `Authorization`. +- A sandbox token never works against a production host. + +## Prerequisites + +- More than one endpoint is failing. If one call fails while others succeed, read that call's own error instead. +- You have the full response body, not only the status code. + +## Work through these in order + +1. **Has the token expired?** An expired token returns this message. Read the lifetime from the token response, `expiresIn` or `expires_in`, instead of assuming one. Fetch a new token and retry the failing call once. A retry with the old token fails the same way. +2. **Does the value start with `Bearer `?** The header value is the word `Bearer`, a space, then the token. A bare token returns `401`. +3. **Is the token in the header the call reads?** Send the same value in both `bearer_auth` and `Authorization`. +4. **Are the token and the host from the same environment?** A sandbox token does not work against a production host, or the reverse. Compare the host that issued the token with the host of the failing call. [Base URLs](/docs/nhcx/v1/getting-started/base-urls) lists both. +5. **Is the token call itself healthy?** If minting a token fails, check the credentials and the body. The session address needs `grantType` set to `client_credentials`. [Session Token](/docs/nhcx/v1/getting-started/session-token) has the call. + +## What you see when it works + +A call that returned `401` now returns its normal response. It keeps doing so across several calls, over more than one token lifetime. One success can be a token that happened to be fresh, so confirm again after the next refresh. + +## When it goes wrong + +A `401` on linking or de-linking a policy, while other calls work, is a different fault. The token must come from the client ID that created the payer or [TPA](/docs/nhcx/v1/getting-started/glossary#organisations-and-programmes) named in the link. Run the linking job under those credentials. + +If all five checks pass and calls still return `401`, the credentials may have been revoked or reissued. Write to `hcx.integration@nha.gov.in` with the call, its time and the full response body. Never send the token or the client secret. + +## Next steps + +- [Session Token](/docs/nhcx/v1/getting-started/session-token): minting the token and keeping it fresh. +- [Troubleshooting](/docs/nhcx/v1/reference/troubleshooting): the symptom table, if the `401` names a header. +- [When something breaks](/docs/nhcx/v1/troubleshooting): the other symptoms. diff --git a/site/docs/nhcx/v1/troubleshooting/index.md b/site/docs/nhcx/v1/troubleshooting/index.md new file mode 100644 index 000000000..d43826ef1 --- /dev/null +++ b/site/docs/nhcx/v1/troubleshooting/index.md @@ -0,0 +1,27 @@ +--- +title: When something breaks +sidebar_label: When something breaks +sidebar_position: 1 +description: Find the symptom you see, not the error code, and open the chapter that walks its checks +verification: unverified +source: nhcx-package/docs/08-Troubleshooting/01-When Something Breaks.md +generated: true +--- + +# When something breaks + +Find the symptom you are seeing, not the error code. Each chapter here walks the checks in order, so you can start without knowing which code applies. They run in the order a message travels: your token, your address, delivery, encryption, the bundle, then the identifiers that tie a cycle together. + +- [Every NHCX call returns 401](/docs/nhcx/v1/troubleshooting/every-call-returns-401): every endpoint fails the same way, not one call. +- [Your callback URL is rejected or never called](/docs/nhcx/v1/troubleshooting/your-callback-url-is-rejected): the endpoint update is refused, or nothing ever reaches your server. +- [Accepted with 202, and no callback arrives](/docs/nhcx/v1/troubleshooting/accepted-then-no-callback): the exchange took your request and nothing followed. +- [The recipient cannot decrypt your message](/docs/nhcx/v1/troubleshooting/the-recipient-cannot-decrypt): the answer is a `ProtocolResponse` carrying `PAYR-1001`. +- [The payer rejects your FHIR bundle](/docs/nhcx/v1/troubleshooting/the-payer-rejects-your-bundle): the answer names a bundle fault such as `PAYR-1004` or `PAYR-1008`. +- [Responses arrive against the wrong request](/docs/nhcx/v1/troubleshooting/responses-arrive-against-the-wrong-request): answers land on the wrong case, or the exchange refuses a duplicate. + +If you already hold an error code, [Troubleshooting](/docs/nhcx/v1/reference/troubleshooting) in the Reference is organised the other way, by layer and by code. [Error Codes](/docs/nhcx/v1/reference/error-code-guide) lists every code either side can send. + +## Next steps + +- [Troubleshooting](/docs/nhcx/v1/reference/troubleshooting): the five layers and the symptom table. +- [Get your sandbox credentials](/docs/nhcx/v1/getting-started/get-your-sandbox-credentials): where to write, and what to put in the message. diff --git a/site/docs/nhcx/v1/troubleshooting/responses-arrive-against-the-wrong-request.md b/site/docs/nhcx/v1/troubleshooting/responses-arrive-against-the-wrong-request.md new file mode 100644 index 000000000..ff399eebf --- /dev/null +++ b/site/docs/nhcx/v1/troubleshooting/responses-arrive-against-the-wrong-request.md @@ -0,0 +1,56 @@ +--- +title: Responses arrive against the wrong request +sidebar_label: Responses arrive against the wrong request +sidebar_position: 7 +description: "Answers on the wrong case, duplicates refused, callbacks unmatched: correlation and API call IDs" +verification: unverified +source: nhcx-package/docs/08-Troubleshooting/07-Responses Arrive Against the Wrong Request.md +generated: true +covers: + - nhcx.troubleshooting.duplicate-or-mismatched-correlation +--- + +# Responses arrive against the wrong request + +An answer lands on the wrong case in your system. Or the exchange refuses a request as a duplicate, or refuses a callback it cannot match. All three come from how your system sets and reads the [correlation ID](/docs/nhcx/v1/getting-started/glossary#messages) and the [API call ID](/docs/nhcx/v1/getting-started/glossary#messages). + +## In short + +- Open each cycle with a new correlation ID, equal to that request's API call ID. +- Every message in the cycle echoes it. Every call gets a new API call ID. +- A failed cycle's correlation ID is inactive, so start a new cycle. +- Match incoming messages on the correlation ID, never on arrival order. + +## Prerequisites + +- You log the `x-hcx-correlation_id` and `x-hcx-api_call_id` of every message you send and receive. + +## Work through these in order + +1. **Does each request cycle get its own correlation ID?** Generate a new random 36-character identifier for every request that opens a cycle. Set it equal to that request's API call ID. Never copy one from an example. +2. **Does every message in the cycle carry it unchanged?** The answer, any query and every callback echo the request's correlation ID. The answer's own API call ID is different. +3. **Is the API call ID new on every call?** Generate a fresh one for every call, retries included. +4. **Did you reuse a failed cycle's correlation ID?** After an error the correlation ID becomes inactive. A new request with it is refused with `NHCX-1006`. Start a fresh cycle with a new ID. +5. **Do you match answers by correlation ID?** Store the correlation ID against the case before you send. Match every incoming message on it, never on arrival order or time. +6. **If you are the payer, is the recipient right?** The recipient code of your answer is the sender code of the request you answer. + +## What you see when it works + +Every callback lands on the case whose request carried its correlation ID. New requests are accepted with `202`, and your logs show no `NHCX-1006` or `NHCX-1010`. + +## When it goes wrong + +If one case's answers keep landing elsewhere, compare the correlation ID in the misplaced callback with the one stored on each case. Two cases holding the same value point at a generator that repeats. A [status check](/docs/nhcx/v1/api/status/endpoints/status-v1-status) shows which request the exchange holds for an ID. + +| Code | What it means | +| :---- | :---- | +| `NHCX-1006` | A request with the same correlation ID already exists | +| `NHCX-1010` | No data for the correlation ID of a callback | +| `NHCX-1012` | No records for an API call ID | +| `PAYR-1516` | No event found for the API call ID and correlation ID of an error response | + +## Next steps + +- [Envelope Fields](/docs/nhcx/v1/reference/envelope-fields): every identifier on the envelope, and when each one changes. +- [JWE, Status and Errors](/docs/nhcx/v1/concepts/jwe-status-and-errors): how a cycle threads from request to answer. +- [When something breaks](/docs/nhcx/v1/troubleshooting): the other symptoms. diff --git a/site/docs/nhcx/v1/troubleshooting/the-payer-rejects-your-bundle.md b/site/docs/nhcx/v1/troubleshooting/the-payer-rejects-your-bundle.md new file mode 100644 index 000000000..9b635569c --- /dev/null +++ b/site/docs/nhcx/v1/troubleshooting/the-payer-rejects-your-bundle.md @@ -0,0 +1,59 @@ +--- +title: The payer rejects your FHIR bundle +sidebar_label: The payer rejects your FHIR bundle +sidebar_position: 6 +description: "`PAYR-1004`, `PAYR-1008` and the missing identifier codes: validate, then check shape, identifiers and attachments" +verification: unverified +source: nhcx-package/docs/08-Troubleshooting/06-The Payer Rejects Your Bundle.md +generated: true +covers: + - nhcx.troubleshooting.bundle-rejected +--- + +# The payer rejects your FHIR bundle + +The payer opened your message and could not accept the Fast Healthcare Interoperability Resources (FHIR) bundle inside it. The answer names the fault with a code. + +| Code | What it means | +| :---- | :---- | +| `PAYR-1004` | The bundle is malformed, followed by error details | +| `PAYR-1008` | The bundle is invalid or cannot be parsed | +| `PAYR-1009` | No identifier for the patient | +| `PAYR-1013` | No identifier for the provider organisation | + +## In short + +- Read the message with the code. `PAYR-1004` has two meanings. +- Run the [NRCeS](/docs/nhcx/v1/getting-started/glossary#organisations-and-programmes) validator on the exact bundle you sealed, and fix what it reports first. +- Every resource declares its NRCeS profile. The patient, both organisations and the claim each carry an identifier with a type. +- Attachments are Base64, named, and of an allowed content type. + +## Prerequisites + +- You have the full answer, including the message and any details after the code. +- You can run the NRCeS validator on the exact bundle you sealed. + +## Work through these in order + +Read the message with the code first. `PAYR-1004` also means "Provider is not registered with the payer for requested policy" on the standard payer sheet. The message text tells you which fault you have, and [Error Codes](/docs/nhcx/v1/reference/error-code-guide) explains the two sheets. + +1. **Does the bundle pass the NRCeS validator?** Run it on the exact bundle you sealed, and fix what it reports first. +2. **Is the bundle shaped right?** It is a `Bundle` of type `collection`. Every resource declares its NRCeS profile in `meta.profile`. Resources reference each other as `urn:uuid:` identifiers, not relative paths. +3. **Does every resource carry its identifier and type?** The patient, both organisations and the claim each need an identifier with a type. +4. **Is your hospital identified correctly?** Send the [HFR](/docs/nhcx/v1/getting-started/glossary#identity-and-registration) ID as an identifier typed `NPI` in the provider `Organization`. It must match the registry ID recorded for you as sender. +5. **Are the attachments valid?** Each has Base64 data and a name that is not empty. Its content type is one of `application/pdf`, `application/jpg`, `application/jpeg`, `application/png` or `application/fhir+json`. +6. **Are the values clean?** Trim leading and trailing spaces. Codes are case sensitive and must match the expected values exactly. + +## What you see when it works + +The validator passes the bundle. The payer's answer is an adjudication, a claim response or an eligibility response with an outcome, not a bundle error. + +## When it goes wrong + +If the validator passes and the payer still refuses the bundle, send the bundle to `hcx.integration@nha.gov.in` for review by the NRCeS team. Include the payer's full error message, and replace personal data with test values first. + +## Next steps + +- [Bundles and Conventions](/docs/nhcx/v1/reference/fhir): the rules every bundle follows. +- [Codes and Value Sets](/docs/nhcx/v1/reference/fhir/codes-and-value-sets): the exact codes each element takes. +- [Troubleshooting](/docs/nhcx/v1/reference/troubleshooting): every bundle code, in the layer 4 rows. diff --git a/site/docs/nhcx/v1/troubleshooting/the-recipient-cannot-decrypt.md b/site/docs/nhcx/v1/troubleshooting/the-recipient-cannot-decrypt.md new file mode 100644 index 000000000..c22e6ce42 --- /dev/null +++ b/site/docs/nhcx/v1/troubleshooting/the-recipient-cannot-decrypt.md @@ -0,0 +1,52 @@ +--- +title: The recipient cannot decrypt your message +sidebar_label: The recipient cannot decrypt your message +sidebar_position: 5 +description: "A `PAYR-1001` protocol response: the certificate, its cache, the algorithms and the compact form" +verification: unverified +source: nhcx-package/docs/08-Troubleshooting/05-The Recipient Cannot Decrypt.md +generated: true +covers: + - nhcx.troubleshooting.recipient-cannot-decrypt +--- + +# The recipient cannot decrypt your message + +The payer's answer is a clear-text `ProtocolResponse` carrying `PAYR-1001`: an error occurred while decrypting the payload. The recipient could not open your [JWE](/docs/nhcx/v1/getting-started/glossary#messages) with its private key. The fault is almost always on the sending side: the wrong certificate, the wrong algorithm or the wrong form. + +## In short + +- Seal with the certificate of the participant in `x-hcx-recipient_code`, fetched within the last 24 hours. +- Use `RSA-OAEP-256` with `A256GCM`, in compact form. +- Resend with a new correlation ID and a new API call ID. +- `PAYR-1002` is the reverse fault. Update your own registered certificate. + +## Prerequisites + +- You have the `ProtocolResponse`, including `x-hcx-error_details` and the correlation ID. +- You know which certificate you sealed with, and when you fetched it. + +## Work through these in order + +1. **Did you seal to the recipient you addressed?** The certificate must belong to the participant in `x-hcx-recipient_code`. [Fetch it](/docs/nhcx/v1/api/registry/endpoints/registry-fetch-certs), passing that code as `participantid`. When a [TPA](/docs/nhcx/v1/getting-started/glossary#organisations-and-programmes) processes the policy, that code is the `processingid`. +2. **Is your cached copy stale?** Cache a certificate for 24 hours at most. On `PAYR-1001`, fetch it again and resend. A recipient that rotated its key has a new certificate. +3. **Did the key import correctly?** The call can return a PEM X.509 certificate or a bare SubjectPublicKeyInfo (SPKI) public key. Try the X.509 import first, then fall back to the bare key. +4. **Are the algorithms right?** The protected header carries `alg` `RSA-OAEP-256` and `enc` `A256GCM`. +5. **Is the form right?** The body is `{"payload": ""}`, one compact string with four dots. +6. **Is the [protected header](/docs/nhcx/v1/getting-started/glossary#messages) complete?** Check every `x-hcx-` field against [Envelope Fields](/docs/nhcx/v1/reference/envelope-fields). The sender and recipient codes come from the registry. The API call ID and correlation ID are fresh. + +The reverse fault has its own code. `PAYR-1002` means the payer could not seal its answer to you with the certificate registered for you. Update it with [the certificate update call](/docs/nhcx/v1/api/registry/endpoints/registry-v2-update-cert) or the participant update. The payer fetches the new one and sends its answer. + +## What you see when it works + +You resend with a new correlation ID and a new API call ID. The answer arrives as a sealed payload on your callback, not a `ProtocolResponse`. Your own code opens it with your private key. + +## When it goes wrong + +If every check passes and `PAYR-1001` persists, ask the recipient to confirm that its registered certificate matches the private key it decrypts with. Then write to `hcx.integration@nha.gov.in` with the recipient code and the correlation ID. + +## Next steps + +- [Fetching a Recipient Certificate](/docs/nhcx/v1/getting-started/fetching-a-recipient-certificate): which certificate, and how long to cache it. +- [Building and Sending a JWE](/docs/nhcx/v1/getting-started/building-and-sending-a-jwe): the algorithms and the compact form. +- [Your Certificate](/docs/nhcx/v1/getting-started/your-certificate): replacing yours when the payer reports `PAYR-1002`. diff --git a/site/docs/nhcx/v1/troubleshooting/your-callback-url-is-rejected.md b/site/docs/nhcx/v1/troubleshooting/your-callback-url-is-rejected.md new file mode 100644 index 000000000..8e13f454b --- /dev/null +++ b/site/docs/nhcx/v1/troubleshooting/your-callback-url-is-rejected.md @@ -0,0 +1,55 @@ +--- +title: Your callback URL is rejected or never called +sidebar_label: Your callback URL is rejected or never called +sidebar_position: 3 +description: The endpoint update is refused, or nothing ever reaches your server +verification: unverified +source: nhcx-package/docs/08-Troubleshooting/03-Your Callback URL Is Rejected.md +generated: true +covers: + - nhcx.troubleshooting.callback-url-rejected +--- + +# Your callback URL is rejected or never called + +The National Health Claims Exchange (NHCX) delivers requests and answers to the `endpoint_url` on your participant record. Either the update that sets it is refused, or it saves and nothing ever arrives. A sender addressing you sees `NHCX-1001`, receiver system not reachable. + +## In short + +- The URL is HTTPS, uses a domain name with no port, and points at a server in India. +- Allow the exchange's three addresses through your firewall. +- An endpoint update activates only after you confirm its passcode within 24 hours. +- Answer every delivery `202` within 30 seconds. + +## Prerequisites + +- Your participant is active, and you can call the participant update. +- You know the rules the address must meet. [Receiving a Callback](/docs/nhcx/v1/getting-started/receiving-a-callback) has them. + +## Work through these in order + +1. **Is the URL HTTPS and publicly reachable?** It must be publicly accessible and reachable from the exchange. +2. **Does it use a domain name?** Use a fully qualified domain name. An IP address, or a port number in the URL, is not accepted. +3. **Is the server hosted in India?** Callback servers must be. +4. **Are the exchange's addresses allowed in?** Allow `3.109.99.210`, `13.126.152.0` and `13.200.129.223` in your server configuration and firewall. Confirm no firewall rule blocks incoming requests from them. +5. **Did you confirm the update?** An endpoint update sends a passcode. The new endpoint activates only after you confirm it with [the update validation call](/docs/nhcx/v1/api/onboarding/endpoints/onboarding-update-validate), within 24 hours. +6. **Does your application route every path the exchange calls?** Requests arrive on use-case paths such as `/v1/claim/on_submit`. Check that load balancers, gateways and reverse proxies send each path to the right service and version. +7. **Does your endpoint answer fast enough?** Answer `202` with the receipt body within 30 seconds. Otherwise the exchange retries five times, then deletes the request. + +## What you see when it works + +Your participant record shows the new endpoint as active. The next message addressed to you arrives on the right path, and your endpoint answers it `202` within 30 seconds. + +To see a delivery arrive, send a coverage eligibility check to the [dummy payer](/docs/nhcx/v1/getting-started/glossary#messages), `1000003538@hcx`. Its `/v1/coverageeligibility/on_check` callback arrives at your endpoint. + +## When it goes wrong + +If every check passes and nothing arrives, find out whether the request was ever sent to you. See [Accepted with 202, and no callback arrives](/docs/nhcx/v1/troubleshooting/accepted-then-no-callback). + +If the update itself keeps failing, write to `hcx.integration@nha.gov.in` with your participant code, the endpoint URL and the full response. + +## Next steps + +- [Receiving a Callback](/docs/nhcx/v1/getting-started/receiving-a-callback): the endpoint, the receipt and the paths to host. +- [Creating and Updating a Participant](/docs/nhcx/v1/getting-started/creating-and-updating-a-participant): the update and its confirmation. +- [When something breaks](/docs/nhcx/v1/troubleshooting): the other symptoms. diff --git a/site/docs/whats-new/2026-09-15.mdx b/site/docs/whats-new/2026-09-15.mdx new file mode 100644 index 000000000..42d804a09 --- /dev/null +++ b/site/docs/whats-new/2026-09-15.mdx @@ -0,0 +1,62 @@ +--- +title: 15 September 2026 +sidebar_label: 15 September 2026 +sidebar_position: 1 +hide_title: true +description: What changed in these pages on 15 September 2026. +verification: unverified +source: catalogue/openapi/nhcx/v1, catalogue/nhcx +--- + +import ReleaseGroup from '@site/src/components/docs/ReleaseGroup'; + + + +### NHCX has API references + +[NHCX API references](/docs/nhcx/v1/api) cover the exchange in 14 modules, from the session +token and the participant registry to claims, payment notices and biometric authentication. +Each of its 63 calls has its own page with the headers, the body and a request you can send, +and each of the 21 callbacks you host has a page of its own. +[Error codes](/docs/nhcx/v1/reference/error-codes) lists the codes recorded for the exchange +gateway, the standard payer sheet and the PMJAY reference payer. + +### Point your agent at NHCX + +[Build with AI](/docs/nhcx/v1/getting-started/build-with-ai) connects your coding agent to the +Docs MCP server, which searches the NHCX catalogue alongside HIE-CM's. `llms.txt` now lists +an index for each NHCX API module, so an agent can fetch one module's pages as Markdown. + +### Seven NHCX agent skills + +Seven agent skills build NHCX into a hospital information system or a claims desk, one use +case each: coverage, the insurance plan, pre-authorisation, the claim, payment, communication +and reprocess. [Build with AI](/docs/nhcx/v1/getting-started/build-with-ai#agent-skills) lists +them with the command that installs each. + +### Start on the NHCX sandbox + +[Get your sandbox credentials](/docs/nhcx/v1/getting-started/get-your-sandbox-credentials) +covers what you need before you register, the test participants and the dummy payer. The +[Quickstart](/docs/nhcx/v1/getting-started/quickstart) then takes you from a session token to +a participant search and a fetched certificate, with nothing built yet. + +### The NHCX security audit has a page + +[Security audit](/docs/nhcx/v1/go-live/security-audit) covers the functional and security +tests every participant passes before production, and the certificates production onboarding +reviews. + +### Troubleshooting NHCX by what you see + +[Troubleshooting](/docs/nhcx/v1/troubleshooting) starts from what you see rather than from +the error code: + +- Every call returns 401. +- Your callback URL is rejected. +- A 202 arrives and no callback follows. +- The recipient cannot decrypt your message. +- The payer rejects your bundle. +- Responses arrive against the wrong request. + + diff --git a/site/src/components/docs/SkillPicker.tsx b/site/src/components/docs/SkillPicker.tsx index 38f3e0c4e..745953d14 100644 --- a/site/src/components/docs/SkillPicker.tsx +++ b/site/src/components/docs/SkillPicker.tsx @@ -2,6 +2,7 @@ import React, {useState} from 'react'; import useDocusaurusContext from '@docusaurus/useDocusaurusContext'; import {cn} from '@site/src/lib/utils'; import SkillInstall from './SkillInstall'; +import manifest from '@site/src/data/skills.json'; /** * Choose what you are building; see the one skill that serves it. Twenty two @@ -68,8 +69,60 @@ const CHOICES: Choice[] = [ }, ]; -export default function SkillPicker(): React.ReactNode { - const [choice, setChoice] = useState(CHOICES[0]); +// One skill per NHCX use case, in episode order. Each is a folder that +// installs and runs alone. +const NHCX_CHOICES: Choice[] = [ + { + slug: 'nhcx-coverage', + label: 'Coverage', + note: 'Finds the policy, opens the claim episode on it, and asks the payer whether the cover is in force.', + }, + { + slug: 'nhcx-insurance', + label: 'Insurance plan', + note: "Requests the payer's package master once per facility and policy, reuses it, and quotes treatment lines from it.", + }, + { + slug: 'nhcx-preauth', + label: 'Pre-authorisation', + note: 'Sends the pre-authorisation, answers its queries, raises enhancements, cancels, and asks for a predetermination.', + }, + { + slug: 'nhcx-claim', + label: 'Claim', + note: "Records the discharge, files the claim under the pre-authorisation's number, and reads the decision.", + }, + { + slug: 'nhcx-payment', + label: 'Payment', + note: "Records the payer's payment notice once against its claim, and acknowledges it at once.", + }, + { + slug: 'nhcx-communication', + label: 'Communication', + note: "Sorts the payer's messages into queries and notifications, acknowledges notifications, and answers queries.", + }, + { + slug: 'nhcx-reprocess', + label: 'Reprocess and status', + note: 'Reopens a decided claim, asks for the balance of a short payment, and asks where a case stands.', + }, +]; + +const SETS: Record = {abdm: CHOICES, nhcx: NHCX_CHOICES}; + +/** A skill of more than one file downloads as its archive, not its SKILL.md. */ +const isFolder = (slug: string) => + (manifest as Record)[slug]?.folder === true; + +type SkillPickerProps = { + /** Which gateway's skills to offer: ABDM's by default, or NHCX's. */ + set?: 'abdm' | 'nhcx'; +}; + +export default function SkillPicker({set = 'abdm'}: SkillPickerProps): React.ReactNode { + const choices = SETS[set] ?? CHOICES; + const [choice, setChoice] = useState(choices[0]); const {siteConfig} = useDocusaurusContext(); const base = `${siteConfig.url}${siteConfig.baseUrl}`.replace(/\/+$/, ''); @@ -79,7 +132,7 @@ export default function SkillPicker(): React.ReactNode { className="skill-install__targets skill-picker__choices" role="tablist" aria-label="What are you building?"> - {CHOICES.map((option) => ( + {choices.map((option) => (